Applied downs' lphobos update

This commit is contained in:
Tomas Lindquist Olsen
2008-08-04 19:28:49 +02:00
parent 9500e89eeb
commit 3f1767fd49
51 changed files with 27281 additions and 420 deletions

View File

@@ -5,69 +5,96 @@ mkdir -p obj
rm -f obj/*.bc
rm -f ../lib/*.bc
LLVMDCFLAGS="-c -odobj -g"
REBUILDFLAGS="-dc=llvmdc-posix-internal -c -oqobj -g"
LLVMDCFLAGS="-c -odobj -oq -gc -noasm"
LLVMDCFLAGS_ASM="-c -odobj -oq -gc"
echo "compiling contract runtime"
llvmdc internal/contract.d -c -of../lib/llvmdcore.bc -noruntime || exit 1
llvmdc internal/contract.d -c -of../lib/llvmdcore.bc || exit 1 #-noruntime || exit 1
echo "compiling common runtime"
rebuild internal/arrays.d \
llvmdc-build internal/arrays.d \
internal/mem.d \
$REBUILDFLAGS || exit 1
internal/critical.d \
internal/dmain2.d \
$LLVMDCFLAGS_ASM || exit 1
mv *.bc obj
echo "compiling module init backend"
llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/internal.*.bc` ../lib/llvmdcore.bc obj/moduleinit_backend.bc || exit 1
echo "compiling typeinfo 1"
rebuild typeinfos1.d $REBUILDFLAGS || exit 1
llvmdc-build typeinfos1.d $LLVMDCFLAGS || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo1.*.bc` ../lib/llvmdcore.bc || exit 1
echo "compiling typeinfo 2"
rebuild typeinfos2.d $REBUILDFLAGS || exit 1
llvmdc-build typeinfos2.d $LLVMDCFLAGS || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo2.*.bc` ../lib/llvmdcore.bc || exit 1
echo "compiling exceptions"
llvmdc-build internal/eh.d $LLVMDCFLAGS -debug || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc obj/*eh.bc ../lib/llvmdcore.bc || exit 1
echo "compiling object/interface casting runtime support"
llvmdc internal/cast.d $LLVMDCFLAGS || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc obj/cast.bc ../lib/llvmdcore.bc || exit 1
echo "compiling string foreach/switch runtime support"
llvmdc internal/aApply.d $LLVMDCFLAGS || exit 1
llvmdc internal/aApplyR.d $LLVMDCFLAGS || exit 1
llvmdc internal/switch.d $LLVMDCFLAGS || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc obj/aApply.bc obj/aApplyR.bc obj/switch.bc ../lib/llvmdcore.bc || exit 1
echo "compiling array runtime support"
llvmdc internal/qsort2.d $LLVMDCFLAGS || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc obj/qsort2.bc ../lib/llvmdcore.bc || exit 1
llvmdc internal/adi.d $LLVMDCFLAGS || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc obj/adi.bc ../lib/llvmdcore.bc || exit 1
llvmdc internal/aaA.d $LLVMDCFLAGS || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc obj/aaA.bc ../lib/llvmdcore.bc || exit 1
echo "compiling object implementation"
llvmdc internal/objectimpl.d $LLVMDCFLAGS || exit 1
llvmdc internal/objectimpl.d -c -odobj -g || exit 1
llvm-link -f -o=../lib/llvmdcore.bc obj/objectimpl.bc ../lib/llvmdcore.bc || exit 1
echo "compiling llvm runtime support"
rebuild llvmsupport.d $REBUILDFLAGS || exit 1
llvmdc-build llvmsupport.d $LLVMDCFLAGS || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || exit 1
echo "compiling garbage collector"
llvmdc gc/gclinux.d $LLVMDCFLAGS || exit 1
llvmdc gc/gcx.d $LLVMDCFLAGS -Igc || exit 1
llvmdc gc/gcbits.d $LLVMDCFLAGS -Igc || exit 1
llvmdc gc/gc.d $LLVMDCFLAGS -Igc || exit 1
cd gc
llvmdc $(ls *.d |grep -v win32) $LLVMDCFLAGS_ASM -I.. ||exit 1
# llvmdc gclinux.d $LLVMDCFLAGS -I.. || exit 1
# llvmdc gcx.d $LLVMDCFLAGS -I.. || exit 1
# llvmdc gcbits.d $LLVMDCFLAGS -I.. || exit 1
# llvmdc gc.d $LLVMDCFLAGS -I.. || exit 1
mv std.gc.bc gc.bc
mv *.bc ../obj
cd ..
llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcx.bc obj/gcbits.bc obj/gc.bc ../lib/llvmdcore.bc || exit 1
echo "compiling phobos"
rebuild phobos.d $REBUILDFLAGS || exit 1
llvmdc-build phobos.d $LLVMDCFLAGS || exit 1
mv *.bc obj
echo "linking phobos"
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1
echo "Compiling auxiliary"
llvmdc-build etc/c/zlib.d $LLVMDCFLAGS || exit 1
mv *.bc obj
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/etc.*.bc` ../lib/llvmdcore.bc || exit 1
echo "optimizing"
opt -f -std-compile-opts -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc || exit 1
opt -stats -p -f -std-compile-opts -disable-inlining -o=../lib/llvmdcore.bc ../lib/llvmdcore.bc || exit 1
echo "SUCCESS"

1215
lphobos/etc/c/zlib.d Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
module gcc.gc_guess_stack;
void * stackOriginGuess;

View File

@@ -4,13 +4,24 @@
// www.digitalmars.com
// Written by Walter Bright
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, September 2004
*/
import std.c.string;
import std.c.stdlib;
import std.outofmemory;
import std.intrinsic;
//version = Asm86;
version = bitops;
version (GNU) {
// bitop intrinsics not implemented yet
} else {
version = bitops;
}
struct GCBits
{

File diff suppressed because it is too large Load Diff

168
lphobos/gc/win32.d Normal file
View File

@@ -0,0 +1,168 @@
// Copyright (C) 2001-2002 by Digital Mars
// All Rights Reserved
// www.digitalmars.com
// Written by Walter Bright
import std.c.windows.windows;
alias int pthread_t;
/***********************************
* Map memory.
*/
void *os_mem_map(uint nbytes)
{
return VirtualAlloc(null, nbytes, MEM_RESERVE, PAGE_READWRITE);
}
/***********************************
* Commit memory.
* Returns:
* 0 success
* !=0 failure
*/
int os_mem_commit(void *base, uint offset, uint nbytes)
{
void *p;
p = VirtualAlloc(base + offset, nbytes, MEM_COMMIT, PAGE_READWRITE);
return cast(int)(p == null);
}
/***********************************
* Decommit memory.
* Returns:
* 0 success
* !=0 failure
*/
int os_mem_decommit(void *base, uint offset, uint nbytes)
{
return cast(int)VirtualFree(base + offset, nbytes, MEM_DECOMMIT) == 0;
}
/***********************************
* Unmap memory allocated with os_mem_map().
* Memory must have already been decommitted.
* Returns:
* 0 success
* !=0 failure
*/
int os_mem_unmap(void *base, uint nbytes)
{
return cast(int)VirtualFree(base, 0, MEM_RELEASE) == 0;
}
/********************************************
*/
pthread_t pthread_self()
{
//printf("pthread_self() = %x\n", GetCurrentThreadId());
return cast(pthread_t) GetCurrentThreadId();
}
/**********************************************
* Determine "bottom" of stack (actually the top on Win32 systems).
*/
void *os_query_stackBottom()
{
asm
{
naked ;
mov EAX,FS:4 ;
ret ;
}
}
/**********************************************
* Determine base address and size of static data segment.
*/
version (GNU)
{
// This is MinGW specific
extern (C)
{
// TODO: skip the .rdata between .data and .bss?
extern int _data_start__;
extern int _bss_end__;
}
void os_query_staticdataseg(void **base, uint *nbytes)
{
*base = cast(void *)&_data_start__;
*nbytes = cast(uint)(cast(char *)&_bss_end__ - cast(char *)&_data_start__);
}
}
else
{
extern (C)
{
extern int _xi_a; // &_xi_a just happens to be start of data segment
extern int _edata; // &_edata is start of BSS segment
extern int _end; // &_end is past end of BSS
}
void os_query_staticdataseg(void **base, uint *nbytes)
{
*base = cast(void *)&_xi_a;
*nbytes = cast(uint)(cast(char *)&_end - cast(char *)&_xi_a);
}
}
/++++
void os_query_staticdataseg(void **base, uint *nbytes)
{
static char dummy = 6;
SYSTEM_INFO si;
MEMORY_BASIC_INFORMATION mbi;
char *p;
void *bottom = null;
uint size = 0;
// Tests show the following does not work reliably.
// The reason is that the data segment is arbitrarily divided
// up into PAGE_READWRITE and PAGE_WRITECOPY.
// This means there are multiple regions to query, and
// can even wind up including the code segment.
assert(0); // fix implementation
GetSystemInfo(&si);
p = (char *)((uint)(&dummy) & ~(si.dwPageSize - 1));
while (VirtualQuery(p, &mbi, sizeof(mbi)) == sizeof(mbi) &&
mbi.Protect & (PAGE_READWRITE | PAGE_WRITECOPY) &&
!(mbi.Protect & PAGE_GUARD) &&
mbi.AllocationBase != 0)
{
bottom = (void *)mbi.BaseAddress;
size = (uint)mbi.RegionSize;
printf("dwPageSize = x%x\n", si.dwPageSize);
printf("&dummy = %p\n", &dummy);
printf("BaseAddress = %p\n", mbi.BaseAddress);
printf("AllocationBase = %p\n", mbi.AllocationBase);
printf("AllocationProtect = x%x\n", mbi.AllocationProtect);
printf("RegionSize = x%x\n", mbi.RegionSize);
printf("State = x%x\n", mbi.State);
printf("Protect = x%x\n", mbi.Protect);
printf("Type = x%x\n\n", mbi.Type);
p -= si.dwPageSize;
}
*base = bottom;
*nbytes = size;
}
++++/

5
lphobos/hello.d Normal file
View File

@@ -0,0 +1,5 @@
module hello;
import std.stdio;
void main() { writefln("Hello World"); }

View File

@@ -60,14 +60,14 @@ static size_t[] prime_list = [
*/
alias Array ArrayRet_t;
pragma(LLVM_internal, "notypeinfo")
pragma(no_typeinfo)
struct Array
{
size_t length;
void* ptr;
}
pragma(LLVM_internal, "notypeinfo")
pragma(no_typeinfo)
struct aaA
{
aaA *left;
@@ -77,7 +77,7 @@ struct aaA
/* value */
}
pragma(LLVM_internal, "notypeinfo")
pragma(no_typeinfo)
struct BB
{
aaA*[] b;
@@ -226,7 +226,7 @@ size_t _aaLen(AA aa)
* Add entry for key if it is not already there.
*/
void* _aaGet(AA* aa, TypeInfo keyti, void* pkey, size_t valuesize)
void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey)
in
{
assert(aa);

View File

@@ -38,7 +38,7 @@ import std.c.string;
import std.outofmemory;
import std.utf;
pragma(LLVM_internal, "notypeinfo")
pragma(no_typeinfo)
struct Array
{
size_t length;
@@ -462,13 +462,13 @@ unittest
extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
{
//printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
// printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
if (a1.length != a2.length)
return 0; // not equal
auto sz = ti.tsize();
auto sz = ti.next.tsize();
auto p1 = a1.ptr;
auto p2 = a2.ptr;
/+
for (int i = 0; i < a1.length; i++)
{
@@ -480,10 +480,10 @@ extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
if (sz == 1)
// We should really have a ti.isPOD() check for this
return (memcmp(p1, p2, a1.length) == 0);
for (size_t i = 0; i < a1.length; i++)
{
if (!ti.equals(p1 + i * sz, p2 + i * sz))
if (!ti.next.equals(p1 + i * sz, p2 + i * sz))
return 0; // not equal
}
return 1; // equal

View File

@@ -1,13 +1,21 @@
module internal.contract;
import std.string: toString;
extern(C):
void exit(int);
void _d_assert(bool cond, uint line, char[] msg)
/*void _d_assert(bool cond, uint line, char[] msg)
{
if (!cond) {
printf("Aborted(%u): %.*s\n", line, msg.length, msg.ptr);
exit(1);
}
}*/
void _d_assert(string file, uint line) {
throw new Exception(file~":"~.toString(line)~": Assertion failed!");
}
void _d_assert_msg(string msg, string file, uint line) {
throw new Exception(file~": "~.toString(line)~": Assertion failed: \""~msg~"\"");
}

View File

@@ -0,0 +1,49 @@
module internal.critical;
extern(C):
import std.c.linux.linux, std.c.stdlib:ccalloc=calloc, cmalloc=malloc, cfree=free;
struct CritSec {
pthread_mutex_t* p;
}
const PTHREAD_MUTEX_RECURSIVE = 1, PTHREAD_MUTEX_ERRORCHECK=2;
extern(C) int pthread_self();
void _d_criticalenter(CritSec* cs) {
if (!cs.p) {
auto newp = cast(pthread_mutex_t*) cmalloc(pthread_mutex_t.sizeof);
auto cspp = &cs.p;
pthread_mutexattr_t mt; pthread_mutexattr_init(&mt);
pthread_mutexattr_settype(&mt, PTHREAD_MUTEX_RECURSIVE);
printf("Create -> %i\n", pthread_mutex_init(newp, &mt));
asm { xor EAX, EAX; mov ECX, newp; mov EDX, cspp; lock; cmpxchg int ptr [EDX], ECX; }
if (cs.p != newp) pthread_mutex_destroy(newp);
}
auto count = (cast(uint*) cs.p)[1];
// printf("%i ::%u\n", pthread_self(), count);
//printf("%i: Lock %p -> %i\n", pthread_self(), cs.p,
pthread_mutex_lock(cs.p);//);
}
void _d_criticalexit(CritSec* cs) {
//printf("%i: Unlock %p -> %i\n", pthread_self(), cs.p,
pthread_mutex_unlock(cs.p);//);
}
void _d_monitorenter(Object h)
{
_d_criticalenter(cast(CritSec*) &h.__monitor);
}
void _d_monitorexit(Object h)
{
_d_criticalexit(cast(CritSec*) &h.__monitor);
}
void _STI_monitor_staticctor() { }
void _STI_critical_init() { }
void _STI_critical_term() { }
void _STD_monitor_staticdtor() { }
void _STD_critical_term() { }

122
lphobos/internal/dmain2.d Normal file
View File

@@ -0,0 +1,122 @@
/*
* Placed into the Public Domain.
* written by Walter Bright
* www.digitalmars.com
*/
module internal.dmain2;
import object;
import std.c.stdio;
import std.c.string;
import std.c.stdlib;
import std.string;
extern (C) void _STI_monitor_staticctor();
extern (C) void _STD_monitor_staticdtor();
extern (C) void _STI_critical_init();
extern (C) void _STD_critical_term();
extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleDtor();
extern (C) void _moduleUnitTests();
extern (C) bool no_catch_exceptions;
/***********************************
* The D main() function supplied by the user's program
*/
int main(char[][] args);
/***********************************
* Substitutes for the C main() function.
* It's purpose is to wrap the call to the D main()
* function and catch any unhandled exceptions.
*/
extern (C) int main(size_t argc, char **argv)
{
char[] *am;
char[][] args;
int result;
int myesp;
int myebx;
version (linux)
{
_STI_monitor_staticctor();
_STI_critical_init();
gc_init();
am = cast(char[] *) malloc(argc * (char[]).sizeof);
// BUG: alloca() conflicts with try-catch-finally stack unwinding
//am = (char[] *) alloca(argc * (char[]).sizeof);
}
version (Win32)
{
gc_init();
_minit();
am = cast(char[] *) alloca(argc * (char[]).sizeof);
}
if (no_catch_exceptions)
{
_moduleCtor();
_moduleUnitTests();
for (size_t i = 0; i < argc; i++)
{
auto len = strlen(argv[i]);
am[i] = argv[i][0 .. len];
}
args = am[0 .. argc];
result = main(args);
_moduleDtor();
gc_term();
}
else
{
try
{
_moduleCtor();
_moduleUnitTests();
for (size_t i = 0; i < argc; i++)
{
auto len = strlen(argv[i]);
am[i] = argv[i][0 .. len];
}
args = am[0 .. argc];
result = main(args);
_moduleDtor();
gc_term();
}
catch (Object o)
{
version (none)
{
printf("Error: ");
o.print();
}
else
{
auto foo = o.toString();
fprintf(stderr, "Error: %.*s\n", foo.length, foo.ptr);
}
exit(EXIT_FAILURE);
}
}
version (linux)
{
free(am);
_STD_critical_term();
_STD_monitor_staticdtor();
}
return result;
}

374
lphobos/internal/eh.d Normal file
View File

@@ -0,0 +1,374 @@
/**
* This module contains functions and structures required for
* exception handling.
*/
module eh;
// debug = EH_personality;
// debug = EH_personality_verbose;
// current EH implementation works on x86 linux only
version(X86) version(linux) version=X86_LINUX;
private extern(C) void abort();
private extern(C) int printf(char*, ...);
// D runtime functions
extern(C) {
int _d_isbaseof(ClassInfo oc, ClassInfo c);
}
// libunwind headers
extern(C)
{
enum _Unwind_Reason_Code
{
NO_REASON = 0,
FOREIGN_EXCEPTION_CAUGHT = 1,
FATAL_PHASE2_ERROR = 2,
FATAL_PHASE1_ERROR = 3,
NORMAL_STOP = 4,
END_OF_STACK = 5,
HANDLER_FOUND = 6,
INSTALL_CONTEXT = 7,
CONTINUE_UNWIND = 8
}
enum _Unwind_Action
{
SEARCH_PHASE = 1,
CLEANUP_PHASE = 2,
HANDLER_PHASE = 3,
FORCE_UNWIND = 4
}
alias void* _Unwind_Context_Ptr;
alias void function(_Unwind_Reason_Code, _Unwind_Exception*) _Unwind_Exception_Cleanup_Fn;
struct _Unwind_Exception
{
char[8] exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
int private_1;
int private_2;
}
version(X86_LINUX)
{
void _Unwind_Resume(_Unwind_Exception*);
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*);
ulong _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context);
ulong _Unwind_GetIP(_Unwind_Context_Ptr context);
ulong _Unwind_SetIP(_Unwind_Context_Ptr context, ulong new_value);
ulong _Unwind_SetGR(_Unwind_Context_Ptr context, int index, ulong new_value);
ulong _Unwind_GetRegionStart(_Unwind_Context_Ptr context);
}
else
{
// runtime calls these directly
void _Unwind_Resume(_Unwind_Exception*)
{
printf("_Unwind_Resume is not implemented on this platform.\n");
}
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*)
{
printf("_Unwind_RaiseException is not implemented on this platform.\n");
return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
}
}
}
// helpers for reading certain DWARF data
//TODO: It may not be a good idea to use exceptions for error handling within exception handling code
private ubyte* get_uleb128(ubyte* addr, ref size_t res)
{
res = 0;
size_t bitsize = 0;
// read as long as high bit is set
while(*addr & 0x80) {
res |= (*addr & 0x7f) << bitsize;
bitsize += 7;
addr += 1;
if(bitsize >= size_t.sizeof*8)
throw new Exception("tried to read uleb128 that exceeded size of size_t");
}
// read last
if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
throw new Exception("tried to read uleb128 that exceeded size of size_t");
res |= (*addr) << bitsize;
return addr + 1;
}
private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res)
{
res = 0;
size_t bitsize = 0;
// read as long as high bit is set
while(*addr & 0x80) {
res |= (*addr & 0x7f) << bitsize;
bitsize += 7;
addr += 1;
if(bitsize >= size_t.sizeof*8)
throw new Exception("tried to read sleb128 that exceeded size of size_t");
}
// read last
if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
throw new Exception("tried to read sleb128 that exceeded size of size_t");
res |= (*addr) << bitsize;
// take care of sign
if(bitsize < size_t.sizeof*8 && ((*addr) & 0x40))
res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1);
return addr + 1;
}
// exception struct used by the runtime.
// _d_throw allocates a new instance and passes the address of its
// _Unwind_Exception member to the unwind call. The personality
// routine is then able to get the whole struct by looking at the data
// surrounding the unwind info.
struct _d_exception
{
Object exception_object;
_Unwind_Exception unwind_info;
}
// the 8-byte string identifying the type of exception
// the first 4 are for vendor, the second 4 for language
//TODO: This may be the wrong way around
char[8] _d_exception_class = "LLDCD1\0\0";
//
// x86 Linux specific implementation of personality function
// and helpers
//
version(X86_LINUX)
{
// the personality routine gets called by the unwind handler and is responsible for
// reading the EH tables and deciding what to do
extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context)
{
printf("eh_personality is running\n");
// check ver: the C++ Itanium ABI only allows ver == 1
if(ver != 1) {
printf("Fatal Phase1 #1\n");
return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
}
// check exceptionClass
//TODO: Treat foreign exceptions with more respect
if((cast(char*)&exception_class)[0..8] != _d_exception_class) {
printf("Fatal Phase1 #2: %s != %s\n", cast(char*)&exception_class, cast(char*) _d_exception_class);
return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
}
// find call site table, action table and classinfo table
// Note: callsite and action tables do not contain static-length
// data and will be parsed as needed
// Note: classinfo_table points past the end of the table
ubyte* callsite_table;
ubyte* action_table;
ClassInfo* classinfo_table;
_d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table);
/*
find landing pad and action table index belonging to ip by walking
the callsite_table
*/
ubyte* callsite_walker = callsite_table;
// get the instruction pointer
// will be used to find the right entry in the callsite_table
// -1 because it will point past the last instruction
ulong ip = _Unwind_GetIP(context) - 1;
// address block_start is relative to
ulong region_start = _Unwind_GetRegionStart(context);
// table entries
uint block_start_offset, block_size;
ulong landing_pad;
size_t action_offset;
while(true) {
// if we've gone through the list and found nothing...
if(callsite_walker >= action_table) {
printf("Continue unwind #3\n");
return _Unwind_Reason_Code.CONTINUE_UNWIND;
}
block_start_offset = *cast(uint*)callsite_walker;
block_size = *(cast(uint*)callsite_walker + 1);
landing_pad = *(cast(uint*)callsite_walker + 2);
if(landing_pad)
landing_pad += region_start;
callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset);
/*debug(EH_personality_verbose) */printf("%d %d %d\n", block_start_offset, block_size, landing_pad);
// since the list is sorted, as soon as we're past the ip
// there's no handler to be found
if(ip < region_start + block_start_offset) {
printf("Continue unwind #4\n");
return _Unwind_Reason_Code.CONTINUE_UNWIND;
}
// if we've found our block, exit
if(ip < region_start + block_start_offset + block_size)
break;
}
/*debug(EH_personality) */printf("Found correct landing pad and actionOffset %d\n", action_offset);
// now we need the exception's classinfo to find a handler
// the exception_info is actually a member of a larger _d_exception struct
// the runtime allocated. get that now
_d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof);
// if there's no action offset and no landing pad, continue unwinding
if(!action_offset && !landing_pad) {
printf("Continue unwind #5\n");
return _Unwind_Reason_Code.CONTINUE_UNWIND;
}
// if there's no action offset but a landing pad, this is a cleanup handler
else if(!action_offset && landing_pad) {
printf("Install cleanup handler #6\n");
return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
}
/*
walk action table chain, comparing classinfos using _d_isbaseof
*/
ubyte* action_walker = action_table + action_offset - 1;
ptrdiff_t ti_offset, next_action_offset;
while(true) {
action_walker = get_sleb128(action_walker, ti_offset);
// it is intentional that we not modify action_walker here
// next_action_offset is from current action_walker position
get_sleb128(action_walker, next_action_offset);
// negative are 'filters' which we don't use
assert(ti_offset >= 0 && "Filter actions are unsupported");
// zero means cleanup, which we require to be the last action
if(ti_offset == 0) {
assert(next_action_offset == 0 && "Cleanup action must be last in chain");
printf("Cleanup handler #7\n");
return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
}
// get classinfo for action and check if the one in the
// exception structure is a base
ClassInfo catch_ci = classinfo_table[-ti_offset];
/*debug(EH_personality) */printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr);
if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci)) {
printf("Install catch context #8\n");
return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context);
}
// we've walked through all actions and found nothing...
if(next_action_offset == 0) {
printf("Continue unwind #9\n");
return _Unwind_Reason_Code.CONTINUE_UNWIND;
} else
action_walker += next_action_offset;
}
printf("Assertion failure ;_;\n");
assert(false);
}
// These are the register numbers for SetGR that
// llvm's eh.exception and eh.selector intrinsics
// will pick up.
// Found by trial-and-error and probably platform dependent!
private int eh_exception_regno = 0;
private int eh_selector_regno = 2;
private _Unwind_Reason_Code _d_eh_install_catch_context(_Unwind_Action actions, ptrdiff_t switchval, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
{
debug(EH_personality) printf("Found catch clause!\n");
if(actions & _Unwind_Action.SEARCH_PHASE)
return _Unwind_Reason_Code.HANDLER_FOUND;
else if(actions & _Unwind_Action.HANDLER_PHASE)
{
debug(EH_personality) printf("Setting switch value to: %d!\n", switchval);
_Unwind_SetGR(context, eh_exception_regno, cast(ulong)cast(void*)(exception_struct.exception_object));
_Unwind_SetGR(context, eh_selector_regno, switchval);
_Unwind_SetIP(context, landing_pad);
return _Unwind_Reason_Code.INSTALL_CONTEXT;
}
assert(false);
}
private _Unwind_Reason_Code _d_eh_install_finally_context(_Unwind_Action actions, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
{
// if we're merely in search phase, continue
if(actions & _Unwind_Action.SEARCH_PHASE)
return _Unwind_Reason_Code.CONTINUE_UNWIND;
debug(EH_personality) printf("Calling cleanup routine...\n");
_Unwind_SetGR(context, eh_exception_regno, cast(ulong)exception_struct);
_Unwind_SetGR(context, eh_selector_regno, 0);
_Unwind_SetIP(context, landing_pad);
return _Unwind_Reason_Code.INSTALL_CONTEXT;
}
private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci)
{
ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
//TODO: Do proper DWARF reading here
assert(*data++ == 0xff);
assert(*data++ == 0x00);
size_t cioffset;
data = get_uleb128(data, cioffset);
ci = cast(ClassInfo*)(data + cioffset);
assert(*data++ == 0x03);
size_t callsitelength;
data = get_uleb128(data, callsitelength);
action = data + callsitelength;
callsite = data;
}
} // end of x86 Linux specific implementation
extern(C) void _d_throw_exception(Object e)
{
if (e !is null)
{
_d_exception* exc_struct = new _d_exception;
exc_struct.unwind_info.exception_class[] = _d_exception_class;
exc_struct.exception_object = e;
printf("Raising exception\n");
_Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info);
printf("_Unwind_RaiseException failed with reason code: %i\n", ret);
}
abort();
}
extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct)
{
_Unwind_Resume(&exception_struct.unwind_info);
}

