mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-03-03 19:13:15 +01:00
Applied downs' lphobos update
This commit is contained in:
@@ -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
1215
lphobos/etc/c/zlib.d
Normal file
File diff suppressed because it is too large
Load Diff
1179
lphobos/gc/gc.d
1179
lphobos/gc/gc.d
File diff suppressed because it is too large
Load Diff
3
lphobos/gc/gc_guess_stack.d
Normal file
3
lphobos/gc/gc_guess_stack.d
Normal file
@@ -0,0 +1,3 @@
|
||||
module gcc.gc_guess_stack;
|
||||
void * stackOriginGuess;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
2628
lphobos/gc/gcx.d
2628
lphobos/gc/gcx.d
File diff suppressed because it is too large
Load Diff
168
lphobos/gc/win32.d
Normal file
168
lphobos/gc/win32.d
Normal 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
5
lphobos/hello.d
Normal file
@@ -0,0 +1,5 @@
|
||||
module hello;
|
||||
|
||||
import std.stdio;
|
||||
|
||||
void main() { writefln("Hello World"); }
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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~"\"");
|
||||
}
|
||||
|
||||
49
lphobos/internal/critical.d
Normal file
49
lphobos/internal/critical.d
Normal 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
122
lphobos/internal/dmain2.d
Normal 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
374
lphobos/internal/eh.d
Normal 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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import std.c.stdlib;
|
||||
|
||||
pragma(LLVM_internal, "notypeinfo")
|
||||
pragma(no_typeinfo)
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
|
||||
@@ -422,5 +422,7 @@ unittest
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _d_switch_error(string fn, int line)
|
||||
{
|
||||
throw new Exception(fn~toString(line)~": switch missing default");
|
||||
}
|
||||
|
||||
@@ -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> )
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
955
lphobos/std/bitarray.d
Normal 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 & ~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 &= ~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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
246
lphobos/std/c/windows/com.d
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
49
lphobos/std/c/windows/stat.d
Normal file
49
lphobos/std/c/windows/stat.d
Normal 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 *);
|
||||
}
|
||||
2722
lphobos/std/c/windows/windows.d
Normal file
2722
lphobos/std/c/windows/windows.d
Normal file
File diff suppressed because it is too large
Load Diff
540
lphobos/std/c/windows/winsock.d
Normal file
540
lphobos/std/c/windows/winsock.d
Normal 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
228
lphobos/std/cstream.d
Normal 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
1074
lphobos/std/date.d
Normal file
File diff suppressed because it is too large
Load Diff
1074
lphobos/std/date.d~
Normal file
1074
lphobos/std/date.d~
Normal file
File diff suppressed because it is too large
Load Diff
788
lphobos/std/dateparse.d
Normal file
788
lphobos/std/dateparse.d
Normal 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
1588
lphobos/std/file.d
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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
504
lphobos/std/md5.d
Normal 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
648
lphobos/std/mmfile.d
Normal 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");
|
||||
}
|
||||
}
|
||||
@@ -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
368
lphobos/std/outbuffer.d
Normal 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
1252
lphobos/std/path.d
Normal file
File diff suppressed because it is too large
Load Diff
293
lphobos/std/process.d
Normal file
293
lphobos/std/process.d
Normal 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
161
lphobos/std/random.d
Normal 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
3208
lphobos/std/regexp.d
Normal file
File diff suppressed because it is too large
Load Diff
1666
lphobos/std/socket.d
Normal file
1666
lphobos/std/socket.d
Normal file
File diff suppressed because it is too large
Load Diff
2961
lphobos/std/stream.d
Normal file
2961
lphobos/std/stream.d
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
95
lphobos/std/system.d
Normal 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;
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
520
lphobos/std/zip.d
Normal 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
618
lphobos/std/zlib.d
Normal 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[] );
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user