View File

@@ -1132,16 +1132,27 @@ class ModuleInfo
void function() ctor;
void function() dtor;
void function() unitTest;
void* xgetMembers;
void function() ictor;
/******************
* Return collection of all modules in the program.
*/
static ModuleInfo[] modules()
{
return std.moduleinit._moduleinfo_array;
static int opApply(int delegate(ref ModuleInfo) dg) {
foreach (ref mod; std.moduleinit._moduleinfo_array)
if (auto i = dg(mod)) return i;
return 0;
}
}
struct ModuleReference
{
ModuleReference* next;
ModuleInfo mod;
}
extern(C) ModuleReference* _Dmodule_ref;
/**
* All recoverable exceptions should be derived from class Exception.
*/
@@ -1189,4 +1200,3 @@ class Error : Exception
}
//extern (C) int nullext = 0;

View File

@@ -14,7 +14,7 @@
import std.c.stdlib;
pragma(LLVM_internal, "notypeinfo")
pragma(no_typeinfo)
struct Array
{
size_t length;

View File

@@ -422,5 +422,7 @@ unittest
}
}
void _d_switch_error(string fn, int line)
{
throw new Exception(fn~toString(line)~": switch missing default");
}

View File

@@ -2,110 +2,110 @@ module llvm.intrinsic;
// code generator intrinsics
/*
pragma(LLVM_internal, "intrinsic", "llvm.returnaddress")
pragma(intrinsic, "llvm.returnaddress")
void* llvm_returnaddress(uint level);
*/
pragma(LLVM_internal, "intrinsic", "llvm.frameaddress")
pragma(intrinsic, "llvm.frameaddress")
void* llvm_frameaddress(uint level);
/*
pragma(LLVM_internal, "intrinsic", "llvm.stacksave")
pragma(intrinsic, "llvm.stacksave")
void* llvm_stacksave();
pragma(LLVM_internal, "intrinsic", "llvm.stackrestore")
pragma(intrinsic, "llvm.stackrestore")
void llvm_stackrestore(void* ptr);
pragma(LLVM_internal, "intrinsic", "llvm.pcmarker")
pragma(intrinsic, "llvm.pcmarker")
void llvm_pcmarker(uint id);
pragma(LLVM_internal, "intrinsic", "llvm.prefetch")
pragma(intrinsic, "llvm.prefetch")
void llvm_prefetch(void* ptr, uint rw, uint locality);
*/
pragma(LLVM_internal, "intrinsic", "llvm.readcyclecounter")
pragma(intrinsic, "llvm.readcyclecounter")
ulong readcyclecounter();
// standard C intrinsics
pragma(LLVM_internal, "intrinsic", "llvm.memcpy.i32")
pragma(intrinsic, "llvm.memcpy.i32")
void llvm_memcpy_i32(void* dst, void* src, uint len, uint alignment);
pragma(LLVM_internal, "intrinsic", "llvm.memcpy.i64")
pragma(intrinsic, "llvm.memcpy.i64")
void llvm_memcpy_i64(void* dst, void* src, ulong len, uint alignment);
pragma(LLVM_internal, "intrinsic", "llvm.memmove.i32")
pragma(intrinsic, "llvm.memmove.i32")
void llvm_memmove_i32(void* dst, void* src, uint len, uint alignment);
pragma(LLVM_internal, "intrinsic", "llvm.memmove.i64")
pragma(intrinsic, "llvm.memmove.i64")
void llvm_memmove_i64(void* dst, void* src, ulong len, int alignment);
pragma(LLVM_internal, "intrinsic", "llvm.memset.i32")
pragma(intrinsic, "llvm.memset.i32")
void llvm_memset_i32(void* dst, ubyte val, uint len, uint alignment);
pragma(LLVM_internal, "intrinsic", "llvm.memset.i64")
pragma(intrinsic, "llvm.memset.i64")
void llvm_memset_i64(void* dst, ubyte val, ulong len, uint alignment);
pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f32")
pragma(intrinsic, "llvm.sqrt.f32")
float llvm_sqrt(float val);
pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f64")
pragma(intrinsic, "llvm.sqrt.f64")
{
double llvm_sqrt(double val);
real llvm_sqrt(real val);
// real llvm_sqrt(real val);
}
pragma(LLVM_internal, "intrinsic", "llvm.powi.f32")
pragma(intrinsic, "llvm.powi.f32")
float llvm_powi(float val, int power);
pragma(LLVM_internal, "intrinsic", "llvm.powi.f64")
pragma(intrinsic, "llvm.powi.f64")
{
double llvm_powi(double val, int power);
real llvm_powi(real val, int power);
// real llvm_powi(real val, int power);
}
// bit manipulation intrinsics
pragma(LLVM_internal, "intrinsic", "llvm.bswap.i16.i16")
pragma(intrinsic, "llvm.bswap.i16.i16")
ushort llvm_bswap(ushort val);
pragma(LLVM_internal, "intrinsic", "llvm.bswap.i32.i32")
pragma(intrinsic, "llvm.bswap.i32.i32")
uint llvm_bswap(uint val);
pragma(LLVM_internal, "intrinsic", "llvm.bswap.i64.i64")
pragma(intrinsic, "llvm.bswap.i64.i64")
ulong llvm_bswap(ulong val);
/*
pragma(LLVM_internal, "intrinsic", "llvm.ctpop.i8")
pragma(intrinsic, "llvm.ctpop.i8")
uint llvm_ctpop_i8(ubyte src);
pragma(LLVM_internal, "intrinsic", "llvm.ctpop.i16")
pragma(intrinsic, "llvm.ctpop.i16")
uint llvm_ctpop_i16(ushort src);
pragma(LLVM_internal, "intrinsic", "llvm.ctpop.i32")
pragma(intrinsic, "llvm.ctpop.i32")
uint llvm_ctpop_i32(uint src);
pragma(LLVM_internal, "intrinsic", "llvm.ctpop.i64")
pragma(intrinsic, "llvm.ctpop.i64")
uint llvm_ctpop_i64(ulong src);
pragma(LLVM_internal, "intrinsic", "llvm.ctlz.i8")
pragma(intrinsic, "llvm.ctlz.i8")
uint llvm_ctlz_i8(ubyte src);
pragma(LLVM_internal, "intrinsic", "llvm.ctlz.i16")
pragma(intrinsic, "llvm.ctlz.i16")
uint llvm_ctlz_i16(ushort src);
pragma(LLVM_internal, "intrinsic", "llvm.ctlz.i32")
pragma(intrinsic, "llvm.ctlz.i32")
uint llvm_ctlz_i32(uint src);
pragma(LLVM_internal, "intrinsic", "llvm.ctlz.i64")
pragma(intrinsic, "llvm.ctlz.i64")
uint llvm_ctlz_i64(ulong src);
pragma(LLVM_internal, "intrinsic", "llvm.cttz.i8")
pragma(intrinsic, "llvm.cttz.i8")
uint llvm_cttz_i8(ubyte src);
pragma(LLVM_internal, "intrinsic", "llvm.cttz.i16")
pragma(intrinsic, "llvm.cttz.i16")
uint llvm_cttz_i16(ushort src);
pragma(LLVM_internal, "intrinsic", "llvm.cttz.i32")
pragma(intrinsic, "llvm.cttz.i32")
uint llvm_cttz_i32(uint src);
pragma(LLVM_internal, "intrinsic", "llvm.cttz.i64")
pragma(intrinsic, "llvm.cttz.i64")
uint llvm_cttz_i64(ulong src);
*/
@@ -114,7 +114,7 @@ pragma(LLVM_internal, "intrinsic", "llvm.cttz.i64")
/*
//declare i8 @llvm.atomic.lcs.i8.i8p.i8.i8( i8* <ptr>, i8 <cmp>, i8 <val> )
pragma(LLVM_internal, "intrinsic", "llvm.atomic.lcs.i8.i8p.i8.i8")
pragma(intrinsic, "llvm.atomic.lcs.i8.i8p.i8.i8")
ubyte llvm_atomic_lcs_i8(void* ptr, ubyte cmp, ubyte val);
declare i16 @llvm.atomic.lcs.i16.i16p.i16.i16( i16* <ptr>, i16 <cmp>, i16 <val> )

View File

@@ -1,4 +1,3 @@
// Implementation is in internal\object.d
module object;
@@ -173,11 +172,19 @@ class ModuleInfo
void function() ctor;
void function() dtor;
void function() unitTest;
void* xgetMembers;
void function() ictor;
// Return collection of all modules in the program.
static ModuleInfo[] modules();
static int opApply(int delegate(ref ModuleInfo));
}
struct ModuleReference {
ModuleReference* next;
ModuleInfo mod;
}
extern(C) extern ModuleReference* _Dmodule_ref;
// Recoverable errors
class Exception : Object
@@ -198,4 +205,3 @@ class Error : Exception
this(string msg);
this(string msg, Error next);
}

View File

@@ -27,7 +27,12 @@ std.c.stddef,
std.c.stdio,
std.c.stdlib,
std.c.string,
std.c.time;
std.c.time,
std.file,
std.date,
std.socket,
std.zlib,
std.cstream;
version(linux) {
import

955
lphobos/std/bitarray.d Normal file
View File

@@ -0,0 +1,955 @@
/***********************
* Macros:
* WIKI = StdBitarray
*/
module std.bitarray;
//debug = bitarray; // uncomment to turn on debugging printf's
private import std.intrinsic;
/**
* An array of bits.
*/
struct BitArray
{
size_t len;
uint* ptr;
size_t dim()
{
return (len + 31) / 32;
}
size_t length()
{
return len;
}
void length(size_t newlen)
{
if (newlen != len)
{
size_t olddim = dim();
size_t newdim = (newlen + 31) / 32;
if (newdim != olddim)
{
// Create a fake array so we can use D's realloc machinery
uint[] b = ptr[0 .. olddim];
b.length = newdim; // realloc
ptr = b.ptr;
if (newdim & 31)
{ // Set any pad bits to 0
ptr[newdim - 1] &= ~(~0 << (newdim & 31));
}
}
len = newlen;
}
}
/**********************************************
* Support for [$(I index)] operation for BitArray.
*/
bool opIndex(size_t i)
in
{
assert(i < len);
}
body
{
return cast(bool)bt(ptr, i);
}
/** ditto */
bool opIndexAssign(bool b, size_t i)
in
{
assert(i < len);
}
body
{
if (b)
bts(ptr, i);
else
btr(ptr, i);
return b;
}
/**********************************************
* Support for array.dup property for BitArray.
*/
BitArray dup()
{
BitArray ba;
uint[] b = ptr[0 .. dim].dup;
ba.len = len;
ba.ptr = b.ptr;
return ba;
}
unittest
{
BitArray a;
BitArray b;
int i;
debug(bitarray) printf("BitArray.dup.unittest\n");
a.length = 3;
a[0] = 1; a[1] = 0; a[2] = 1;
b = a.dup;
assert(b.length == 3);
for (i = 0; i < 3; i++)
{ debug(bitarray) printf("b[%d] = %d\n", i, b[i]);
assert(b[i] == (((i ^ 1) & 1) ? true : false));
}
}
/**********************************************
* Support for foreach loops for BitArray.
*/
int opApply(int delegate(inout bool) dg)
{
int result;
for (size_t i = 0; i < len; i++)
{ bool b = opIndex(i);
result = dg(b);
(*this)[i] = b;
if (result)
break;
}
return result;
}
/** ditto */
int opApply(int delegate(inout size_t, inout bool) dg)
{
int result;
for (size_t i = 0; i < len; i++)
{ bool b = opIndex(i);
result = dg(i, b);
(*this)[i] = b;
if (result)
break;
}
return result;
}
unittest
{
debug(bitarray) printf("BitArray.opApply unittest\n");
static bool[] ba = [1,0,1];
BitArray a; a.init(ba);
int i;
foreach (b;a)
{
switch (i)
{ case 0: assert(b == true); break;
case 1: assert(b == false); break;
case 2: assert(b == true); break;
default: assert(0);
}
i++;
}
foreach (j,b;a)
{
switch (j)
{ case 0: assert(b == true); break;
case 1: assert(b == false); break;
case 2: assert(b == true); break;
default: assert(0);
}
}
}
/**********************************************
* Support for array.reverse property for BitArray.
*/
BitArray reverse()
out (result)
{
assert(result == *this);
}
body
{
if (len >= 2)
{
bool t;
size_t lo, hi;
lo = 0;
hi = len - 1;
for (; lo < hi; lo++, hi--)
{
t = (*this)[lo];
(*this)[lo] = (*this)[hi];
(*this)[hi] = t;
}
}
return *this;
}
unittest
{
debug(bitarray) printf("BitArray.reverse.unittest\n");
BitArray b;
static bool[5] data = [1,0,1,1,0];
int i;
b.init(data);
b.reverse;
for (i = 0; i < data.length; i++)
{
assert(b[i] == data[4 - i]);
}
}
/**********************************************
* Support for array.sort property for BitArray.
*/
BitArray sort()
out (result)
{
assert(result == *this);
}
body
{
if (len >= 2)
{
size_t lo, hi;
lo = 0;
hi = len - 1;
while (1)
{
while (1)
{
if (lo >= hi)
goto Ldone;
if ((*this)[lo] == true)
break;
lo++;
}
while (1)
{
if (lo >= hi)
goto Ldone;
if ((*this)[hi] == false)
break;
hi--;
}
(*this)[lo] = false;
(*this)[hi] = true;
lo++;
hi--;
}
Ldone:
;
}
return *this;
}
unittest
{
debug(bitarray) printf("BitArray.sort.unittest\n");
static uint x = 0b1100011000;
static BitArray ba = { 10, &x };
ba.sort;
for (size_t i = 0; i < 6; i++)
assert(ba[i] == false);
for (size_t i = 6; i < 10; i++)
assert(ba[i] == true);
}
/***************************************
* Support for operators == and != for bit arrays.
*/
int opEquals(BitArray a2)
{ size_t i;
if (this.length != a2.length)
return 0; // not equal
uint *p1 = cast(uint*)this.ptr;
uint *p2 = cast(uint*)a2.ptr;
size_t n = this.length / (8 * uint.sizeof);
for (i = 0; i < n; i++)
{
if (p1[i] != p2[i])
return 0; // not equal
}
uint mask;
n = this.length & ((8 * uint.sizeof) - 1);
mask = (1 << n) - 1;
//printf("i = %d, n = %d, mask = %x, %x, %x\n", i, n, mask, p1[i], p2[i]);
return (mask == 0) || (p1[i] & mask) == (p2[i] & mask);
}
unittest
{
debug(bitarray) printf("BitArray.opEquals unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1];
static bool[] bc = [1,0,1,0,1,0,1];
static bool[] bd = [1,0,1,1,1];
static bool[] be = [1,0,1,0,1];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
BitArray c; c.init(bc);
BitArray d; d.init(bd);
BitArray e; e.init(be);
assert(a != b);
assert(a != c);
assert(a != d);
assert(a == e);
}
/***************************************
* Implement comparison operators.
*/
int opCmp(BitArray a2)
{
size_t len;
size_t i;
len = this.length;
if (a2.length < len)
len = a2.length;
uint* p1 = cast(uint*)this.ptr;
uint* p2 = cast(uint*)a2.ptr;
size_t n = len / (8 * uint.sizeof);
for (i = 0; i < n; i++)
{
if (p1[i] != p2[i])
break; // not equal
}
/*
for (uint j = i * 8; j < len; j++)
{ ubyte mask = cast(ubyte)(1 << j);
int c;
c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
if (c)
return c;
}
*/
uint mask = 1;
for (size_t j = i * (8 * uint.sizeof); j < len; j++)
{ int c;
c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask);
if (c)
return c;
mask <<= 1;
}
ptrdiff_t c = cast(ptrdiff_t)this.len - cast(ptrdiff_t)a2.length;
if (c < 0)
return -1;
else if (c > 0)
return 1;
return 0;
}
unittest
{
debug(bitarray) printf("BitArray.opCmp unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1];
static bool[] bc = [1,0,1,0,1,0,1];
static bool[] bd = [1,0,1,1,1];
static bool[] be = [1,0,1,0,1];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
BitArray c; c.init(bc);
BitArray d; d.init(bd);
BitArray e; e.init(be);
assert(a > b);
assert(a >= b);
assert(a < c);
assert(a <= c);
assert(a < d);
assert(a <= d);
assert(a == e);
assert(a <= e);
assert(a >= e);
}
/***************************************
* Set BitArray to contents of ba[]
*/
void init(bool[] ba)
{
length = ba.length;
foreach (i, b; ba)
{
(*this)[i] = b;
}
}
/***************************************
* Map BitArray onto v[], with numbits being the number of bits
* in the array. Does not copy the data.
*
* This is the inverse of opCast.
*/
void init(void[] v, size_t numbits)
in
{
assert(numbits <= v.length * 8);
assert((v.length & 3) == 0);
}
body
{
ptr = cast(uint*)v.ptr;
len = numbits;
}
unittest
{
debug(bitarray) printf("BitArray.init unittest\n");
static bool[] ba = [1,0,1,0,1];
BitArray a; a.init(ba);
BitArray b;
void[] v;
v = cast(void[])a;
b.init(v, a.length);
assert(b[0] == 1);
assert(b[1] == 0);
assert(b[2] == 1);
assert(b[3] == 0);
assert(b[4] == 1);
a[0] = 0;
assert(b[0] == 0);
assert(a == b);
}
/***************************************
* Convert to void[].
*/
void[] opCast()
{
return cast(void[])ptr[0 .. dim];
}
unittest
{
debug(bitarray) printf("BitArray.opCast unittest\n");
static bool[] ba = [1,0,1,0,1];
BitArray a; a.init(ba);
void[] v = cast(void[])a;
assert(v.length == a.dim * uint.sizeof);
}
/***************************************
* Support for unary operator ~ for bit arrays.
*/
BitArray opCom()
{
auto dim = this.dim();
BitArray result;
result.length = len;
for (size_t i = 0; i < dim; i++)
result.ptr[i] = ~this.ptr[i];
if (len & 31)
result.ptr[dim - 1] &= ~(~0 << (len & 31));
return result;
}
unittest
{
debug(bitarray) printf("BitArray.opCom unittest\n");
static bool[] ba = [1,0,1,0,1];
BitArray a; a.init(ba);
BitArray b = ~a;
assert(b[0] == 0);
assert(b[1] == 1);
assert(b[2] == 0);
assert(b[3] == 1);
assert(b[4] == 0);
}
/***************************************
* Support for binary operator & for bit arrays.
*/
BitArray opAnd(BitArray e2)
in
{
assert(len == e2.length);
}
body
{
auto dim = this.dim();
BitArray result;
result.length = len;
for (size_t i = 0; i < dim; i++)
result.ptr[i] = this.ptr[i] & e2.ptr[i];
return result;
}
unittest
{
debug(bitarray) printf("BitArray.opAnd unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
BitArray c = a & b;
assert(c[0] == 1);
assert(c[1] == 0);
assert(c[2] == 1);
assert(c[3] == 0);
assert(c[4] == 0);
}
/***************************************
* Support for binary operator | for bit arrays.
*/
BitArray opOr(BitArray e2)
in
{
assert(len == e2.length);
}
body
{
auto dim = this.dim();
BitArray result;
result.length = len;
for (size_t i = 0; i < dim; i++)
result.ptr[i] = this.ptr[i] | e2.ptr[i];
return result;
}
unittest
{
debug(bitarray) printf("BitArray.opOr unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
BitArray c = a | b;
assert(c[0] == 1);
assert(c[1] == 0);
assert(c[2] == 1);
assert(c[3] == 1);
assert(c[4] == 1);
}
/***************************************
* Support for binary operator ^ for bit arrays.
*/
BitArray opXor(BitArray e2)
in
{
assert(len == e2.length);
}
body
{
auto dim = this.dim();
BitArray result;
result.length = len;
for (size_t i = 0; i < dim; i++)
result.ptr[i] = this.ptr[i] ^ e2.ptr[i];
return result;
}
unittest
{
debug(bitarray) printf("BitArray.opXor unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
BitArray c = a ^ b;
assert(c[0] == 0);
assert(c[1] == 0);
assert(c[2] == 0);
assert(c[3] == 1);
assert(c[4] == 1);
}
/***************************************
* Support for binary operator - for bit arrays.
*
* $(I a - b) for BitArrays means the same thing as $(I a &amp; ~b).
*/
BitArray opSub(BitArray e2)
in
{
assert(len == e2.length);
}
body
{
auto dim = this.dim();
BitArray result;
result.length = len;
for (size_t i = 0; i < dim; i++)
result.ptr[i] = this.ptr[i] & ~e2.ptr[i];
return result;
}
unittest
{
debug(bitarray) printf("BitArray.opSub unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
BitArray c = a - b;
assert(c[0] == 0);
assert(c[1] == 0);
assert(c[2] == 0);
assert(c[3] == 0);
assert(c[4] == 1);
}
/***************************************
* Support for operator &= bit arrays.
*/
BitArray opAndAssign(BitArray e2)
in
{
assert(len == e2.length);
}
body
{
auto dim = this.dim();
for (size_t i = 0; i < dim; i++)
ptr[i] &= e2.ptr[i];
return *this;
}
unittest
{
debug(bitarray) printf("BitArray.opAndAssign unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
a &= b;
assert(a[0] == 1);
assert(a[1] == 0);
assert(a[2] == 1);
assert(a[3] == 0);
assert(a[4] == 0);
}
/***************************************
* Support for operator |= for bit arrays.
*/
BitArray opOrAssign(BitArray e2)
in
{
assert(len == e2.length);
}
body
{
auto dim = this.dim();
for (size_t i = 0; i < dim; i++)
ptr[i] |= e2.ptr[i];
return *this;
}
unittest
{
debug(bitarray) printf("BitArray.opOrAssign unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
a |= b;
assert(a[0] == 1);
assert(a[1] == 0);
assert(a[2] == 1);
assert(a[3] == 1);
assert(a[4] == 1);
}
/***************************************
* Support for operator ^= for bit arrays.
*/
BitArray opXorAssign(BitArray e2)
in
{
assert(len == e2.length);
}
body
{
auto dim = this.dim();
for (size_t i = 0; i < dim; i++)
ptr[i] ^= e2.ptr[i];
return *this;
}
unittest
{
debug(bitarray) printf("BitArray.opXorAssign unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
a ^= b;
assert(a[0] == 0);
assert(a[1] == 0);
assert(a[2] == 0);
assert(a[3] == 1);
assert(a[4] == 1);
}
/***************************************
* Support for operator -= for bit arrays.
*
* $(I a -= b) for BitArrays means the same thing as $(I a &amp;= ~b).
*/
BitArray opSubAssign(BitArray e2)
in
{
assert(len == e2.length);
}
body
{
auto dim = this.dim();
for (size_t i = 0; i < dim; i++)
ptr[i] &= ~e2.ptr[i];
return *this;
}
unittest
{
debug(bitarray) printf("BitArray.opSubAssign unittest\n");
static bool[] ba = [1,0,1,0,1];
static bool[] bb = [1,0,1,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
a -= b;
assert(a[0] == 0);
assert(a[1] == 0);
assert(a[2] == 0);
assert(a[3] == 0);
assert(a[4] == 1);
}
/***************************************
* Support for operator ~= for bit arrays.
*/
BitArray opCatAssign(bool b)
{
length = len + 1;
(*this)[len - 1] = b;
return *this;
}
unittest
{
debug(bitarray) printf("BitArray.opCatAssign unittest\n");
static bool[] ba = [1,0,1,0,1];
BitArray a; a.init(ba);
BitArray b;
b = (a ~= true);
assert(a[0] == 1);
assert(a[1] == 0);
assert(a[2] == 1);
assert(a[3] == 0);
assert(a[4] == 1);
assert(a[5] == 1);
assert(b == a);
}
/***************************************
* ditto
*/
BitArray opCatAssign(BitArray b)
{
auto istart = len;
length = len + b.length;
for (auto i = istart; i < len; i++)
(*this)[i] = b[i - istart];
return *this;
}
unittest
{
debug(bitarray) printf("BitArray.opCatAssign unittest\n");
static bool[] ba = [1,0];
static bool[] bb = [0,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
BitArray c;
c = (a ~= b);
assert(a.length == 5);
assert(a[0] == 1);
assert(a[1] == 0);
assert(a[2] == 0);
assert(a[3] == 1);
assert(a[4] == 0);
assert(c == a);
}
/***************************************
* Support for binary operator ~ for bit arrays.
*/
BitArray opCat(bool b)
{
BitArray r;
r = this.dup;
r.length = len + 1;
r[len] = b;
return r;
}
/** ditto */
BitArray opCat_r(bool b)
{
BitArray r;
r.length = len + 1;
r[0] = b;
for (size_t i = 0; i < len; i++)
r[1 + i] = (*this)[i];
return r;
}
/** ditto */
BitArray opCat(BitArray b)
{
BitArray r;
r = this.dup();
r ~= b;
return r;
}
unittest
{
debug(bitarray) printf("BitArray.opCat unittest\n");
static bool[] ba = [1,0];
static bool[] bb = [0,1,0];
BitArray a; a.init(ba);
BitArray b; b.init(bb);
BitArray c;
c = (a ~ b);
assert(c.length == 5);
assert(c[0] == 1);
assert(c[1] == 0);
assert(c[2] == 0);
assert(c[3] == 1);
assert(c[4] == 0);
c = (a ~ true);
assert(c.length == 3);
assert(c[0] == 1);
assert(c[1] == 0);
assert(c[2] == 1);
c = (false ~ a);
assert(c.length == 3);
assert(c[0] == 0);
assert(c[1] == 1);
assert(c[2] == 0);
}
}

View File

@@ -13,14 +13,14 @@ module std.c.stdarg;
public import llvm.va_list;
pragma(LLVM_internal, "va_start")
pragma(va_start)
void va_start(T)(va_list ap, ref T);
pragma(LLVM_internal, "va_arg")
pragma(va_arg)
T va_arg(T)(va_list ap);
pragma(LLVM_internal, "va_intrinsic", "llvm.va_end")
pragma(va_end)
void va_end(va_list args);
pragma(LLVM_internal, "va_intrinsic", "llvm.va_copy")
pragma(va_copy)
void va_copy(va_list dst, va_list src);

View File

@@ -42,7 +42,7 @@ struct lldiv_t { long quot,rem; }
int system(char *);
pragma(LLVM_internal, "alloca")
pragma(alloca)
void *alloca(uint); ///
void *calloc(size_t, size_t); ///
@@ -64,8 +64,11 @@ struct lldiv_t { long quot,rem; }
int random(int num); /// ditto
void randomize(); /// ditto
int getErrno(); /// ditto
int setErrno(int); /// ditto
int* __errno_location();
int getErrno() { return *__errno_location(); }
int setErrno(int i) { return *__errno_location = i; }
//int getErrno(); /// ditto
//int setErrno(int); /// ditto
const int ERANGE = 34; // on both Windows and linux

246
lphobos/std/c/windows/com.d Normal file
View File

@@ -0,0 +1,246 @@
module std.c.windows.com;
private import std.c.windows.windows;
private import std.string;
alias WCHAR OLECHAR;
alias OLECHAR *LPOLESTR;
alias OLECHAR *LPCOLESTR;
enum
{
rmm = 23, // OLE 2 version number info
rup = 639,
}
enum : int
{
S_OK = 0,
S_FALSE = 0x00000001,
NOERROR = 0,
E_NOTIMPL = cast(int)0x80004001,
E_NOINTERFACE = cast(int)0x80004002,
E_POINTER = cast(int)0x80004003,
E_ABORT = cast(int)0x80004004,
E_FAIL = cast(int)0x80004005,
E_HANDLE = cast(int)0x80070006,
CLASS_E_NOAGGREGATION = cast(int)0x80040110,
E_OUTOFMEMORY = cast(int)0x8007000E,
E_INVALIDARG = cast(int)0x80070057,
E_UNEXPECTED = cast(int)0x8000FFFF,
}
struct GUID { // size is 16
align(1):
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
}
enum
{
CLSCTX_INPROC_SERVER = 0x1,
CLSCTX_INPROC_HANDLER = 0x2,
CLSCTX_LOCAL_SERVER = 0x4,
CLSCTX_INPROC_SERVER16 = 0x8,
CLSCTX_REMOTE_SERVER = 0x10,
CLSCTX_INPROC_HANDLER16 = 0x20,
CLSCTX_INPROC_SERVERX86 = 0x40,
CLSCTX_INPROC_HANDLERX86 = 0x80,
CLSCTX_INPROC = (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER),
CLSCTX_ALL = (CLSCTX_INPROC_SERVER| CLSCTX_INPROC_HANDLER| CLSCTX_LOCAL_SERVER),
CLSCTX_SERVER = (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER),
}
alias GUID IID;
alias GUID CLSID;
extern (C)
{
extern IID IID_IUnknown;
extern IID IID_IClassFactory;
extern IID IID_IMarshal;
extern IID IID_IMallocSpy;
extern IID IID_IStdMarshalInfo;
extern IID IID_IExternalConnection;
extern IID IID_IMultiQI;
extern IID IID_IEnumUnknown;
extern IID IID_IBindCtx;
extern IID IID_IEnumMoniker;
extern IID IID_IRunnableObject;
extern IID IID_IRunningObjectTable;
extern IID IID_IPersist;
extern IID IID_IPersistStream;
extern IID IID_IMoniker;
extern IID IID_IROTData;
extern IID IID_IEnumString;
extern IID IID_ISequentialStream;
extern IID IID_IStream;
extern IID IID_IEnumSTATSTG;
extern IID IID_IStorage;
extern IID IID_IPersistFile;
extern IID IID_IPersistStorage;
extern IID IID_ILockBytes;
extern IID IID_IEnumFORMATETC;
extern IID IID_IEnumSTATDATA;
extern IID IID_IRootStorage;
extern IID IID_IAdviseSink;
extern IID IID_IAdviseSink2;
extern IID IID_IDataObject;
extern IID IID_IDataAdviseHolder;
extern IID IID_IMessageFilter;
extern IID IID_IRpcChannelBuffer;
extern IID IID_IRpcProxyBuffer;
extern IID IID_IRpcStubBuffer;
extern IID IID_IPSFactoryBuffer;
extern IID IID_IPropertyStorage;
extern IID IID_IPropertySetStorage;
extern IID IID_IEnumSTATPROPSTG;
extern IID IID_IEnumSTATPROPSETSTG;
extern IID IID_IFillLockBytes;
extern IID IID_IProgressNotify;
extern IID IID_ILayoutStorage;
extern IID GUID_NULL;
extern IID IID_IRpcChannel;
extern IID IID_IRpcStub;
extern IID IID_IStubManager;
extern IID IID_IRpcProxy;
extern IID IID_IProxyManager;
extern IID IID_IPSFactory;
extern IID IID_IInternalMoniker;
extern IID IID_IDfReserved1;
extern IID IID_IDfReserved2;
extern IID IID_IDfReserved3;
extern IID IID_IStub;
extern IID IID_IProxy;
extern IID IID_IEnumGeneric;
extern IID IID_IEnumHolder;
extern IID IID_IEnumCallback;
extern IID IID_IOleManager;
extern IID IID_IOlePresObj;
extern IID IID_IDebug;
extern IID IID_IDebugStream;
extern IID IID_StdOle;
extern IID IID_ICreateTypeInfo;
extern IID IID_ICreateTypeInfo2;
extern IID IID_ICreateTypeLib;
extern IID IID_ICreateTypeLib2;
extern IID IID_IDispatch;
extern IID IID_IEnumVARIANT;
extern IID IID_ITypeComp;
extern IID IID_ITypeInfo;
extern IID IID_ITypeInfo2;
extern IID IID_ITypeLib;
extern IID IID_ITypeLib2;
extern IID IID_ITypeChangeEvents;
extern IID IID_IErrorInfo;
extern IID IID_ICreateErrorInfo;
extern IID IID_ISupportErrorInfo;
extern IID IID_IOleAdviseHolder;
extern IID IID_IOleCache;
extern IID IID_IOleCache2;
extern IID IID_IOleCacheControl;
extern IID IID_IParseDisplayName;
extern IID IID_IOleContainer;
extern IID IID_IOleClientSite;
extern IID IID_IOleObject;
extern IID IID_IOleWindow;
extern IID IID_IOleLink;
extern IID IID_IOleItemContainer;
extern IID IID_IOleInPlaceUIWindow;
extern IID IID_IOleInPlaceActiveObject;
extern IID IID_IOleInPlaceFrame;
extern IID IID_IOleInPlaceObject;
extern IID IID_IOleInPlaceSite;
extern IID IID_IContinue;
extern IID IID_IViewObject;
extern IID IID_IViewObject2;
extern IID IID_IDropSource;
extern IID IID_IDropTarget;
extern IID IID_IEnumOLEVERB;
}
extern (Windows)
{
export
{
DWORD CoBuildVersion();
int StringFromGUID2(GUID *rguid, LPOLESTR lpsz, int cbMax);
/* init/uninit */
HRESULT CoInitialize(LPVOID pvReserved);
void CoUninitialize();
DWORD CoGetCurrentProcess();
HRESULT CoCreateInstance(CLSID *rclsid, IUnknown UnkOuter,
DWORD dwClsContext, IID* riid, void* ppv);
//HINSTANCE CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree);
void CoFreeLibrary(HINSTANCE hInst);
void CoFreeAllLibraries();
void CoFreeUnusedLibraries();
}
interface IUnknown
{
HRESULT QueryInterface(IID* riid, void** pvObject);
ULONG AddRef();
ULONG Release();
}
interface IClassFactory : IUnknown
{
HRESULT CreateInstance(IUnknown UnkOuter, IID* riid, void** pvObject);
HRESULT LockServer(BOOL fLock);
}
class ComObject : IUnknown
{
extern (Windows):
HRESULT QueryInterface(IID* riid, void** ppv)
{
if (*riid == IID_IUnknown)
{
*ppv = cast(void*)cast(IUnknown)this;
AddRef();
return S_OK;
}
else
{ *ppv = null;
return E_NOINTERFACE;
}
}
ULONG AddRef()
{
return InterlockedIncrement(&count);
}
ULONG Release()
{
LONG lRef = InterlockedDecrement(&count);
if (lRef == 0)
{
// free object
// If we delete this object, then the postinvariant called upon
// return from Release() will fail.
// Just let the GC reap it.
//delete this;
return 0;
}
return cast(ULONG)lRef;
}
LONG count = 0; // object reference count
}
}

View File

@@ -0,0 +1,49 @@
/// Placed into public domain
/// Author: Walter Bright
module std.c.windows.stat;
extern (C):
// linux version is in std.c.linux.linux
version (Windows)
{
const S_IFMT = 0xF000;
const S_IFDIR = 0x4000;
const S_IFCHR = 0x2000;
const S_IFIFO = 0x1000;
const S_IFREG = 0x8000;
const S_IREAD = 0x0100;
const S_IWRITE = 0x0080;
const S_IEXEC = 0x0040;
const S_IFBLK = 0x6000;
const S_IFNAM = 0x5000;
int S_ISREG(int m) { return (m & S_IFMT) == S_IFREG; }
int S_ISBLK(int m) { return (m & S_IFMT) == S_IFBLK; }
int S_ISNAM(int m) { return (m & S_IFMT) == S_IFNAM; }
int S_ISDIR(int m) { return (m & S_IFMT) == S_IFDIR; }
int S_ISCHR(int m) { return (m & S_IFMT) == S_IFCHR; }
struct struct_stat
{
short st_dev;
ushort st_ino;
ushort st_mode;
short st_nlink;
ushort st_uid;
ushort st_gid;
short st_rdev;
short dummy;
int st_size;
int st_atime;
int st_mtime;
int st_ctime;
}
int stat(char *, struct_stat *);
int fstat(int, struct_stat *);
int _wstat(wchar *, struct_stat *);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,540 @@
/*
Written by Christopher E. Miller
Placed into public domain.
*/
module std.c.windows.winsock;
private import std.stdint;
private import std.c.windows.windows;
extern(Windows):
alias UINT SOCKET;
alias int socklen_t;
const SOCKET INVALID_SOCKET = cast(SOCKET)~0;
const int SOCKET_ERROR = -1;
const int WSADESCRIPTION_LEN = 256;
const int WSASYS_STATUS_LEN = 128;
struct WSADATA
{
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN + 1];
char szSystemStatus[WSASYS_STATUS_LEN + 1];
USHORT iMaxSockets;
USHORT iMaxUdpDg;
char* lpVendorInfo;
}
alias WSADATA* LPWSADATA;
const int IOCPARM_MASK = 0x7F;
const int IOC_IN = cast(int)0x80000000;
const int FIONBIO = cast(int)(IOC_IN | ((UINT.sizeof & IOCPARM_MASK) << 16) | (102 << 8) | 126);
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
int WSACleanup();
SOCKET socket(int af, int type, int protocol);
int ioctlsocket(SOCKET s, int cmd, uint* argp);
int bind(SOCKET s, sockaddr* name, int namelen);
int connect(SOCKET s, sockaddr* name, int namelen);
int listen(SOCKET s, int backlog);
SOCKET accept(SOCKET s, sockaddr* addr, int* addrlen);
int closesocket(SOCKET s);
int shutdown(SOCKET s, int how);
int getpeername(SOCKET s, sockaddr* name, int* namelen);
int getsockname(SOCKET s, sockaddr* name, int* namelen);
int send(SOCKET s, void* buf, int len, int flags);
int sendto(SOCKET s, void* buf, int len, int flags, sockaddr* to, int tolen);
int recv(SOCKET s, void* buf, int len, int flags);
int recvfrom(SOCKET s, void* buf, int len, int flags, sockaddr* from, int* fromlen);
int getsockopt(SOCKET s, int level, int optname, void* optval, int* optlen);
int setsockopt(SOCKET s, int level, int optname, void* optval, int optlen);
uint inet_addr(char* cp);
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout);
char* inet_ntoa(in_addr ina);
hostent* gethostbyname(char* name);
hostent* gethostbyaddr(void* addr, int len, int type);
protoent* getprotobyname(char* name);
protoent* getprotobynumber(int number);
servent* getservbyname(char* name, char* proto);
servent* getservbyport(int port, char* proto);
int gethostname(char* name, int namelen);
int getaddrinfo(char* nodename, char* servname, addrinfo* hints, addrinfo** res);
void freeaddrinfo(addrinfo* ai);
int getnameinfo(sockaddr* sa, socklen_t salen, char* host, DWORD hostlen, char* serv, DWORD servlen, int flags);
enum: int
{
WSAEWOULDBLOCK = 10035,
WSAEINTR = 10004,
WSAHOST_NOT_FOUND = 11001,
}
int WSAGetLastError();
enum: int
{
AF_UNSPEC = 0,
AF_UNIX = 1,
AF_INET = 2,
AF_IMPLINK = 3,
AF_PUP = 4,
AF_CHAOS = 5,
AF_NS = 6,
AF_IPX = AF_NS,
AF_ISO = 7,
AF_OSI = AF_ISO,
AF_ECMA = 8,
AF_DATAKIT = 9,
AF_CCITT = 10,
AF_SNA = 11,
AF_DECnet = 12,
AF_DLI = 13,
AF_LAT = 14,
AF_HYLINK = 15,
AF_APPLETALK = 16,
AF_NETBIOS = 17,
AF_VOICEVIEW = 18,
AF_FIREFOX = 19,
AF_UNKNOWN1 = 20,
AF_BAN = 21,
AF_ATM = 22,
AF_INET6 = 23,
AF_CLUSTER = 24,
AF_12844 = 25,
AF_IRDA = 26,
AF_NETDES = 28,
AF_MAX = 29,
PF_UNSPEC = AF_UNSPEC,
PF_UNIX = AF_UNIX,
PF_INET = AF_INET,
PF_IMPLINK = AF_IMPLINK,
PF_PUP = AF_PUP,
PF_CHAOS = AF_CHAOS,
PF_NS = AF_NS,
PF_IPX = AF_IPX,
PF_ISO = AF_ISO,
PF_OSI = AF_OSI,
PF_ECMA = AF_ECMA,
PF_DATAKIT = AF_DATAKIT,
PF_CCITT = AF_CCITT,
PF_SNA = AF_SNA,
PF_DECnet = AF_DECnet,
PF_DLI = AF_DLI,
PF_LAT = AF_LAT,
PF_HYLINK = AF_HYLINK,
PF_APPLETALK = AF_APPLETALK,
PF_VOICEVIEW = AF_VOICEVIEW,
PF_FIREFOX = AF_FIREFOX,
PF_UNKNOWN1 = AF_UNKNOWN1,
PF_BAN = AF_BAN,
PF_INET6 = AF_INET6,
PF_MAX = AF_MAX,
}
enum: int
{
SOL_SOCKET = 0xFFFF,
}
enum: int
{
SO_DEBUG = 0x0001,
SO_ACCEPTCONN = 0x0002,
SO_REUSEADDR = 0x0004,
SO_KEEPALIVE = 0x0008,
SO_DONTROUTE = 0x0010,
SO_BROADCAST = 0x0020,
SO_USELOOPBACK = 0x0040,
SO_LINGER = 0x0080,
SO_DONTLINGER = ~SO_LINGER,
SO_OOBINLINE = 0x0100,
SO_SNDBUF = 0x1001,
SO_RCVBUF = 0x1002,
SO_SNDLOWAT = 0x1003,
SO_RCVLOWAT = 0x1004,
SO_SNDTIMEO = 0x1005,
SO_RCVTIMEO = 0x1006,
SO_ERROR = 0x1007,
SO_TYPE = 0x1008,
SO_EXCLUSIVEADDRUSE = ~SO_REUSEADDR,
TCP_NODELAY = 1,
IP_MULTICAST_LOOP = 0x4,
IP_ADD_MEMBERSHIP = 0x5,
IP_DROP_MEMBERSHIP = 0x6,
IPV6_UNICAST_HOPS = 4,
IPV6_MULTICAST_IF = 9,
IPV6_MULTICAST_HOPS = 10,
IPV6_MULTICAST_LOOP = 11,
IPV6_ADD_MEMBERSHIP = 12,
IPV6_DROP_MEMBERSHIP = 13,
IPV6_JOIN_GROUP = IPV6_ADD_MEMBERSHIP,
IPV6_LEAVE_GROUP = IPV6_DROP_MEMBERSHIP,
}
const uint FD_SETSIZE = 64;
struct fd_set
{
UINT fd_count;
SOCKET[FD_SETSIZE] fd_array;
}
// Removes.
void FD_CLR(SOCKET fd, fd_set* set)
{
uint c = set.fd_count;
SOCKET* start = set.fd_array.ptr;
SOCKET* stop = start + c;
for(; start != stop; start++)
{
if(*start == fd)
goto found;
}
return; //not found
found:
for(++start; start != stop; start++)
{
*(start - 1) = *start;
}
set.fd_count = c - 1;
}
// Tests.
int FD_ISSET(SOCKET fd, fd_set* set)
{
SOCKET* start = set.fd_array.ptr;
SOCKET* stop = start + set.fd_count;
for(; start != stop; start++)
{
if(*start == fd)
return true;
}
return false;
}
// Adds.
void FD_SET(SOCKET fd, fd_set* set)
{
uint c = set.fd_count;
set.fd_array.ptr[c] = fd;
set.fd_count = c + 1;
}
// Resets to zero.
void FD_ZERO(fd_set* set)
{
set.fd_count = 0;
}
struct linger
{
USHORT l_onoff;
USHORT l_linger;
}
struct protoent
{
char* p_name;
char** p_aliases;
SHORT p_proto;
}
struct servent
{
char* s_name;
char** s_aliases;
SHORT s_port;
char* s_proto;
}
/+
union in6_addr
{
private union _u_t
{
BYTE[16] Byte;
WORD[8] Word;
}
_u_t u;
}
struct in_addr6
{
BYTE[16] s6_addr;
}
+/
version(BigEndian)
{
uint16_t htons(uint16_t x)
{
return x;
}
uint32_t htonl(uint32_t x)
{
return x;
}
}
else version(LittleEndian)
{
private import std.intrinsic;
uint16_t htons(uint16_t x)
{
return cast(uint16_t)((x >> 8) | (x << 8));
}
uint32_t htonl(uint32_t x)
{
return bswap(x);
}
}
else
{
static assert(0);
}
uint16_t ntohs(uint16_t x)
{
return htons(x);
}
uint32_t ntohl(uint32_t x)
{
return htonl(x);
}
enum: int
{
SOCK_STREAM = 1,
SOCK_DGRAM = 2,
SOCK_RAW = 3,
SOCK_RDM = 4,
SOCK_SEQPACKET = 5,
}
enum: int
{
IPPROTO_IP = 0,
IPPROTO_ICMP = 1,
IPPROTO_IGMP = 2,
IPPROTO_GGP = 3,
IPPROTO_TCP = 6,
IPPROTO_PUP = 12,
IPPROTO_UDP = 17,
IPPROTO_IDP = 22,
IPPROTO_IPV6 = 41,
IPPROTO_ND = 77,
IPPROTO_RAW = 255,
IPPROTO_MAX = 256,
}
enum: int
{
MSG_OOB = 0x1,
MSG_PEEK = 0x2,
MSG_DONTROUTE = 0x4,
MSG_NOSIGNAL = 0x0, /// not supported on win32, would be 0x4000 if it was
}
enum: int
{
SD_RECEIVE = 0,
SD_SEND = 1,
SD_BOTH = 2,
}
enum: uint
{
INADDR_ANY = 0,
INADDR_LOOPBACK = 0x7F000001,
INADDR_BROADCAST = 0xFFFFFFFF,
INADDR_NONE = 0xFFFFFFFF,
ADDR_ANY = INADDR_ANY,
}
enum: int
{
AI_PASSIVE = 0x1,
AI_CANONNAME = 0x2,
AI_NUMERICHOST = 0x4,
}
struct timeval
{
int32_t tv_sec;
int32_t tv_usec;
}
union in_addr
{
private union _S_un_t
{
private struct _S_un_b_t
{
uint8_t s_b1, s_b2, s_b3, s_b4;
}
_S_un_b_t S_un_b;
private struct _S_un_w_t
{
uint16_t s_w1, s_w2;
}
_S_un_w_t S_un_w;
uint32_t S_addr;
}
_S_un_t S_un;
uint32_t s_addr;
struct
{
uint8_t s_net, s_host;
union
{
uint16_t s_imp;
struct
{
uint8_t s_lh, s_impno;
}
}
}
}
union in6_addr
{
private union _in6_u_t
{
uint8_t[16] u6_addr8;
uint16_t[8] u6_addr16;
uint32_t[4] u6_addr32;
}
_in6_u_t in6_u;
uint8_t[16] s6_addr8;
uint16_t[8] s6_addr16;
uint32_t[4] s6_addr32;
alias s6_addr8 s6_addr;
}
const in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
const in6_addr IN6ADDR_LOOPBACK = { s6_addr8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] };
//alias IN6ADDR_ANY IN6ADDR_ANY_INIT;
//alias IN6ADDR_LOOPBACK IN6ADDR_LOOPBACK_INIT;
const uint INET_ADDRSTRLEN = 16;
const uint INET6_ADDRSTRLEN = 46;
struct sockaddr
{
int16_t sa_family;
ubyte[14] sa_data;
}
struct sockaddr_in
{
int16_t sin_family = AF_INET;
uint16_t sin_port;
in_addr sin_addr;
ubyte[8] sin_zero;
}
struct sockaddr_in6
{
int16_t sin6_family = AF_INET6;
uint16_t sin6_port;
uint32_t sin6_flowinfo;
in6_addr sin6_addr;
uint32_t sin6_scope_id;
}
struct addrinfo
{
int32_t ai_flags;
int32_t ai_family;
int32_t ai_socktype;
int32_t ai_protocol;
size_t ai_addrlen;
char* ai_canonname;
sockaddr* ai_addr;
addrinfo* ai_next;
}
struct hostent
{
char* h_name;
char** h_aliases;
int16_t h_addrtype;
int16_t h_length;
char** h_addr_list;
char* h_addr()
{
return h_addr_list[0];
}
}

228
lphobos/std/cstream.d Normal file
View File

@@ -0,0 +1,228 @@
/**
* The std.cstream module bridges std.c.stdio (or std.stdio) and std.stream.
* Both std.c.stdio and std.stream are publicly imported by std.cstream.
* Authors: Ben Hinkle
* License: Public Domain
* Macros:
* WIKI=Phobos/StdCstream
*/
module std.cstream;
import std.stream;
import std.c.stdio;
/**
* A Stream wrapper for a C file of type FILE*.
*/
class CFile : Stream {
FILE* cfile;
/**
* Create the stream wrapper for the given C file.
* Params:
* mode = a bitwise combination of $(B FileMode.In) for a readable file
* and $(B FileMode.Out) for a writeable file.
* seekable = indicates if the stream should be _seekable.
*/
this(FILE* cfile, FileMode mode, bool seekable = false) {
super();
this.file = cfile;
readable = cast(bool)(mode & FileMode.In);
writeable = cast(bool)(mode & FileMode.Out);
this.seekable = seekable;
}
/**
* Closes the stream.
*/
~this() { close(); }
/**
* Property to get or set the underlying file for this stream.
* Setting the file marks the stream as open.
*/
FILE* file() { return cfile; }
/**
* Ditto
*/
void file(FILE* cfile) {
this.cfile = cfile;
isopen = true;
}
/**
* Overrides of the $(B Stream) methods to call the underlying $(B FILE*)
* C functions.
*/
override void flush() { fflush(cfile); }
/**
* Ditto
*/
override void close() {
if (isopen)
fclose(cfile);
isopen = readable = writeable = seekable = false;
}
/**
* Ditto
*/
override bool eof() {
return cast(bool)(readEOF || feof(cfile));
}
/**
* Ditto
*/
override char getc() {
return cast(char)fgetc(cfile);
}
/**
* Ditto
*/
override char ungetc(char c) {
return cast(char)std.c.stdio.ungetc(c,cfile);
}
/**
* Ditto
*/
override size_t readBlock(void* buffer, size_t size) {
size_t n = fread(buffer,1,size,cfile);
readEOF = cast(bool)(n == 0);
return n;
}
/**
* Ditto
*/
override size_t writeBlock(void* buffer, size_t size) {
return fwrite(buffer,1,size,cfile);
}
/**
* Ditto
*/
override ulong seek(long offset, SeekPos rel) {
readEOF = false;
if (fseek(cfile,cast(int)offset,rel) != 0)
throw new SeekException("unable to move file pointer");
return ftell(cfile);
}
/**
* Ditto
*/
override void writeLine(char[] s) {
writeString(s);
writeString("\n");
}
/**
* Ditto
*/
override void writeLineW(wchar[] s) {
writeStringW(s);
writeStringW("\n");
}
// run a few tests
unittest {
FILE* f = fopen("stream.txt","w");
assert(f !is null);
CFile file = new CFile(f,FileMode.Out);
int i = 666;
// should be ok to write
assert(file.writeable);
file.writeLine("Testing stream.d:");
file.writeString("Hello, world!");
file.write(i);
// string#1 + string#2 + int should give exacly that
version (Win32)
assert(file.position() == 19 + 13 + 4);
version (linux)
assert(file.position() == 18 + 13 + 4);
file.close();
// no operations are allowed when file is closed
assert(!file.readable && !file.writeable && !file.seekable);
f = fopen("stream.txt","r");
file = new CFile(f,FileMode.In,true);
// should be ok to read
assert(file.readable);
char[] line = file.readLine();
char[] exp = "Testing stream.d:";
assert(line[0] == 'T');
assert(line.length == exp.length);
assert(!std.string.cmp(line, "Testing stream.d:"));
// jump over "Hello, "
file.seek(7, SeekPos.Current);
version (Win32)
assert(file.position() == 19 + 7);
version (linux)
assert(file.position() == 18 + 7);
assert(!std.string.cmp(file.readString(6), "world!"));
i = 0; file.read(i);
assert(i == 666);
// string#1 + string#2 + int should give exacly that
version (Win32)
assert(file.position() == 19 + 13 + 4);
version (linux)
assert(file.position() == 18 + 13 + 4);
// we must be at the end of file
file.close();
f = fopen("stream.txt","w+");
file = new CFile(f,FileMode.In|FileMode.Out,true);
file.writeLine("Testing stream.d:");
file.writeLine("Another line");
file.writeLine("");
file.writeLine("That was blank");
file.position = 0;
char[][] lines;
foreach(char[] line; file) {
lines ~= line.dup;
}
assert( lines.length == 5 );
assert( lines[0] == "Testing stream.d:");
assert( lines[1] == "Another line");
assert( lines[2] == "");
assert( lines[3] == "That was blank");
file.position = 0;
lines = new char[][5];
foreach(ulong n, char[] line; file) {
lines[cast(size_t)(n-1)] = line.dup;
}
assert( lines[0] == "Testing stream.d:");
assert( lines[1] == "Another line");
assert( lines[2] == "");
assert( lines[3] == "That was blank");
file.close();
remove("stream.txt");
}
}
/**
* CFile wrapper of std.c.stdio.stdin (not seekable).
*/
CFile din;
/**
* CFile wrapper of std.c.stdio.stdout (not seekable).
*/
CFile dout;
/**
* CFile wrapper of std.c.stdio.stderr (not seekable).
*/
CFile derr;
static this() {
// open standard I/O devices
din = new CFile(std.c.stdio.stdin,FileMode.In);
dout = new CFile(std.c.stdio.stdout,FileMode.Out);
derr = new CFile(std.c.stdio.stderr,FileMode.Out);
}

1074
lphobos/std/date.d Normal file

File diff suppressed because it is too large Load Diff

1074
lphobos/std/date.d~ Normal file

File diff suppressed because it is too large Load Diff

788
lphobos/std/dateparse.d Normal file
View File

@@ -0,0 +1,788 @@
/*
* Copyright (C) 1999-2004 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module std.dateparse;
private
{
import std.string;
import std.c.stdlib;
import std.date;
}
//debug=dateparse;
class DateParseError : Error
{
this(char[] s)
{
super("Invalid date string: " ~ s);
}
}
struct DateParse
{
void parse(char[] s, out Date date)
{
*this = DateParse.init;
//version (Win32)
buffer = (cast(char *)alloca(s.length))[0 .. s.length];
//else
//buffer = new char[s.length];
debug(dateparse) printf("DateParse.parse('%.*s')\n",
cast(int) s.length, s.ptr);
if (!parseString(s))
{
goto Lerror;
}
/+
if (year == year.init)
year = 0;
else
+/
debug(dateparse)
printf("year = %d, month = %d, day = %d\n%02d:%02d:%02d.%03d\nweekday = %d, tzcorrection = %d\n",
year, month, day,
hours, minutes, seconds, ms,
weekday, tzcorrection);
if (
year == year.init ||
(month < 1 || month > 12) ||
(day < 1 || day > 31) ||
(hours < 0 || hours > 23) ||
(minutes < 0 || minutes > 59) ||
(seconds < 0 || seconds > 59) ||
(tzcorrection != int.min &&
((tzcorrection < -2300 || tzcorrection > 2300) ||
(tzcorrection % 10)))
)
{
Lerror:
throw new DateParseError(s);
}
if (ampm)
{ if (hours > 12)
goto Lerror;
if (hours < 12)
{
if (ampm == 2) // if P.M.
hours += 12;
}
else if (ampm == 1) // if 12am
{
hours = 0; // which is midnight
}
}
// if (tzcorrection != tzcorrection.init)
// tzcorrection /= 100;
if (year >= 0 && year <= 99)
year += 1900;
date.year = year;
date.month = month;
date.day = day;
date.hour = hours;
date.minute = minutes;
date.second = seconds;
date.ms = ms;
date.weekday = weekday;
date.tzcorrection = tzcorrection;
}
private:
int year = int.min; // our "nan" Date value
int month; // 1..12
int day; // 1..31
int hours; // 0..23
int minutes; // 0..59
int seconds; // 0..59
int ms; // 0..999
int weekday; // 1..7
int ampm; // 0: not specified
// 1: AM
// 2: PM
int tzcorrection = int.min; // -1200..1200 correction in hours
char[] s;
int si;
int number;
char[] buffer;
enum DP : byte
{
err,
weekday,
month,
number,
end,
colon,
minus,
slash,
ampm,
plus,
tz,
dst,
dsttz,
}
DP nextToken()
{ int nest;
uint c;
int bi;
DP result = DP.err;
//printf("DateParse::nextToken()\n");
for (;;)
{
assert(si <= s.length);
if (si == s.length)
{ result = DP.end;
goto Lret;
}
//printf("\ts[%d] = '%c'\n", si, s[si]);
switch (s[si])
{
case ':': result = DP.colon; goto ret_inc;
case '+': result = DP.plus; goto ret_inc;
case '-': result = DP.minus; goto ret_inc;
case '/': result = DP.slash; goto ret_inc;
case '.':
version(DATE_DOT_DELIM)
{
result = DP.slash;
goto ret_inc;
}
else
{
si++;
break;
}
ret_inc:
si++;
goto Lret;
case ' ':
case '\n':
case '\r':
case '\t':
case ',':
si++;
break;
case '(': // comment
nest = 1;
for (;;)
{
si++;
if (si == s.length)
goto Lret; // error
switch (s[si])
{
case '(':
nest++;
break;
case ')':
if (--nest == 0)
goto Lendofcomment;
break;
default:
break;
}
}
Lendofcomment:
si++;
break;
default:
number = 0;
for (;;)
{
if (si == s.length)
// c cannot be undefined here
break;
c = s[si];
if (!(c >= '0' && c <= '9'))
break;
result = DP.number;
number = number * 10 + (c - '0');
si++;
}
if (result == DP.number)
goto Lret;
bi = 0;
bufloop:
while (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
{
if (c < 'a') // if upper case
c += cast(uint)'a' - cast(uint)'A'; // to lower case
buffer[bi] = cast(char)c;
bi++;
do
{
si++;
if (si == s.length)
break bufloop;
c = s[si];
} while (c == '.'); // ignore embedded '.'s
}
result = classify(buffer[0 .. bi]);
goto Lret;
}
}
Lret:
//printf("-DateParse::nextToken()\n");
return result;
}
DP classify(char[] buf)
{
struct DateID
{
char[] name;
DP tok;
short value;
}
static DateID dateidtab[] =
[
{ "january", DP.month, 1},
{ "february", DP.month, 2},
{ "march", DP.month, 3},
{ "april", DP.month, 4},
{ "may", DP.month, 5},
{ "june", DP.month, 6},
{ "july", DP.month, 7},
{ "august", DP.month, 8},
{ "september", DP.month, 9},
{ "october", DP.month, 10},
{ "november", DP.month, 11},
{ "december", DP.month, 12},
{ "jan", DP.month, 1},
{ "feb", DP.month, 2},
{ "mar", DP.month, 3},
{ "apr", DP.month, 4},
{ "jun", DP.month, 6},
{ "jul", DP.month, 7},
{ "aug", DP.month, 8},
{ "sep", DP.month, 9},
{ "sept", DP.month, 9},
{ "oct", DP.month, 10},
{ "nov", DP.month, 11},
{ "dec", DP.month, 12},
{ "sunday", DP.weekday, 1},
{ "monday", DP.weekday, 2},
{ "tuesday", DP.weekday, 3},
{ "tues", DP.weekday, 3},
{ "wednesday", DP.weekday, 4},
{ "wednes", DP.weekday, 4},
{ "thursday", DP.weekday, 5},
{ "thur", DP.weekday, 5},
{ "thurs", DP.weekday, 5},
{ "friday", DP.weekday, 6},
{ "saturday", DP.weekday, 7},
{ "sun", DP.weekday, 1},
{ "mon", DP.weekday, 2},
{ "tue", DP.weekday, 3},
{ "wed", DP.weekday, 4},
{ "thu", DP.weekday, 5},
{ "fri", DP.weekday, 6},
{ "sat", DP.weekday, 7},
{ "am", DP.ampm, 1},
{ "pm", DP.ampm, 2},
{ "gmt", DP.tz, +000},
{ "ut", DP.tz, +000},
{ "utc", DP.tz, +000},
{ "wet", DP.tz, +000},
{ "z", DP.tz, +000},
{ "wat", DP.tz, +100},
{ "a", DP.tz, +100},
{ "at", DP.tz, +200},
{ "b", DP.tz, +200},
{ "c", DP.tz, +300},
{ "ast", DP.tz, +400},
{ "d", DP.tz, +400},
{ "est", DP.tz, +500},
{ "e", DP.tz, +500},
{ "cst", DP.tz, +600},
{ "f", DP.tz, +600},
{ "mst", DP.tz, +700},
{ "g", DP.tz, +700},
{ "pst", DP.tz, +800},
{ "h", DP.tz, +800},
{ "yst", DP.tz, +900},
{ "i", DP.tz, +900},
{ "ahst", DP.tz, +1000},
{ "cat", DP.tz, +1000},
{ "hst", DP.tz, +1000},
{ "k", DP.tz, +1000},
{ "nt", DP.tz, +1100},
{ "l", DP.tz, +1100},
{ "idlw", DP.tz, +1200},
{ "m", DP.tz, +1200},
{ "cet", DP.tz, -100},
{ "fwt", DP.tz, -100},
{ "met", DP.tz, -100},
{ "mewt", DP.tz, -100},
{ "swt", DP.tz, -100},
{ "n", DP.tz, -100},
{ "eet", DP.tz, -200},
{ "o", DP.tz, -200},
{ "bt", DP.tz, -300},
{ "p", DP.tz, -300},
{ "zp4", DP.tz, -400},
{ "q", DP.tz, -400},
{ "zp5", DP.tz, -500},
{ "r", DP.tz, -500},
{ "zp6", DP.tz, -600},
{ "s", DP.tz, -600},
{ "wast", DP.tz, -700},
{ "t", DP.tz, -700},
{ "cct", DP.tz, -800},
{ "u", DP.tz, -800},
{ "jst", DP.tz, -900},
{ "v", DP.tz, -900},
{ "east", DP.tz, -1000},
{ "gst", DP.tz, -1000},
{ "w", DP.tz, -1000},
{ "x", DP.tz, -1100},
{ "idle", DP.tz, -1200},
{ "nzst", DP.tz, -1200},
{ "nzt", DP.tz, -1200},
{ "y", DP.tz, -1200},
{ "bst", DP.dsttz, 000},
{ "adt", DP.dsttz, +400},
{ "edt", DP.dsttz, +500},
{ "cdt", DP.dsttz, +600},
{ "mdt", DP.dsttz, +700},
{ "pdt", DP.dsttz, +800},
{ "ydt", DP.dsttz, +900},
{ "hdt", DP.dsttz, +1000},
{ "mest", DP.dsttz, -100},
{ "mesz", DP.dsttz, -100},
{ "sst", DP.dsttz, -100},
{ "fst", DP.dsttz, -100},
{ "wadt", DP.dsttz, -700},
{ "eadt", DP.dsttz, -1000},
{ "nzdt", DP.dsttz, -1200},
{ "dst", DP.dst, 0},
];
//message(DTEXT("DateParse::classify('%s')\n"), buf);
// Do a linear search. Yes, it would be faster with a binary
// one.
for (uint i = 0; i < dateidtab.length; i++)
{
if (std.string.cmp(dateidtab[i].name, buf) == 0)
{
number = dateidtab[i].value;
return dateidtab[i].tok;
}
}
return DP.err;
}
int parseString(char[] s)
{
int n1;
int dp;
int sisave;
int result;
//message(DTEXT("DateParse::parseString('%ls')\n"), s);
this.s = s;
si = 0;
dp = nextToken();
for (;;)
{
//message(DTEXT("\tdp = %d\n"), dp);
switch (dp)
{
case DP.end:
result = 1;
Lret:
return result;
case DP.err:
case_error:
//message(DTEXT("\terror\n"));
default:
result = 0;
goto Lret;
case DP.minus:
break; // ignore spurious '-'
case DP.weekday:
weekday = number;
break;
case DP.month: // month day, [year]
month = number;
dp = nextToken();
if (dp == DP.number)
{
day = number;
sisave = si;
dp = nextToken();
if (dp == DP.number)
{
n1 = number;
dp = nextToken();
if (dp == DP.colon)
{ // back up, not a year
si = sisave;
}
else
{ year = n1;
continue;
}
break;
}
}
continue;
case DP.number:
n1 = number;
dp = nextToken();
switch (dp)
{
case DP.end:
year = n1;
break;
case DP.minus:
case DP.slash: // n1/ ? ? ?
dp = parseCalendarDate(n1);
if (dp == DP.err)
goto case_error;
break;
case DP.colon: // hh:mm [:ss] [am | pm]
dp = parseTimeOfDay(n1);
if (dp == DP.err)
goto case_error;
break;
case DP.ampm:
hours = n1;
minutes = 0;
seconds = 0;
ampm = number;
break;
case DP.month:
day = n1;
month = number;
dp = nextToken();
if (dp == DP.number)
{ // day month year
year = number;
dp = nextToken();
}
break;
default:
year = n1;
break;
}
continue;
}
dp = nextToken();
}
assert(0);
}
int parseCalendarDate(int n1)
{
int n2;
int n3;
int dp;
debug(dateparse) printf("DateParse.parseCalendarDate(%d)\n", n1);
dp = nextToken();
if (dp == DP.month) // day/month
{
day = n1;
month = number;
dp = nextToken();
if (dp == DP.number)
{ // day/month year
year = number;
dp = nextToken();
}
else if (dp == DP.minus || dp == DP.slash)
{ // day/month/year
dp = nextToken();
if (dp != DP.number)
goto case_error;
year = number;
dp = nextToken();
}
return dp;
}
if (dp != DP.number)
goto case_error;
n2 = number;
//message(DTEXT("\tn2 = %d\n"), n2);
dp = nextToken();
if (dp == DP.minus || dp == DP.slash)
{
dp = nextToken();
if (dp != DP.number)
goto case_error;
n3 = number;
//message(DTEXT("\tn3 = %d\n"), n3);
dp = nextToken();
// case1: year/month/day
// case2: month/day/year
int case1, case2;
case1 = (n1 > 12 ||
(n2 >= 1 && n2 <= 12) &&
(n3 >= 1 && n3 <= 31));
case2 = ((n1 >= 1 && n1 <= 12) &&
(n2 >= 1 && n2 <= 31) ||
n3 > 31);
if (case1 == case2)
goto case_error;
if (case1)
{
year = n1;
month = n2;
day = n3;
}
else
{
month = n1;
day = n2;
year = n3;
}
}
else
{ // must be month/day
month = n1;
day = n2;
}
return dp;
case_error:
return DP.err;
}
int parseTimeOfDay(int n1)
{
int dp;
int sign;
// 12am is midnight
// 12pm is noon
//message(DTEXT("DateParse::parseTimeOfDay(%d)\n"), n1);
hours = n1;
dp = nextToken();
if (dp != DP.number)
goto case_error;
minutes = number;
dp = nextToken();
if (dp == DP.colon)
{
dp = nextToken();
if (dp != DP.number)
goto case_error;
seconds = number;
dp = nextToken();
}
else
seconds = 0;
if (dp == DP.ampm)
{
ampm = number;
dp = nextToken();
}
else if (dp == DP.plus || dp == DP.minus)
{
Loffset:
sign = (dp == DP.minus) ? -1 : 1;
dp = nextToken();
if (dp != DP.number)
goto case_error;
tzcorrection = -sign * number;
dp = nextToken();
}
else if (dp == DP.tz)
{
tzcorrection = number;
dp = nextToken();
if (number == 0 && (dp == DP.plus || dp == DP.minus))
goto Loffset;
if (dp == DP.dst)
{ tzcorrection += 100;
dp = nextToken();
}
}
else if (dp == DP.dsttz)
{
tzcorrection = number;
dp = nextToken();
}
return dp;
case_error:
return DP.err;
}
}
unittest
{
DateParse dp;
Date d;
dp.parse("March 10, 1959 12:00 -800", d);
assert(d.year == 1959);
assert(d.month == 3);
assert(d.day == 10);
assert(d.hour == 12);
assert(d.minute == 0);
assert(d.second == 0);
assert(d.ms == 0);
assert(d.weekday == 0);
assert(d.tzcorrection == 800);
dp.parse("Tue Apr 02 02:04:57 GMT-0800 1996", d);
assert(d.year == 1996);
assert(d.month == 4);
assert(d.day == 2);
assert(d.hour == 2);
assert(d.minute == 4);
assert(d.second == 57);
assert(d.ms == 0);
assert(d.weekday == 3);
assert(d.tzcorrection == 800);
dp.parse("March 14, -1980 21:14:50", d);
assert(d.year == 1980);
assert(d.month == 3);
assert(d.day == 14);
assert(d.hour == 21);
assert(d.minute == 14);
assert(d.second == 50);
assert(d.ms == 0);
assert(d.weekday == 0);
assert(d.tzcorrection == int.min);
dp.parse("Tue Apr 02 02:04:57 1996", d);
assert(d.year == 1996);
assert(d.month == 4);
assert(d.day == 2);
assert(d.hour == 2);
assert(d.minute == 4);
assert(d.second == 57);
assert(d.ms == 0);
assert(d.weekday == 3);
assert(d.tzcorrection == int.min);
dp.parse("Tue, 02 Apr 1996 02:04:57 G.M.T.", d);
assert(d.year == 1996);
assert(d.month == 4);
assert(d.day == 2);
assert(d.hour == 2);
assert(d.minute == 4);
assert(d.second == 57);
assert(d.ms == 0);
assert(d.weekday == 3);
assert(d.tzcorrection == 0);
dp.parse("December 31, 3000", d);
assert(d.year == 3000);
assert(d.month == 12);
assert(d.day == 31);
assert(d.hour == 0);
assert(d.minute == 0);
assert(d.second == 0);
assert(d.ms == 0);
assert(d.weekday == 0);
assert(d.tzcorrection == int.min);
dp.parse("Wed, 31 Dec 1969 16:00:00 GMT", d);
assert(d.year == 1969);
assert(d.month == 12);
assert(d.day == 31);
assert(d.hour == 16);
assert(d.minute == 0);
assert(d.second == 0);
assert(d.ms == 0);
assert(d.weekday == 4);
assert(d.tzcorrection == 0);
dp.parse("1/1/1999 12:30 AM", d);
assert(d.year == 1999);
assert(d.month == 1);
assert(d.day == 1);
assert(d.hour == 0);
assert(d.minute == 30);
assert(d.second == 0);
assert(d.ms == 0);
assert(d.weekday == 0);
assert(d.tzcorrection == int.min);
dp.parse("Tue, 20 May 2003 15:38:58 +0530", d);
assert(d.year == 2003);
assert(d.month == 5);
assert(d.day == 20);
assert(d.hour == 15);
assert(d.minute == 38);
assert(d.second == 58);
assert(d.ms == 0);
assert(d.weekday == 3);
assert(d.tzcorrection == -530);
debug(dateparse) printf("year = %d, month = %d, day = %d\n%02d:%02d:%02d.%03d\nweekday = %d, tzcorrection = %d\n",
d.year, d.month, d.day,
d.hour, d.minute, d.second, d.ms,
d.weekday, d.tzcorrection);
}

1588
lphobos/std/file.d Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -207,7 +207,7 @@ else
becomes byte 0.
*/
version (LLVM)
pragma(LLVM_internal, "intrinsic", "llvm.bswap.i32")
pragma(intrinsic, "llvm.bswap.i32")
uint bswap(uint val);
else
uint bswap(uint v);

View File

@@ -190,13 +190,14 @@ unittest
* Results are undefined if |x| >= $(POWER 2,64).
*/
pragma(LLVM_internal, "intrinsic", "llvm.cos.f32")
pragma(intrinsic, "llvm.cos.f32")
float cos(float x);
pragma(LLVM_internal, "intrinsic", "llvm.cos.f64") {
pragma(intrinsic, "llvm.cos.f64")
double cos(double x); // ditto
pragma(intrinsic, "llvm.cos.f80")
real cos(real x); /// ditto
}
/***********************************
@@ -212,13 +213,14 @@ real cos(real x); /// ditto
* Results are undefined if |x| >= $(POWER 2,64).
*/
pragma(LLVM_internal, "intrinsic", "llvm.sin.f32")
pragma(intrinsic, "llvm.sin.f32")
float sin(float x);
pragma(LLVM_internal, "intrinsic", "llvm.sin.f64") {
pragma(intrinsic, "llvm.sin.f64")
double sin(double x); // ditto
pragma(intrinsic, "llvm.sin.f80")
real sin(real x); /// ditto
}
/****************************************************************************
@@ -553,13 +555,14 @@ extern (C) real rndtonl(real x);
* )
*/
pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f32")
pragma(intrinsic, "llvm.sqrt.f32")
float sqrt(float x); /* intrinsic */
pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f64") {
pragma(intrinsic, "llvm.sqrt.f64")
double sqrt(double x); /* intrinsic */ /// ditto
pragma(intrinsic, "llvm.sqrt.f80")
real sqrt(real x); /* intrinsic */ /// ditto
}
creal sqrt(creal z)
{
@@ -1499,19 +1502,23 @@ real fma(real x, real y, real z) { return (x * y) + z; }
* Fast integral powers.
*/
pragma(LLVM_internal, "intrinsic", "llvm.powi.f32")
pragma(intrinsic, "llvm.powi.f32")
{
float pow(float x, uint n);
/// ditto
float pow(float x, int n);
}
pragma(LLVM_internal, "intrinsic", "llvm.powi.f64")
pragma(intrinsic, "llvm.powi.f64")
{
/// ditto
double pow(double x, uint n);
/// ditto
double pow(double x, int n);
}
pragma(intrinsic, "llvm.powi.f80")
{
/// ditto
real pow(real x, uint n);
/// ditto
@@ -1606,16 +1613,14 @@ real pow(real x, int n);
* )
*/
pragma(LLVM_internal, "intrinsic", "llvm.pow.f32")
pragma(intrinsic, "llvm.pow.f32")
float pow(float x, float y);
pragma(LLVM_internal, "intrinsic", "llvm.pow.f64")
{
/// ditto
pragma(intrinsic, "llvm.pow.f64")
double pow(double x, double y);
/// ditto
pragma(intrinsic, "llvm.pow.f80")
real pow(real x, real y);
}
/+
real pow(real x, real y);

504
lphobos/std/md5.d Normal file
View File

@@ -0,0 +1,504 @@
/* md5.d - RSA Data Security, Inc., MD5 message-digest algorithm
* Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
*/
/**
* Computes MD5 digests of arbitrary data. MD5 digests are 16 byte quantities that are like a checksum or crc, but are more robust.
*
* There are two ways to do this. The first does it all in one function call to
* sum(). The second is for when the data is buffered.
*
* Bugs:
* MD5 digests have been demonstrated to not be unique.
*
* Author:
* The routines and algorithms are derived from the
* $(I RSA Data Security, Inc. MD5 Message-Digest Algorithm).
*
* References:
* $(LINK2 http://en.wikipedia.org/wiki/Md5, Wikipedia on MD5)
*
* Macros:
* WIKI = Phobos/StdMd5
*/
/++++++++++++++++++++++++++++++++
Example:
--------------------
// This code is derived from the
// RSA Data Security, Inc. MD5 Message-Digest Algorithm.
import std.md5;
private import std.stdio;
private import std.string;
private import std.c.stdio;
private import std.c.string;
int main(char[][] args)
{
foreach (char[] arg; args)
MDFile(arg);
return 0;
}
/* Digests a file and prints the result. */
void MDFile(char[] filename)
{
FILE* file;
MD5_CTX context;
int len;
ubyte[4 * 1024] buffer;
ubyte digest[16];
if ((file = fopen(std.string.toStringz(filename), "rb")) == null)
writefln("%s can't be opened", filename);
else
{
context.start();
while ((len = fread(buffer, 1, buffer.sizeof, file)) != 0)
context.update(buffer[0 .. len]);
context.finish(digest);
fclose(file);
writefln("MD5 (%s) = %s", filename, digestToString(digest));
}
}
--------------------
+/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, September 2004
*/
module std.md5;
//debug=md5; // uncomment to turn on debugging printf's
import std.string;
version(D_InlineAsm)
version(X86)
version = Asm86;
/***************************************
* Computes MD5 digest of array of data.
*/
void sum(ubyte[16] digest, void[] data)
{
MD5_CTX context;
context.start();
context.update(data);
context.finish(digest);
}
/******************
* Prints a message digest in hexadecimal to stdout.
*/
void printDigest(ubyte digest[16])
{
foreach (ubyte u; digest)
printf("%02x", u);
}
/****************************************
* Converts MD5 digest to a string.
*/
char[] digestToString(ubyte[16] digest)
{
char[] result = new char[32];
int i;
foreach (ubyte u; digest)
{
result[i] = std.string.hexdigits[u >> 4];
result[i + 1] = std.string.hexdigits[u & 15];
i += 2;
}
return result;
}
/**
* Holds context of MD5 computation.
*
* Used when data to be digested is buffered.
*/
struct MD5_CTX
{
uint state[4] = /* state (ABCD) */
/* magic initialization constants */
[0x67452301,0xefcdab89,0x98badcfe,0x10325476];
ulong count; /* number of bits, modulo 2^64 */
ubyte buffer[64]; /* input buffer */
static ubyte[64] PADDING =
[
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
];
/* F, G, H and I are basic MD5 functions.
*/
private static
{
uint F(uint x, uint y, uint z) { return (x & y) | (~x & z); }
uint G(uint x, uint y, uint z) { return (x & z) | (y & ~z); }
uint H(uint x, uint y, uint z) { return x ^ y ^ z; }
uint I(uint x, uint y, uint z) { return y ^ (x | ~z); }
}
/* ROTATE_LEFT rotates x left n bits.
*/
static uint ROTATE_LEFT(uint x, uint n)
{
version (Asm86)
{
version (GNU)
{
asm
{
naked ;
mov ECX, n ;
mov EAX, x ;
rol EAX, CL ;
ret ;
}
}
else
{
asm
{ naked ;
mov ECX,EAX ;
mov EAX,4[ESP] ;
rol EAX,CL ;
ret 4 ;
}
}
}
else
{
return (x << n) | (x >> (32-n));
}
}
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
* Rotation is separate from addition to prevent recomputation.
*/
static void FF(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
{
a += F (b, c, d) + x + cast(uint)(ac);
a = ROTATE_LEFT (a, s);
a += b;
}
static void GG(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
{
a += G (b, c, d) + x + cast(uint)(ac);
a = ROTATE_LEFT (a, s);
a += b;
}
static void HH(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
{
a += H (b, c, d) + x + cast(uint)(ac);
a = ROTATE_LEFT (a, s);
a += b;
}
static void II(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
{
a += I (b, c, d) + x + cast(uint)(ac);
a = ROTATE_LEFT (a, s);
a += b;
}
/**
* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void start()
{
*this = MD5_CTX.init;
}
/** MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void update(void[] input)
{
uint index, partLen;
size_t i;
size_t inputLen = input.length;
/* Compute number of bytes mod 64 */
index = (cast(uint)count >> 3) & (64 - 1);
/* Update number of bits */
count += inputLen * 8;
partLen = 64 - index;
/* Transform as many times as possible. */
if (inputLen >= partLen)
{
std.c.string.memcpy(&buffer[index], input.ptr, partLen);
transform (buffer.ptr);
for (i = partLen; i + 63 < inputLen; i += 64)
transform ((cast(ubyte[])input)[i .. i + 64].ptr);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
if (inputLen - i)
std.c.string.memcpy(&buffer[index], &input[i], inputLen-i);
}
/** MD5 finalization. Ends an MD5 message-digest operation, writing the
* the message to digest and zeroing the context.
*/
void finish(ubyte[16] digest) /* message digest */
{
ubyte bits[8];
uint index, padLen;
uint[2] cnt;
/* Save number of bits */
cnt[0] = cast(uint)count;
cnt[1] = cast(uint)(count >> 32);
Encode (bits.ptr, cnt.ptr, 8);
/* Pad out to 56 mod 64. */
index = (cast(uint)count >> 3) & (64 - 1);
padLen = (index < 56) ? (56 - index) : (120 - index);
update (PADDING[0 .. padLen]);
/* Append length (before padding) */
update (bits);
/* Store state in digest */
Encode (digest.ptr, state.ptr, 16);
/* Zeroize sensitive information. */
std.c.string.memset (this, 0, MD5_CTX.sizeof);
}
/* MD5 basic transformation. Transforms state based on block.
*/
/* Constants for MD5Transform routine. */
enum
{
S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22,
S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20,
S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23,
S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21,
}
private void transform (ubyte* /*[64]*/ block)
{
uint a = state[0],
b = state[1],
c = state[2],
d = state[3];
uint[16] x;
Decode (x.ptr, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
x[] = 0;
}
/* Encodes input (uint) into output (ubyte). Assumes len is
a multiple of 4.
*/
private static void Encode (ubyte *output, uint *input, uint len)
{
uint i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
uint u = input[i];
output[j] = cast(ubyte)(u);
output[j+1] = cast(ubyte)(u >> 8);
output[j+2] = cast(ubyte)(u >> 16);
output[j+3] = cast(ubyte)(u >> 24);
}
}
/* Decodes input (ubyte) into output (uint). Assumes len is
a multiple of 4.
*/
private static void Decode (uint *output, ubyte *input, uint len)
{
uint i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
version (LittleEndian)
{
output[i] = *cast(uint*)&input[j];
}
else
{
output[i] = (cast(uint)input[j]) | ((cast(uint)input[j+1]) << 8) |
((cast(uint)input[j+2]) << 16) | ((cast(uint)input[j+3]) << 24);
}
}
}
}
unittest
{
debug(md5) printf("std.md5.unittest\n");
ubyte[16] digest;
sum (digest, "");
assert(digest == cast(ubyte[])x"d41d8cd98f00b204e9800998ecf8427e");
sum (digest, "a");
assert(digest == cast(ubyte[])x"0cc175b9c0f1b6a831c399e269772661");
sum (digest, "abc");
assert(digest == cast(ubyte[])x"900150983cd24fb0d6963f7d28e17f72");
sum (digest, "message digest");
assert(digest == cast(ubyte[])x"f96b697d7cb7938d525a2f31aaf161d0");
sum (digest, "abcdefghijklmnopqrstuvwxyz");
assert(digest == cast(ubyte[])x"c3fcd3d76192e4007dfb496cca67e13b");
sum (digest, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
assert(digest == cast(ubyte[])x"d174ab98d277d9f5a5611c2c9f419d9f");
sum (digest,
"1234567890123456789012345678901234567890"
"1234567890123456789012345678901234567890");
assert(digest == cast(ubyte[])x"57edf4a22be3c955ac49da2e2107b67a");
assert(digestToString(cast(ubyte[16])x"c3fcd3d76192e4007dfb496cca67e13b")
== "C3FCD3D76192E4007DFB496CCA67E13B");
}

648
lphobos/std/mmfile.d Normal file
View File

@@ -0,0 +1,648 @@
/* Copyright 2004-2005 by Digital Mars
* Written by Walter Bright and Matthew Wilson
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* - The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* - Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* - This notice may not be removed or altered from any source
* distribution.
*
*/
/**
* Read and write memory mapped files.
* Macros:
* WIKI=Phobos/StdMmfile
*/
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, September 2004
*/
module std.mmfile;
private import std.c.stdio;
private import std.c.stdlib;
private import std.string;
//debug = MMFILE;
version (Win32)
{
private import std.c.windows.windows;
private import std.utf;
private uint dwVersion;
static this()
{ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getversion.asp
dwVersion = GetVersion();
}
private const bool Have_MMFile = true; // private for now...
}
else version (Unix)
{
version (/*GNU_Unix_Have_MMap*/Unix)
{
version(linux) {
import std.c.linux.linux;
alias std.c.linux.linux unix;
} else {
private import std.c.unix.unix;
alias std.c.unix.unix unix;
}
version = unix_mm;
private const bool Have_MMFile = true;
}
else
{
private const bool Have_MMFile = false;
}
}
else
{
private const bool Have_MMFile = false;
// Can't simply fail because std.stream imports this module.
//static assert(0);
}
static if (Have_MMFile)
{
private import std.file;
private import std.path;
}
/**
* MmFile objects control the memory mapped file resource.
*/
class MmFile
{
/**
* The mode the memory mapped file is opened with.
*/
enum Mode
{ Read, /// read existing file
ReadWriteNew, /// delete existing file, write new file
ReadWrite, /// read/write existing file, create if not existing
ReadCopyOnWrite, /// read/write existing file, copy on write
}
/**
* Open memory mapped file filename for reading.
* File is closed when the object instance is deleted.
* Throws:
* std.file.FileException
*/
this(char[] filename)
{
this(filename, Mode.Read, 0, null);
}
/**
* Open memory mapped file filename in mode.
* File is closed when the object instance is deleted.
* Params:
* filename = name of the file.
* If null, an anonymous file mapping is created.
* mode = access mode defined above.
* size = the size of the file. If 0, it is taken to be the
* size of the existing file.
* address = the preferred address to map the file to,
* although the system is not required to honor it.
* If null, the system selects the most convenient address.
* window = preferred block size of the amount of data to map at one time
* with 0 meaning map the entire file. The window size must be a
* multiple of the memory allocation page size.
* Throws:
* std.file.FileException
*/
this(char[] filename, Mode mode, ulong size, void* address,
size_t window = 0)
{
this.filename = filename;
this.mMode = mode;
this.window = window;
this.address = address;
version (Win32)
{
void* p;
uint dwDesiredAccess2;
uint dwShareMode;
uint dwCreationDisposition;
uint flProtect;
if (dwVersion & 0x80000000 && (dwVersion & 0xFF) == 3)
{
throw new FileException(filename,
"Win32s does not implement mm files");
}
switch (mode)
{
case Mode.Read:
dwDesiredAccess2 = GENERIC_READ;
dwShareMode = FILE_SHARE_READ;
dwCreationDisposition = OPEN_EXISTING;
flProtect = PAGE_READONLY;
dwDesiredAccess = FILE_MAP_READ;
break;
case Mode.ReadWriteNew:
assert(size != 0);
dwDesiredAccess2 = GENERIC_READ | GENERIC_WRITE;
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
dwCreationDisposition = CREATE_ALWAYS;
flProtect = PAGE_READWRITE;
dwDesiredAccess = FILE_MAP_WRITE;
break;
case Mode.ReadWrite:
dwDesiredAccess2 = GENERIC_READ | GENERIC_WRITE;
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
dwCreationDisposition = OPEN_ALWAYS;
flProtect = PAGE_READWRITE;
dwDesiredAccess = FILE_MAP_WRITE;
break;
case Mode.ReadCopyOnWrite:
if (dwVersion & 0x80000000)
{
throw new FileException(filename,
"Win9x does not implement copy on write");
}
dwDesiredAccess2 = GENERIC_READ | GENERIC_WRITE;
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
dwCreationDisposition = OPEN_EXISTING;
flProtect = PAGE_WRITECOPY;
dwDesiredAccess = FILE_MAP_COPY;
break;
default:
assert(0);
}
if (filename)
{
if (useWfuncs)
{
auto namez = std.utf.toUTF16z(filename);
hFile = CreateFileW(namez,
dwDesiredAccess2,
dwShareMode,
null,
dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL,
cast(HANDLE)null);
}
else
{
auto namez = std.file.toMBSz(filename);
hFile = CreateFileA(namez,
dwDesiredAccess2,
dwShareMode,
null,
dwCreationDisposition,
FILE_ATTRIBUTE_NORMAL,
cast(HANDLE)null);
}
if (hFile == INVALID_HANDLE_VALUE)
goto err1;
}
else
hFile = null;
int hi = cast(int)(size>>32);
hFileMap = CreateFileMappingA(hFile, null, flProtect, hi, cast(uint)size, null);
if (hFileMap == null) // mapping failed
goto err1;
if (size == 0)
{
uint sizehi;
uint sizelow = GetFileSize(hFile,&sizehi);
size = (cast(ulong)sizehi << 32) + sizelow;
}
this.size = size;
size_t initial_map = (window && 2*window<size)? 2*window : cast(size_t)size;
p = MapViewOfFileEx(hFileMap, dwDesiredAccess, 0, 0, initial_map, address);
if (!p) goto err1;
data = p[0 .. initial_map];
debug (MMFILE) printf("MmFile.this(): p = %p, size = %d\n", p, size);
return;
err1:
if (hFileMap != null)
CloseHandle(hFileMap);
hFileMap = null;
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
errNo();
}
else version (unix_mm)
{
char* namez = toStringz(filename);
void* p;
int oflag;
int fmode;
switch (mode)
{
case Mode.Read:
flags = MAP_SHARED;
prot = PROT_READ;
oflag = O_RDONLY;
fmode = 0;
break;
case Mode.ReadWriteNew:
assert(size != 0);
flags = MAP_SHARED;
prot = PROT_READ | PROT_WRITE;
oflag = O_CREAT | O_RDWR | O_TRUNC;
fmode = 0660;
break;
case Mode.ReadWrite:
flags = MAP_SHARED;
prot = PROT_READ | PROT_WRITE;
oflag = O_CREAT | O_RDWR;
fmode = 0660;
break;
case Mode.ReadCopyOnWrite:
flags = MAP_PRIVATE;
prot = PROT_READ | PROT_WRITE;
oflag = O_RDWR;
fmode = 0;
break;
default:
assert(0);
}
if (filename.length)
{
struct_stat statbuf;
fd = unix.open(namez, oflag, fmode);
if (fd == -1)
{
// printf("\topen error, errno = %d\n",getErrno());
errNo();
}
if (unix.fstat(fd, &statbuf))
{
//printf("\tfstat error, errno = %d\n",getErrno());
unix.close(fd);
errNo();
}
if (prot & PROT_WRITE && size > statbuf.st_size)
{
// Need to make the file size bytes big
unix.lseek(fd, cast(off_t)(size - 1), SEEK_SET);
char c = 0;
unix.write(fd, &c, 1);
}
else if (prot & PROT_READ && size == 0)
size = statbuf.st_size;
}
else
{
fd = -1;
flags |= MAP_ANONYMOUS;
}
this.size = size;
size_t initial_map = (window && 2*window<size)? 2*window : cast(size_t)size;
p = mmap(address, initial_map, prot, flags, fd, 0);
if (p == MAP_FAILED) {
if (fd != -1)
unix.close(fd);
errNo();
}
data = p[0 .. initial_map];
}
else static if (! Have_MMFile)
{
throw new FileException("This system does support memory mapped files");
}
else
{
static assert(0);
}
}
/**
* Flushes pending output and closes the memory mapped file.
*/
~this()
{
debug (MMFILE) printf("MmFile.~this()\n");
unmap();
version (Win32)
{
if (hFileMap != null && CloseHandle(hFileMap) != TRUE)
errNo();
hFileMap = null;
if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE)
errNo();
hFile = INVALID_HANDLE_VALUE;
}
else version (unix_mm)
{
if (fd != -1 && unix.close(fd) == -1)
errNo();
fd = -1;
}
else static if (! Have_MMFile)
{
}
else
{
static assert(0);
}
data = null;
}
/* Flush any pending output.
*/
void flush()
{
debug (MMFILE) printf("MmFile.flush()\n");
version (Win32)
{
FlushViewOfFile(data.ptr, data.length);
}
else version (unix_mm)
{
int i;
i = msync(cast(void*)data, data.length, MS_SYNC); // sys/mman.h
if (i != 0)
errNo();
}
else static if (! Have_MMFile)
{
}
else
{
static assert(0);
}
}
/**
* Gives size in bytes of the memory mapped file.
*/
ulong length()
{
debug (MMFILE) printf("MmFile.length()\n");
return size;
}
/**
* Read-only property returning the file mode.
*/
Mode mode()
{
debug (MMFILE) printf("MmFile.mode()\n");
return mMode;
}
/**
* Returns entire file contents as an array.
*/
void[] opSlice()
{
debug (MMFILE) printf("MmFile.opSlice()\n");
return opSlice(0,size);
}
/**
* Returns slice of file contents as an array.
*/
void[] opSlice(ulong i1, ulong i2)
{
debug (MMFILE) printf("MmFile.opSlice(%lld, %lld)\n", i1, i2);
ensureMapped(i1,i2);
size_t off1 = cast(size_t)(i1-start);
size_t off2 = cast(size_t)(i2-start);
return data[off1 .. off2];
}
/**
* Returns byte at index i in file.
*/
ubyte opIndex(ulong i)
{
debug (MMFILE) printf("MmFile.opIndex(%lld)\n", i);
ensureMapped(i);
size_t off = cast(size_t)(i-start);
return (cast(ubyte[])data)[off];
}
/**
* Sets and returns byte at index i in file to value.
*/
ubyte opIndexAssign(ubyte value, ulong i)
{
debug (MMFILE) printf("MmFile.opIndex(%lld, %d)\n", i, value);
ensureMapped(i);
size_t off = cast(size_t)(i-start);
return (cast(ubyte[])data)[off] = value;
}
// return true if the given position is currently mapped
private int mapped(ulong i)
{
debug (MMFILE) printf("MmFile.mapped(%lld, %lld, %d)\n", i,start,
data.length);
return i >= start && i < start+data.length;
}
// unmap the current range
private void unmap()
{
debug (MMFILE) printf("MmFile.unmap()\n");
version(Windows) {
/* Note that under Windows 95, UnmapViewOfFile() seems to return
* random values, not TRUE or FALSE.
*/
if (data && UnmapViewOfFile(data.ptr) == FALSE &&
(dwVersion & 0x80000000) == 0)
errNo();
} else version (unix_mm) {
if (data && munmap(cast(void*)data, data.length) != 0)
errNo();
}
data = null;
}
// map range
private void map(ulong start, size_t len)
{
debug (MMFILE) printf("MmFile.map(%lld, %d)\n", start, len);
void* p;
if (start+len > size)
len = cast(size_t)(size-start);
version(Windows) {
uint hi = cast(uint)(start>>32);
p = MapViewOfFileEx(hFileMap, dwDesiredAccess, hi, cast(uint)start, len, address);
if (!p) errNo();
} else version (unix_mm) {
p = mmap(address, len, prot, flags, fd, cast(off_t)start);
if (p == MAP_FAILED) errNo();
}
data = p[0 .. len];
this.start = start;
}
// ensure a given position is mapped
private void ensureMapped(ulong i)
{
debug (MMFILE) printf("MmFile.ensureMapped(%lld)\n", i);
if (!mapped(i)) {
unmap();
if (window == 0) {
map(0,cast(size_t)size);
} else {
ulong block = i/window;
if (block == 0)
map(0,2*window);
else
map(window*(block-1),3*window);
}
}
}
// ensure a given range is mapped
private void ensureMapped(ulong i, ulong j)
{
debug (MMFILE) printf("MmFile.ensureMapped(%lld, %lld)\n", i, j);
if (!mapped(i) || !mapped(j-1)) {
unmap();
if (window == 0) {
map(0,cast(size_t)size);
} else {
ulong iblock = i/window;
ulong jblock = (j-1)/window;
if (iblock == 0) {
map(0,cast(size_t)(window*(jblock+2)));
} else {
map(window*(iblock-1),cast(size_t)(window*(jblock-iblock+3)));
}
}
}
}
private:
char[] filename;
void[] data;
ulong start;
size_t window;
ulong size;
Mode mMode;
void* address;
version (Win32)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hFileMap = null;
uint dwDesiredAccess;
}
else version (unix_mm)
{
int fd;
int prot;
int flags;
int fmode;
}
else static if (! Have_MMFile)
{
}
else
{
static assert(0);
}
// Report error, where errno gives the error number
void errNo()
{
version (Win32)
{
throw new FileException(filename, GetLastError());
}
else version (Unix)
{
throw new FileException(filename, getErrno());
}
else static if (! Have_MMFile)
{
throw new FileException(filename, "MMFile unsupported");
}
else
{
static assert(0);
}
}
}
unittest {
static if (Have_MMFile)
{
const size_t K = 1024;
size_t win = 64*K; // assume the page size is 64K
version(Win32) {
/+ these aren't defined in std.c.windows.windows so let's use the default
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
win = sysinfo.dwAllocationGranularity;
+/
} else version (Unix) {
// getpagesize() is not defined in the unix D headers so use the guess
}
MmFile mf = new MmFile("testing.txt",MmFile.Mode.ReadWriteNew,100*K,null,win);
ubyte[] str = cast(ubyte[])"1234567890";
ubyte[] data = cast(ubyte[])mf[0 .. 10];
data[] = str[];
assert( mf[0 .. 10] == str );
data = cast(ubyte[])mf[50 .. 60];
data[] = str[];
assert( mf[50 .. 60] == str );
ubyte[] data2 = cast(ubyte[])mf[20*K .. 60*K];
assert( data2.length == 40*K );
assert( data2[length-1] == 0 );
mf[100*K-1] = cast(ubyte)'b';
data2 = cast(ubyte[])mf[21*K .. 100*K];
assert( data2.length == 79*K );
assert( data2[length-1] == 'b' );
delete mf;
std.file.remove("testing.txt");
}
}

View File

@@ -51,16 +51,12 @@ extern (C) void _moduleCtor()
debug printf("_moduleCtor()\n");
int len = 0;
ModuleInfo* mrbegin = cast(ModuleInfo*)_d_get_moduleinfo_array();
assert(mrbegin !is null);
ModuleInfo* mr;
for (mr = mrbegin; *mr !is null; ++mr)
for (auto mr = _Dmodule_ref; mr; mr=mr.next)
len++;
_moduleinfo_array = new ModuleInfo[len];
len = 0;
for (mr = mrbegin; *mr !is null; ++mr)
{ _moduleinfo_array[len] = *mr;
for (auto mr = _Dmodule_ref; mr; mr=mr.next)
{ _moduleinfo_array[len] = mr.mod;
len++;
}
@@ -97,16 +93,18 @@ void _moduleCtor2(ModuleInfo[] mi, int skip)
debug printf("\tmodule[%d] = '%p'\n", i, m);
if (!m)
continue;
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name.length, m.name.ptr);
if (m.flags & MIctordone)
continue;
debug printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
debug printf("\tmodule[%d] = '%.*s', m = 0x%x\n", i, m.name.length, m.name.ptr, m);
if (m.ctor || m.dtor)
{
if (m.flags & MIctorstart)
{ if (skip || m.flags & MIstandalone)
continue;
debug printf("\tmodule[%d] = '%.*s', cyclic dependency!\n", i, m.name.length, m.name.ptr);
int x = 0; x /= x;
throw new ModuleCtorError(m);
}
@@ -160,7 +158,7 @@ extern (C) void _moduleDtor()
extern (C) void _moduleUnitTests()
{
debug printf("_moduleUnitTests()\n");
debug printf("_moduleUnitTests() %i\n", _moduleinfo_array.length);
for (uint i = 0; i < _moduleinfo_array.length; i++)
{
ModuleInfo m = _moduleinfo_array[i];

368
lphobos/std/outbuffer.d Normal file
View File

@@ -0,0 +1,368 @@
// outbuffer.d
/**
* Boilerplate:
* $(std_boilerplate.html)
* Macros:
* WIKI = Phobos/StdOutbuffer
* Copyright:
* Copyright (c) 2001-2005 by Digital Mars
* All Rights Reserved
* www.digitalmars.com
*/
// Written by Walter Bright
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, September 2004
*/
module std.outbuffer;
private
{
import std.string;
import std.gc;
import std.c.stdio;
import std.c.stdlib;
import std.c.stdarg;
}
/*********************************************
* OutBuffer provides a way to build up an array of bytes out
* of raw data. It is useful for things like preparing an
* array of bytes to write out to a file.
* OutBuffer's byte order is the format native to the computer.
* To control the byte order (endianness), use a class derived
* from OutBuffer.
*/
class OutBuffer
{
ubyte data[];
size_t offset;
invariant
{
//printf("this = %p, offset = %x, data.length = %u\n", this, offset, data.length);
assert(offset <= data.length);
assert(data.length <= std.gc.capacity(data.ptr));
}
this()
{
//printf("in OutBuffer constructor\n");
}
/*********************************
* Convert to array of bytes.
*/
ubyte[] toBytes() { return data[0 .. offset]; }
/***********************************
* Preallocate nbytes more to the size of the internal buffer.
*
* This is a
* speed optimization, a good guess at the maximum size of the resulting
* buffer will improve performance by eliminating reallocations and copying.
*/
void reserve(size_t nbytes)
in
{
assert(offset + nbytes >= offset);
}
out
{
assert(offset + nbytes <= data.length);
assert(data.length <= std.gc.capacity(data.ptr));
}
body
{
if (data.length < offset + nbytes)
{
//std.c.stdio.printf("OutBuffer.reserve: ptr = %p, length = %d, offset = %d, nbytes = %d, capacity = %d\n", data.ptr, data.length, offset, nbytes, std.gc.capacity(data.ptr));
data.length = (offset + nbytes) * 2;
//std.c.stdio.printf("OutBuffer.reserve: ptr = %p, length = %d, capacity = %d\n", data.ptr, data.length, std.gc.capacity(data.ptr));
std.gc.hasPointers(data.ptr);
}
}
/*************************************
* Append data to the internal buffer.
*/
void write(ubyte[] bytes)
{
reserve(bytes.length);
data[offset .. offset + bytes.length] = bytes;
offset += bytes.length;
}
void write(ubyte b) /// ditto
{
reserve(ubyte.sizeof);
this.data[offset] = b;
offset += ubyte.sizeof;
}
void write(byte b) { write(cast(ubyte)b); } /// ditto
void write(char c) { write(cast(ubyte)c); } /// ditto
void write(ushort w) /// ditto
{
reserve(ushort.sizeof);
*cast(ushort *)&data[offset] = w;
offset += ushort.sizeof;
}
void write(short s) { write(cast(ushort)s); } /// ditto
void write(wchar c) /// ditto
{
reserve(wchar.sizeof);
*cast(wchar *)&data[offset] = c;
offset += wchar.sizeof;
}
void write(uint w) /// ditto
{
reserve(uint.sizeof);
*cast(uint *)&data[offset] = w;
offset += uint.sizeof;
}
void write(int i) { write(cast(uint)i); } /// ditto
void write(ulong l) /// ditto
{
reserve(ulong.sizeof);
*cast(ulong *)&data[offset] = l;
offset += ulong.sizeof;
}
void write(long l) { write(cast(ulong)l); } /// ditto
void write(float f) /// ditto
{
reserve(float.sizeof);
*cast(float *)&data[offset] = f;
offset += float.sizeof;
}
void write(double f) /// ditto
{
reserve(double.sizeof);
*cast(double *)&data[offset] = f;
offset += double.sizeof;
}
void write(real f) /// ditto
{
reserve(real.sizeof);
*cast(real *)&data[offset] = f;
offset += real.sizeof;
}
void write(char[] s) /// ditto
{
write(cast(ubyte[])s);
}
void write(OutBuffer buf) /// ditto
{
write(buf.toBytes());
}
/****************************************
* Append nbytes of 0 to the internal buffer.
*/
void fill0(uint nbytes)
{
reserve(nbytes);
data[offset .. offset + nbytes] = 0;
offset += nbytes;
}
/**********************************
* 0-fill to align on power of 2 boundary.
*/
void alignSize(size_t alignsize)
in
{
assert(alignsize && (alignsize & (alignsize - 1)) == 0);
}
out
{
assert((offset & (alignsize - 1)) == 0);
}
body
{ size_t nbytes;
nbytes = offset & (alignsize - 1);
if (nbytes)
fill0(alignsize - nbytes);
}
/****************************************
* Optimize common special case alignSize(2)
*/
void align2()
{
if (offset & 1)
write(cast(byte)0);
}
/****************************************
* Optimize common special case alignSize(4)
*/
void align4()
{
if (offset & 3)
{ size_t nbytes = (4 - offset) & 3;
fill0(nbytes);
}
}
/**************************************
* Convert internal buffer to array of chars.
*/
char[] toString()
{
//printf("OutBuffer.toString()\n");
return cast(char[])data[0 .. offset];
}
/*****************************************
* Append output of C's vprintf() to internal buffer.
*/
void vprintf(char[] format, va_list args)
{
char[128] buffer;
char* p;
char* f;
uint psize;
int count;
va_list args_copy;
f = toStringz(format);
p = buffer.ptr;
psize = buffer.length;
for (;;)
{
va_copy(args_copy, args);
version(Win32)
{
count = _vsnprintf(p,psize,f,args_copy);
if (count != -1)
break;
psize *= 2;
p = cast(char *) alloca(psize); // buffer too small, try again with larger size
}
else version(GNU) {
count = vsnprintf(p,psize,f,args_copy);
if (count == -1)
psize *= 2;
else if (count >= psize)
psize = count + 1;
else
break;
p = cast(char *) alloca(psize); // buffer too small, try again with larger size
}
else version(linux)
{
count = vsnprintf(p,psize,f,args_copy);
if (count == -1)
psize *= 2;
else if (count >= psize)
psize = count + 1;
else
break;
/+
if (p != buffer)
c.stdlib.free(p);
p = (char *) c.stdlib.malloc(psize); // buffer too small, try again with larger size
+/
p = cast(char *) alloca(psize); // buffer too small, try again with larger size
}
}
write(p[0 .. count]);
/+
version (linux)
{
if (p != buffer)
c.stdlib.free(p);
}
+/
}
/*****************************************
* Append output of C's printf() to internal buffer.
*/
void printf(char[] format, ...)
{
version (GNU)
{
vprintf(format, _argptr);
}
else
{
va_list ap;
ap = cast(va_list)&format;
ap += format.sizeof;
vprintf(format, ap);
}
}
/*****************************************
* At offset index into buffer, create nbytes of space by shifting upwards
* all data past index.
*/
void spread(size_t index, size_t nbytes)
in
{
assert(index <= offset);
}
body
{
reserve(nbytes);
// This is an overlapping copy - should use memmove()
for (size_t i = offset; i > index; )
{
--i;
data[i + nbytes] = data[i];
}
offset += nbytes;
}
}
unittest
{
//printf("Starting OutBuffer test\n");
OutBuffer buf = new OutBuffer();
//printf("buf = %p\n", buf);
//printf("buf.offset = %x\n", buf.offset);
assert(buf.offset == 0);
buf.write("hello");
buf.write(cast(byte)0x20);
buf.write("world");
buf.printf(" %d", 6);
//printf("buf = '%.*s'\n", buf.toString());
assert(cmp(buf.toString(), "hello world 6") == 0);
}

1252
lphobos/std/path.d Normal file

File diff suppressed because it is too large Load Diff

293
lphobos/std/process.d Normal file
View File

@@ -0,0 +1,293 @@
/*
* Copyright (C) 2003-2004 by Digital Mars, www.digitalmars.com
* Written by Matthew Wilson and Walter Bright
*
* Incorporating idea (for execvpe() on Linux) from Russ Lewis
*
* Updated: 21st August 2004
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, October 2004
*/
/**
* Macros:
* WIKI=Phobos/StdProcess
*/
module std.process;
private import std.c.stdlib;
private import std.c.string;
private import std.string;
private import std.c.process;
/**
* Execute command in a _command shell.
*
* Returns: exit status of command
*/
int system(char[] command)
{
return std.c.process.system(toStringz(command));
}
private void toAStringz(char[][] a, char**az)
{
foreach(char[] s; a)
{
*az++ = toStringz(s);
}
*az = null;
}
/* ========================================================== */
//version (Windows)
//{
// int spawnvp(int mode, char[] pathname, char[][] argv)
// {
// char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length));
//
// toAStringz(argv, argv_);
//
// return std.c.process.spawnvp(mode, toStringz(pathname), argv_);
// }
//}
// Incorporating idea (for spawnvp() on linux) from Dave Fladebo
alias std.c.process._P_WAIT P_WAIT;
alias std.c.process._P_NOWAIT P_NOWAIT;
int spawnvp(int mode, char[] pathname, char[][] argv)
{
char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length));
toAStringz(argv, argv_);
version(Unix)
{
return _spawnvp(mode, toStringz(pathname), argv_);
}
else
{
return std.c.process.spawnvp(mode, toStringz(pathname), argv_);
}
}
version(Unix)
{
version(linux) import std.c.linux.linux;
else import std.c.unix.unix;
int _spawnvp(int mode, char *pathname, char **argv)
{
int retval = 0;
pid_t pid = fork();
if(!pid)
{ // child
std.c.process.execvp(pathname, argv);
goto Lerror;
}
else if(pid > 0)
{ // parent
if(mode == _P_NOWAIT)
{
retval = pid; // caller waits
}
else
{
while(1)
{
int status;
pid_t wpid = waitpid(pid, &status, 0);
if(exited(status))
{
retval = exitstatus(status);
break;
}
else if(signaled(status))
{
retval = -termsig(status);
break;
}
else if(stopped(status)) // ptrace support
continue;
else
goto Lerror;
}
}
return retval;
}
Lerror:
retval = getErrno;
throw new Exception(
"Cannot spawn " ~ toString(pathname) ~ "; "
~ toString(strerror(retval))
~ " [errno " ~ toString(retval) ~ "]");
} // _spawnvp
private
{
bool stopped(int status) { return cast(bool)((status & 0xff) == 0x7f); }
bool signaled(int status) { return cast(bool)((cast(char)((status & 0x7f) + 1) >> 1) > 0); }
int termsig(int status) { return status & 0x7f; }
bool exited(int status) { return cast(bool)((status & 0x7f) == 0); }
int exitstatus(int status) { return (status & 0xff00) >> 8; }
} // private
} // version(linux)
/* ========================================================== */
/**
* Execute program specified by pathname, passing it the arguments (argv)
* and the environment (envp), returning the exit status.
* The 'p' versions of exec search the PATH environment variable
* setting for the program.
*/
int execv(char[] pathname, char[][] argv)
{
char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length));
toAStringz(argv, argv_);
return std.c.process.execv(toStringz(pathname), argv_);
}
/** ditto */
int execve(char[] pathname, char[][] argv, char[][] envp)
{
char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length));
char** envp_ = cast(char**)alloca((char*).sizeof * (1 + envp.length));
toAStringz(argv, argv_);
toAStringz(envp, envp_);
return std.c.process.execve(toStringz(pathname), argv_, envp_);
}
/** ditto */
int execvp(char[] pathname, char[][] argv)
{
char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length));
toAStringz(argv, argv_);
return std.c.process.execvp(toStringz(pathname), argv_);
}
/** ditto */
int execvpe(char[] pathname, char[][] argv, char[][] envp)
{
version (GNU_Need_execvpe)
{
// Is pathname rooted?
if(pathname[0] == '/')
{
// Yes, so just call execve()
return execve(pathname, argv, envp);
}
else
{
// No, so must traverse PATHs, looking for first match
char[][] envPaths = std.string.split(std.string.toString(std.c.stdlib.getenv("PATH")), ":");
int iRet = 0;
// Note: if any call to execve() succeeds, this process will cease
// execution, so there's no need to check the execve() result through
// the loop.
foreach(char[] pathDir; envPaths)
{
char[] composite = pathDir ~ "/" ~ pathname;
iRet = execve(composite, argv, envp);
}
if(0 != iRet)
{
iRet = execve(pathname, argv, envp);
}
return iRet;
}
}
else version(Windows)
{
char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length));
char** envp_ = cast(char**)alloca((char*).sizeof * (1 + envp.length));
toAStringz(argv, argv_);
toAStringz(envp, envp_);
return std.c.process.execvpe(toStringz(pathname), argv_, envp_);
}
else
{
throw new Exception("Not supported on this platform.");
} // version
}
/* ////////////////////////////////////////////////////////////////////////// */
version(MainTest)
{
int main(char[][] args)
{
if(args.length < 2)
{
printf("Must supply executable (and optional arguments)\n");
return 1;
}
else
{
char[][] dummy_env;
dummy_env ~= "VAL0=value";
dummy_env ~= "VAL1=value";
/+
foreach(char[] arg; args)
{
printf("%.*s\n", arg);
}
+/
// int i = execv(args[1], args[1 .. args.length]);
// int i = execvp(args[1], args[1 .. args.length]);
int i = execvpe(args[1], args[1 .. args.length], dummy_env);
printf("exec??() has returned! Error code: %d; errno: %d\n", i, /* std.c.stdlib.getErrno() */-1);
return 0;
}
}
}
/* ////////////////////////////////////////////////////////////////////////// */

161
lphobos/std/random.d Normal file
View File

@@ -0,0 +1,161 @@
/**
* Macros:
* WIKI = Phobos/StdRandom
*/
// random.d
// www.digitalmars.com
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, September 2007
*/
module std.random;
// Segments of the code in this file Copyright (c) 1997 by Rick Booth
// From "Inner Loops" by Rick Booth, Addison-Wesley
version (Win32)
{
extern(Windows) int QueryPerformanceCounter(ulong *count);
}
else version (Unix)
{
version(linux) import std.c.linux.linux;
else private import std.c.unix.unix;
}
/* ===================== Random ========================= */
// BUG: not multithreaded
private uint seed; // starting seed
private uint index; // ith random number
/**
* The random number generator is seeded at program startup with a random value.
This ensures that each program generates a different sequence of random
numbers. To generate a repeatable sequence, use rand_seed() to start the
sequence. seed and index start it, and each successive value increments index.
This means that the $(I n)th random number of the sequence can be directly
generated
by passing index + $(I n) to rand_seed().
Note: This is more random, but slower, than C's rand() function.
To use C's rand() instead, import std.c.stdlib.
*/
void rand_seed(uint seed, uint index)
{
.seed = seed;
.index = index;
}
/**
* Get the next random number in sequence.
* BUGS: shares a global single state, not multithreaded
*/
uint rand()
{
static uint xormix1[20] =
[
0xbaa96887, 0x1e17d32c, 0x03bcdc3c, 0x0f33d1b2,
0x76a6491d, 0xc570d85d, 0xe382b1e3, 0x78db4362,
0x7439a9d4, 0x9cea8ac5, 0x89537c5c, 0x2588f55d,
0x415b5e1d, 0x216e3d95, 0x85c662e7, 0x5e8ab368,
0x3ea5cc8c, 0xd26a0f74, 0xf3a9222b, 0x48aad7e4
];
static uint xormix2[20] =
[
0x4b0f3b58, 0xe874f0c3, 0x6955c5a6, 0x55a7ca46,
0x4d9a9d86, 0xfe28a195, 0xb1ca7865, 0x6b235751,
0x9a997a61, 0xaa6e95c8, 0xaaa98ee1, 0x5af9154c,
0xfc8e2263, 0x390f5e8c, 0x58ffd802, 0xac0a5eba,
0xac4874f6, 0xa9df0913, 0x86be4c74, 0xed2c123b
];
uint hiword, loword, hihold, temp, itmpl, itmph, i;
loword = seed;
hiword = index++;
for (i = 0; i < 4; i++) // loop limit can be 2..20, we choose 4
{
hihold = hiword; // save hiword for later
temp = hihold ^ xormix1[i]; // mix up bits of hiword
itmpl = temp & 0xffff; // decompose to hi & lo
itmph = temp >> 16; // 16-bit words
temp = itmpl * itmpl + ~(itmph * itmph); // do a multiplicative mix
temp = (temp >> 16) | (temp << 16); // swap hi and lo halves
hiword = loword ^ ((temp ^ xormix2[i]) + itmpl * itmph); //loword mix
loword = hihold; // old hiword is loword
}
return hiword;
}
static this()
{
ulong s;
version(Win32)
{
QueryPerformanceCounter(&s);
}
else version(Unix)
{
// time.h
// sys/time.h
timeval tv;
if (gettimeofday(&tv, null))
{ // Some error happened - try time() instead
s = time(null);
}
else
{
s = cast(ulong)((cast(long)tv.tv_sec << 32) + tv.tv_usec);
}
}
else version(NoSystem)
{
// nothing
}
else
static assert(false);
rand_seed(cast(uint) s, cast(uint)(s >> 32));
}
unittest
{
static uint results[10] =
[
0x8c0188cb,
0xb161200c,
0xfc904ac5,
0x2702e049,
0x9705a923,
0x1c139d89,
0x346b6d1f,
0xf8c33e32,
0xdb9fef76,
0xa97fcb3f
];
int i;
uint seedsave = seed;
uint indexsave = index;
rand_seed(1234, 5678);
for (i = 0; i < 10; i++)
{ uint r = rand();
//printf("0x%x,\n", rand());
assert(r == results[i]);
}
seed = seedsave;
index = indexsave;
}

3208
lphobos/std/regexp.d Normal file

File diff suppressed because it is too large Load Diff

1666
lphobos/std/socket.d Normal file

File diff suppressed because it is too large Load Diff

2961
lphobos/std/stream.d Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3443,85 +3443,85 @@ bool isNumeric(...)
}
/// Check only the first parameter, all others will be ignored.
bool isNumeric(TypeInfo[] _arguments, va_list _argptr)
bool isNumeric(TypeInfo[] _args, va_list _ptr)
{
char[] s = "";
wchar[] ws = "";
dchar[] ds = "";
//writefln("isNumeric(...) called!");
if (_arguments.length == 0)
if (_args.length == 0)
return false;
if (_arguments[0] == typeid(char[]))
return isNumeric(va_arg!(char[])(_argptr));
else if (_arguments[0] == typeid(wchar[]))
return isNumeric(std.utf.toUTF8(va_arg!(wchar[])(_argptr)));
else if (_arguments[0] == typeid(dchar[]))
return isNumeric(std.utf.toUTF8(va_arg!(dchar[])(_argptr)));
else if (_arguments[0] == typeid(real))
if (_args[0] == typeid(char[]))
return isNumeric(va_arg!(char[])(_ptr));
else if (_args[0] == typeid(wchar[]))
return isNumeric(std.utf.toUTF8(va_arg!(wchar[])(_ptr)));
else if (_args[0] == typeid(dchar[]))
return isNumeric(std.utf.toUTF8(va_arg!(dchar[])(_ptr)));
else if (_args[0] == typeid(real))
return true;
else if (_arguments[0] == typeid(double))
else if (_args[0] == typeid(double))
return true;
else if (_arguments[0] == typeid(float))
else if (_args[0] == typeid(float))
return true;
else if (_arguments[0] == typeid(ulong))
else if (_args[0] == typeid(ulong))
return true;
else if (_arguments[0] == typeid(long))
else if (_args[0] == typeid(long))
return true;
else if (_arguments[0] == typeid(uint))
else if (_args[0] == typeid(uint))
return true;
else if (_arguments[0] == typeid(int))
else if (_args[0] == typeid(int))
return true;
else if (_arguments[0] == typeid(ushort))
else if (_args[0] == typeid(ushort))
return true;
else if (_arguments[0] == typeid(short))
else if (_args[0] == typeid(short))
return true;
else if (_arguments[0] == typeid(ubyte))
else if (_args[0] == typeid(ubyte))
{
s.length = 1;
s[0]= va_arg!(ubyte)(_argptr);
s[0]= va_arg!(ubyte)(_ptr);
return isNumeric(cast(char[])s);
}
else if (_arguments[0] == typeid(byte))
else if (_args[0] == typeid(byte))
{
s.length = 1;
s[0] = va_arg!(byte)(_argptr);
s[0] = va_arg!(byte)(_ptr);
return isNumeric(cast(char[])s);
}
else if (_arguments[0] == typeid(ireal))
else if (_args[0] == typeid(ireal))
return true;
else if (_arguments[0] == typeid(idouble))
else if (_args[0] == typeid(idouble))
return true;
else if (_arguments[0] == typeid(ifloat))
else if (_args[0] == typeid(ifloat))
return true;
else if (_arguments[0] == typeid(creal))
else if (_args[0] == typeid(creal))
return true;
else if (_arguments[0] == typeid(cdouble))
else if (_args[0] == typeid(cdouble))
return true;
else if (_arguments[0] == typeid(cfloat))
else if (_args[0] == typeid(cfloat))
return true;
else if (_arguments[0] == typeid(char))
else if (_args[0] == typeid(char))
{
s.length = 1;
s[0] = va_arg!(char)(_argptr);
s[0] = va_arg!(char)(_ptr);
return isNumeric(s);
}
else if (_arguments[0] == typeid(wchar))
else if (_args[0] == typeid(wchar))
{
ws.length = 1;
ws[0] = va_arg!(wchar)(_argptr);
ws[0] = va_arg!(wchar)(_ptr);
return isNumeric(std.utf.toUTF8(ws));
}
else if (_arguments[0] == typeid(dchar))
else if (_args[0] == typeid(dchar))
{
ds.length = 1;
ds[0] = va_arg!(dchar)(_argptr);
ds[0] = va_arg!(dchar)(_ptr);
return isNumeric(std.utf.toUTF8(ds));
}
//else if (_arguments[0] == typeid(cent))
//else if (_args[0] == typeid(cent))
// return true;
//else if (_arguments[0] == typeid(ucent))
//else if (_args[0] == typeid(ucent))
// return true;
else
return false;

95
lphobos/std/system.d Normal file
View File

@@ -0,0 +1,95 @@
// Written in the D programming language
/**
* Information about the target operating system, environment, and CPU
* Authors: Walter Bright, www.digitalmars.com
* License: Public Domain
* Macros:
* WIKI = Phobos/StdSystem
*/
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, September 2007
*/
// Information about the target operating system, environment, and CPU
module std.system;
const
{
// Operating system family
enum Family
{
Win32 = 1, // Microsoft 32 bit Windows systems
linux, // all linux systems
Unix, // Unix-like
NoSystem // No operating system
}
version (Win32)
{
Family family = Family.Win32;
}
else version (linux)
{
Family family = Family.linux;
}
else version (Unix)
{
Family family = Family.Unix;
}
else version (NoSystem)
{
Family family = Family.NoSystem;
}
else
{
static assert(0);
}
// More specific operating system name
enum OS
{
Windows95 = 1,
Windows98,
WindowsME,
WindowsNT,
Windows2000,
WindowsXP,
RedHatLinux,
}
/// Byte order endianness
enum Endian
{
BigEndian, /// big endian byte order
LittleEndian /// little endian byte order
}
version(LittleEndian)
{
/// Native system endianness
Endian endian = Endian.LittleEndian;
}
else
{
Endian endian = Endian.BigEndian;
}
}
// The rest should get filled in dynamically at runtime
OS os = OS.WindowsXP;
// Operating system version as in
// os_major.os_minor
uint os_major = 4;
uint os_minor = 0;

View File

@@ -658,7 +658,7 @@ class Thread
}
state = TS.RUNNING;
//printf("creating thread x%x\n", this);
printf("creating thread x%x\n", this);
//result = pthread_create(&id, null, &threadstart, this);
// Create with thread attributes to allow non-default stack size - Dave Fladebo
int result = pthread_create(&id, &threadAttrs, &threadstart, cast(void*)this);
@@ -668,7 +668,7 @@ class Thread
idx = -1;
error("failed to start"); // BUG: should report errno
}
//printf("t = x%x, id = %d\n", this, id);
printf("t = x%x, id = %d\n", this, id);
}
int run()

View File

@@ -127,37 +127,14 @@ unittest
assert(is (TL[1] == I));
}
/* *******************************************
*/
template isStaticArray_impl(T)
{
const T inst = void;
static if (is(typeof(T.length)))
{
static if (!is(typeof(T) == typeof(T.init)))
{ // abuses the fact that int[5].init == int
static if (is(T == typeof(T[0])[inst.length]))
{ // sanity check. this check alone isn't enough because dmd complains about dynamic arrays
const bool res = true;
}
else
const bool res = false;
}
else
const bool res = false;
}
else
{
const bool res = false;
}
}
/**
* Detect whether type T is a static array.
*/
template isStaticArray(T)
{
const bool isStaticArray = isStaticArray_impl!(T).res;
static if (isArray!(T))
const bool isStaticArray = !is(T == typeof(T[0])[]);
else const bool isStaticArray = false;
}

520
lphobos/std/zip.d Normal file
View File

@@ -0,0 +1,520 @@
/**
* Read/write data in the $(LINK2 http://www.info-_zip.org, zip archive) format.
* Makes use of the etc.c.zlib compression library.
*
* Bugs:
* $(UL
* $(LI Multi-disk zips not supported.)
* $(LI Only Zip version 20 formats are supported.)
* $(LI Only supports compression modes 0 (no compression) and 8 (deflate).)
* $(LI Does not support encryption.)
* )
*
* Macros:
* WIKI = Phobos/StdZip
*/
module std.zip;
private import std.zlib;
private import std.date;
private import std.intrinsic;
//debug=print;
/** Thrown on error.
*/
class ZipException : Exception
{
this(char[] msg)
{
super("ZipException: " ~ msg);
}
}
/**
* A member of the ZipArchive.
*/
class ArchiveMember
{
ushort madeVersion = 20; /// Read Only
ushort extractVersion = 20; /// Read Only
ushort flags; /// Read/Write: normally set to 0
ushort compressionMethod; /// Read/Write: 0 for compression, 8 for deflate
std.date.DosFileTime time; /// Read/Write: Last modified time of the member. It's in the DOS date/time format.
uint crc32; /// Read Only: cyclic redundancy check (CRC) value
uint compressedSize; /// Read Only: size of data of member in compressed form.
uint expandedSize; /// Read Only: size of data of member in expanded form.
ushort diskNumber; /// Read Only: should be 0.
ushort internalAttributes; /// Read/Write
uint externalAttributes; /// Read/Write
private uint offset;
/**
* Read/Write: Usually the file name of the archive member; it is used to
* index the archive directory for the member. Each member must have a unique
* name[]. Do not change without removing member from the directory first.
*/
char[] name;
ubyte[] extra; /// Read/Write: extra data for this member.
char[] comment; /// Read/Write: comment associated with this member.
ubyte[] compressedData; /// Read Only: data of member in compressed form.
ubyte[] expandedData; /// Read/Write: data of member in uncompressed form.
debug(print)
{
void print()
{
printf("name = '%.*s'\n", cast(int) name.length, name.ptr);
printf("\tcomment = '%.*s'\n", cast(int) comment.length, comment.ptr);
printf("\tmadeVersion = x%04x\n", madeVersion);
printf("\textractVersion = x%04x\n", extractVersion);
printf("\tflags = x%04x\n", flags);
printf("\tcompressionMethod = %d\n", compressionMethod);
printf("\ttime = %d\n", time);
printf("\tcrc32 = x%08x\n", crc32);
printf("\texpandedSize = %d\n", expandedSize);
printf("\tcompressedSize = %d\n", compressedSize);
printf("\tinternalAttributes = x%04x\n", internalAttributes);
printf("\texternalAttributes = x%08x\n", externalAttributes);
}
}
}
/**
* Object representing the entire archive.
* ZipArchives are collections of ArchiveMembers.
*/
class ZipArchive
{
ubyte[] data; /// Read Only: array representing the entire contents of the archive.
uint endrecOffset;
uint diskNumber; /// Read Only: 0 since multi-disk zip archives are not supported.
uint diskStartDir; /// Read Only: 0 since multi-disk zip archives are not supported.
uint numEntries; /// Read Only: number of ArchiveMembers in the directory.
uint totalEntries; /// Read Only: same as totalEntries.
char[] comment; /// Read/Write: the archive comment. Must be less than 65536 bytes in length.
/**
* Read Only: array indexed by the name of each member of the archive.
* Example:
* All the members of the archive can be accessed with a foreach loop:
* --------------------
* ZipArchive archive = new ZipArchive(data);
* foreach (ArchiveMember am; archive.directory)
* {
* writefln("member name is '%s'", am.name);
* }
* --------------------
*/
ArchiveMember[char[]] directory;
debug (print)
{
void print()
{
printf("\tdiskNumber = %u\n", diskNumber);
printf("\tdiskStartDir = %u\n", diskStartDir);
printf("\tnumEntries = %u\n", numEntries);
printf("\ttotalEntries = %u\n", totalEntries);
printf("\tcomment = '%.*s'\n", cast(int) comment.length, comment.ptr);
}
}
/* ============ Creating a new archive =================== */
/** Constructor to use when creating a new archive.
*/
this()
{
}
/** Add de to the archive.
*/
void addMember(ArchiveMember de)
{
directory[de.name] = de;
}
/** Delete de from the archive.
*/
void deleteMember(ArchiveMember de)
{
directory.remove(de.name);
}
/**
* Construct an archive out of the current members of the archive.
*
* Fills in the properties data[], diskNumber, diskStartDir, numEntries,
* totalEntries, and directory[].
* For each ArchiveMember, fills in properties crc32, compressedSize,
* compressedData[].
*
* Returns: array representing the entire archive.
*/
void[] build()
{ uint i;
uint directoryOffset;
if (comment.length > 0xFFFF)
throw new ZipException("archive comment longer than 65535");
// Compress each member; compute size
uint archiveSize = 0;
uint directorySize = 0;
foreach (ArchiveMember de; directory)
{
de.expandedSize = de.expandedData.length;
switch (de.compressionMethod)
{
case 0:
de.compressedData = de.expandedData;
break;
case 8:
de.compressedData = cast(ubyte[])std.zlib.compress(cast(void[])de.expandedData);
de.compressedData = de.compressedData[2 .. de.compressedData.length - 4];
break;
default:
throw new ZipException("unsupported compression method");
}
de.compressedSize = de.compressedData.length;
de.crc32 = std.zlib.crc32(0, cast(void[])de.expandedData);
archiveSize += 30 + de.name.length +
de.extra.length +
de.compressedSize;
directorySize += 46 + de.name.length +
de.extra.length +
de.comment.length;
}
data = new ubyte[archiveSize + directorySize + 22 + comment.length];
// Populate the data[]
// Store each archive member
i = 0;
foreach (ArchiveMember de; directory)
{
de.offset = i;
data[i .. i + 4] = cast(ubyte[])"PK\x03\x04";
putUshort(i + 4, de.extractVersion);
putUshort(i + 6, de.flags);
putUshort(i + 8, de.compressionMethod);
putUint (i + 10, cast(uint)de.time);
putUint (i + 14, de.crc32);
putUint (i + 18, de.compressedSize);
putUint (i + 22, de.expandedData.length);
putUshort(i + 26, cast(ushort)de.name.length);
putUshort(i + 28, cast(ushort)de.extra.length);
i += 30;
data[i .. i + de.name.length] = cast(ubyte[])de.name[];
i += de.name.length;
data[i .. i + de.extra.length] = cast(ubyte[])de.extra[];
i += de.extra.length;
data[i .. i + de.compressedSize] = de.compressedData[];
i += de.compressedSize;
}
// Write directory
directoryOffset = i;
numEntries = 0;
foreach (ArchiveMember de; directory)
{
data[i .. i + 4] = cast(ubyte[])"PK\x01\x02";
putUshort(i + 4, de.madeVersion);
putUshort(i + 6, de.extractVersion);
putUshort(i + 8, de.flags);
putUshort(i + 10, de.compressionMethod);
putUint (i + 12, cast(uint)de.time);
putUint (i + 16, de.crc32);
putUint (i + 20, de.compressedSize);
putUint (i + 24, de.expandedSize);
putUshort(i + 28, cast(ushort)de.name.length);
putUshort(i + 30, cast(ushort)de.extra.length);
putUshort(i + 32, cast(ushort)de.comment.length);
putUshort(i + 34, de.diskNumber);
putUshort(i + 36, de.internalAttributes);
putUint (i + 38, de.externalAttributes);
putUint (i + 42, de.offset);
i += 46;
data[i .. i + de.name.length] = cast(ubyte[])de.name[];
i += de.name.length;
data[i .. i + de.extra.length] = cast(ubyte[])de.extra[];
i += de.extra.length;
data[i .. i + de.comment.length] = cast(ubyte[])de.comment[];
i += de.comment.length;
numEntries++;
}
totalEntries = numEntries;
// Write end record
endrecOffset = i;
data[i .. i + 4] = cast(ubyte[])"PK\x05\x06";
putUshort(i + 4, cast(ushort)diskNumber);
putUshort(i + 6, cast(ushort)diskStartDir);
putUshort(i + 8, cast(ushort)numEntries);
putUshort(i + 10, cast(ushort)totalEntries);
putUint (i + 12, directorySize);
putUint (i + 16, directoryOffset);
putUshort(i + 20, cast(ushort)comment.length);
i += 22;
// Write archive comment
assert(i + comment.length == data.length);
data[i .. data.length] = cast(ubyte[])comment[];
return cast(void[])data;
}
/* ============ Reading an existing archive =================== */
/**
* Constructor to use when reading an existing archive.
*
* Fills in the properties data[], diskNumber, diskStartDir, numEntries,
* totalEntries, comment[], and directory[].
* For each ArchiveMember, fills in
* properties madeVersion, extractVersion, flags, compressionMethod, time,
* crc32, compressedSize, expandedSize, compressedData[], diskNumber,
* internalAttributes, externalAttributes, name[], extra[], comment[].
* Use expand() to get the expanded data for each ArchiveMember.
*
* Params:
* buffer = the entire contents of the archive.
*/
this(void[] buffer)
{ int iend;
int i;
int endcommentlength;
uint directorySize;
uint directoryOffset;
this.data = cast(ubyte[]) buffer;
// Find 'end record index' by searching backwards for signature
iend = data.length - 66000;
if (iend < 0)
iend = 0;
for (i = data.length - 22; 1; i--)
{
if (i < iend)
throw new ZipException("no end record");
if (data[i .. i + 4] == cast(ubyte[])"PK\x05\x06")
{
endcommentlength = getUshort(i + 20);
if (i + 22 + endcommentlength > data.length)
continue;
comment = cast(char[])data[i + 22 .. i + 22 + endcommentlength];
endrecOffset = i;
break;
}
}
// Read end record data
diskNumber = getUshort(i + 4);
diskStartDir = getUshort(i + 6);
numEntries = getUshort(i + 8);
totalEntries = getUshort(i + 10);
if (numEntries != totalEntries)
throw new ZipException("multiple disk zips not supported");
directorySize = getUint(i + 12);
directoryOffset = getUint(i + 16);
if (directoryOffset + directorySize > i)
throw new ZipException("corrupted directory");
i = directoryOffset;
for (int n = 0; n < numEntries; n++)
{
/* The format of an entry is:
* 'PK' 1, 2
* directory info
* path
* extra data
* comment
*/
uint offset;
uint namelen;
uint extralen;
uint commentlen;
if (data[i .. i + 4] != cast(ubyte[])"PK\x01\x02")
throw new ZipException("invalid directory entry 1");
ArchiveMember de = new ArchiveMember();
de.madeVersion = getUshort(i + 4);
de.extractVersion = getUshort(i + 6);
de.flags = getUshort(i + 8);
de.compressionMethod = getUshort(i + 10);
de.time = cast(DosFileTime)getUint(i + 12);
de.crc32 = getUint(i + 16);
de.compressedSize = getUint(i + 20);
de.expandedSize = getUint(i + 24);
namelen = getUshort(i + 28);
extralen = getUshort(i + 30);
commentlen = getUshort(i + 32);
de.diskNumber = getUshort(i + 34);
de.internalAttributes = getUshort(i + 36);
de.externalAttributes = getUint(i + 38);
de.offset = getUint(i + 42);
i += 46;
if (i + namelen + extralen + commentlen > directoryOffset + directorySize)
throw new ZipException("invalid directory entry 2");
de.name = cast(char[])data[i .. i + namelen];
i += namelen;
de.extra = data[i .. i + extralen];
i += extralen;
de.comment = cast(char[])data[i .. i + commentlen];
i += commentlen;
directory[de.name] = de;
}
if (i != directoryOffset + directorySize)
throw new ZipException("invalid directory entry 3");
}
/*****
* Decompress the contents of archive member de and return the expanded
* data.
*
* Fills in properties extractVersion, flags, compressionMethod, time,
* crc32, compressedSize, expandedSize, expandedData[], name[], extra[].
*/
ubyte[] expand(ArchiveMember de)
{ uint namelen;
uint extralen;
if (data[de.offset .. de.offset + 4] != cast(ubyte[])"PK\x03\x04")
throw new ZipException("invalid directory entry 4");
// These values should match what is in the main zip archive directory
de.extractVersion = getUshort(de.offset + 4);
de.flags = getUshort(de.offset + 6);
de.compressionMethod = getUshort(de.offset + 8);
de.time = cast(DosFileTime)getUint(de.offset + 10);
de.crc32 = getUint(de.offset + 14);
de.compressedSize = getUint(de.offset + 18);
de.expandedSize = getUint(de.offset + 22);
namelen = getUshort(de.offset + 26);
extralen = getUshort(de.offset + 28);
debug(print)
{
printf("\t\texpandedSize = %d\n", de.expandedSize);
printf("\t\tcompressedSize = %d\n", de.compressedSize);
printf("\t\tnamelen = %d\n", namelen);
printf("\t\textralen = %d\n", extralen);
}
if (de.flags & 1)
throw new ZipException("encryption not supported");
int i;
i = de.offset + 30 + namelen + extralen;
if (i + de.compressedSize > endrecOffset)
throw new ZipException("invalid directory entry 5");
de.compressedData = data[i .. i + de.compressedSize];
debug(print) arrayPrint(de.compressedData);
switch (de.compressionMethod)
{
case 0:
de.expandedData = de.compressedData;
return de.expandedData;
case 8:
// -15 is a magic value used to decompress zip files.
// It has the effect of not requiring the 2 byte header
// and 4 byte trailer.
de.expandedData = cast(ubyte[])std.zlib.uncompress(cast(void[])de.compressedData, de.expandedSize, -15);
return de.expandedData;
default:
throw new ZipException("unsupported compression method");
}
assert(0);
}
/* ============ Utility =================== */
ushort getUshort(int i)
{
version (LittleEndian)
{
return *cast(ushort *)&data[i];
}
else
{
ubyte b0 = data[i];
ubyte b1 = data[i + 1];
return (b1 << 8) | b0;
}
}
uint getUint(int i)
{
version (LittleEndian)
{
return *cast(uint *)&data[i];
}
else
{
return bswap(*cast(uint *)&data[i]);
}
}
void putUshort(int i, ushort us)
{
version (LittleEndian)
{
*cast(ushort *)&data[i] = us;
}
else
{
data[i] = cast(ubyte)us;
data[i + 1] = cast(ubyte)(us >> 8);
}
}
void putUint(int i, uint ui)
{
version (BigEndian)
{
ui = bswap(ui);
}
*cast(uint *)&data[i] = ui;
}
}
debug(print)
{
void arrayPrint(ubyte[] array)
{
printf("array %p,%d\n", cast(void*)array, array.length);
for (int i = 0; i < array.length; i++)
{
printf("%02x ", array[i]);
if (((i + 1) & 15) == 0)
printf("\n");
}
printf("\n");
}
}

618
lphobos/std/zlib.d Normal file
View File

@@ -0,0 +1,618 @@
/**
* Compress/decompress data using the $(LINK2 http://www._zlib.net, zlib library).
*
* References:
* $(LINK2 http://en.wikipedia.org/wiki/Zlib, Wikipedia)
* License:
* Public Domain
*
* Macros:
* WIKI = Phobos/StdZlib
*/
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
Modified by David Friedman, February 2007
*/
module std.zlib;
//debug=zlib; // uncomment to turn on debugging printf's
private import etc.c.zlib, std.stdint;
// Values for 'mode'
enum
{
Z_NO_FLUSH = 0,
Z_SYNC_FLUSH = 2,
Z_FULL_FLUSH = 3,
Z_FINISH = 4,
}
/*************************************
* Errors throw a ZlibException.
*/
class ZlibException : Exception
{
this(int errnum)
{ char[] msg;
switch (errnum)
{
case Z_STREAM_END: msg = "stream end"; break;
case Z_NEED_DICT: msg = "need dict"; break;
case Z_ERRNO: msg = "errno"; break;
case Z_STREAM_ERROR: msg = "stream error"; break;
case Z_DATA_ERROR: msg = "data error"; break;
case Z_MEM_ERROR: msg = "mem error"; break;
case Z_BUF_ERROR: msg = "buf error"; break;
case Z_VERSION_ERROR: msg = "version error"; break;
default: msg = "unknown error"; break;
}
super(msg);
}
}
/**************************************************
* Compute the Adler32 checksum of the data in buf[]. adler is the starting
* value when computing a cumulative checksum.
*/
uint adler32(uint adler, void[] buf)
{
return etc.c.zlib.adler32(adler, cast(ubyte *)buf, buf.length);
}
unittest
{
static ubyte[] data = [1,2,3,4,5,6,7,8,9,10];
uint adler;
debug(zlib) printf("D.zlib.adler32.unittest\n");
adler = adler32(0u, cast(void[])data);
debug(zlib) printf("adler = %x\n", adler);
assert(adler == 0xdc0037);
}
/*********************************
* Compute the CRC32 checksum of the data in buf[]. crc is the starting value
* when computing a cumulative checksum.
*/
uint crc32(uint crc, void[] buf)
{
return etc.c.zlib.crc32(crc, cast(ubyte *)buf, buf.length);
}
unittest
{
static ubyte[] data = [1,2,3,4,5,6,7,8,9,10];
uint crc;
debug(zlib) printf("D.zlib.crc32.unittest\n");
crc = crc32(0u, cast(void[])data);
debug(zlib) printf("crc = %x\n", crc);
assert(crc == 0x2520577b);
}
/*********************************************
* Compresses the data in srcbuf[] using compression _level level.
* The default value
* for level is 6, legal values are 1..9, with 1 being the least compression
* and 9 being the most.
* Returns the compressed data.
*/
void[] compress(void[] srcbuf, int level)
in
{
assert(-1 <= level && level <= 9);
}
body
{
int err;
ubyte[] destbuf;
Culong_t destlen;
destlen = srcbuf.length + ((srcbuf.length + 1023) / 1024) + 12;
destbuf = new ubyte[destlen];
err = etc.c.zlib.compress2(destbuf.ptr, &destlen, cast(ubyte *)srcbuf, srcbuf.length, level);
if (err)
{ delete destbuf;
throw new ZlibException(err);
}
destbuf.length = destlen;
return destbuf;
}
/*********************************************
* ditto
*/
void[] compress(void[] buf)
{
return compress(buf, Z_DEFAULT_COMPRESSION);
}
/*********************************************
* Decompresses the data in srcbuf[].
* Params: destlen = size of the uncompressed data.
* It need not be accurate, but the decompression will be faster if the exact
* size is supplied.
* Returns: the decompressed data.
*/
void[] uncompress(void[] srcbuf, size_t destlen = 0u, int winbits = 15)
{
int err;
ubyte[] destbuf;
if (!destlen)
destlen = srcbuf.length * 2 + 1;
while (1)
{
etc.c.zlib.z_stream zs;
destbuf = new ubyte[destlen];
zs.next_in = cast(ubyte*) srcbuf;
zs.avail_in = srcbuf.length;
zs.next_out = destbuf.ptr;
zs.avail_out = destlen;
err = etc.c.zlib.inflateInit2(&zs, winbits);
if (err)
{ delete destbuf;
throw new ZlibException(err);
}
err = etc.c.zlib.inflate(&zs, Z_NO_FLUSH);
switch (err)
{
case Z_OK:
etc.c.zlib.inflateEnd(&zs);
destlen = destbuf.length * 2;
continue;
case Z_STREAM_END:
destbuf.length = zs.total_out;
err = etc.c.zlib.inflateEnd(&zs);
if (err != Z_OK)
goto Lerr;
return destbuf;
default:
etc.c.zlib.inflateEnd(&zs);
Lerr:
delete destbuf;
throw new ZlibException(err);
}
}
assert(0);
}
unittest
{
ubyte[] src = cast(ubyte[])
"the quick brown fox jumps over the lazy dog\r
the quick brown fox jumps over the lazy dog\r
";
ubyte[] dst;
ubyte[] result;
//arrayPrint(src);
dst = cast(ubyte[])compress(cast(void[])src);
//arrayPrint(dst);
result = cast(ubyte[])uncompress(cast(void[])dst);
//arrayPrint(result);
assert(result == src);
}
/+
void arrayPrint(ubyte[] array)
{
//printf("array %p,%d\n", (void*)array, array.length);
for (int i = 0; i < array.length; i++)
{
printf("%02x ", array[i]);
if (((i + 1) & 15) == 0)
printf("\n");
}
printf("\n\n");
}
+/
/*********************************************
* Used when the data to be compressed is not all in one buffer.
*/
class Compress
{
private:
z_stream zs;
int level = Z_DEFAULT_COMPRESSION;
int inited;
void error(int err)
{
if (inited)
{ deflateEnd(&zs);
inited = 0;
}
throw new ZlibException(err);
}
public:
/**
* Construct. level is the same as for D.zlib.compress().
*/
this(int level)
in
{
assert(1 <= level && level <= 9);
}
body
{
this.level = level;
}
/// ditto
this()
{
}
~this()
{ int err;
if (inited)
{
inited = 0;
err = deflateEnd(&zs);
if (err)
error(err);
}
}
/**
* Compress the data in buf and return the compressed data.
* The buffers
* returned from successive calls to this should be concatenated together.
*/
void[] compress(void[] buf)
{ int err;
ubyte[] destbuf;
if (buf.length == 0)
return null;
if (!inited)
{
err = deflateInit(&zs, level);
if (err)
error(err);
inited = 1;
}
destbuf = new ubyte[zs.avail_in + buf.length];
zs.next_out = destbuf.ptr;
zs.avail_out = destbuf.length;
if (zs.avail_in)
buf = cast(void[])zs.next_in[0 .. zs.avail_in] ~ buf;
zs.next_in = cast(ubyte*) buf.ptr;
zs.avail_in = buf.length;
err = deflate(&zs, Z_NO_FLUSH);
if (err != Z_STREAM_END && err != Z_OK)
{ delete destbuf;
error(err);
}
destbuf.length = destbuf.length - zs.avail_out;
return destbuf;
}
/***
* Compress and return any remaining data.
* The returned data should be appended to that returned by compress().
* Params:
* mode = one of the following:
* $(DL
$(DT Z_SYNC_FLUSH )
$(DD Syncs up flushing to the next byte boundary.
Used when more data is to be compressed later on.)
$(DT Z_FULL_FLUSH )
$(DD Syncs up flushing to the next byte boundary.
Used when more data is to be compressed later on,
and the decompressor needs to be restartable at this
point.)
$(DT Z_FINISH)
$(DD (default) Used when finished compressing the data. )
)
*/
void[] flush(int mode = Z_FINISH)
in
{
assert(mode == Z_FINISH || mode == Z_SYNC_FLUSH || mode == Z_FULL_FLUSH);
}
body
{
void[] destbuf;
ubyte[512] tmpbuf = void;
int err;
if (!inited)
return null;
/* may be zs.avail_out+<some constant>
* zs.avail_out is set nonzero by deflate in previous compress()
*/
//tmpbuf = new void[zs.avail_out];
zs.next_out = tmpbuf.ptr;
zs.avail_out = tmpbuf.length;
while( (err = deflate(&zs, mode)) != Z_STREAM_END)
{
if (err == Z_OK)
{
if (zs.avail_out != 0 && mode != Z_FINISH)
break;
else if(zs.avail_out == 0)
{
destbuf ~= tmpbuf;
zs.next_out = tmpbuf.ptr;
zs.avail_out = tmpbuf.length;
continue;
}
err = Z_BUF_ERROR;
}
delete destbuf;
error(err);
}
destbuf ~= tmpbuf[0 .. (tmpbuf.length - zs.avail_out)];
if (mode == Z_FINISH)
{
err = deflateEnd(&zs);
inited = 0;
if (err)
error(err);
}
return destbuf;
}
}
/******
* Used when the data to be decompressed is not all in one buffer.
*/
class UnCompress
{
private:
z_stream zs;
int inited;
int done;
uint destbufsize;
void error(int err)
{
if (inited)
{ inflateEnd(&zs);
inited = 0;
}
throw new ZlibException(err);
}
public:
/**
* Construct. destbufsize is the same as for D.zlib.uncompress().
*/
this(uint destbufsize)
{
this.destbufsize = destbufsize;
}
/** ditto */
this()
{
}
~this()
{ int err;
if (inited)
{
inited = 0;
err = inflateEnd(&zs);
if (err)
error(err);
}
done = 1;
}
/**
* Decompress the data in buf and return the decompressed data.
* The buffers returned from successive calls to this should be concatenated
* together.
*/
void[] uncompress(void[] buf)
in
{
assert(!done);
}
body
{ int err;
ubyte[] destbuf;
if (buf.length == 0)
return null;
if (!inited)
{
err = inflateInit(&zs);
if (err)
error(err);
inited = 1;
}
if (!destbufsize)
destbufsize = buf.length * 2;
destbuf = new ubyte[zs.avail_in * 2 + destbufsize];
zs.next_out = destbuf.ptr;
zs.avail_out = destbuf.length;
if (zs.avail_in)
buf = cast(void[])zs.next_in[0 .. zs.avail_in] ~ buf;
zs.next_in = cast(ubyte*) buf;
zs.avail_in = buf.length;
err = inflate(&zs, Z_NO_FLUSH);
if (err != Z_STREAM_END && err != Z_OK)
{ delete destbuf;
error(err);
}
destbuf.length = destbuf.length - zs.avail_out;
return destbuf;
}
/**
* Decompress and return any remaining data.
* The returned data should be appended to that returned by uncompress().
* The UnCompress object cannot be used further.
*/
void[] flush()
in
{
assert(!done);
}
out
{
assert(done);
}
body
{
ubyte[] extra;
ubyte[] destbuf;
int err;
done = 1;
if (!inited)
return null;
L1:
destbuf = new ubyte[zs.avail_in * 2 + 100];
zs.next_out = destbuf.ptr;
zs.avail_out = destbuf.length;
err = etc.c.zlib.inflate(&zs, Z_NO_FLUSH);
if (err == Z_OK && zs.avail_out == 0)
{
extra ~= destbuf;
goto L1;
}
if (err != Z_STREAM_END)
{
delete destbuf;
if (err == Z_OK)
err = Z_BUF_ERROR;
error(err);
}
destbuf = destbuf.ptr[0 .. zs.next_out - destbuf.ptr];
err = etc.c.zlib.inflateEnd(&zs);
inited = 0;
if (err)
error(err);
if (extra.length)
destbuf = extra ~ destbuf;
return destbuf;
}
}
/* ========================== unittest ========================= */
private import std.stdio;
private import std.random;
unittest // by Dave
{
debug(zlib) printf("std.zlib.unittest\n");
bool CompressThenUncompress (ubyte[] src)
{
try {
ubyte[] dst = cast(ubyte[])std.zlib.compress(cast(void[])src);
double ratio = (dst.length / cast(double)src.length);
debug(zlib) writef("src.length: ", src.length, ", dst: ", dst.length, ", Ratio = ", ratio);
ubyte[] uncompressedBuf;
uncompressedBuf = cast(ubyte[])std.zlib.uncompress(cast(void[])dst);
assert(src.length == uncompressedBuf.length);
assert(src == uncompressedBuf);
}
catch {
debug(zlib) writefln(" ... Exception thrown when src.length = ", src.length, ".");
return false;
}
return true;
}
// smallish buffers
for(int idx = 0; idx < 25; idx++) {
char[] buf = new char[rand() % 100];
// Alternate between more & less compressible
foreach(inout char c; buf) c = ' ' + (rand() % (idx % 2 ? 91 : 2));
if(CompressThenUncompress(cast(ubyte[])buf)) {
debug(zlib) printf("; Success.\n");
} else {
return;
}
}
// larger buffers
for(int idx = 0; idx < 25; idx++) {
char[] buf = new char[rand() % 1000/*0000*/];
// Alternate between more & less compressible
foreach(inout char c; buf) c = ' ' + (rand() % (idx % 2 ? 91 : 10));
if(CompressThenUncompress(cast(ubyte[])buf)) {
debug(zlib) printf("; Success.\n");
} else {
return;
}
}
debug(zlib) printf("PASSED std.zlib.unittest\n");
}
unittest // by Artem Rebrov
{
Compress cmp = new Compress;
UnCompress decmp = new UnCompress;
void[] input;
input = "tesatdffadf";
void[] buf = cmp.compress(input);
buf ~= cmp.flush();
void[] output = decmp.uncompress(buf);
//writefln("input = '%s'", cast(char[])input);
//writefln("output = '%s'", cast(char[])output);
assert( output[] == input[] );
}

View File

@@ -3,6 +3,7 @@
module typeinfo1.ti_float;
import std.gc: malloc;
class TypeInfo_f : TypeInfo
{
char[] toString() { return "float"; }
@@ -62,9 +63,8 @@ class TypeInfo_f : TypeInfo
}
void[] init()
{ static float r;
return (&r)[0 .. 1];
{
return (cast(float*)malloc(float.sizeof))[0..1];
}
}