mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 10:53:14 +01:00
Removed Phobos 1 from LDC tree.
If anyone wanted to ever resurrect LDC1/Phobos (lphobos/README.txt had an »unmaintained« notice for more than three years now), this should be done in an external repository.
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
|
||||
[Environment]
|
||||
|
||||
DFLAGS=-I%@P%/../lphobos -L-L%@P%/../lib -R%@P%/../lib
|
||||
@@ -1,2 +0,0 @@
|
||||
The code in this directory is not maintained and is most likely broken.
|
||||
There are no plans to revive official Phobos support.
|
||||
104
lphobos/build.sh
104
lphobos/build.sh
@@ -1,104 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "removing old objects"
|
||||
mkdir -p obj
|
||||
rm -f obj/*.bc
|
||||
rm -f ../lib/*.bc
|
||||
|
||||
LDCFLAGS_ASM="-c -oq -release"
|
||||
LDCFLAGS="$LDCFLAGS_ASM -noasm"
|
||||
|
||||
echo "compiling contract runtime"
|
||||
ldc internal/contract.d -c -of../lib/ldcore.bc || exit 1 #-noruntime || exit 1
|
||||
|
||||
echo "compiling common runtime"
|
||||
./ldc-build internal/arrays.d \
|
||||
internal/mem.d \
|
||||
internal/critical.d \
|
||||
internal/dmain2.d \
|
||||
internal/inv.d \
|
||||
$LDCFLAGS_ASM || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc obj/internal.*.bc ../lib/ldcore.bc
|
||||
|
||||
echo "compiling typeinfo 1"
|
||||
./ldc-build typeinfos1.d $LDCFLAGS || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc `ls obj/typeinfo1.*.bc` ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "compiling typeinfo 2"
|
||||
./ldc-build typeinfos2.d $LDCFLAGS || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc `ls obj/typeinfo2.*.bc` ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "compiling exceptions"
|
||||
./ldc-build internal/eh.d $LDCFLAGS -debug || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc obj/*eh.bc ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "compiling object/interface casting runtime support"
|
||||
ldc internal/cast.d $LDCFLAGS || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc obj/cast.bc ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "compiling string foreach/switch runtime support"
|
||||
ldc internal/aApply.d $LDCFLAGS || exit 1
|
||||
ldc internal/aApplyR.d $LDCFLAGS || exit 1
|
||||
ldc internal/switch.d $LDCFLAGS || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc obj/aApply.bc obj/aApplyR.bc obj/switch.bc ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "compiling array runtime support"
|
||||
ldc internal/qsort2.d internal/adi.d internal/aaA.d $LDCFLAGS || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc obj/qsort2.bc obj/adi.bc obj/aaA.bc ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "compiling object implementation"
|
||||
ldc internal/objectimpl.d $LDCFLAGS || exit 1
|
||||
mv object.bc objectimpl.bc
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc obj/objectimpl.bc ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "compiling crc32"
|
||||
ldc crc32.d $LDCFLAGS || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc ../lib/ldcore.bc obj/crc32.bc || exit 1
|
||||
|
||||
echo "compiling llvm runtime support"
|
||||
# ./ldc-build llvmsupport.d $LDCFLAGS || exit 1
|
||||
ldc llvmsupport.d -oq -c || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc `ls obj/llvm*.bc` ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "compiling garbage collector"
|
||||
cd gc
|
||||
ldc $(ls *.d |grep -v win32) $LDCFLAGS_ASM -I.. ||exit 1
|
||||
# ldc gclinux.d $LDCFLAGS -I.. || exit 1
|
||||
# ldc gcx.d $LDCFLAGS -I.. || exit 1
|
||||
# ldc gcbits.d $LDCFLAGS -I.. || exit 1
|
||||
# ldc gc.d -oq -c -I.. || exit 1
|
||||
mv std.gc.bc std_gc.bc
|
||||
mv *.bc ../obj
|
||||
# mv -v obj/*.bc ../obj
|
||||
cd ..
|
||||
llvm-link -f -o=../lib/ldcore.bc obj/gclinux.bc obj/gcx.bc obj/gcbits.bc obj/std_gc.bc ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "compiling phobos"
|
||||
./ldc-build phobos.d $LDCFLAGS || exit 1
|
||||
mv *.bc obj
|
||||
echo "linking phobos"
|
||||
# llvm-link -f -o=../lib/ldcore.bc `ls obj/std.*.bc` ../lib/ldcore.bc || exit 1
|
||||
for i in $(ls obj/std.*.bc); do
|
||||
echo $i
|
||||
llvm-link -f -o=../lib/ldcore.bc ../lib/ldcore.bc $i || exit 1
|
||||
done
|
||||
|
||||
echo "Compiling auxiliary"
|
||||
./ldc-build etc/c/zlib.d $LDCFLAGS || exit 1
|
||||
mv *.bc obj
|
||||
llvm-link -f -o=../lib/ldcore.bc `ls obj/etc.*.bc` ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "optimizing"
|
||||
opt -stats -p -f -std-compile-opts -o=../lib/ldcore.bc ../lib/ldcore.bc || exit 1
|
||||
|
||||
echo "SUCCESS"
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2002
|
||||
* Pavel "EvilOne" Minayev
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Author makes no representations about
|
||||
* the suitability of this software for any purpose. It is provided
|
||||
* "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
// CRC-32 calculation
|
||||
module crc32;
|
||||
|
||||
private uint[256] crc32_table =
|
||||
[
|
||||
0x00000000,0x77073096,0xee0e612c,0x990951ba,0x076dc419,0x706af48f,0xe963a535,
|
||||
0x9e6495a3,0x0edb8832,0x79dcb8a4,0xe0d5e91e,0x97d2d988,0x09b64c2b,0x7eb17cbd,
|
||||
0xe7b82d07,0x90bf1d91,0x1db71064,0x6ab020f2,0xf3b97148,0x84be41de,0x1adad47d,
|
||||
0x6ddde4eb,0xf4d4b551,0x83d385c7,0x136c9856,0x646ba8c0,0xfd62f97a,0x8a65c9ec,
|
||||
0x14015c4f,0x63066cd9,0xfa0f3d63,0x8d080df5,0x3b6e20c8,0x4c69105e,0xd56041e4,
|
||||
0xa2677172,0x3c03e4d1,0x4b04d447,0xd20d85fd,0xa50ab56b,0x35b5a8fa,0x42b2986c,
|
||||
0xdbbbc9d6,0xacbcf940,0x32d86ce3,0x45df5c75,0xdcd60dcf,0xabd13d59,0x26d930ac,
|
||||
0x51de003a,0xc8d75180,0xbfd06116,0x21b4f4b5,0x56b3c423,0xcfba9599,0xb8bda50f,
|
||||
0x2802b89e,0x5f058808,0xc60cd9b2,0xb10be924,0x2f6f7c87,0x58684c11,0xc1611dab,
|
||||
0xb6662d3d,0x76dc4190,0x01db7106,0x98d220bc,0xefd5102a,0x71b18589,0x06b6b51f,
|
||||
0x9fbfe4a5,0xe8b8d433,0x7807c9a2,0x0f00f934,0x9609a88e,0xe10e9818,0x7f6a0dbb,
|
||||
0x086d3d2d,0x91646c97,0xe6635c01,0x6b6b51f4,0x1c6c6162,0x856530d8,0xf262004e,
|
||||
0x6c0695ed,0x1b01a57b,0x8208f4c1,0xf50fc457,0x65b0d9c6,0x12b7e950,0x8bbeb8ea,
|
||||
0xfcb9887c,0x62dd1ddf,0x15da2d49,0x8cd37cf3,0xfbd44c65,0x4db26158,0x3ab551ce,
|
||||
0xa3bc0074,0xd4bb30e2,0x4adfa541,0x3dd895d7,0xa4d1c46d,0xd3d6f4fb,0x4369e96a,
|
||||
0x346ed9fc,0xad678846,0xda60b8d0,0x44042d73,0x33031de5,0xaa0a4c5f,0xdd0d7cc9,
|
||||
0x5005713c,0x270241aa,0xbe0b1010,0xc90c2086,0x5768b525,0x206f85b3,0xb966d409,
|
||||
0xce61e49f,0x5edef90e,0x29d9c998,0xb0d09822,0xc7d7a8b4,0x59b33d17,0x2eb40d81,
|
||||
0xb7bd5c3b,0xc0ba6cad,0xedb88320,0x9abfb3b6,0x03b6e20c,0x74b1d29a,0xead54739,
|
||||
0x9dd277af,0x04db2615,0x73dc1683,0xe3630b12,0x94643b84,0x0d6d6a3e,0x7a6a5aa8,
|
||||
0xe40ecf0b,0x9309ff9d,0x0a00ae27,0x7d079eb1,0xf00f9344,0x8708a3d2,0x1e01f268,
|
||||
0x6906c2fe,0xf762575d,0x806567cb,0x196c3671,0x6e6b06e7,0xfed41b76,0x89d32be0,
|
||||
0x10da7a5a,0x67dd4acc,0xf9b9df6f,0x8ebeeff9,0x17b7be43,0x60b08ed5,0xd6d6a3e8,
|
||||
0xa1d1937e,0x38d8c2c4,0x4fdff252,0xd1bb67f1,0xa6bc5767,0x3fb506dd,0x48b2364b,
|
||||
0xd80d2bda,0xaf0a1b4c,0x36034af6,0x41047a60,0xdf60efc3,0xa867df55,0x316e8eef,
|
||||
0x4669be79,0xcb61b38c,0xbc66831a,0x256fd2a0,0x5268e236,0xcc0c7795,0xbb0b4703,
|
||||
0x220216b9,0x5505262f,0xc5ba3bbe,0xb2bd0b28,0x2bb45a92,0x5cb36a04,0xc2d7ffa7,
|
||||
0xb5d0cf31,0x2cd99e8b,0x5bdeae1d,0x9b64c2b0,0xec63f226,0x756aa39c,0x026d930a,
|
||||
0x9c0906a9,0xeb0e363f,0x72076785,0x05005713,0x95bf4a82,0xe2b87a14,0x7bb12bae,
|
||||
0x0cb61b38,0x92d28e9b,0xe5d5be0d,0x7cdcefb7,0x0bdbdf21,0x86d3d2d4,0xf1d4e242,
|
||||
0x68ddb3f8,0x1fda836e,0x81be16cd,0xf6b9265b,0x6fb077e1,0x18b74777,0x88085ae6,
|
||||
0xff0f6a70,0x66063bca,0x11010b5c,0x8f659eff,0xf862ae69,0x616bffd3,0x166ccf45,
|
||||
0xa00ae278,0xd70dd2ee,0x4e048354,0x3903b3c2,0xa7672661,0xd06016f7,0x4969474d,
|
||||
0x3e6e77db,0xaed16a4a,0xd9d65adc,0x40df0b66,0x37d83bf0,0xa9bcae53,0xdebb9ec5,
|
||||
0x47b2cf7f,0x30b5ffe9,0xbdbdf21c,0xcabac28a,0x53b39330,0x24b4a3a6,0xbad03605,
|
||||
0xcdd70693,0x54de5729,0x23d967bf,0xb3667a2e,0xc4614ab8,0x5d681b02,0x2a6f2b94,
|
||||
0xb40bbe37,0xc30c8ea1,0x5a05df1b,0x2d02ef8d
|
||||
];
|
||||
|
||||
uint init_crc32()
|
||||
{
|
||||
return cast(uint)-1;
|
||||
}
|
||||
|
||||
uint update_crc32(ubyte val, uint crc)
|
||||
{
|
||||
return crc32_table[cast(ubyte) crc ^ val] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
uint update_crc32(char val, uint crc)
|
||||
{
|
||||
return update_crc32(cast(ubyte) val, crc);
|
||||
}
|
||||
|
||||
uint strcrc32(char[] s)
|
||||
{
|
||||
uint crc = init_crc32();
|
||||
for (size_t i = 0; i < s.length; i++)
|
||||
crc = update_crc32(s[i], crc);
|
||||
return crc;
|
||||
}
|
||||
1215
lphobos/etc/c/zlib.d
1215
lphobos/etc/c/zlib.d
File diff suppressed because it is too large
Load Diff
1034
lphobos/gc/gc.d
1034
lphobos/gc/gc.d
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
module gcc.gc_guess_stack;
|
||||
void * stackOriginGuess;
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
|
||||
// Copyright (C) 2001-2002 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
|
||||
*/
|
||||
|
||||
import std.c.string;
|
||||
import std.c.stdlib;
|
||||
import std.outofmemory;
|
||||
import std.intrinsic;
|
||||
|
||||
//version = Asm86;
|
||||
version (GNU) {
|
||||
// bitop intrinsics not implemented yet
|
||||
} else {
|
||||
version = bitops;
|
||||
}
|
||||
|
||||
|
||||
struct GCBits
|
||||
{
|
||||
const int BITS_PER_WORD = 32;
|
||||
const int BITS_SHIFT = 5;
|
||||
const int BITS_MASK = 31;
|
||||
|
||||
uint *data = null;
|
||||
uint nwords = 0; // allocated words in data[] excluding sentinals
|
||||
uint nbits = 0; // number of bits in data[] excluding sentinals
|
||||
|
||||
void Dtor()
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
free(data);
|
||||
data = null;
|
||||
}
|
||||
}
|
||||
|
||||
invariant
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
assert(nwords * data[0].sizeof * 8 >= nbits);
|
||||
}
|
||||
}
|
||||
|
||||
void alloc(uint nbits)
|
||||
{
|
||||
this.nbits = nbits;
|
||||
nwords = (nbits + (BITS_PER_WORD - 1)) >> BITS_SHIFT;
|
||||
data = cast(uint *)calloc(nwords + 2, uint.sizeof);
|
||||
if (!data)
|
||||
_d_OutOfMemory();
|
||||
}
|
||||
|
||||
uint test(uint i)
|
||||
in
|
||||
{
|
||||
assert(i < nbits);
|
||||
}
|
||||
body
|
||||
{
|
||||
//return (cast(bit *)(data + 1))[i];
|
||||
return data[1 + (i >> BITS_SHIFT)] & (1 << (i & BITS_MASK));
|
||||
}
|
||||
|
||||
void set(uint i)
|
||||
in
|
||||
{
|
||||
assert(i < nbits);
|
||||
}
|
||||
body
|
||||
{
|
||||
//(cast(bit *)(data + 1))[i] = 1;
|
||||
data[1 + (i >> BITS_SHIFT)] |= (1 << (i & BITS_MASK));
|
||||
}
|
||||
|
||||
void clear(uint i)
|
||||
in
|
||||
{
|
||||
assert(i < nbits);
|
||||
}
|
||||
body
|
||||
{
|
||||
//(cast(bit *)(data + 1))[i] = 0;
|
||||
data[1 + (i >> BITS_SHIFT)] &= ~(1 << (i & BITS_MASK));
|
||||
}
|
||||
|
||||
uint testClear(uint i)
|
||||
{
|
||||
version (bitops)
|
||||
{
|
||||
return std.intrinsic.btr(data + 1, i);
|
||||
}
|
||||
else version (Asm86)
|
||||
{
|
||||
asm
|
||||
{
|
||||
naked ;
|
||||
mov EAX,data[EAX] ;
|
||||
mov ECX,i-4[ESP] ;
|
||||
btr 4[EAX],ECX ;
|
||||
sbb EAX,EAX ;
|
||||
ret 4 ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ uint result;
|
||||
|
||||
//result = (cast(bit *)(data + 1))[i];
|
||||
//(cast(bit *)(data + 1))[i] = 0;
|
||||
|
||||
uint *p = &data[1 + (i >> BITS_SHIFT)];
|
||||
uint mask = (1 << (i & BITS_MASK));
|
||||
result = *p & mask;
|
||||
*p &= ~mask;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void zero()
|
||||
{
|
||||
memset(data + 1, 0, nwords * uint.sizeof);
|
||||
}
|
||||
|
||||
void copy(GCBits *f)
|
||||
in
|
||||
{
|
||||
assert(nwords == f.nwords);
|
||||
}
|
||||
body
|
||||
{
|
||||
memcpy(data + 1, f.data + 1, nwords * uint.sizeof);
|
||||
}
|
||||
|
||||
uint *base()
|
||||
in
|
||||
{
|
||||
assert(data);
|
||||
}
|
||||
body
|
||||
{
|
||||
return data + 1;
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
GCBits b;
|
||||
|
||||
b.alloc(786);
|
||||
assert(b.test(123) == 0);
|
||||
assert(b.testClear(123) == 0);
|
||||
b.set(123);
|
||||
assert(b.test(123) != 0);
|
||||
assert(b.testClear(123) != 0);
|
||||
assert(b.test(123) == 0);
|
||||
|
||||
b.set(785);
|
||||
b.set(0);
|
||||
assert(b.test(785) != 0);
|
||||
assert(b.test(0) != 0);
|
||||
b.zero();
|
||||
assert(b.test(785) == 0);
|
||||
assert(b.test(0) == 0);
|
||||
|
||||
GCBits b2;
|
||||
b2.alloc(786);
|
||||
b2.set(38);
|
||||
b.copy(&b2);
|
||||
assert(b.test(38) != 0);
|
||||
b2.Dtor();
|
||||
|
||||
b.Dtor();
|
||||
}
|
||||
|
||||
/+
|
||||
void main()
|
||||
{
|
||||
}
|
||||
+/
|
||||
@@ -1,107 +0,0 @@
|
||||
|
||||
// Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com
|
||||
// All Rights Reserved
|
||||
// Written by Walter Bright
|
||||
|
||||
import std.c.linux.linuxextern;
|
||||
import std.c.linux.linux;
|
||||
|
||||
/+
|
||||
extern (C)
|
||||
{
|
||||
// from <sys/mman.h>
|
||||
void* mmap(void* addr, uint len, int prot, int flags, int fd, uint offset);
|
||||
int munmap(void* addr, uint len);
|
||||
const void* MAP_FAILED = cast(void*)-1;
|
||||
|
||||
// from <bits/mman.h>
|
||||
enum { PROT_NONE = 0, PROT_READ = 1, PROT_WRITE = 2, PROT_EXEC = 4 }
|
||||
enum { MAP_SHARED = 1, MAP_PRIVATE = 2, MAP_TYPE = 0x0F,
|
||||
MAP_FIXED = 0x10, MAP_FILE = 0, MAP_ANON = 0x20 }
|
||||
}
|
||||
+/
|
||||
|
||||
/***********************************
|
||||
* Map memory.
|
||||
*/
|
||||
|
||||
void *os_mem_map(uint nbytes)
|
||||
{ void *p;
|
||||
|
||||
//errno = 0;
|
||||
p = mmap(null, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
return (p == MAP_FAILED) ? null : p;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Commit memory.
|
||||
* Returns:
|
||||
* 0 success
|
||||
* !=0 failure
|
||||
*/
|
||||
|
||||
int os_mem_commit(void *base, uint offset, uint nbytes)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Decommit memory.
|
||||
* Returns:
|
||||
* 0 success
|
||||
* !=0 failure
|
||||
*/
|
||||
|
||||
int os_mem_decommit(void *base, uint offset, uint nbytes)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Unmap memory allocated with os_mem_map().
|
||||
* Returns:
|
||||
* 0 success
|
||||
* !=0 failure
|
||||
*/
|
||||
|
||||
int os_mem_unmap(void *base, uint nbytes)
|
||||
{
|
||||
return munmap(base, nbytes);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Determine "bottom" of stack (actually the top on x86 systems).
|
||||
*/
|
||||
|
||||
void *os_query_stackBottom()
|
||||
{
|
||||
version (none)
|
||||
{ // See discussion: http://autopackage.org/forums/viewtopic.php?t=22
|
||||
static void** libc_stack_end;
|
||||
|
||||
if (libc_stack_end == libc_stack_end.init)
|
||||
{
|
||||
void* handle = dlopen(null, RTLD_NOW);
|
||||
libc_stack_end = cast(void **)dlsym(handle, "__libc_stack_end");
|
||||
dlclose(handle);
|
||||
}
|
||||
return *libc_stack_end;
|
||||
}
|
||||
else
|
||||
{ // This doesn't resolve on all versions of Linux
|
||||
return __libc_stack_end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Determine base address and size of static data segment.
|
||||
*/
|
||||
|
||||
void os_query_staticdataseg(void **base, uint *nbytes)
|
||||
{
|
||||
*base = cast(void *)&__data_start;
|
||||
*nbytes = cast(byte *)&_end - cast(byte *)&__data_start;
|
||||
}
|
||||
2681
lphobos/gc/gcx.d
2681
lphobos/gc/gcx.d
File diff suppressed because it is too large
Load Diff
@@ -1,168 +0,0 @@
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
++++/
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) 1999-2002 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
|
||||
struct GCStats
|
||||
{
|
||||
size_t poolsize; // total size of pool
|
||||
size_t usedsize; // bytes allocated
|
||||
size_t freeblocks; // number of blocks marked FREE
|
||||
size_t freelistsize; // total of memory on free lists
|
||||
size_t pageblocks; // number of blocks marked PAGE
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
module hello;
|
||||
|
||||
import std.stdio;
|
||||
|
||||
void main() { writefln("Hello World"); }
|
||||
@@ -1,410 +0,0 @@
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 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, in both source and binary form, 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.
|
||||
*/
|
||||
|
||||
/* This code handles decoding UTF strings for foreach loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
import std.utf;
|
||||
|
||||
//debug=apply;
|
||||
|
||||
/**********************************************
|
||||
*/
|
||||
|
||||
// dg is D, but _aApplycd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplycd1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
d = std.utf.decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
d = std.utf.decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ d = std.utf.decode(aa, i);
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
char[] b;
|
||||
|
||||
d = std.utf.decode(aa, i);
|
||||
b = std.utf.toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
i++;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
char[] b;
|
||||
|
||||
b = std.utf.toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
// dg is D, but _aApplycd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplycd2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{
|
||||
n = i;
|
||||
d = std.utf.decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
n = i;
|
||||
d = std.utf.decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ n = i;
|
||||
d = std.utf.decode(aa, n);
|
||||
n -= i;
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
char[] b;
|
||||
|
||||
n = i;
|
||||
d = std.utf.decode(aa, n);
|
||||
n -= i;
|
||||
b = std.utf.toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
n = 1;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplydc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i++)
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
char[] b;
|
||||
|
||||
b = std.utf.toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
|
||||
foreach (size_t i, dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,977 +0,0 @@
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 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, in both source and binary form, 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.
|
||||
*/
|
||||
|
||||
/* This code handles decoding UTF strings for foreach_reverse loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
import std.utf;
|
||||
|
||||
//debug=apply;
|
||||
|
||||
/**********************************************/
|
||||
/* 1 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplyRcd1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd1.unittest\n");
|
||||
|
||||
char[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd1.unittest\n");
|
||||
|
||||
wchar[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw1.unittest\n");
|
||||
|
||||
char[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
char[] b;
|
||||
|
||||
b = std.utf.toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc1.unittest\n");
|
||||
|
||||
wchar[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0;)
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
char[] b;
|
||||
|
||||
b = std.utf.toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc1.unittest\n");
|
||||
|
||||
dchar[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw1.unittest\n");
|
||||
|
||||
dchar[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* 2 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplyRcd2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
|
||||
for (i = len; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd2.unittest\n");
|
||||
|
||||
char[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); assert(k == 8); break;
|
||||
case 1: assert(d == '\U00100456'); assert(k == 4); break;
|
||||
case 2: assert(d == '\u1234'); assert(k == 1); break;
|
||||
case 3: assert(d == 'a'); assert(k == 0); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd2.unittest\n");
|
||||
|
||||
wchar[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == '\U00100456'); break;
|
||||
case 2: assert(k == 1); assert(d == '\u1234'); break;
|
||||
case 3: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
throw new std.utf.UtfException("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw2.unittest\n");
|
||||
|
||||
char[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 8); assert(d == 'b'); break;
|
||||
case 1: assert(k == 4); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 4); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
throw new std.utf.UtfException("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
char[] b;
|
||||
|
||||
b = std.utf.toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc2.unittest\n");
|
||||
|
||||
wchar[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
char[] b;
|
||||
|
||||
b = std.utf.toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc2.unittest\n");
|
||||
|
||||
dchar[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw2.unittest\n");
|
||||
|
||||
dchar[] s = "hello";
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 2); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,825 +0,0 @@
|
||||
//_ aaA.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Implementation of associative arrays.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2007 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified for LDC by Tomas Lindquist Olsen.
|
||||
* The DMD implementation wont quite work due to the differences in how
|
||||
* structs are handled.
|
||||
*/
|
||||
|
||||
|
||||
//import std.stdio;
|
||||
import std.c.stdarg;
|
||||
import std.c.stdio;
|
||||
import std.c.stdlib;
|
||||
import std.c.string;
|
||||
//import std.string;
|
||||
|
||||
import std.outofmemory;
|
||||
|
||||
// Auto-rehash and pre-allocate - Dave Fladebo
|
||||
|
||||
static size_t[] prime_list = [
|
||||
97UL, 389UL,
|
||||
1543UL, 6151UL,
|
||||
24593UL, 98317UL,
|
||||
393241UL, 1572869UL,
|
||||
6291469UL, 25165843UL,
|
||||
100663319UL, 402653189UL,
|
||||
1610612741UL, 4294967291UL
|
||||
];
|
||||
|
||||
/* This is the type of the return value for dynamic arrays.
|
||||
* It should be a type that is returned in registers.
|
||||
*/
|
||||
alias Array ArrayRet_t;
|
||||
|
||||
pragma(no_typeinfo)
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
pragma(no_typeinfo)
|
||||
struct aaA
|
||||
{
|
||||
aaA *left;
|
||||
aaA *right;
|
||||
hash_t hash;
|
||||
/* key */
|
||||
/* value */
|
||||
}
|
||||
|
||||
pragma(no_typeinfo)
|
||||
struct BB
|
||||
{
|
||||
aaA*[] b;
|
||||
size_t nodes; // total number of aaA nodes
|
||||
}
|
||||
|
||||
/* This is the type actually seen by the programmer, although
|
||||
* it is completely opaque.
|
||||
*/
|
||||
|
||||
alias BB* AA;
|
||||
|
||||
/**********************************
|
||||
* Align to next pointer boundary, so that
|
||||
* GC won't be faced with misaligned pointers
|
||||
* in value.
|
||||
*/
|
||||
|
||||
size_t aligntsize(size_t tsize)
|
||||
{
|
||||
// Is pointer alignment on the x86-64 4 bytes or 8?
|
||||
//return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
|
||||
return (tsize + 3) & (~3);
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
/*************************************************
|
||||
* Invariant for aa.
|
||||
*/
|
||||
|
||||
/+
|
||||
void _aaInvAh(aaA*[] aa)
|
||||
{
|
||||
for (size_t i = 0; i < aa.length; i++)
|
||||
{
|
||||
if (aa[i])
|
||||
_aaInvAh_x(aa[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private int _aaCmpAh_x(aaA *e1, aaA *e2)
|
||||
{ int c;
|
||||
|
||||
c = e1.hash - e2.hash;
|
||||
if (c == 0)
|
||||
{
|
||||
c = e1.key.length - e2.key.length;
|
||||
if (c == 0)
|
||||
c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private void _aaInvAh_x(aaA *e)
|
||||
{
|
||||
hash_t key_hash;
|
||||
aaA *e1;
|
||||
aaA *e2;
|
||||
|
||||
key_hash = getHash(e.key);
|
||||
assert(key_hash == e.hash);
|
||||
|
||||
while (1)
|
||||
{ int c;
|
||||
|
||||
e1 = e.left;
|
||||
if (e1)
|
||||
{
|
||||
_aaInvAh_x(e1); // ordinary recursion
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e1, e);
|
||||
assert(c < 0);
|
||||
e1 = e1.right;
|
||||
} while (e1 != null);
|
||||
}
|
||||
|
||||
e2 = e.right;
|
||||
if (e2)
|
||||
{
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e, e2);
|
||||
assert(c < 0);
|
||||
e2 = e2.left;
|
||||
} while (e2 != null);
|
||||
e = e.right; // tail recursion
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
+/
|
||||
|
||||
/****************************************************
|
||||
* Determine number of entries in associative array.
|
||||
*/
|
||||
|
||||
size_t _aaLen(AA aa)
|
||||
in
|
||||
{
|
||||
//printf("_aaLen()+\n");
|
||||
//_aaInv(aa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
void _aaLen_x(aaA* ex)
|
||||
{
|
||||
auto e = ex;
|
||||
len++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (e.right)
|
||||
_aaLen_x(e.right);
|
||||
e = e.left;
|
||||
if (!e)
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (aa)
|
||||
{
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaLen_x(e);
|
||||
}
|
||||
}
|
||||
assert(len == result);
|
||||
|
||||
//printf("_aaLen()-\n");
|
||||
}
|
||||
body
|
||||
{
|
||||
return aa ? aa.nodes : 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Add entry for key if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey)
|
||||
in
|
||||
{
|
||||
assert(aa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(result);
|
||||
assert(*aa);
|
||||
assert((*aa).b.length);
|
||||
//assert(_aaInAh(*aa, key));
|
||||
}
|
||||
body
|
||||
{
|
||||
//auto pkey = cast(void *)(&valuesize + 1);
|
||||
size_t i;
|
||||
aaA* e;
|
||||
auto keysize = aligntsize(keyti.tsize());
|
||||
|
||||
if (!*aa)
|
||||
*aa = new BB();
|
||||
|
||||
if (!(*aa).b.length)
|
||||
{
|
||||
alias aaA *pa;
|
||||
auto len = prime_list[0];
|
||||
|
||||
(*aa).b = new pa[len];
|
||||
}
|
||||
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
i = key_hash % (*aa).b.length;
|
||||
auto pe = &(*aa).b[i];
|
||||
while ((e = *pe) != null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
goto Lret;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
e = cast(aaA *) cast(void*) new void[aaA.sizeof + keysize + valuesize];
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
e.hash = key_hash;
|
||||
*pe = e;
|
||||
|
||||
auto nodes = ++(*aa).nodes;
|
||||
//printf("length = %d, nodes = %d\n", (*aa).length, nodes);
|
||||
if (nodes > (*aa).b.length * 4)
|
||||
{
|
||||
_aaRehash(aa,keyti);
|
||||
}
|
||||
|
||||
Lret:
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Returns null if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, void* pkey)
|
||||
{
|
||||
//printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
|
||||
if (!aa)
|
||||
return null;
|
||||
|
||||
//auto pkey = cast(void *)(&valuesize + 1);
|
||||
auto keysize = aligntsize(keyti.tsize());
|
||||
auto len = aa.b.length;
|
||||
|
||||
if (len)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % len;
|
||||
auto e = aa.b[i];
|
||||
while (e != null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
return null; // not found, caller will throw exception
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Determine if key is in aa.
|
||||
* Returns:
|
||||
* null not in aa
|
||||
* !=null in aa, return pointer to value
|
||||
*/
|
||||
|
||||
void* _aaIn(AA aa, TypeInfo keyti, void* pkey)
|
||||
in
|
||||
{
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//assert(result == 0 || result == 1);
|
||||
}
|
||||
body
|
||||
{
|
||||
if (aa)
|
||||
{
|
||||
//auto pkey = cast(void *)(&keyti + 1);
|
||||
|
||||
//printf("_aaIn(), .length = %d, .ptr = %x\n", aa.length, cast(uint)aa.ptr);
|
||||
auto len = aa.b.length;
|
||||
|
||||
if (len)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % len;
|
||||
auto e = aa.b[i];
|
||||
while (e != null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + aligntsize(keyti.tsize());
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Delete key entry in aa[].
|
||||
* If key is not in aa[], do nothing.
|
||||
*/
|
||||
|
||||
void _aaDel(AA aa, TypeInfo keyti, void* pkey)
|
||||
{
|
||||
//auto pkey = cast(void *)(&keyti + 1);
|
||||
aaA* e;
|
||||
|
||||
if (aa && aa.b.length)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % aa.b.length;
|
||||
auto pe = &aa.b[i];
|
||||
while ((e = *pe) != null) // null means not found
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
{
|
||||
if (!e.left && !e.right)
|
||||
{
|
||||
*pe = null;
|
||||
}
|
||||
else if (e.left && !e.right)
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
}
|
||||
else if (!e.left && e.right)
|
||||
{
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
do
|
||||
pe = &(*pe).right;
|
||||
while (*pe);
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
|
||||
aa.nodes--;
|
||||
|
||||
// Should notify GC that e can be free'd now
|
||||
break;
|
||||
}
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Produce array of values from aa.
|
||||
*/
|
||||
|
||||
ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize)
|
||||
in
|
||||
{
|
||||
assert(keysize == aligntsize(keysize));
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t resi;
|
||||
Array a;
|
||||
|
||||
void _aaValues_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(a.ptr + resi * valuesize,
|
||||
cast(byte*)e + aaA.sizeof + keysize,
|
||||
valuesize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaValues_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e != null);
|
||||
}
|
||||
|
||||
if (aa)
|
||||
{
|
||||
a.length = _aaLen(aa);
|
||||
a.ptr = (new void[a.length * valuesize]).ptr;
|
||||
resi = 0;
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaValues_x(e);
|
||||
}
|
||||
assert(resi == a.length);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Rehash an array.
|
||||
*/
|
||||
|
||||
void* _aaRehash(AA* paa, TypeInfo keyti)
|
||||
in
|
||||
{
|
||||
assert(paa);
|
||||
//_aaInvAh(paa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//_aaInvAh(result);
|
||||
}
|
||||
body
|
||||
{
|
||||
BB newb;
|
||||
|
||||
void _aaRehash_x(aaA* olde)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
auto left = olde.left;
|
||||
auto right = olde.right;
|
||||
olde.left = null;
|
||||
olde.right = null;
|
||||
|
||||
aaA* e;
|
||||
|
||||
//printf("rehash %p\n", olde);
|
||||
auto key_hash = olde.hash;
|
||||
size_t i = key_hash % newb.b.length;
|
||||
auto pe = &newb.b[i];
|
||||
while ((e = *pe) != null)
|
||||
{
|
||||
//printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right);
|
||||
assert(e.left != e);
|
||||
assert(e.right != e);
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(olde + 1, e + 1);
|
||||
assert(c != 0);
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
*pe = olde;
|
||||
|
||||
if (right)
|
||||
{
|
||||
if (!left)
|
||||
{ olde = right;
|
||||
continue;
|
||||
}
|
||||
_aaRehash_x(right);
|
||||
}
|
||||
if (!left)
|
||||
break;
|
||||
olde = left;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("Rehash\n");
|
||||
if (paa)
|
||||
{
|
||||
auto aa = *paa;
|
||||
auto len = _aaLen(*paa);
|
||||
if (len)
|
||||
{ size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (len <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
len = prime_list[i];
|
||||
newb.b = new aaA*[len];
|
||||
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaRehash_x(e);
|
||||
}
|
||||
|
||||
newb.nodes = aa.nodes;
|
||||
}
|
||||
|
||||
**paa = newb;
|
||||
}
|
||||
return *paa;
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Produce array of N byte keys from aa.
|
||||
*/
|
||||
|
||||
ArrayRet_t _aaKeys(AA aa, size_t keysize)
|
||||
{
|
||||
byte[] res;
|
||||
size_t resi;
|
||||
|
||||
void _aaKeys_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaKeys_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e != null);
|
||||
}
|
||||
|
||||
auto len = _aaLen(aa);
|
||||
if (!len)
|
||||
return ArrayRet_t.init;
|
||||
res = cast(byte[])new void[len * keysize];
|
||||
resi = 0;
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaKeys_x(e);
|
||||
}
|
||||
assert(resi == len);
|
||||
|
||||
return Array(len, res.ptr);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* 'apply' for associative arrays - to support foreach
|
||||
*/
|
||||
|
||||
// dg is D, but _aaApply() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
int _aaApply(AA aa, size_t keysize, dg_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa)
|
||||
{
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// dg is D, but _aaApply2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
int _aaApply2(AA aa, size_t keysize, dg2_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa)
|
||||
{
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Construct an associative array of type ti from
|
||||
* length pairs of key/value pairs.
|
||||
*/
|
||||
|
||||
version(none) // not used, C variadics can't be implemented in LLVM on x86-64
|
||||
{
|
||||
BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
|
||||
{
|
||||
auto valuesize = ti.next.tsize(); // value size
|
||||
auto keyti = ti.key;
|
||||
auto keysize = keyti.tsize(); // key size
|
||||
BB* result;
|
||||
|
||||
//printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length);
|
||||
//writefln("tivalue = %s", ti.next.classinfo.name);
|
||||
if (length == 0 || valuesize == 0 || keysize == 0)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
va_list q;
|
||||
va_start!(size_t)(q, length);
|
||||
|
||||
result = new BB();
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (length <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
auto len = prime_list[i];
|
||||
result.b = new aaA*[len];
|
||||
|
||||
size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
|
||||
size_t keytsize = aligntsize(keysize);
|
||||
|
||||
for (size_t j = 0; j < length; j++)
|
||||
{ void* pkey = q;
|
||||
q += keystacksize;
|
||||
void* pvalue = q;
|
||||
q += valuestacksize;
|
||||
aaA* e;
|
||||
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
i = key_hash % len;
|
||||
auto pe = &result.b[i];
|
||||
while (1)
|
||||
{
|
||||
e = *pe;
|
||||
if (!e)
|
||||
{
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize];
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
e.hash = key_hash;
|
||||
*pe = e;
|
||||
result.nodes++;
|
||||
break;
|
||||
}
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize);
|
||||
}
|
||||
|
||||
va_end(q);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,838 +0,0 @@
|
||||
//_ adi.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Dynamic array property support routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2006 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, in both source and binary form, 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.
|
||||
*/
|
||||
|
||||
//debug=adi; // uncomment to turn on debugging printf's
|
||||
|
||||
//import std.stdio;
|
||||
import std.c.stdio;
|
||||
import std.c.stdlib;
|
||||
import std.c.string;
|
||||
//import std.string;
|
||||
import std.outofmemory;
|
||||
import std.utf;
|
||||
|
||||
pragma(no_typeinfo)
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of chars.
|
||||
* Handled separately because embedded multibyte encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) char[] _adReverseChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
char[6] tmp;
|
||||
char[6] tmplo;
|
||||
char* lo = a.ptr;
|
||||
char* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
//printf("lo = %d, hi = %d\n", lo, hi);
|
||||
if (clo <= 0x7F && chi <= 0x7F)
|
||||
{
|
||||
//printf("\tascii\n");
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint stridelo = std.utf.UTF8stride[clo];
|
||||
|
||||
uint stridehi = 1;
|
||||
while ((chi & 0xC0) == 0x80)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
//printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
|
||||
if (stridelo == stridehi)
|
||||
{
|
||||
|
||||
memcpy(tmp.ptr, lo, stridelo);
|
||||
memcpy(lo, hi, stridelo);
|
||||
memcpy(hi, tmp.ptr, stridelo);
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi);
|
||||
memcpy(tmplo.ptr, lo, stridelo);
|
||||
memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo);
|
||||
memcpy(lo, tmp.ptr, stridehi);
|
||||
memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
string a = "abcd";
|
||||
string r;
|
||||
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\u1235\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234\u1235a");
|
||||
|
||||
a = "ab\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234ba");
|
||||
|
||||
a = "\u3026\u2021\u3061\n";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "\n\u3061\u2021\u3026");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of wchars.
|
||||
* Handled separately because embedded multiword encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) wchar[] _adReverseWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
wchar[2] tmp;
|
||||
wchar* lo = a.ptr;
|
||||
wchar* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
if ((clo < 0xD800 || clo > 0xDFFF) &&
|
||||
(chi < 0xD800 || chi > 0xDFFF))
|
||||
{
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
|
||||
|
||||
int stridehi = 1;
|
||||
if (chi >= 0xDC00 && chi <= 0xDFFF)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
if (stridelo == stridehi)
|
||||
{ int stmp;
|
||||
|
||||
assert(stridelo == 2);
|
||||
assert(stmp.sizeof == 2 * (*lo).sizeof);
|
||||
stmp = *cast(int*)lo;
|
||||
*cast(int*)lo = *cast(int*)hi;
|
||||
*cast(int*)hi = stmp;
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
|
||||
memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
|
||||
memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
|
||||
memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
wstring a = "abcd";
|
||||
wstring r;
|
||||
|
||||
r = a.dup.reverse;
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\U00012356\U00012346c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012346\U00012356a");
|
||||
|
||||
a = "ab\U00012345c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012345ba");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Support for array.reverse property.
|
||||
*/
|
||||
|
||||
extern (C) Array _adReverse(Array a, size_t szelem)
|
||||
{
|
||||
if (a.length >= 2)
|
||||
{
|
||||
byte* tmp;
|
||||
byte[16] buffer;
|
||||
|
||||
void* lo = a.ptr;
|
||||
void* hi = a.ptr + (a.length - 1) * szelem;
|
||||
|
||||
tmp = buffer.ptr;
|
||||
if (szelem > 16)
|
||||
{
|
||||
//version (Win32)
|
||||
//tmp = cast(byte*) alloca(szelem);
|
||||
//else
|
||||
tmp = (new byte[szelem]).ptr;
|
||||
}
|
||||
|
||||
for (; lo < hi; lo += szelem, hi -= szelem)
|
||||
{
|
||||
memcpy(tmp, lo, szelem);
|
||||
memcpy(lo, hi, szelem);
|
||||
memcpy(hi, tmp, szelem);
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (szelem > 16)
|
||||
// BUG: bad code is generate for delete pointer, tries
|
||||
// to call delclass.
|
||||
//delete tmp;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.reverse.unittest\n");
|
||||
|
||||
int[] a = new int[5];
|
||||
int[] b;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
a[i] = i;
|
||||
b = a.reverse;
|
||||
assert(b is a);
|
||||
for (i = 0; i < 5; i++)
|
||||
assert(a[i] == 4 - i);
|
||||
|
||||
struct X20
|
||||
{ // More than 16 bytes in size
|
||||
int a;
|
||||
int b, c, d, e;
|
||||
}
|
||||
|
||||
X20[] c = new X20[5];
|
||||
X20[] d;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{ c[i].a = i;
|
||||
c[i].e = 10;
|
||||
}
|
||||
d = c.reverse;
|
||||
assert(d is c);
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
assert(c[i].a == 4 - i);
|
||||
assert(c[i].e == 10);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Support for array.reverse property for bit[].
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C) bit[] _adReverseBit(bit[] a)
|
||||
out (result)
|
||||
{
|
||||
assert(result is a);
|
||||
}
|
||||
body
|
||||
{
|
||||
if (a.length >= 2)
|
||||
{
|
||||
bit t;
|
||||
int lo, hi;
|
||||
|
||||
lo = 0;
|
||||
hi = a.length - 1;
|
||||
for (; lo < hi; lo++, hi--)
|
||||
{
|
||||
t = a[lo];
|
||||
a[lo] = a[hi];
|
||||
a[hi] = t;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.reverse_Bit[].unittest\n");
|
||||
|
||||
bit[] b;
|
||||
b = new bit[5];
|
||||
static bit[5] data = [1,0,1,1,0];
|
||||
int i;
|
||||
|
||||
b[] = data[];
|
||||
b.reverse;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
assert(b[i] == data[4 - i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of chars.
|
||||
*/
|
||||
|
||||
extern (C) char[] _adSortChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ char[4] buf;
|
||||
string t = toUTF8(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of wchars.
|
||||
*/
|
||||
|
||||
extern (C) wchar[] _adSortWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ wchar[2] buf;
|
||||
wstring t = toUTF16(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Support for array.sort property for bit[].
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C) bit[] _adSortBit(bit[] a)
|
||||
out (result)
|
||||
{
|
||||
assert(result is a);
|
||||
}
|
||||
body
|
||||
{
|
||||
if (a.length >= 2)
|
||||
{
|
||||
size_t lo, hi;
|
||||
|
||||
lo = 0;
|
||||
hi = a.length - 1;
|
||||
while (1)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (lo >= hi)
|
||||
goto Ldone;
|
||||
if (a[lo] == true)
|
||||
break;
|
||||
lo++;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (lo >= hi)
|
||||
goto Ldone;
|
||||
if (a[hi] == false)
|
||||
break;
|
||||
hi--;
|
||||
}
|
||||
|
||||
a[lo] = false;
|
||||
a[hi] = true;
|
||||
|
||||
lo++;
|
||||
hi--;
|
||||
}
|
||||
Ldone:
|
||||
;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.sort_Bit[].unittest\n");
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array equality test.
|
||||
*/
|
||||
|
||||
extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
// 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.next.tsize();
|
||||
auto p1 = a1.ptr;
|
||||
auto p2 = a2.ptr;
|
||||
|
||||
/+
|
||||
for (int i = 0; i < a1.length; i++)
|
||||
{
|
||||
printf("%4x %4x\n", (cast(short*)p1)[i], (cast(short*)p2)[i]);
|
||||
}
|
||||
printf("sz = %u\n", sz);
|
||||
+/
|
||||
|
||||
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.next.equals(p1 + i * sz, p2 + i * sz))
|
||||
return 0; // not equal
|
||||
}
|
||||
return 1; // equal
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Eq unittest\n");
|
||||
|
||||
string a = "hello";
|
||||
|
||||
assert(a != "hel");
|
||||
assert(a != "helloo");
|
||||
assert(a != "betty");
|
||||
assert(a == "hello");
|
||||
assert(a != "hxxxx");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for bit array equality test for bit arrays.
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C) int _adEqBit(Array a1, Array a2)
|
||||
{ size_t i;
|
||||
|
||||
if (a1.length != a2.length)
|
||||
return 0; // not equal
|
||||
auto p1 = cast(byte*)a1.ptr;
|
||||
auto p2 = cast(byte*)a2.ptr;
|
||||
auto n = a1.length / 8;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (p1[i] != p2[i])
|
||||
return 0; // not equal
|
||||
}
|
||||
|
||||
ubyte mask;
|
||||
|
||||
n = a1.length & 7;
|
||||
mask = cast(ubyte)((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(adi) printf("array.EqBit unittest\n");
|
||||
|
||||
static bit[] a = [1,0,1,0,1];
|
||||
static bit[] b = [1,0,1];
|
||||
static bit[] c = [1,0,1,0,1,0,1];
|
||||
static bit[] d = [1,0,1,1,1];
|
||||
static bit[] e = [1,0,1,0,1];
|
||||
|
||||
assert(a != b);
|
||||
assert(a != c);
|
||||
assert(a != d);
|
||||
assert(a == e);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
*/
|
||||
|
||||
extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
//printf("adCmp()\n");
|
||||
auto len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
auto sz = ti.tsize();
|
||||
void *p1 = a1.ptr;
|
||||
void *p2 = a2.ptr;
|
||||
|
||||
if (sz == 1)
|
||||
{ // We should really have a ti.isPOD() check for this
|
||||
auto c = memcmp(p1, p2, len);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
auto c = ti.compare(p1 + i * sz, p2 + i * sz);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
}
|
||||
if (a1.length == a2.length)
|
||||
return 0;
|
||||
return (a1.length > a2.length) ? 1 : -1;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Cmp unittest\n");
|
||||
|
||||
string a = "hello";
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for char array compare test.
|
||||
*/
|
||||
|
||||
extern (C) int _adCmpChar(Array a1, Array a2)
|
||||
{
|
||||
version (D_InlineAsm_X86)
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
|
||||
push EDI ;
|
||||
push ESI ;
|
||||
|
||||
mov ESI,a1+4[4+ESP] ;
|
||||
mov EDI,a2+4[4+ESP] ;
|
||||
|
||||
mov ECX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
cmp ECX,EDX ;
|
||||
jb GotLength ;
|
||||
|
||||
mov ECX,EDX ;
|
||||
|
||||
GotLength:
|
||||
cmp ECX,4 ;
|
||||
jb DoBytes ;
|
||||
|
||||
// Do alignment if neither is dword aligned
|
||||
test ESI,3 ;
|
||||
jz Aligned ;
|
||||
|
||||
test EDI,3 ;
|
||||
jz Aligned ;
|
||||
DoAlign:
|
||||
mov AL,[ESI] ; //align ESI to dword bounds
|
||||
mov DL,[EDI] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
inc ESI ;
|
||||
inc EDI ;
|
||||
|
||||
test ESI,3 ;
|
||||
|
||||
lea ECX,[ECX-1] ;
|
||||
jnz DoAlign ;
|
||||
Aligned:
|
||||
mov EAX,ECX ;
|
||||
|
||||
// do multiple of 4 bytes at a time
|
||||
|
||||
shr ECX,2 ;
|
||||
jz TryOdd ;
|
||||
|
||||
repe ;
|
||||
cmpsd ;
|
||||
|
||||
jnz UnequalQuad ;
|
||||
|
||||
TryOdd:
|
||||
mov ECX,EAX ;
|
||||
DoBytes:
|
||||
// if still equal and not end of string, do up to 3 bytes slightly
|
||||
// slower.
|
||||
|
||||
and ECX,3 ;
|
||||
jz Equal ;
|
||||
|
||||
repe ;
|
||||
cmpsb ;
|
||||
|
||||
jnz Unequal ;
|
||||
Equal:
|
||||
mov EAX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
sub EAX,EDX ;
|
||||
pop ESI ;
|
||||
|
||||
pop EDI ;
|
||||
ret ;
|
||||
|
||||
UnequalQuad:
|
||||
mov EDX,[EDI-4] ;
|
||||
mov EAX,[ESI-4] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
jnz Unequal ;
|
||||
|
||||
shr EAX,16 ;
|
||||
|
||||
shr EDX,16 ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
Unequal:
|
||||
sbb EAX,EAX ;
|
||||
pop ESI ;
|
||||
|
||||
or EAX,1 ;
|
||||
pop EDI ;
|
||||
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int len;
|
||||
int c;
|
||||
|
||||
//printf("adCmpChar()\n");
|
||||
len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
|
||||
if (!c)
|
||||
c = cast(int)a1.length - cast(int)a2.length;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.CmpChar unittest\n");
|
||||
|
||||
string a = "hello";
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for bit array compare test.
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C) int _adCmpBit(Array a1, Array a2)
|
||||
{
|
||||
int len;
|
||||
uint i;
|
||||
|
||||
len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
ubyte *p1 = cast(ubyte*)a1.ptr;
|
||||
ubyte *p2 = cast(ubyte*)a2.ptr;
|
||||
uint n = len / 8;
|
||||
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;
|
||||
}
|
||||
return cast(int)a1.length - cast(int)a2.length;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.CmpBit unittest\n");
|
||||
|
||||
static bit[] a = [1,0,1,0,1];
|
||||
static bit[] b = [1,0,1];
|
||||
static bit[] c = [1,0,1,0,1,0,1];
|
||||
static bit[] d = [1,0,1,1,1];
|
||||
static bit[] e = [1,0,1,0,1];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Support for array.dup property.
|
||||
*/
|
||||
|
||||
extern(C)
|
||||
void* _d_realloc(void*, size_t);
|
||||
|
||||
extern(C)
|
||||
Array _adDupT(TypeInfo ti, Array a)
|
||||
{
|
||||
Array r;
|
||||
if (a.length)
|
||||
{
|
||||
auto sizeelem = ti.next.tsize(); // array element size
|
||||
auto size = a.length * sizeelem;
|
||||
r.ptr = _d_realloc(null,size);
|
||||
r.length = a.length;
|
||||
memcpy(r.ptr, a.ptr, size);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
int[] a;
|
||||
int[] b;
|
||||
int i;
|
||||
|
||||
debug(adi) printf("array.dup.unittest\n");
|
||||
|
||||
a = new int[3];
|
||||
a[0] = 1; a[1] = 2; a[2] = 3;
|
||||
b = a.dup;
|
||||
assert(b.length == 3);
|
||||
for (i = 0; i < 3; i++)
|
||||
assert(b[i] == i + 1);
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
module internal.arrays;
|
||||
|
||||
private import llvm.intrinsic;
|
||||
|
||||
extern(C):
|
||||
|
||||
int memcmp(void*,void*,size_t);
|
||||
size_t strlen(char*);
|
||||
|
||||
version(LLVM64)
|
||||
alias llvm_memcpy_i64 llvm_memcpy;
|
||||
else
|
||||
alias llvm_memcpy_i32 llvm_memcpy;
|
||||
|
||||
// per-element array init routines
|
||||
|
||||
void _d_array_init_i1(bool* a, size_t n, bool v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_i8(ubyte* a, size_t n, ubyte v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_i16(ushort* a, size_t n, ushort v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_i32(uint* a, size_t n, uint v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_i64(ulong* a, size_t n, ulong v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_float(float* a, size_t n, float v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_double(double* a, size_t n, double v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_pointer(void** a, size_t n, void* v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_mem(void* a, size_t na, void* v, size_t nv)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a + na*nv;
|
||||
while (p !is end) {
|
||||
llvm_memcpy(p,v,nv,0);
|
||||
p += nv;
|
||||
}
|
||||
}
|
||||
|
||||
// for array cast
|
||||
size_t _d_array_cast_len(size_t len, size_t elemsz, size_t newelemsz)
|
||||
{
|
||||
if (newelemsz == 1) {
|
||||
return len*elemsz;
|
||||
}
|
||||
else if (len % newelemsz) {
|
||||
throw new Exception("Bad array cast");
|
||||
}
|
||||
return (len*elemsz)/newelemsz;
|
||||
}
|
||||
|
||||
// creating args for main
|
||||
void _d_main_args(uint n, char** args, ref char[][] res)
|
||||
{
|
||||
assert(res.length == n);
|
||||
foreach(i,v; args[0..n])
|
||||
{
|
||||
res[i] = v[0 .. strlen(v)];
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 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, in both source and binary form, 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.
|
||||
*/
|
||||
|
||||
|
||||
import object;
|
||||
import std.c.stdio;
|
||||
|
||||
extern (C):
|
||||
|
||||
/******************************************
|
||||
* Given a pointer:
|
||||
* If it is an Object, return that Object.
|
||||
* If it is an interface, return the Object implementing the interface.
|
||||
* If it is null, return null.
|
||||
* Else, undefined crash
|
||||
*/
|
||||
|
||||
Object _d_toObject(void* p)
|
||||
{ Object o;
|
||||
|
||||
if (p)
|
||||
{
|
||||
o = cast(Object)p;
|
||||
//ClassInfo oc = o.classinfo;
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
|
||||
/* Interface.offset lines up with ClassInfo.name.ptr,
|
||||
* so we rely on pointers never being less than 64K,
|
||||
* and Objects never being greater.
|
||||
*/
|
||||
if (pi.offset < 0x10000)
|
||||
{
|
||||
//printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Attempts to cast Object o to class c.
|
||||
* Returns o if successful, null if not.
|
||||
*/
|
||||
|
||||
Object _d_interface_cast(void* p, ClassInfo c)
|
||||
{ Object o;
|
||||
|
||||
//printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
|
||||
if (p)
|
||||
{
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
|
||||
//printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
return _d_dynamic_cast(o, c);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
Object _d_dynamic_cast(Object o, ClassInfo c)
|
||||
{ ClassInfo oc;
|
||||
uint offset = 0;
|
||||
|
||||
//printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
|
||||
|
||||
if (o)
|
||||
{
|
||||
oc = o.classinfo;
|
||||
if (_d_isbaseof2(oc, c, offset))
|
||||
{
|
||||
//printf("\toffset = %d\n", offset);
|
||||
o = cast(Object)(cast(void*)o + offset);
|
||||
}
|
||||
else
|
||||
o = null;
|
||||
}
|
||||
//printf("\tresult = %p\n", o);
|
||||
return o;
|
||||
}
|
||||
|
||||
int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout uint offset)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (ic is c)
|
||||
{ offset = oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (_d_isbaseof2(ic, c, offset))
|
||||
{ offset = oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _d_isbaseof(ClassInfo oc, ClassInfo c)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (ic is c || _d_isbaseof(ic, c))
|
||||
return 1;
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* Find the vtbl[] associated with Interface ic.
|
||||
*/
|
||||
|
||||
void *_d_interface_vtbl(ClassInfo ic, Object o)
|
||||
{ int i;
|
||||
ClassInfo oc;
|
||||
|
||||
//printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
|
||||
|
||||
assert(o);
|
||||
|
||||
oc = o.classinfo;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo oic;
|
||||
|
||||
oic = oc.interfaces[i].classinfo;
|
||||
if (oic is ic)
|
||||
{
|
||||
return cast(void *)oc.interfaces[i].vtbl;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
module internal.contract;
|
||||
|
||||
import std.string: toString;
|
||||
extern(C):
|
||||
|
||||
void exit(int);
|
||||
|
||||
/*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~"\"");
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
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() { }
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
/**
|
||||
* 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* malloc(size_t size);
|
||||
|
||||
extern(C) void _d_throw_exception(Object e)
|
||||
{
|
||||
if (e !is null)
|
||||
{
|
||||
// _d_exception* exc_struct = new _d_exception;
|
||||
auto exc_struct = cast(_d_exception*)malloc(_d_exception.sizeof);
|
||||
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);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
module internal.mem;
|
||||
|
||||
extern(C):
|
||||
|
||||
void* realloc(void*,size_t);
|
||||
void free(void*);
|
||||
|
||||
void* _d_realloc(void* ptr, size_t n)
|
||||
{
|
||||
return realloc(ptr, n);
|
||||
}
|
||||
|
||||
void _d_free(void* ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,69 +0,0 @@
|
||||
|
||||
/*
|
||||
* Placed into Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*
|
||||
* This is a public domain version of qsort.d.
|
||||
* All it does is call C's qsort(), but runs a little slower since
|
||||
* it needs to synchronize a global variable.
|
||||
*/
|
||||
|
||||
|
||||
//debug=qsort;
|
||||
|
||||
import std.c.stdlib;
|
||||
|
||||
pragma(no_typeinfo)
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void *ptr;
|
||||
}
|
||||
|
||||
private TypeInfo tiglobal;
|
||||
|
||||
extern (C) int cmp(void* p1, void* p2)
|
||||
{
|
||||
return tiglobal.compare(p1, p2);
|
||||
}
|
||||
|
||||
extern (C) Array _adSort(Array a, TypeInfo ti)
|
||||
{
|
||||
synchronized
|
||||
{
|
||||
tiglobal = ti;
|
||||
std.c.stdlib.qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(qsort) printf("array.sort.unittest()\n");
|
||||
|
||||
int a[] = new int[10];
|
||||
|
||||
a[0] = 23;
|
||||
a[1] = 1;
|
||||
a[2] = 64;
|
||||
a[3] = 5;
|
||||
a[4] = 6;
|
||||
a[5] = 5;
|
||||
a[6] = 17;
|
||||
a[7] = 3;
|
||||
a[8] = 0;
|
||||
a[9] = -1;
|
||||
|
||||
a.sort;
|
||||
|
||||
for (int i = 0; i < a.length - 1; i++)
|
||||
{
|
||||
//printf("i = %d", i);
|
||||
//printf(" %d %d\n", a[i], a[i + 1]);
|
||||
assert(a[i] <= a[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,428 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2007 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, in both source and binary form, 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.
|
||||
*/
|
||||
|
||||
|
||||
import std.c.stdio;
|
||||
import std.c.string;
|
||||
import std.string;
|
||||
|
||||
/******************************************************
|
||||
* Support for switch statements switching on strings.
|
||||
* Input:
|
||||
* table[] sorted array of strings generated by compiler
|
||||
* ca string to look up in table
|
||||
* Output:
|
||||
* result index of match in table[]
|
||||
* -1 if not in table
|
||||
*/
|
||||
|
||||
extern (C):
|
||||
|
||||
int _d_switch_string(char[][] table, char[] ca)
|
||||
in
|
||||
{
|
||||
//printf("in _d_switch_string()\n");
|
||||
assert(table.length >= 0);
|
||||
assert(ca.length >= 0);
|
||||
|
||||
// Make sure table[] is sorted correctly
|
||||
int j;
|
||||
|
||||
for (j = 1; j < table.length; j++)
|
||||
{
|
||||
int len1 = table[j - 1].length;
|
||||
int len2 = table[j].length;
|
||||
|
||||
assert(len1 <= len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
int ci;
|
||||
|
||||
ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
|
||||
assert(ci < 0); // ci==0 means a duplicate
|
||||
}
|
||||
}
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
int i;
|
||||
int cj;
|
||||
|
||||
//printf("out _d_switch_string()\n");
|
||||
if (result == -1)
|
||||
{
|
||||
// Not found
|
||||
for (i = 0; i < table.length; i++)
|
||||
{
|
||||
if (table[i].length == ca.length)
|
||||
{ cj = memcmp(table[i].ptr, ca.ptr, ca.length);
|
||||
assert(cj != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0 <= result && result < table.length);
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
assert(i < table.length);
|
||||
if (table[i].length == ca.length)
|
||||
{
|
||||
cj = memcmp(table[i].ptr, ca.ptr, ca.length);
|
||||
if (cj == 0)
|
||||
{
|
||||
assert(i == result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body
|
||||
{
|
||||
//printf("body _d_switch_string(%.*s)\n", ca);
|
||||
int low;
|
||||
int high;
|
||||
int mid;
|
||||
int c;
|
||||
char[] pca;
|
||||
|
||||
low = 0;
|
||||
high = table.length;
|
||||
|
||||
version (none)
|
||||
{
|
||||
// Print table
|
||||
printf("ca[] = '%s'\n", cast(char *)ca);
|
||||
for (mid = 0; mid < high; mid++)
|
||||
{
|
||||
pca = table[mid];
|
||||
printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
|
||||
}
|
||||
}
|
||||
if (high &&
|
||||
ca.length >= table[0].length &&
|
||||
ca.length <= table[high - 1].length)
|
||||
{
|
||||
// Looking for 0 length string, which would only be at the beginning
|
||||
if (ca.length == 0)
|
||||
return 0;
|
||||
|
||||
char c1 = ca[0];
|
||||
|
||||
// Do binary search
|
||||
while (low < high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
pca = table[mid];
|
||||
c = ca.length - pca.length;
|
||||
if (c == 0)
|
||||
{
|
||||
c = cast(ubyte)c1 - cast(ubyte)pca[0];
|
||||
if (c == 0)
|
||||
{
|
||||
c = memcmp(ca.ptr, pca.ptr, ca.length);
|
||||
if (c == 0)
|
||||
{ //printf("found %d\n", mid);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//printf("not found\n");
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
switch (cast(char []) "c")
|
||||
{
|
||||
case "coo":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Same thing, but for wide chars.
|
||||
*/
|
||||
|
||||
int _d_switch_ustring(wchar[][] table, wchar[] ca)
|
||||
in
|
||||
{
|
||||
//printf("in _d_switch_ustring()\n");
|
||||
assert(table.length >= 0);
|
||||
assert(ca.length >= 0);
|
||||
|
||||
// Make sure table[] is sorted correctly
|
||||
int j;
|
||||
|
||||
for (j = 1; j < table.length; j++)
|
||||
{
|
||||
int len1 = table[j - 1].length;
|
||||
int len2 = table[j].length;
|
||||
|
||||
assert(len1 <= len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
|
||||
assert(c < 0); // c==0 means a duplicate
|
||||
}
|
||||
}
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
//printf("out _d_switch_string()\n");
|
||||
if (result == -1)
|
||||
{
|
||||
// Not found
|
||||
for (i = 0; i < table.length; i++)
|
||||
{
|
||||
if (table[i].length == ca.length)
|
||||
{ c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
|
||||
assert(c != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0 <= result && result < table.length);
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
assert(i < table.length);
|
||||
if (table[i].length == ca.length)
|
||||
{
|
||||
c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
|
||||
if (c == 0)
|
||||
{
|
||||
assert(i == result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body
|
||||
{
|
||||
//printf("body _d_switch_ustring()\n");
|
||||
int low;
|
||||
int high;
|
||||
int mid;
|
||||
int c;
|
||||
wchar[] pca;
|
||||
|
||||
low = 0;
|
||||
high = table.length;
|
||||
|
||||
/*
|
||||
// Print table
|
||||
wprintf("ca[] = '%.*s'\n", ca);
|
||||
for (mid = 0; mid < high; mid++)
|
||||
{
|
||||
pca = table[mid];
|
||||
wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
|
||||
}
|
||||
*/
|
||||
|
||||
// Do binary search
|
||||
while (low < high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
pca = table[mid];
|
||||
c = ca.length - pca.length;
|
||||
if (c == 0)
|
||||
{
|
||||
c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
|
||||
if (c == 0)
|
||||
{ //printf("found %d\n", mid);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
//printf("not found\n");
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
switch (cast(wchar []) "c")
|
||||
{
|
||||
case "coo":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
* Same thing, but for wide chars.
|
||||
*/
|
||||
|
||||
int _d_switch_dstring(dchar[][] table, dchar[] ca)
|
||||
in
|
||||
{
|
||||
//printf("in _d_switch_dstring()\n");
|
||||
assert(table.length >= 0);
|
||||
assert(ca.length >= 0);
|
||||
|
||||
// Make sure table[] is sorted correctly
|
||||
int j;
|
||||
|
||||
for (j = 1; j < table.length; j++)
|
||||
{
|
||||
int len1 = table[j - 1].length;
|
||||
int len2 = table[j].length;
|
||||
|
||||
assert(len1 <= len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
|
||||
assert(c < 0); // c==0 means a duplicate
|
||||
}
|
||||
}
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
//printf("out _d_switch_string()\n");
|
||||
if (result == -1)
|
||||
{
|
||||
// Not found
|
||||
for (i = 0; i < table.length; i++)
|
||||
{
|
||||
if (table[i].length == ca.length)
|
||||
{ c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
|
||||
assert(c != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0 <= result && result < table.length);
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
assert(i < table.length);
|
||||
if (table[i].length == ca.length)
|
||||
{
|
||||
c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
|
||||
if (c == 0)
|
||||
{
|
||||
assert(i == result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body
|
||||
{
|
||||
//printf("body _d_switch_ustring()\n");
|
||||
int low;
|
||||
int high;
|
||||
int mid;
|
||||
int c;
|
||||
dchar[] pca;
|
||||
|
||||
low = 0;
|
||||
high = table.length;
|
||||
|
||||
/*
|
||||
// Print table
|
||||
wprintf("ca[] = '%.*s'\n", ca);
|
||||
for (mid = 0; mid < high; mid++)
|
||||
{
|
||||
pca = table[mid];
|
||||
wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
|
||||
}
|
||||
*/
|
||||
|
||||
// Do binary search
|
||||
while (low < high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
pca = table[mid];
|
||||
c = ca.length - pca.length;
|
||||
if (c == 0)
|
||||
{
|
||||
c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
|
||||
if (c == 0)
|
||||
{ //printf("found %d\n", mid);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
//printf("not found\n");
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
switch (cast(dchar []) "c")
|
||||
{
|
||||
case "coo":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _d_switch_error(string fn, int line)
|
||||
{
|
||||
throw new Exception(fn~toString(line)~": switch missing default");
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
export PATH=$PATH:/opt/llvm/bin
|
||||
export FILE=$1; shift
|
||||
export LDC_PATH=~/ldc
|
||||
PARAM=$(for p_file in $($LDC_PATH/bin/ldc $FILE -I~/ldc/lphobos -c -v -of/dev/null |grep import \
|
||||
|sed -e "s/import *//" -e "s/\t.*//" \
|
||||
|sed -e "s/\./\//g" -e "s/$/\.d/"); do if [ -f $p_file ]; then echo $p_file; fi; done)
|
||||
echo ldc $FILE $@ $PARAM
|
||||
$LDC_PATH/bin/ldc $FILE $@ $PARAM
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
[Environment]
|
||||
|
||||
DFLAGS=-I%@P%/../lphobos -I%@P%/../import -L-L%@P%/../lib
|
||||
# -R%@P%/../lib
|
||||
@@ -1,140 +0,0 @@
|
||||
module llvm.intrinsic;
|
||||
|
||||
// code generator intrinsics
|
||||
/*
|
||||
pragma(intrinsic, "llvm.returnaddress")
|
||||
void* llvm_returnaddress(uint level);
|
||||
*/
|
||||
pragma(intrinsic, "llvm.frameaddress")
|
||||
void* llvm_frameaddress(uint level);
|
||||
/*
|
||||
pragma(intrinsic, "llvm.stacksave")
|
||||
void* llvm_stacksave();
|
||||
|
||||
pragma(intrinsic, "llvm.stackrestore")
|
||||
void llvm_stackrestore(void* ptr);
|
||||
|
||||
pragma(intrinsic, "llvm.pcmarker")
|
||||
void llvm_pcmarker(uint id);
|
||||
|
||||
pragma(intrinsic, "llvm.prefetch")
|
||||
void llvm_prefetch(void* ptr, uint rw, uint locality);
|
||||
*/
|
||||
|
||||
pragma(intrinsic, "llvm.readcyclecounter")
|
||||
ulong readcyclecounter();
|
||||
|
||||
// standard C intrinsics
|
||||
pragma(intrinsic, "llvm.memcpy.i32")
|
||||
void llvm_memcpy_i32(void* dst, void* src, uint len, uint alignment);
|
||||
|
||||
pragma(intrinsic, "llvm.memcpy.i64")
|
||||
void llvm_memcpy_i64(void* dst, void* src, ulong len, uint alignment);
|
||||
|
||||
pragma(intrinsic, "llvm.memmove.i32")
|
||||
void llvm_memmove_i32(void* dst, void* src, uint len, uint alignment);
|
||||
|
||||
pragma(intrinsic, "llvm.memmove.i64")
|
||||
void llvm_memmove_i64(void* dst, void* src, ulong len, int alignment);
|
||||
|
||||
pragma(intrinsic, "llvm.memset.i32")
|
||||
void llvm_memset_i32(void* dst, ubyte val, uint len, uint alignment);
|
||||
|
||||
pragma(intrinsic, "llvm.memset.i64")
|
||||
void llvm_memset_i64(void* dst, ubyte val, ulong len, uint alignment);
|
||||
|
||||
pragma(intrinsic, "llvm.sqrt.f32")
|
||||
float llvm_sqrt(float val);
|
||||
|
||||
pragma(intrinsic, "llvm.sqrt.f64")
|
||||
{
|
||||
double llvm_sqrt(double val);
|
||||
// real llvm_sqrt(real val);
|
||||
}
|
||||
|
||||
pragma(intrinsic, "llvm.powi.f32")
|
||||
float llvm_powi(float val, int power);
|
||||
|
||||
pragma(intrinsic, "llvm.powi.f64")
|
||||
{
|
||||
double llvm_powi(double val, int power);
|
||||
// real llvm_powi(real val, int power);
|
||||
}
|
||||
|
||||
// bit manipulation intrinsics
|
||||
pragma(intrinsic, "llvm.bswap.i16.i16")
|
||||
ushort llvm_bswap(ushort val);
|
||||
|
||||
pragma(intrinsic, "llvm.bswap.i32.i32")
|
||||
uint llvm_bswap(uint val);
|
||||
|
||||
pragma(intrinsic, "llvm.bswap.i64.i64")
|
||||
ulong llvm_bswap(ulong val);
|
||||
|
||||
/*
|
||||
pragma(intrinsic, "llvm.ctpop.i8")
|
||||
uint llvm_ctpop_i8(ubyte src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctpop.i16")
|
||||
uint llvm_ctpop_i16(ushort src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctpop.i32")
|
||||
uint llvm_ctpop_i32(uint src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctpop.i64")
|
||||
uint llvm_ctpop_i64(ulong src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctlz.i8")
|
||||
uint llvm_ctlz_i8(ubyte src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctlz.i16")
|
||||
uint llvm_ctlz_i16(ushort src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctlz.i32")
|
||||
uint llvm_ctlz_i32(uint src);
|
||||
|
||||
pragma(intrinsic, "llvm.ctlz.i64")
|
||||
uint llvm_ctlz_i64(ulong src);
|
||||
|
||||
pragma(intrinsic, "llvm.cttz.i8")
|
||||
uint llvm_cttz_i8(ubyte src);
|
||||
|
||||
pragma(intrinsic, "llvm.cttz.i16")
|
||||
uint llvm_cttz_i16(ushort src);
|
||||
|
||||
pragma(intrinsic, "llvm.cttz.i32")
|
||||
uint llvm_cttz_i32(uint src);
|
||||
|
||||
pragma(intrinsic, "llvm.cttz.i64")
|
||||
uint llvm_cttz_i64(ulong src);
|
||||
*/
|
||||
|
||||
// atomic operations and synchronization intrinsics
|
||||
// TODO
|
||||
/*
|
||||
|
||||
//declare i8 @llvm.atomic.lcs.i8.i8p.i8.i8( i8* <ptr>, i8 <cmp>, i8 <val> )
|
||||
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> )
|
||||
declare i32 @llvm.atomic.lcs.i32.i32p.i32.i32( i32* <ptr>, i32 <cmp>, i32 <val> )
|
||||
declare i64 @llvm.atomic.lcs.i64.i64p.i64.i64( i64* <ptr>, i64 <cmp>, i64 <val> )
|
||||
|
||||
declare i8 @llvm.atomic.ls.i8.i8p.i8( i8* <ptr>, i8 <val> )
|
||||
declare i16 @llvm.atomic.ls.i16.i16p.i16( i16* <ptr>, i16 <val> )
|
||||
declare i32 @llvm.atomic.ls.i32.i32p.i32( i32* <ptr>, i32 <val> )
|
||||
declare i64 @llvm.atomic.ls.i64.i64p.i64( i64* <ptr>, i64 <val> )
|
||||
|
||||
declare i8 @llvm.atomic.las.i8.i8p.i8( i8* <ptr>, i8 <delta> )
|
||||
declare i16 @llvm.atomic.las.i16.i16p.i16( i16* <ptr>, i16 <delta> )
|
||||
declare i32 @llvm.atomic.las.i32.i32p.i32( i32* <ptr>, i32 <delta> )
|
||||
declare i64 @llvm.atomic.las.i64.i64p.i64( i64* <ptr>, i64 <delta> )
|
||||
|
||||
declare i8 @llvm.atomic.lss.i8.i8.i8( i8* <ptr>, i8 <delta> )
|
||||
declare i16 @llvm.atomic.lss.i16.i16.i16( i16* <ptr>, i16 <delta> )
|
||||
declare i32 @llvm.atomic.lss.i32.i32.i32( i32* <ptr>, i32 <delta> )
|
||||
declare i64 @llvm.atomic.lss.i64.i64.i64( i64* <ptr>, i64 <delta> )
|
||||
|
||||
declare void @llvm.memory.barrier( i1 <ll>, i1 <ls>, i1 <sl>, i1 <ss> )
|
||||
*/
|
||||
@@ -1,25 +0,0 @@
|
||||
module llvm.va_list;
|
||||
|
||||
alias void* va_list;
|
||||
|
||||
/*
|
||||
|
||||
version(X86)
|
||||
{
|
||||
alias void* va_list;
|
||||
}
|
||||
else version(X86_64)
|
||||
{
|
||||
struct X86_64_va_list
|
||||
{
|
||||
uint gp_offset;
|
||||
uint fp_offset;
|
||||
void* overflow_arg_area;
|
||||
void* reg_save_area;
|
||||
}
|
||||
alias X86_64_va_list va_list;
|
||||
}
|
||||
else
|
||||
static assert("only x86 and x86-64 support va_list");
|
||||
|
||||
*/
|
||||
@@ -1,5 +0,0 @@
|
||||
module llvmsupport;
|
||||
|
||||
import
|
||||
llvm.intrinsic,
|
||||
llvm.va_list;
|
||||
209
lphobos/object.d
209
lphobos/object.d
@@ -1,209 +0,0 @@
|
||||
// Implementation is in internal\object.d
|
||||
|
||||
module object;
|
||||
|
||||
//alias bit bool;
|
||||
alias bool bit;
|
||||
|
||||
alias typeof(int.sizeof) size_t;
|
||||
alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t;
|
||||
alias size_t hash_t;
|
||||
|
||||
alias char[] string;
|
||||
alias wchar[] wstring;
|
||||
alias dchar[] dstring;
|
||||
|
||||
extern (C)
|
||||
{ int printf(char *, ...);
|
||||
void trace_term();
|
||||
}
|
||||
|
||||
class Object
|
||||
{
|
||||
void print();
|
||||
char[] toString();
|
||||
hash_t toHash();
|
||||
int opCmp(Object o);
|
||||
int opEquals(Object o);
|
||||
|
||||
final void notifyRegister(void delegate(Object) dg);
|
||||
final void notifyUnRegister(void delegate(Object) dg);
|
||||
|
||||
static Object factory(char[] classname);
|
||||
}
|
||||
|
||||
struct Interface
|
||||
{
|
||||
ClassInfo classinfo;
|
||||
void *[] vtbl;
|
||||
int offset; // offset to Interface 'this' from Object 'this'
|
||||
}
|
||||
|
||||
class ClassInfo : Object
|
||||
{
|
||||
byte[] init; // class static initializer
|
||||
char[] name; // class name
|
||||
void *[] vtbl; // virtual function pointer table
|
||||
Interface[] interfaces;
|
||||
ClassInfo base;
|
||||
void *destructor;
|
||||
void (*classInvariant)(Object);
|
||||
uint flags;
|
||||
// 1: // IUnknown
|
||||
// 2: // has no possible pointers into GC memory
|
||||
// 4: // has offTi[] member
|
||||
// 8: // has constructors
|
||||
void *deallocator;
|
||||
OffsetTypeInfo[] offTi;
|
||||
void* defaultConstructor; // default Constructor
|
||||
|
||||
static ClassInfo find(char[] classname);
|
||||
Object create();
|
||||
}
|
||||
|
||||
struct OffsetTypeInfo
|
||||
{
|
||||
size_t offset;
|
||||
TypeInfo ti;
|
||||
}
|
||||
|
||||
class TypeInfo
|
||||
{
|
||||
hash_t getHash(void *p);
|
||||
int equals(void *p1, void *p2);
|
||||
int compare(void *p1, void *p2);
|
||||
size_t tsize();
|
||||
void swap(void *p1, void *p2);
|
||||
TypeInfo next();
|
||||
void[] init();
|
||||
uint flags();
|
||||
// 1: // has possible pointers into GC memory
|
||||
OffsetTypeInfo[] offTi();
|
||||
}
|
||||
|
||||
pragma(no_typeinfo)
|
||||
class TypeInfo_Typedef : TypeInfo
|
||||
{
|
||||
TypeInfo base;
|
||||
char[] name;
|
||||
void[] m_init;
|
||||
}
|
||||
|
||||
class TypeInfo_Enum : TypeInfo_Typedef
|
||||
{
|
||||
}
|
||||
|
||||
class TypeInfo_Pointer : TypeInfo
|
||||
{
|
||||
TypeInfo m_next;
|
||||
}
|
||||
|
||||
class TypeInfo_Array : TypeInfo
|
||||
{
|
||||
TypeInfo value;
|
||||
}
|
||||
|
||||
class TypeInfo_StaticArray : TypeInfo
|
||||
{
|
||||
TypeInfo value;
|
||||
size_t len;
|
||||
}
|
||||
|
||||
class TypeInfo_AssociativeArray : TypeInfo
|
||||
{
|
||||
TypeInfo value;
|
||||
TypeInfo key;
|
||||
}
|
||||
|
||||
class TypeInfo_Function : TypeInfo
|
||||
{
|
||||
TypeInfo next;
|
||||
}
|
||||
|
||||
class TypeInfo_Delegate : TypeInfo
|
||||
{
|
||||
TypeInfo next;
|
||||
}
|
||||
|
||||
class TypeInfo_Class : TypeInfo
|
||||
{
|
||||
ClassInfo info;
|
||||
}
|
||||
|
||||
class TypeInfo_Interface : TypeInfo
|
||||
{
|
||||
ClassInfo info;
|
||||
}
|
||||
|
||||
class TypeInfo_Struct : TypeInfo
|
||||
{
|
||||
char[] name;
|
||||
void[] m_init;
|
||||
|
||||
uint function(void*) xtoHash;
|
||||
int function(void*,void*) xopEquals;
|
||||
int function(void*,void*) xopCmp;
|
||||
char[] function(void*) xtoString;
|
||||
|
||||
uint m_flags;
|
||||
}
|
||||
|
||||
class TypeInfo_Tuple : TypeInfo
|
||||
{
|
||||
TypeInfo[] elements;
|
||||
}
|
||||
|
||||
class TypeInfo_Const : TypeInfo
|
||||
{
|
||||
TypeInfo next;
|
||||
}
|
||||
|
||||
class TypeInfo_Invariant : TypeInfo_Const
|
||||
{
|
||||
}
|
||||
|
||||
class ModuleInfo
|
||||
{
|
||||
char[] name;
|
||||
ModuleInfo[] importedModules;
|
||||
ClassInfo[] localClasses;
|
||||
|
||||
uint flags; // initialization state
|
||||
|
||||
void function() ctor;
|
||||
void function() dtor;
|
||||
void function() unitTest;
|
||||
void* xgetMembers;
|
||||
void function() ictor;
|
||||
|
||||
// Return collection of all modules in the program.
|
||||
static int opApply(int delegate(ref ModuleInfo));
|
||||
}
|
||||
|
||||
struct ModuleReference {
|
||||
ModuleReference* next;
|
||||
ModuleInfo mod;
|
||||
}
|
||||
extern(C) extern ModuleReference* _Dmodule_ref;
|
||||
|
||||
// Recoverable errors
|
||||
|
||||
class Exception : Object
|
||||
{
|
||||
string msg;
|
||||
|
||||
this(string msg);
|
||||
override void print();
|
||||
override string toString();
|
||||
}
|
||||
|
||||
// Non-recoverable errors
|
||||
|
||||
class Error : Exception
|
||||
{
|
||||
Error next;
|
||||
|
||||
this(string msg);
|
||||
this(string msg, Error next);
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
module phobos;
|
||||
|
||||
import
|
||||
std.array,
|
||||
std.base64,
|
||||
std.ctype,
|
||||
std.format,
|
||||
std.intrinsic,
|
||||
std.math,
|
||||
std.moduleinit,
|
||||
std.outofmemory,
|
||||
std.stdarg,
|
||||
std.stdint,
|
||||
std.stdio,
|
||||
std.string,
|
||||
std.thread,
|
||||
std.traits,
|
||||
std.uni,
|
||||
std.utf,
|
||||
|
||||
std.c.fenv,
|
||||
std.c.locale,
|
||||
std.c.math,
|
||||
std.c.process,
|
||||
std.c.stdarg,
|
||||
std.c.stddef,
|
||||
std.c.stdio,
|
||||
std.c.stdlib,
|
||||
std.c.string,
|
||||
std.c.time,
|
||||
std.file,
|
||||
std.date,
|
||||
std.socket,
|
||||
std.zlib,
|
||||
std.cstream;
|
||||
|
||||
version(linux) {
|
||||
import
|
||||
std.c.linux.linux,
|
||||
std.c.linux.linuxextern,
|
||||
std.c.linux.pthread,
|
||||
std.c.linux.socket;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
|
||||
module std.array;
|
||||
|
||||
private import std.c.stdio;
|
||||
|
||||
class ArrayBoundsError : Error
|
||||
{
|
||||
private:
|
||||
|
||||
uint linnum;
|
||||
char[] filename;
|
||||
|
||||
public:
|
||||
this(char[] filename, uint linnum)
|
||||
{
|
||||
this.linnum = linnum;
|
||||
this.filename = filename;
|
||||
|
||||
char[] buffer = new char[19 + filename.length + linnum.sizeof * 3 + 1];
|
||||
int len;
|
||||
len = sprintf(buffer.ptr, "ArrayBoundsError %.*s(%u)", filename, linnum);
|
||||
super(buffer[0..len]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Called by the compiler generated module assert function.
|
||||
* Builds an ArrayBoundsError exception and throws it.
|
||||
*/
|
||||
|
||||
extern (C) static void _d_array_bounds(char[] filename, uint line)
|
||||
{
|
||||
//printf("_d_assert(%s, %d)\n", (char *)filename, line);
|
||||
ArrayBoundsError a = new ArrayBoundsError(filename, line);
|
||||
//printf("assertion %p created\n", a);
|
||||
throw a;
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
/**
|
||||
* Encodes/decodes MIME base64 data.
|
||||
*
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdBase64
|
||||
* References:
|
||||
* <a href="http://en.wikipedia.org/wiki/Base64">Wikipedia Base64</a>$(BR)
|
||||
* <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>$(BR)
|
||||
*/
|
||||
|
||||
|
||||
/* base64.d
|
||||
* Modified from C. Miller's version, his copyright is below.
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (C) 2004 Christopher E. Miller
|
||||
|
||||
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:
|
||||
|
||||
1. 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.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
module std.base64;
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
class Base64Exception: Exception
|
||||
{
|
||||
this(char[] msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
class Base64CharException: Base64Exception
|
||||
{
|
||||
this(char[] msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char[] array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of bytes needed to encode a string of length slen.
|
||||
*/
|
||||
|
||||
uint encodeLength(uint slen)
|
||||
{
|
||||
uint result;
|
||||
result = slen / 3;
|
||||
if(slen % 3)
|
||||
result++;
|
||||
return result * 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes str[] and places the result in buf[].
|
||||
* Params:
|
||||
* str = string to encode
|
||||
* buf = destination buffer, must be large enough for the result.
|
||||
* Returns:
|
||||
* slice into buf[] representing encoded result
|
||||
*/
|
||||
|
||||
char[] encode(char[] str, char[] buf)
|
||||
in
|
||||
{
|
||||
assert(buf.length >= encodeLength(str.length));
|
||||
}
|
||||
body
|
||||
{
|
||||
if(!str.length)
|
||||
return buf[0 .. 0];
|
||||
|
||||
uint stri;
|
||||
uint strmax = str.length / 3;
|
||||
uint strleft = str.length % 3;
|
||||
uint x;
|
||||
char* sp, bp;
|
||||
|
||||
bp = &buf[0];
|
||||
sp = &str[0];
|
||||
for(stri = 0; stri != strmax; stri++)
|
||||
{
|
||||
x = (sp[0] << 16) | (sp[1] << 8) | (sp[2]);
|
||||
sp+= 3;
|
||||
*bp++ = array[(x & 0b11111100_00000000_00000000) >> 18];
|
||||
*bp++ = array[(x & 0b00000011_11110000_00000000) >> 12];
|
||||
*bp++ = array[(x & 0b00000000_00001111_11000000) >> 6];
|
||||
*bp++ = array[(x & 0b00000000_00000000_00111111)];
|
||||
}
|
||||
|
||||
switch(strleft)
|
||||
{
|
||||
case 2:
|
||||
x = (sp[0] << 16) | (sp[1] << 8);
|
||||
sp += 2;
|
||||
*bp++ = array[(x & 0b11111100_00000000_00000000) >> 18];
|
||||
*bp++ = array[(x & 0b00000011_11110000_00000000) >> 12];
|
||||
*bp++ = array[(x & 0b00000000_00001111_11000000) >> 6];
|
||||
*bp++ = '=';
|
||||
break;
|
||||
|
||||
case 1:
|
||||
x = *sp++ << 16;
|
||||
*bp++ = array[(x & 0b11111100_00000000_00000000) >> 18];
|
||||
*bp++ = array[(x & 0b00000011_11110000_00000000) >> 12];
|
||||
*bp++ = '=';
|
||||
*bp++ = '=';
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return buf[0 .. (bp - &buf[0])];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encodes str[] and returns the result.
|
||||
*/
|
||||
|
||||
char[] encode(char[] str)
|
||||
{
|
||||
return encode(str, new char[encodeLength(str.length)]);
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
assert(encode("f") == "Zg==");
|
||||
assert(encode("fo") == "Zm8=");
|
||||
assert(encode("foo") == "Zm9v");
|
||||
assert(encode("foos") == "Zm9vcw==");
|
||||
assert(encode("all your base64 are belong to foo") == "YWxsIHlvdXIgYmFzZTY0IGFyZSBiZWxvbmcgdG8gZm9v");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of bytes needed to decode an encoded string of this
|
||||
* length.
|
||||
*/
|
||||
uint decodeLength(uint elen)
|
||||
{
|
||||
return elen / 4 * 3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes str[] and places the result in buf[].
|
||||
* Params:
|
||||
* str = string to encode
|
||||
* buf = destination buffer, must be large enough for the result.
|
||||
* Returns:
|
||||
* slice into buf[] representing encoded result
|
||||
* Errors:
|
||||
* Throws Base64Exception on invalid base64 encoding in estr[].
|
||||
* Throws Base64CharException on invalid base64 character in estr[].
|
||||
*/
|
||||
char[] decode(char[] estr, char[] buf)
|
||||
in
|
||||
{
|
||||
assert(buf.length + 2 >= decodeLength(estr.length)); //account for '=' padding
|
||||
}
|
||||
body
|
||||
{
|
||||
void badc(char ch)
|
||||
{
|
||||
throw new Base64CharException("Invalid base64 character '" ~ (&ch)[0 .. 1] ~ "'");
|
||||
}
|
||||
|
||||
|
||||
uint arrayIndex(char ch)
|
||||
out(result)
|
||||
{
|
||||
assert(ch == array[result]);
|
||||
}
|
||||
body
|
||||
{
|
||||
if(ch >= 'A' && ch <= 'Z')
|
||||
return ch - 'A';
|
||||
if(ch >= 'a' && ch <= 'z')
|
||||
return 'Z' - 'A' + 1 + ch - 'a';
|
||||
if(ch >= '0' && ch <= '9')
|
||||
return 'Z' - 'A' + 1 + 'z' - 'a' + 1 + ch - '0';
|
||||
if(ch == '+')
|
||||
return 'Z' - 'A' + 1 + 'z' - 'a' + 1 + '9' - '0' + 1;
|
||||
if(ch == '/')
|
||||
return 'Z' - 'A' + 1 + 'z' - 'a' + 1 + '9' - '0' + 1 + 1;
|
||||
badc(ch);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
if(!estr.length)
|
||||
return buf[0 .. 0];
|
||||
|
||||
if(estr.length % 4)
|
||||
throw new Base64Exception("Invalid encoded base64 string");
|
||||
|
||||
uint estri;
|
||||
uint estrmax = estr.length / 4;
|
||||
uint x;
|
||||
char* sp, bp;
|
||||
char ch;
|
||||
|
||||
sp = &estr[0];
|
||||
bp = &buf[0];
|
||||
for(estri = 0; estri != estrmax; estri++)
|
||||
{
|
||||
x = arrayIndex(sp[0]) << 18 | arrayIndex(sp[1]) << 12;
|
||||
sp += 2;
|
||||
|
||||
ch = *sp++;
|
||||
if(ch == '=')
|
||||
{
|
||||
if(*sp++ != '=')
|
||||
badc('=');
|
||||
*bp++ = cast(char) (x >> 16);
|
||||
break;
|
||||
}
|
||||
x |= arrayIndex(ch) << 6;
|
||||
|
||||
ch = *sp++;
|
||||
if(ch == '=')
|
||||
{
|
||||
*bp++ = cast(char) (x >> 16);
|
||||
*bp++ = cast(char) ((x >> 8) & 0xFF);
|
||||
break;
|
||||
}
|
||||
x |= arrayIndex(ch);
|
||||
|
||||
*bp++ = cast(char) (x >> 16);
|
||||
*bp++ = cast(char) ((x >> 8) & 0xFF);
|
||||
*bp++ = cast(char) (x & 0xFF);
|
||||
}
|
||||
|
||||
return buf[0 .. (bp - &buf[0])];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes estr[] and returns the result.
|
||||
* Errors:
|
||||
* Throws Base64Exception on invalid base64 encoding in estr[].
|
||||
* Throws Base64CharException on invalid base64 character in estr[].
|
||||
*/
|
||||
|
||||
char[] decode(char[] estr)
|
||||
{
|
||||
return decode(estr, new char[decodeLength(estr.length)]);
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
assert(decode(encode("f")) == "f");
|
||||
assert(decode(encode("fo")) == "fo");
|
||||
assert(decode(encode("foo")) == "foo");
|
||||
assert(decode(encode("foos")) == "foos");
|
||||
assert(decode(encode("all your base64 are belong to foo")) == "all your base64 are belong to foo");
|
||||
|
||||
assert(decode(encode("testing some more")) == "testing some more");
|
||||
assert(decode(encode("asdf jkl;")) == "asdf jkl;");
|
||||
assert(decode(encode("base64 stuff")) == "base64 stuff");
|
||||
assert(decode(encode("\1\2\3\4\5\6\7foo\7\6\5\4\3\2\1!")) == "\1\2\3\4\5\6\7foo\7\6\5\4\3\2\1!");
|
||||
}
|
||||
|
||||
@@ -1,955 +0,0 @@
|
||||
/***********************
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
|
||||
/**
|
||||
* C's <fenv.h>
|
||||
* Authors: Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCFenv
|
||||
*/
|
||||
|
||||
module std.c.fenv;
|
||||
|
||||
extern (C):
|
||||
|
||||
/// Entire floating point environment
|
||||
|
||||
struct fenv_t
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
ushort status;
|
||||
ushort control;
|
||||
ushort round;
|
||||
ushort reserved[2];
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
ushort __control_word;
|
||||
ushort __unused1;
|
||||
ushort __status_word;
|
||||
ushort __unused2;
|
||||
ushort __tags;
|
||||
ushort __unused3;
|
||||
uint __eip;
|
||||
ushort __cs_selector;
|
||||
ushort __opcode;
|
||||
uint __data_offset;
|
||||
ushort __data_selector;
|
||||
ushort __unused5;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
alias int fexcept_t; /// Floating point status flags
|
||||
|
||||
/// The various floating point exceptions
|
||||
enum
|
||||
{
|
||||
FE_INVALID = 1, ///
|
||||
FE_DENORMAL = 2, ///
|
||||
FE_DIVBYZERO = 4, ///
|
||||
FE_OVERFLOW = 8, ///
|
||||
FE_UNDERFLOW = 0x10, ///
|
||||
FE_INEXACT = 0x20, ///
|
||||
FE_ALL_EXCEPT = 0x3F, /// Mask of all the exceptions
|
||||
}
|
||||
|
||||
/// Rounding modes
|
||||
enum
|
||||
{
|
||||
FE_TONEAREST = 0, ///
|
||||
FE_UPWARD = 0x800, ///
|
||||
FE_DOWNWARD = 0x400, ///
|
||||
FE_TOWARDZERO = 0xC00, ///
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
extern fenv_t _FE_DFL_ENV;
|
||||
|
||||
/// Default floating point environment
|
||||
fenv_t* FE_DFL_ENV = &_FE_DFL_ENV;
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
/// Default floating point environment
|
||||
fenv_t* FE_DFL_ENV = cast(fenv_t*)(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
|
||||
/// Floating point precision
|
||||
enum
|
||||
{
|
||||
FE_FLTPREC = 0, ///
|
||||
FE_DBLPREC = 0x200, ///
|
||||
FE_LDBLPREC = 0x300, ///
|
||||
}
|
||||
|
||||
int fetestexcept(int excepts); ///
|
||||
int feraiseexcept(int excepts); ///
|
||||
int feclearexcept(int excepts); ///
|
||||
//int fegetexcept(fexcept_t *flagp,int excepts); ///
|
||||
//int fesetexcept(fexcept_t *flagp,int excepts); ///
|
||||
int fegetround(); ///
|
||||
int fesetround(int round); ///
|
||||
int fegetprec(); ///
|
||||
int fesetprec(int prec); ///
|
||||
int fegetenv(fenv_t *envp); ///
|
||||
int fesetenv(fenv_t *envp); ///
|
||||
//void feprocentry(fenv_t *envp); ///
|
||||
//void feprocexit(const fenv_t *envp); ///
|
||||
|
||||
int fegetexceptflag(fexcept_t *flagp,int excepts); ///
|
||||
int fesetexceptflag(fexcept_t *flagp,int excepts); ///
|
||||
int feholdexcept(fenv_t *envp); ///
|
||||
int feupdateenv(fenv_t *envp); ///
|
||||
|
||||
@@ -1,478 +0,0 @@
|
||||
|
||||
/* Written by Walter Bright, Christopher E. Miller, and many others.
|
||||
* www.digitalmars.com
|
||||
* Placed into public domain.
|
||||
* Linux(R) is the registered trademark of Linus Torvalds in the U.S. and other
|
||||
* countries.
|
||||
*/
|
||||
|
||||
module std.c.linux.linux;
|
||||
|
||||
public import std.c.linux.linuxextern;
|
||||
public import std.c.linux.pthread;
|
||||
|
||||
private import std.c.stdio;
|
||||
|
||||
alias int pid_t;
|
||||
alias int off_t;
|
||||
alias uint mode_t;
|
||||
|
||||
alias uint uid_t;
|
||||
alias uint gid_t;
|
||||
|
||||
static if (size_t.sizeof == 4)
|
||||
alias int ssize_t;
|
||||
else
|
||||
alias long ssize_t;
|
||||
|
||||
enum : int
|
||||
{
|
||||
SIGHUP = 1,
|
||||
SIGINT = 2,
|
||||
SIGQUIT = 3,
|
||||
SIGILL = 4,
|
||||
SIGTRAP = 5,
|
||||
SIGABRT = 6,
|
||||
SIGIOT = 6,
|
||||
SIGBUS = 7,
|
||||
SIGFPE = 8,
|
||||
SIGKILL = 9,
|
||||
SIGUSR1 = 10,
|
||||
SIGSEGV = 11,
|
||||
SIGUSR2 = 12,
|
||||
SIGPIPE = 13,
|
||||
SIGALRM = 14,
|
||||
SIGTERM = 15,
|
||||
SIGSTKFLT = 16,
|
||||
SIGCHLD = 17,
|
||||
SIGCONT = 18,
|
||||
SIGSTOP = 19,
|
||||
SIGTSTP = 20,
|
||||
SIGTTIN = 21,
|
||||
SIGTTOU = 22,
|
||||
SIGURG = 23,
|
||||
SIGXCPU = 24,
|
||||
SIGXFSZ = 25,
|
||||
SIGVTALRM = 26,
|
||||
SIGPROF = 27,
|
||||
SIGWINCH = 28,
|
||||
SIGPOLL = 29,
|
||||
SIGIO = 29,
|
||||
SIGPWR = 30,
|
||||
SIGSYS = 31,
|
||||
SIGUNUSED = 31,
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
O_RDONLY = 0,
|
||||
O_WRONLY = 1,
|
||||
O_RDWR = 2,
|
||||
O_CREAT = 0100,
|
||||
O_EXCL = 0200,
|
||||
O_TRUNC = 01000,
|
||||
O_APPEND = 02000,
|
||||
}
|
||||
|
||||
struct struct_stat // distinguish it from the stat() function
|
||||
{
|
||||
ulong st_dev; /// device
|
||||
ushort __pad1;
|
||||
uint st_ino; /// file serial number
|
||||
uint st_mode; /// file mode
|
||||
uint st_nlink; /// link count
|
||||
uint st_uid; /// user ID of file's owner
|
||||
uint st_gid; /// user ID of group's owner
|
||||
ulong st_rdev; /// if device then device number
|
||||
ushort __pad2;
|
||||
int st_size; /// file size in bytes
|
||||
int st_blksize; /// optimal I/O block size
|
||||
int st_blocks; /// number of allocated 512 byte blocks
|
||||
int st_atime;
|
||||
uint st_atimensec;
|
||||
int st_mtime;
|
||||
uint st_mtimensec;
|
||||
int st_ctime;
|
||||
uint st_ctimensec;
|
||||
|
||||
uint __unused4;
|
||||
uint __unused5;
|
||||
}
|
||||
|
||||
static assert(struct_stat.sizeof == 88);
|
||||
|
||||
enum : int
|
||||
{
|
||||
S_IFIFO = 0010000,
|
||||
S_IFCHR = 0020000,
|
||||
S_IFDIR = 0040000,
|
||||
S_IFBLK = 0060000,
|
||||
S_IFREG = 0100000,
|
||||
S_IFLNK = 0120000,
|
||||
S_IFSOCK = 0140000,
|
||||
|
||||
S_IFMT = 0170000,
|
||||
|
||||
S_IREAD = 0000400,
|
||||
S_IWRITE = 0000200,
|
||||
S_IEXEC = 0000100,
|
||||
}
|
||||
|
||||
extern (C)
|
||||
{
|
||||
int access(char*, int);
|
||||
int open(char*, int, ...);
|
||||
int read(int, void*, int);
|
||||
int write(int, void*, int);
|
||||
int close(int);
|
||||
int lseek(int, int, int);
|
||||
int fstat(int, struct_stat*);
|
||||
int lstat(char*, struct_stat*);
|
||||
int stat(char*, struct_stat*);
|
||||
int chdir(char*);
|
||||
int mkdir(char*, int);
|
||||
int rmdir(char*);
|
||||
char* getcwd(char*, int);
|
||||
int chmod(char*, mode_t);
|
||||
int fork();
|
||||
int dup(int);
|
||||
int dup2(int, int);
|
||||
int pipe(int[2]);
|
||||
pid_t wait(int*);
|
||||
int waitpid(pid_t, int*, int);
|
||||
|
||||
uint alarm(uint);
|
||||
char* basename(char*);
|
||||
//wint_t btowc(int);
|
||||
int chown(char*, uid_t, gid_t);
|
||||
int chroot(char*);
|
||||
size_t confstr(int, char*, size_t);
|
||||
int creat(char*, mode_t);
|
||||
char* ctermid(char*);
|
||||
int dirfd(DIR*);
|
||||
char* dirname(char*);
|
||||
int fattach(int, char*);
|
||||
int fchmod(int, mode_t);
|
||||
int fdatasync(int);
|
||||
int ffs(int);
|
||||
int fmtmsg(int, char*, int, char*, char*, char*);
|
||||
int fpathconf(int, int);
|
||||
int fseeko(FILE*, off_t, int);
|
||||
off_t ftello(FILE*);
|
||||
|
||||
extern char** environ;
|
||||
}
|
||||
|
||||
struct timeval
|
||||
{
|
||||
int tv_sec;
|
||||
int tv_usec;
|
||||
}
|
||||
|
||||
struct struct_timezone
|
||||
{
|
||||
int tz_minuteswest;
|
||||
int tz_dstime;
|
||||
}
|
||||
|
||||
struct tm
|
||||
{
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
int tm_gmtoff;
|
||||
int tm_zone;
|
||||
}
|
||||
|
||||
extern (C)
|
||||
{
|
||||
int gettimeofday(timeval*, struct_timezone*);
|
||||
__time_t time(__time_t*);
|
||||
char* asctime(tm*);
|
||||
char* ctime(__time_t*);
|
||||
tm* gmtime(__time_t*);
|
||||
tm* localtime(__time_t*);
|
||||
__time_t mktime(tm*);
|
||||
char* asctime_r(tm* t, char* buf);
|
||||
char* ctime_r(__time_t* timep, char* buf);
|
||||
tm* gmtime_r(__time_t* timep, tm* result);
|
||||
tm* localtime_r(__time_t* timep, tm* result);
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
// Memory mapping from <sys/mman.h> and <bits/mman.h>
|
||||
|
||||
enum
|
||||
{
|
||||
PROT_NONE = 0,
|
||||
PROT_READ = 1,
|
||||
PROT_WRITE = 2,
|
||||
PROT_EXEC = 4,
|
||||
}
|
||||
|
||||
// Memory mapping sharing types
|
||||
|
||||
enum
|
||||
{ MAP_SHARED = 1,
|
||||
MAP_PRIVATE = 2,
|
||||
MAP_TYPE = 0x0F,
|
||||
MAP_FIXED = 0x10,
|
||||
MAP_FILE = 0,
|
||||
MAP_ANONYMOUS = 0x20,
|
||||
MAP_ANON = 0x20,
|
||||
MAP_GROWSDOWN = 0x100,
|
||||
MAP_DENYWRITE = 0x800,
|
||||
MAP_EXECUTABLE = 0x1000,
|
||||
MAP_LOCKED = 0x2000,
|
||||
MAP_NORESERVE = 0x4000,
|
||||
MAP_POPULATE = 0x8000,
|
||||
MAP_NONBLOCK = 0x10000,
|
||||
}
|
||||
|
||||
// Values for msync()
|
||||
|
||||
enum
|
||||
{ MS_ASYNC = 1,
|
||||
MS_INVALIDATE = 2,
|
||||
MS_SYNC = 4,
|
||||
}
|
||||
|
||||
// Values for mlockall()
|
||||
|
||||
enum
|
||||
{
|
||||
MCL_CURRENT = 1,
|
||||
MCL_FUTURE = 2,
|
||||
}
|
||||
|
||||
// Values for mremap()
|
||||
|
||||
enum
|
||||
{
|
||||
MREMAP_MAYMOVE = 1,
|
||||
}
|
||||
|
||||
// Values for madvise
|
||||
|
||||
enum
|
||||
{ MADV_NORMAL = 0,
|
||||
MADV_RANDOM = 1,
|
||||
MADV_SEQUENTIAL = 2,
|
||||
MADV_WILLNEED = 3,
|
||||
MADV_DONTNEED = 4,
|
||||
}
|
||||
|
||||
extern (C)
|
||||
{
|
||||
void* mmap(void*, size_t, int, int, int, off_t);
|
||||
const void* MAP_FAILED = cast(void*)-1;
|
||||
|
||||
int munmap(void*, size_t);
|
||||
int mprotect(void*, size_t, int);
|
||||
int msync(void*, size_t, int);
|
||||
int madvise(void*, size_t, int);
|
||||
int mlock(void*, size_t);
|
||||
int munlock(void*, size_t);
|
||||
int mlockall(int);
|
||||
int munlockall();
|
||||
void* mremap(void*, size_t, size_t, int);
|
||||
int mincore(void*, size_t, ubyte*);
|
||||
int remap_file_pages(void*, size_t, int, size_t, int);
|
||||
int shm_open(char*, int, int);
|
||||
int shm_unlink(char*);
|
||||
}
|
||||
|
||||
extern(C)
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
DT_UNKNOWN = 0,
|
||||
DT_FIFO = 1,
|
||||
DT_CHR = 2,
|
||||
DT_DIR = 4,
|
||||
DT_BLK = 6,
|
||||
DT_REG = 8,
|
||||
DT_LNK = 10,
|
||||
DT_SOCK = 12,
|
||||
DT_WHT = 14,
|
||||
}
|
||||
|
||||
struct dirent
|
||||
{
|
||||
int d_ino;
|
||||
off_t d_off;
|
||||
ushort d_reclen;
|
||||
ubyte d_type;
|
||||
char[256] d_name;
|
||||
}
|
||||
|
||||
struct DIR
|
||||
{
|
||||
// Managed by OS.
|
||||
}
|
||||
|
||||
DIR* opendir(char* name);
|
||||
int closedir(DIR* dir);
|
||||
dirent* readdir(DIR* dir);
|
||||
void rewinddir(DIR* dir);
|
||||
off_t telldir(DIR* dir);
|
||||
void seekdir(DIR* dir, off_t offset);
|
||||
}
|
||||
|
||||
|
||||
extern(C)
|
||||
{
|
||||
private import std.intrinsic;
|
||||
|
||||
|
||||
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, timeval* timeout);
|
||||
int fcntl(int s, int f, ...);
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
EINTR = 4,
|
||||
EINPROGRESS = 115,
|
||||
}
|
||||
|
||||
|
||||
const uint FD_SETSIZE = 1024;
|
||||
//const uint NFDBITS = 8 * int.sizeof; // DMD 0.110: 8 * (int).sizeof is not an expression
|
||||
const int NFDBITS = 32;
|
||||
|
||||
|
||||
struct fd_set
|
||||
{
|
||||
int[FD_SETSIZE / NFDBITS] fds_bits;
|
||||
alias fds_bits __fds_bits;
|
||||
}
|
||||
|
||||
|
||||
int FDELT(int d)
|
||||
{
|
||||
return d / NFDBITS;
|
||||
}
|
||||
|
||||
|
||||
int FDMASK(int d)
|
||||
{
|
||||
return 1 << (d % NFDBITS);
|
||||
}
|
||||
|
||||
|
||||
// Removes.
|
||||
void FD_CLR(int fd, fd_set* set)
|
||||
{
|
||||
btr(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS));
|
||||
}
|
||||
|
||||
|
||||
// Tests.
|
||||
int FD_ISSET(int fd, fd_set* set)
|
||||
{
|
||||
return bt(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS));
|
||||
}
|
||||
|
||||
|
||||
// Adds.
|
||||
void FD_SET(int fd, fd_set* set)
|
||||
{
|
||||
bts(cast(uint*)&set.fds_bits.ptr[FDELT(fd)], cast(uint)(fd % NFDBITS));
|
||||
}
|
||||
|
||||
|
||||
// Resets to zero.
|
||||
void FD_ZERO(fd_set* set)
|
||||
{
|
||||
set.fds_bits[] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern (C)
|
||||
{
|
||||
/* From <dlfcn.h>
|
||||
* See http://www.opengroup.org/onlinepubs/007908799/xsh/dlsym.html
|
||||
*/
|
||||
|
||||
const int RTLD_NOW = 0x00002; // Correct for Red Hat 8
|
||||
|
||||
void* dlopen(char* file, int mode);
|
||||
int dlclose(void* handle);
|
||||
void* dlsym(void* handle, char* name);
|
||||
char* dlerror();
|
||||
}
|
||||
|
||||
extern (C)
|
||||
{
|
||||
/* from <pwd.h>
|
||||
*/
|
||||
|
||||
struct passwd
|
||||
{
|
||||
char *pw_name;
|
||||
char *pw_passwd;
|
||||
uid_t pw_uid;
|
||||
gid_t pw_gid;
|
||||
char *pw_gecos;
|
||||
char *pw_dir;
|
||||
char *pw_shell;
|
||||
}
|
||||
|
||||
const size_t _SIGSET_NWORDS = 1024 / (8 * uint.sizeof);
|
||||
struct sigset_t
|
||||
{
|
||||
uint[_SIGSET_NWORDS] __val;
|
||||
}
|
||||
|
||||
int getpwnam_r(char*, passwd*, void*, size_t, passwd**);
|
||||
passwd* getpwnam(char*);
|
||||
passwd* getpwuid(uid_t);
|
||||
int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
|
||||
int kill(pid_t, int);
|
||||
int sem_close(sem_t*);
|
||||
int sigemptyset(sigset_t*);
|
||||
int sigfillset(sigset_t*);
|
||||
int sigismember(sigset_t*, int);
|
||||
int sigsuspend(sigset_t*);
|
||||
}
|
||||
|
||||
extern (C)
|
||||
{
|
||||
/* from semaphore.h
|
||||
*/
|
||||
|
||||
struct sem_t
|
||||
{
|
||||
_pthread_fastlock __sem_lock;
|
||||
int __sem_value;
|
||||
void* __sem_waiting;
|
||||
}
|
||||
|
||||
int sem_init(sem_t*, int, uint);
|
||||
int sem_wait(sem_t*);
|
||||
int sem_trywait(sem_t*);
|
||||
int sem_post(sem_t*);
|
||||
int sem_getvalue(sem_t*, int*);
|
||||
int sem_destroy(sem_t*);
|
||||
}
|
||||
|
||||
extern (C)
|
||||
{
|
||||
/* from utime.h
|
||||
*/
|
||||
|
||||
struct utimbuf
|
||||
{
|
||||
__time_t actime;
|
||||
__time_t modtime;
|
||||
}
|
||||
|
||||
int utime(char* filename, utimbuf* buf);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
/* Written by Walter Bright.
|
||||
* www.digitalmars.com
|
||||
* Placed into public domain.
|
||||
* Linux(R) is the registered trademark of Linus Torvalds in the U.S. and other
|
||||
* countries.
|
||||
*/
|
||||
|
||||
/* These are all the globals defined by the linux C runtime library.
|
||||
* Put them separate so they'll be externed - do not link in linuxextern.o
|
||||
*/
|
||||
|
||||
module std.c.linux.linuxextern;
|
||||
|
||||
extern extern (C)
|
||||
{
|
||||
void* __libc_stack_end;
|
||||
int __data_start;
|
||||
int _end;
|
||||
int timezone;
|
||||
|
||||
void *_deh_beg;
|
||||
void *_deh_end;
|
||||
}
|
||||
|
||||
@@ -1,257 +0,0 @@
|
||||
/* Written by Walter Bright, Christopher E. Miller, and many others.
|
||||
* www.digitalmars.com
|
||||
* Placed into public domain.
|
||||
*/
|
||||
|
||||
module std.c.linux.pthread;
|
||||
|
||||
extern (C)
|
||||
{
|
||||
/* pthread declarations taken from pthread headers and
|
||||
http://svn.dsource.org/projects/bindings/trunk/pthreads.d
|
||||
*/
|
||||
|
||||
/* from bits/types.h
|
||||
*/
|
||||
|
||||
typedef int __time_t;
|
||||
|
||||
/* from time.h
|
||||
*/
|
||||
|
||||
struct timespec
|
||||
{
|
||||
__time_t tv_sec; /* seconds */
|
||||
int tv_nsec; /* nanosecs. */
|
||||
}
|
||||
|
||||
/* from bits/pthreadtypes.h
|
||||
*/
|
||||
|
||||
alias uint pthread_t;
|
||||
alias uint pthread_key_t;
|
||||
alias int pthread_once_t;
|
||||
alias int clockid_t;
|
||||
alias int pthread_spinlock_t; // volatile
|
||||
|
||||
struct _pthread_descr_struct
|
||||
{
|
||||
/* Not defined in the headers ???
|
||||
Just needed here to typedef
|
||||
the _pthread_descr pointer
|
||||
*/
|
||||
}
|
||||
|
||||
typedef _pthread_descr_struct* _pthread_descr;
|
||||
|
||||
struct _pthread_fastlock
|
||||
{
|
||||
int __status;
|
||||
int __spinlock;
|
||||
}
|
||||
|
||||
typedef long __pthread_cond_align_t;
|
||||
|
||||
struct pthread_cond_t
|
||||
{
|
||||
_pthread_fastlock __c_lock;
|
||||
_pthread_descr __c_waiting;
|
||||
char[48
|
||||
- _pthread_fastlock.sizeof
|
||||
- _pthread_descr.sizeof
|
||||
- __pthread_cond_align_t.sizeof
|
||||
] __padding;
|
||||
__pthread_cond_align_t __align;
|
||||
}
|
||||
|
||||
struct pthread_condattr_t
|
||||
{
|
||||
int __dummy;
|
||||
}
|
||||
|
||||
struct pthread_mutex_t
|
||||
{
|
||||
int __m_reserved;
|
||||
int __m_count;
|
||||
_pthread_descr __m_owner;
|
||||
int __m_kind;
|
||||
_pthread_fastlock __m_lock;
|
||||
}
|
||||
|
||||
struct pthread_mutexattr_t
|
||||
{
|
||||
int __mutexkind;
|
||||
}
|
||||
|
||||
/* from pthread.h
|
||||
*/
|
||||
|
||||
struct _pthread_cleanup_buffer
|
||||
{
|
||||
void function(void*) __routine;
|
||||
void* __arg;
|
||||
int __canceltype;
|
||||
_pthread_cleanup_buffer* __prev;
|
||||
}
|
||||
|
||||
struct __sched_param // bits/sched.h
|
||||
{
|
||||
int __sched_priority;
|
||||
}
|
||||
|
||||
struct pthread_attr_t
|
||||
{
|
||||
int __detachstate;
|
||||
int __schedpolicy;
|
||||
__sched_param schedparam;
|
||||
int __inheritshed;
|
||||
int __scope;
|
||||
size_t __guardsize;
|
||||
int __stackaddr_set;
|
||||
void* __stackaddr;
|
||||
size_t __stacksize;
|
||||
}
|
||||
|
||||
struct pthread_barrier_t
|
||||
{
|
||||
_pthread_fastlock __ba_lock;
|
||||
int __ba_required;
|
||||
int __ba_present;
|
||||
_pthread_descr __ba_waiting;
|
||||
}
|
||||
|
||||
struct pthread_barrierattr_t
|
||||
{
|
||||
int __pshared;
|
||||
}
|
||||
|
||||
struct pthread_rwlockattr_t
|
||||
{
|
||||
int __lockkind;
|
||||
int __pshared;
|
||||
}
|
||||
|
||||
struct pthread_rwlock_t
|
||||
{
|
||||
_pthread_fastlock __rw_lock;
|
||||
int __rw_readers;
|
||||
_pthread_descr __rw_writer;
|
||||
_pthread_descr __rw_read_waiting;
|
||||
_pthread_descr __rw_write_waiting;
|
||||
int __rw_kind;
|
||||
int __rw_pshared;
|
||||
}
|
||||
|
||||
int pthread_mutex_init(pthread_mutex_t*, pthread_mutexattr_t*);
|
||||
int pthread_mutex_destroy(pthread_mutex_t*);
|
||||
int pthread_mutex_trylock(pthread_mutex_t*);
|
||||
int pthread_mutex_lock(pthread_mutex_t*);
|
||||
int pthread_mutex_unlock(pthread_mutex_t*);
|
||||
|
||||
int pthread_mutexattr_init(pthread_mutexattr_t*);
|
||||
int pthread_mutexattr_destroy(pthread_mutexattr_t*);
|
||||
|
||||
int pthread_cond_init(pthread_cond_t*, pthread_condattr_t*);
|
||||
int pthread_cond_destroy(pthread_cond_t*);
|
||||
int pthread_cond_signal(pthread_cond_t*);
|
||||
int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*);
|
||||
int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, timespec*);
|
||||
|
||||
int pthread_attr_init(pthread_attr_t*);
|
||||
int pthread_attr_destroy(pthread_attr_t*);
|
||||
int pthread_attr_setdetachstate(pthread_attr_t*, int);
|
||||
int pthread_attr_getdetachstate(pthread_attr_t*, int*);
|
||||
int pthread_attr_setinheritsched(pthread_attr_t*, int);
|
||||
int pthread_attr_getinheritsched(pthread_attr_t*, int*);
|
||||
int pthread_attr_setschedparam(pthread_attr_t*, __sched_param*);
|
||||
int pthread_attr_getschedparam(pthread_attr_t*, __sched_param*);
|
||||
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
|
||||
int pthread_attr_getschedpolicy(pthread_attr_t*, int*);
|
||||
int pthread_attr_setscope(pthread_attr_t*, int);
|
||||
int pthread_attr_getscope(pthread_attr_t*, int*);
|
||||
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
|
||||
int pthread_attr_getguardsize(pthread_attr_t*, size_t*);
|
||||
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
|
||||
int pthread_attr_getstack(pthread_attr_t*, void**, size_t*);
|
||||
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
|
||||
int pthread_attr_getstackaddr(pthread_attr_t*, void**);
|
||||
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
|
||||
int pthread_attr_getstacksize(pthread_attr_t*, size_t*);
|
||||
|
||||
int pthread_barrierattr_init(pthread_barrierattr_t*);
|
||||
int pthread_barrierattr_getpshared(pthread_barrierattr_t*, int*);
|
||||
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
|
||||
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
|
||||
|
||||
int pthread_barrier_init(pthread_barrier_t*, pthread_barrierattr_t*, uint);
|
||||
int pthread_barrier_destroy(pthread_barrier_t*);
|
||||
int pthread_barrier_wait(pthread_barrier_t*);
|
||||
|
||||
int pthread_condattr_init(pthread_condattr_t*);
|
||||
int pthread_condattr_destroy(pthread_condattr_t*);
|
||||
int pthread_condattr_getpshared(pthread_condattr_t*, int*);
|
||||
int pthread_condattr_setpshared(pthread_condattr_t*, int);
|
||||
|
||||
int pthread_detach(pthread_t);
|
||||
void pthread_exit(void*);
|
||||
int pthread_getattr_np(pthread_t, pthread_attr_t*);
|
||||
int pthread_getconcurrency();
|
||||
int pthread_getcpuclockid(pthread_t, clockid_t*);
|
||||
|
||||
int pthread_mutexattr_getpshared(pthread_mutexattr_t*, int*);
|
||||
int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
|
||||
int pthread_mutexattr_settype(pthread_mutexattr_t*, int);
|
||||
int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*);
|
||||
int pthread_mutex_timedlock(pthread_mutex_t*, timespec*);
|
||||
int pthread_yield();
|
||||
|
||||
int pthread_rwlock_init(pthread_rwlock_t*, pthread_rwlockattr_t*);
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t*);
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t*);
|
||||
int pthread_rwlock_tryrdlock(pthread_rwlock_t*);
|
||||
int pthread_rwlock_timedrdlock(pthread_rwlock_t*, timespec*);
|
||||
int pthread_rwlock_wrlock(pthread_rwlock_t*);
|
||||
int pthread_rwlock_trywrlock(pthread_rwlock_t*);
|
||||
int pthread_rwlock_timedwrlock(pthread_rwlock_t*, timespec*);
|
||||
int pthread_rwlock_unlock(pthread_rwlock_t*);
|
||||
|
||||
int pthread_rwlockattr_init(pthread_rwlockattr_t*);
|
||||
int pthread_rwlockattr_destroy(pthread_rwlockattr_t*);
|
||||
int pthread_rwlockattr_getpshared(pthread_rwlockattr_t*, int*);
|
||||
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
|
||||
int pthread_rwlockattr_getkind_np(pthread_rwlockattr_t*, int*);
|
||||
int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t*, int);
|
||||
|
||||
int pthread_spin_init(pthread_spinlock_t*, int);
|
||||
int pthread_spin_destroy(pthread_spinlock_t*);
|
||||
int pthread_spin_lock(pthread_spinlock_t*);
|
||||
int pthread_spin_trylock(pthread_spinlock_t*);
|
||||
int pthread_spin_unlock(pthread_spinlock_t*);
|
||||
|
||||
int pthread_cancel(pthread_t);
|
||||
void pthread_testcancel();
|
||||
int pthread_once(pthread_once_t*, void function());
|
||||
|
||||
int pthread_join(pthread_t, void**);
|
||||
int pthread_create(pthread_t*, pthread_attr_t*, void*function(void*), void*);
|
||||
pthread_t pthread_self();
|
||||
int pthread_equal(pthread_t, pthread_t);
|
||||
int pthread_atfork(void function(), void function(), void function());
|
||||
void pthread_kill_other_threads_np();
|
||||
int pthread_setschedparam(pthread_t, int, __sched_param*);
|
||||
int pthread_getschedparam(pthread_t, int*, __sched_param*);
|
||||
int pthread_cond_broadcast(pthread_cond_t*);
|
||||
int pthread_key_create(pthread_key_t*, void function(void*));
|
||||
int pthread_key_delete(pthread_key_t);
|
||||
int pthread_setconcurrency(int);
|
||||
int pthread_setspecific(pthread_key_t, void*);
|
||||
void* pthread_getspecific(pthread_key_t);
|
||||
int pthread_setcanceltype(int, int*);
|
||||
int pthread_setcancelstate(int, int*);
|
||||
|
||||
void _pthread_cleanup_push(_pthread_cleanup_buffer*, void function(void*), void*);
|
||||
void _pthread_cleanup_push_defer(_pthread_cleanup_buffer*, void function(void*), void*);
|
||||
void _pthread_cleanup_pop(_pthread_cleanup_buffer*, int);
|
||||
void _pthread_cleanup_pop_restore(_pthread_cleanup_buffer*, int);
|
||||
}
|
||||
|
||||
@@ -1,396 +0,0 @@
|
||||
/*
|
||||
Written by Christopher E. Miller
|
||||
Placed into public domain.
|
||||
*/
|
||||
|
||||
|
||||
module std.c.linux.socket;
|
||||
|
||||
private import std.stdint;
|
||||
|
||||
|
||||
extern(C):
|
||||
|
||||
alias int socklen_t;
|
||||
|
||||
const int F_GETFL = 3;
|
||||
const int F_SETFL = 4;
|
||||
const int O_NONBLOCK = 0x800;
|
||||
|
||||
|
||||
int socket(int af, int type, int protocol);
|
||||
int bind(int s, sockaddr* name, int namelen);
|
||||
int connect(int s, sockaddr* name, int namelen);
|
||||
int listen(int s, int backlog);
|
||||
int accept(int s, sockaddr* addr, int* addrlen);
|
||||
int shutdown(int s, int how);
|
||||
int getpeername(int s, sockaddr* name, int* namelen);
|
||||
int getsockname(int s, sockaddr* name, int* namelen);
|
||||
int send(int s, void* buf, int len, int flags);
|
||||
int sendto(int s, void* buf, int len, int flags, sockaddr* to, int tolen);
|
||||
int recv(int s, void* buf, int len, int flags);
|
||||
int recvfrom(int s, void* buf, int len, int flags, sockaddr* from, int* fromlen);
|
||||
int getsockopt(int s, int level, int optname, void* optval, int* optlen);
|
||||
int setsockopt(int s, int level, int optname, void* optval, int optlen);
|
||||
uint inet_addr(char* cp);
|
||||
char* inet_ntoa(in_addr ina);
|
||||
hostent* gethostbyname(char* name);
|
||||
int gethostbyname_r(char* name, hostent* ret, void* buf, size_t buflen, hostent** result, int* h_errnop);
|
||||
int gethostbyname2_r(char* name, int af, hostent* ret, void* buf, size_t buflen, hostent** result, int* h_errnop);
|
||||
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* node, socklen_t nodelen, char* service, socklen_t servicelen, int flags);
|
||||
|
||||
|
||||
|
||||
enum: int
|
||||
{
|
||||
AF_UNSPEC = 0,
|
||||
AF_UNIX = 1,
|
||||
AF_INET = 2,
|
||||
AF_IPX = 4,
|
||||
AF_APPLETALK = 5,
|
||||
AF_INET6 = 10,
|
||||
// ...
|
||||
|
||||
PF_UNSPEC = AF_UNSPEC,
|
||||
PF_UNIX = AF_UNIX,
|
||||
PF_INET = AF_INET,
|
||||
PF_IPX = AF_IPX,
|
||||
PF_APPLETALK = AF_APPLETALK,
|
||||
PF_INET6 = AF_INET6,
|
||||
}
|
||||
|
||||
|
||||
version(X86)
|
||||
version=SOL_SOCKET_IS_1;
|
||||
else version(X86_64)
|
||||
version=SOL_SOCKET_IS_1;
|
||||
else version(PPC)
|
||||
version=SOL_SOCKET_IS_1;
|
||||
else version(PPC64)
|
||||
version=SOL_SOCKET_IS_1;
|
||||
else
|
||||
static assert(0, "Unsupported architecture");
|
||||
|
||||
version(SOL_SOCKET_IS_1)
|
||||
{
|
||||
enum: int
|
||||
{
|
||||
SOL_SOCKET = 1,
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Different values on other platforms.
|
||||
static assert(0);
|
||||
}
|
||||
|
||||
|
||||
enum: int
|
||||
{
|
||||
SO_DEBUG = 1,
|
||||
SO_BROADCAST = 6,
|
||||
SO_REUSEADDR = 2,
|
||||
SO_LINGER = 13,
|
||||
SO_DONTLINGER = ~SO_LINGER,
|
||||
SO_OOBINLINE = 10,
|
||||
SO_SNDBUF = 7,
|
||||
SO_RCVBUF = 8,
|
||||
SO_ACCEPTCONN = 30,
|
||||
SO_DONTROUTE = 5,
|
||||
SO_TYPE = 3,
|
||||
|
||||
TCP_NODELAY = 1,
|
||||
|
||||
IP_MULTICAST_LOOP = 34,
|
||||
IP_ADD_MEMBERSHIP = 35,
|
||||
IP_DROP_MEMBERSHIP = 36,
|
||||
|
||||
// ...
|
||||
|
||||
IPV6_ADDRFORM = 1,
|
||||
IPV6_PKTINFO = 2,
|
||||
IPV6_HOPOPTS = 3,
|
||||
IPV6_DSTOPTS = 4,
|
||||
IPV6_RTHDR = 5,
|
||||
IPV6_PKTOPTIONS = 6,
|
||||
IPV6_CHECKSUM = 7,
|
||||
IPV6_HOPLIMIT = 8,
|
||||
IPV6_NEXTHOP = 9,
|
||||
IPV6_AUTHHDR = 10,
|
||||
IPV6_UNICAST_HOPS = 16,
|
||||
IPV6_MULTICAST_IF = 17,
|
||||
IPV6_MULTICAST_HOPS = 18,
|
||||
IPV6_MULTICAST_LOOP = 19,
|
||||
IPV6_JOIN_GROUP = 20,
|
||||
IPV6_LEAVE_GROUP = 21,
|
||||
IPV6_ROUTER_ALERT = 22,
|
||||
IPV6_MTU_DISCOVER = 23,
|
||||
IPV6_MTU = 24,
|
||||
IPV6_RECVERR = 25,
|
||||
IPV6_V6ONLY = 26,
|
||||
IPV6_JOIN_ANYCAST = 27,
|
||||
IPV6_LEAVE_ANYCAST = 28,
|
||||
IPV6_IPSEC_POLICY = 34,
|
||||
IPV6_XFRM_POLICY = 35,
|
||||
}
|
||||
|
||||
|
||||
struct linger
|
||||
{
|
||||
int32_t l_onoff;
|
||||
int32_t l_linger;
|
||||
}
|
||||
|
||||
|
||||
struct protoent
|
||||
{
|
||||
char* p_name;
|
||||
char** p_aliases;
|
||||
int32_t p_proto;
|
||||
}
|
||||
|
||||
|
||||
struct servent
|
||||
{
|
||||
char* s_name;
|
||||
char** s_aliases;
|
||||
int32_t s_port;
|
||||
char* s_proto;
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
sockaddr* ai_addr;
|
||||
char* ai_canonname;
|
||||
addrinfo* ai_next;
|
||||
}
|
||||
|
||||
|
||||
struct hostent
|
||||
{
|
||||
char* h_name;
|
||||
char** h_aliases;
|
||||
int32_t h_addrtype;
|
||||
int32_t h_length;
|
||||
char** h_addr_list;
|
||||
|
||||
|
||||
char* h_addr()
|
||||
{
|
||||
return h_addr_list[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
/**
|
||||
* C's <locale.h>
|
||||
* License: Public Domain
|
||||
* Standards:
|
||||
* ISO/IEC 9899:1999 7.11
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCLocale
|
||||
*/
|
||||
module std.c.locale;
|
||||
|
||||
extern(C):
|
||||
|
||||
/// Structure giving information about numeric and monetary notation.
|
||||
struct lconv{
|
||||
/// The decimal-point character used to format nonmonetary quantities.
|
||||
char* decimal_point;
|
||||
|
||||
/** The character used to separate groups of digits before the
|
||||
* decimal-point character in formatted nonmonetary quantities.
|
||||
**/
|
||||
char* thousands_sep;
|
||||
|
||||
/** A string whose elements indicate the size of each group of digits
|
||||
* in formatted nonmonetary quantities.
|
||||
**/
|
||||
char* grouping;
|
||||
|
||||
/** The international currency symbol applicable to the current locale.
|
||||
* The first three characters contain the alphabetic international
|
||||
* currency symbol in accordance with those specified in ISO 4217.
|
||||
* The fourth character (immediately preceding the null character)
|
||||
* is the character used to separate the international currency symbol
|
||||
* from the monetary quantity.
|
||||
**/
|
||||
char* int_curr_symbol;
|
||||
|
||||
/// The local currency symbol applicable to the current locale.
|
||||
char* currency_symbol;
|
||||
|
||||
/// The decimal-point used to format monetary quantities.
|
||||
char* mon_decimal_point;
|
||||
|
||||
/** The separator for groups of digits before the decimal-point in
|
||||
* formatted monetary quantities.
|
||||
**/
|
||||
char* mon_thousands_sep;
|
||||
|
||||
/** A string whose elements indicate the size of each group of digits
|
||||
* in formatted monetary quantities.
|
||||
**/
|
||||
char* mon_grouping;
|
||||
|
||||
/** The string used to indicate a nonnegative-valued formatted
|
||||
* monetary quantity.
|
||||
**/
|
||||
char* positive_sign;
|
||||
|
||||
/** The string used to indicate a negative-valued formatted monetary
|
||||
* quantity.
|
||||
**/
|
||||
char* negative_sign;
|
||||
|
||||
/** The number of fractional digits (those after the decimal-point) to
|
||||
* be displayed in an internationally formatted monetary quantity.
|
||||
**/
|
||||
char int_frac_digits;
|
||||
|
||||
/** The number of fractional digits (those after the decimal-point) to
|
||||
* be displayed in a locally formatted monetary quantity.
|
||||
**/
|
||||
char frac_digits;
|
||||
|
||||
/// 1 if currency_symbol precedes a positive value, 0 if succeeds.
|
||||
char p_cs_precedes;
|
||||
|
||||
/// 1 if a space separates currency_symbol from a positive value.
|
||||
char p_sep_by_space;
|
||||
|
||||
/// 1 if currency_symbol precedes a negative value, 0 if succeeds.
|
||||
char n_cs_precedes;
|
||||
|
||||
/// 1 if a space separates currency_symbol from a negative value.
|
||||
char n_sep_by_space;
|
||||
|
||||
/* Positive and negative sign positions:
|
||||
0 Parentheses surround the quantity and currency_symbol.
|
||||
1 The sign string precedes the quantity and currency_symbol.
|
||||
2 The sign string follows the quantity and currency_symbol.
|
||||
3 The sign string immediately precedes the currency_symbol.
|
||||
4 The sign string immediately follows the currency_symbol. */
|
||||
char p_sign_posn;
|
||||
char n_sign_posn;
|
||||
|
||||
/// 1 if int_curr_symbol precedes a positive value, 0 if succeeds.
|
||||
char int_p_cs_precedes;
|
||||
|
||||
/// 1 iff a space separates int_curr_symbol from a positive value.
|
||||
char int_p_sep_by_space;
|
||||
|
||||
/// 1 if int_curr_symbol precedes a negative value, 0 if succeeds.
|
||||
char int_n_cs_precedes;
|
||||
|
||||
/// 1 iff a space separates int_curr_symbol from a negative value.
|
||||
char int_n_sep_by_space;
|
||||
|
||||
/* Positive and negative sign positions:
|
||||
0 Parentheses surround the quantity and int_curr_symbol.
|
||||
1 The sign string precedes the quantity and int_curr_symbol.
|
||||
2 The sign string follows the quantity and int_curr_symbol.
|
||||
3 The sign string immediately precedes the int_curr_symbol.
|
||||
4 The sign string immediately follows the int_curr_symbol. */
|
||||
char int_p_sign_posn;
|
||||
char int_n_sign_posn;
|
||||
}
|
||||
|
||||
/** Affects the behavior of C's character handling functions and C's multibyte
|
||||
* and wide character functions.
|
||||
**/
|
||||
const LC_CTYPE = 0;
|
||||
|
||||
/** Affects the decimal-point character for C's formatted input/output functions
|
||||
* and C's string conversion functions, as well as C's nonmonetary formatting
|
||||
* information returned by the localeconv function.
|
||||
**/
|
||||
const LC_NUMERIC = 1;
|
||||
|
||||
/// Affects the behavior of the strftime and wcsftime functions.
|
||||
const LC_TIME = 2;
|
||||
|
||||
/// Affects the behavior of the strcoll and strxfrm functions.
|
||||
const LC_COLLATE = 3;
|
||||
|
||||
/** Affects the monetary formatting information returned by the localeconv
|
||||
* function.
|
||||
**/
|
||||
const LC_MONETARY = 4;
|
||||
|
||||
/// The program's entire locale.
|
||||
const LC_ALL = 6;
|
||||
|
||||
/** The setlocale function selects the appropriate portion of the program's
|
||||
* locale as specified by the category and locale arguments.
|
||||
**/
|
||||
char* setlocale(int category, char* locale);
|
||||
|
||||
/** The localeconv function sets the components of an object with type
|
||||
* lconv with values appropriate for the formatting of numeric quantities
|
||||
* (monetary and otherwise) according to the rules of the current locale.
|
||||
**/
|
||||
lconv* localeconv();
|
||||
|
||||
@@ -1,291 +0,0 @@
|
||||
|
||||
/**
|
||||
* C's <math.h>
|
||||
* Authors: Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCMath
|
||||
*/
|
||||
|
||||
module std.c.math;
|
||||
|
||||
extern (C):
|
||||
|
||||
alias float float_t; ///
|
||||
alias double double_t; ///
|
||||
|
||||
const double HUGE_VAL = double.infinity; ///
|
||||
const float HUGE_VALF = float.infinity; /// ditto
|
||||
const real HUGE_VALL = real.infinity; /// ditto
|
||||
|
||||
const float INFINITY = float.infinity; ///
|
||||
const float NAN = float.nan; ///
|
||||
|
||||
enum
|
||||
{
|
||||
FP_NANS, // extension
|
||||
FP_NANQ, // extension
|
||||
FP_INFINITE, ///
|
||||
FP_NAN = FP_NANQ, ///
|
||||
FP_NORMAL = 3, ///
|
||||
FP_SUBNORMAL = 4, ///
|
||||
FP_ZERO = 5, ///
|
||||
FP_EMPTY = 6, // extension
|
||||
FP_UNSUPPORTED = 7, // extension
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
FP_FAST_FMA = 0, ///
|
||||
FP_FAST_FMAF = 0, ///
|
||||
FP_FAST_FMAL = 0, ///
|
||||
}
|
||||
|
||||
const int FP_ILOGB0 = int.min; ///
|
||||
const int FP_ILOGBNAN = int.min; ///
|
||||
|
||||
const int MATH_ERRNO = 1; ///
|
||||
const int MATH_ERREXCEPT = 2; ///
|
||||
const int math_errhandling = MATH_ERRNO | MATH_ERREXCEPT; ///
|
||||
|
||||
double acos(double x); ///
|
||||
float acosf(float x); /// ditto
|
||||
real acosl(real x); /// ditto
|
||||
|
||||
double asin(double x); ///
|
||||
float asinf(float x); /// ditto
|
||||
real asinl(real x); /// ditto
|
||||
|
||||
double atan(double x); ///
|
||||
float atanf(float x); /// ditto
|
||||
real atanl(real x); /// ditto
|
||||
|
||||
double atan2(double y, double x); ///
|
||||
float atan2f(float y, float x); /// ditto
|
||||
real atan2l(real y, real x); /// ditto
|
||||
|
||||
double cos(double x); ///
|
||||
float cosf(float x); /// ditto
|
||||
real cosl(real x); /// ditto
|
||||
|
||||
double sin(double x); ///
|
||||
float sinf(float x); /// ditto
|
||||
real sinl(real x); /// ditto
|
||||
|
||||
double tan(double x); ///
|
||||
float tanf(float x); /// ditto
|
||||
real tanl(real x); /// ditto
|
||||
|
||||
double acosh(double x); ///
|
||||
float acoshf(float x); /// ditto
|
||||
real acoshl(real x); /// ditto
|
||||
|
||||
double asinh(double x); ///
|
||||
float asinhf(float x); /// ditto
|
||||
real asinhl(real x); /// ditto
|
||||
|
||||
double atanh(double x); ///
|
||||
float atanhf(float x); /// ditto
|
||||
real atanhl(real x); /// ditto
|
||||
|
||||
double cosh(double x); ///
|
||||
float coshf(float x); /// ditto
|
||||
real coshl(real x); /// ditto
|
||||
|
||||
double sinh(double x); ///
|
||||
float sinhf(float x); /// ditto
|
||||
real sinhl(real x); /// ditto
|
||||
|
||||
double tanh(double x); ///
|
||||
float tanhf(float x); /// ditto
|
||||
real tanhl(real x); /// ditto
|
||||
|
||||
double exp(double x); ///
|
||||
float expf(float x); /// ditto
|
||||
real expl(real x); /// ditto
|
||||
|
||||
double exp2(double x); ///
|
||||
float exp2f(float x); /// ditto
|
||||
real exp2l(real x); /// ditto
|
||||
|
||||
double expm1(double x); ///
|
||||
float expm1f(float x); /// ditto
|
||||
real expm1l(real x); /// ditto
|
||||
|
||||
double frexp(double value, int *exp); ///
|
||||
float frexpf(float value, int *exp); /// ditto
|
||||
real frexpl(real value, int *exp); /// ditto
|
||||
|
||||
int ilogb(double x); ///
|
||||
int ilogbf(float x); /// ditto
|
||||
int ilogbl(real x); /// ditto
|
||||
|
||||
double ldexp(double x, int exp); ///
|
||||
float ldexpf(float x, int exp); /// ditto
|
||||
real ldexpl(real x, int exp); /// ditto
|
||||
|
||||
double log(double x); ///
|
||||
float logf(float x); /// ditto
|
||||
real logl(real x); /// ditto
|
||||
|
||||
double log10(double x); ///
|
||||
float log10f(float x); /// ditto
|
||||
real log10l(real x); /// ditto
|
||||
|
||||
double log1p(double x); ///
|
||||
float log1pf(float x); /// ditto
|
||||
real log1pl(real x); /// ditto
|
||||
|
||||
double log2(double x); ///
|
||||
float log2f(float x); /// ditto
|
||||
real log2l(real x); /// ditto
|
||||
|
||||
double logb(double x); ///
|
||||
float logbf(float x); /// ditto
|
||||
real logbl(real x); /// ditto
|
||||
|
||||
double modf(double value, double *iptr); ///
|
||||
float modff(float value, float *iptr); /// ditto
|
||||
real modfl(real value, real *iptr); /// ditto
|
||||
|
||||
double scalbn(double x, int n); ///
|
||||
float scalbnf(float x, int n); /// ditto
|
||||
real scalbnl(real x, int n); /// ditto
|
||||
|
||||
double scalbln(double x, int n); ///
|
||||
float scalblnf(float x, int n); /// ditto
|
||||
real scalblnl(real x, int n); /// ditto
|
||||
|
||||
double cbrt(double x); ///
|
||||
float cbrtf(float x); /// ditto
|
||||
real cbrtl(real x); /// ditto
|
||||
|
||||
double fabs(double x); ///
|
||||
float fabsf(float x); /// ditto
|
||||
real fabsl(real x); /// ditto
|
||||
|
||||
double hypot(double x, double y); ///
|
||||
float hypotf(float x, float y); /// ditto
|
||||
real hypotl(real x, real y); /// ditto
|
||||
|
||||
double pow(double x, double y); ///
|
||||
float powf(float x, float y); /// ditto
|
||||
real powl(real x, real y); /// ditto
|
||||
|
||||
double sqrt(double x); ///
|
||||
float sqrtf(float x); /// ditto
|
||||
real sqrtl(real x); /// ditto
|
||||
|
||||
double erf(double x); ///
|
||||
float erff(float x); /// ditto
|
||||
real erfl(real x); /// ditto
|
||||
|
||||
double erfc(double x); ///
|
||||
float erfcf(float x); /// ditto
|
||||
real erfcl(real x); /// ditto
|
||||
|
||||
double lgamma(double x); ///
|
||||
float lgammaf(float x); /// ditto
|
||||
real lgammal(real x); /// ditto
|
||||
|
||||
double tgamma(double x); ///
|
||||
float tgammaf(float x); /// ditto
|
||||
real tgammal(real x); /// ditto
|
||||
|
||||
double ceil(double x); ///
|
||||
float ceilf(float x); /// ditto
|
||||
real ceill(real x); /// ditto
|
||||
|
||||
double floor(double x); ///
|
||||
float floorf(float x); /// ditto
|
||||
real floorl(real x); /// ditto
|
||||
|
||||
double nearbyint(double x); ///
|
||||
float nearbyintf(float x); /// ditto
|
||||
real nearbyintl(real x); /// ditto
|
||||
|
||||
double rint(double x); ///
|
||||
float rintf(float x); /// ditto
|
||||
real rintl(real x); /// ditto
|
||||
|
||||
int lrint(double x); ///
|
||||
int lrintf(float x); /// ditto
|
||||
int lrintl(real x); /// ditto
|
||||
|
||||
long llrint(double x); ///
|
||||
long llrintf(float x); /// ditto
|
||||
long llrintl(real x); /// ditto
|
||||
|
||||
double round(double x); ///
|
||||
float roundf(float x); /// ditto
|
||||
real roundl(real x); /// ditto
|
||||
|
||||
int lround(double x); ///
|
||||
int lroundf(float x); /// ditto
|
||||
int lroundl(real x); /// ditto
|
||||
|
||||
long llround(double x); ///
|
||||
long llroundf(float x); /// ditto
|
||||
long llroundl(real x); /// ditto
|
||||
|
||||
double trunc(double x); ///
|
||||
float truncf(float x); /// ditto
|
||||
real truncl(real x); /// ditto
|
||||
|
||||
double fmod(double x, double y); ///
|
||||
float fmodf(float x, float y); /// ditto
|
||||
real fmodl(real x, real y); /// ditto
|
||||
|
||||
double remainder(double x, double y); ///
|
||||
float remainderf(float x, float y); /// ditto
|
||||
real remainderl(real x, real y); /// ditto
|
||||
|
||||
double remquo(double x, double y, int *quo); ///
|
||||
float remquof(float x, float y, int *quo); /// ditto
|
||||
real remquol(real x, real y, int *quo); /// ditto
|
||||
|
||||
double copysign(double x, double y); ///
|
||||
float copysignf(float x, float y); /// ditto
|
||||
real copysignl(real x, real y); /// ditto
|
||||
|
||||
double nan(char *tagp); ///
|
||||
float nanf(char *tagp); /// ditto
|
||||
real nanl(char *tagp); /// ditto
|
||||
|
||||
double nextafter(double x, double y); ///
|
||||
float nextafterf(float x, float y); /// ditto
|
||||
real nextafterl(real x, real y); /// ditto
|
||||
|
||||
double nexttoward(double x, real y); ///
|
||||
float nexttowardf(float x, real y); /// ditto
|
||||
real nexttowardl(real x, real y); /// ditto
|
||||
|
||||
double fdim(double x, double y); ///
|
||||
float fdimf(float x, float y); /// ditto
|
||||
real fdiml(real x, real y); /// ditto
|
||||
|
||||
double fmax(double x, double y); ///
|
||||
float fmaxf(float x, float y); /// ditto
|
||||
real fmaxl(real x, real y); /// ditto
|
||||
|
||||
double fmin(double x, double y); ///
|
||||
float fminf(float x, float y); /// ditto
|
||||
real fminl(real x, real y); /// ditto
|
||||
|
||||
double fma(double x, double y, double z); ///
|
||||
float fmaf(float x, float y, float z); /// ditto
|
||||
real fmal(real x, real y, real z); /// ditto
|
||||
|
||||
///
|
||||
int isgreater(real x, real y) { return !(x !> y); }
|
||||
///
|
||||
int isgreaterequal(real x, real y) { return !(x !>= y); }
|
||||
///
|
||||
int isless(real x, real y) { return !(x !< y); }
|
||||
///
|
||||
int islessequal(real x, real y) { return !(x !<= y); }
|
||||
///
|
||||
int islessgreater(real x, real y) { return !(x !<> y); }
|
||||
///
|
||||
int isunordered(real x, real y) { return (x !<>= y); }
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
|
||||
/**
|
||||
* C's <process.h>
|
||||
* Authors: Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCProcess
|
||||
*/
|
||||
|
||||
module std.c.process;
|
||||
|
||||
private import std.c.stddef;
|
||||
|
||||
extern (C):
|
||||
|
||||
void exit(int);
|
||||
void _c_exit();
|
||||
void _cexit();
|
||||
void _exit(int);
|
||||
void abort();
|
||||
void _dodtors();
|
||||
int getpid();
|
||||
|
||||
int system(char *);
|
||||
|
||||
enum { _P_WAIT, _P_NOWAIT, _P_OVERLAY };
|
||||
|
||||
int execl(char *, char *,...);
|
||||
int execle(char *, char *,...);
|
||||
int execlp(char *, char *,...);
|
||||
int execlpe(char *, char *,...);
|
||||
int execv(char *, char **);
|
||||
int execve(char *, char **, char **);
|
||||
int execvp(char *, char **);
|
||||
int execvpe(char *, char **, char **);
|
||||
|
||||
|
||||
enum { WAIT_CHILD, WAIT_GRANDCHILD }
|
||||
|
||||
int cwait(int *,int,int);
|
||||
int wait(int *);
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
uint _beginthread(void function(void *),uint,void *);
|
||||
|
||||
extern (Windows) alias uint (*stdfp)(void *);
|
||||
|
||||
uint _beginthreadex(void* security, uint stack_size,
|
||||
stdfp start_addr, void* arglist, uint initflag,
|
||||
uint* thrdaddr);
|
||||
|
||||
void _endthread();
|
||||
void _endthreadex(uint);
|
||||
|
||||
int spawnl(int, char *, char *,...);
|
||||
int spawnle(int, char *, char *,...);
|
||||
int spawnlp(int, char *, char *,...);
|
||||
int spawnlpe(int, char *, char *,...);
|
||||
int spawnv(int, char *, char **);
|
||||
int spawnve(int, char *, char **, char **);
|
||||
int spawnvp(int, char *, char **);
|
||||
int spawnvpe(int, char *, char **, char **);
|
||||
|
||||
|
||||
int _wsystem(wchar_t *);
|
||||
int _wspawnl(int, wchar_t *, wchar_t *, ...);
|
||||
int _wspawnle(int, wchar_t *, wchar_t *, ...);
|
||||
int _wspawnlp(int, wchar_t *, wchar_t *, ...);
|
||||
int _wspawnlpe(int, wchar_t *, wchar_t *, ...);
|
||||
int _wspawnv(int, wchar_t *, wchar_t **);
|
||||
int _wspawnve(int, wchar_t *, wchar_t **, wchar_t **);
|
||||
int _wspawnvp(int, wchar_t *, wchar_t **);
|
||||
int _wspawnvpe(int, wchar_t *, wchar_t **, wchar_t **);
|
||||
|
||||
int _wexecl(wchar_t *, wchar_t *, ...);
|
||||
int _wexecle(wchar_t *, wchar_t *, ...);
|
||||
int _wexeclp(wchar_t *, wchar_t *, ...);
|
||||
int _wexeclpe(wchar_t *, wchar_t *, ...);
|
||||
int _wexecv(wchar_t *, wchar_t **);
|
||||
int _wexecve(wchar_t *, wchar_t **, wchar_t **);
|
||||
int _wexecvp(wchar_t *, wchar_t **);
|
||||
int _wexecvpe(wchar_t *, wchar_t **, wchar_t **);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
/**
|
||||
* C's <stdarg.h>
|
||||
* Authors: Hauke Duden, Walter Bright and Tomas Lindquist Olsen, Digital Mars, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCStdarg
|
||||
*/
|
||||
|
||||
/* This is for use with extern(C) variable argument lists. */
|
||||
|
||||
module std.c.stdarg;
|
||||
|
||||
public import llvm.va_list;
|
||||
|
||||
pragma(va_start)
|
||||
void va_start(T)(va_list ap, ref T);
|
||||
|
||||
pragma(va_arg)
|
||||
T va_arg(T)(va_list ap);
|
||||
|
||||
pragma(va_end)
|
||||
void va_end(va_list args);
|
||||
|
||||
pragma(va_copy)
|
||||
void va_copy(va_list dst, va_list src);
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
/**
|
||||
* C's <stddef.h>
|
||||
* Authors: Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCStddef
|
||||
*/
|
||||
|
||||
module std.c.stddef;
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
alias wchar wchar_t;
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
alias dchar wchar_t;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
@@ -1,300 +0,0 @@
|
||||
|
||||
/**
|
||||
* C's <stdio.h>
|
||||
* Authors: Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCStdio
|
||||
*/
|
||||
|
||||
|
||||
|
||||
module std.c.stdio;
|
||||
|
||||
import std.c.stddef;
|
||||
private import std.c.stdarg;
|
||||
|
||||
extern (C):
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
const int _NFILE = 60; ///
|
||||
const int BUFSIZ = 0x4000; ///
|
||||
const int EOF = -1; ///
|
||||
const int FOPEN_MAX = 20; ///
|
||||
const int FILENAME_MAX = 256; /// 255 plus NULL
|
||||
const int TMP_MAX = 32767; ///
|
||||
const int _SYS_OPEN = 20; ///
|
||||
const int SYS_OPEN = _SYS_OPEN; ///
|
||||
const wchar WEOF = 0xFFFF; ///
|
||||
}
|
||||
|
||||
version (linux)
|
||||
{
|
||||
const int EOF = -1;
|
||||
const int FOPEN_MAX = 16;
|
||||
const int FILENAME_MAX = 4095;
|
||||
const int TMP_MAX = 238328;
|
||||
const int L_tmpnam = 20;
|
||||
}
|
||||
|
||||
enum { SEEK_SET, SEEK_CUR, SEEK_END }
|
||||
|
||||
struct _iobuf
|
||||
{
|
||||
align (1):
|
||||
version (Win32)
|
||||
{
|
||||
char *_ptr;
|
||||
int _cnt;
|
||||
char *_base;
|
||||
int _flag;
|
||||
int _file;
|
||||
int _charbuf;
|
||||
int _bufsiz;
|
||||
int __tmpnum;
|
||||
}
|
||||
version (linux)
|
||||
{
|
||||
char* _read_ptr;
|
||||
char* _read_end;
|
||||
char* _read_base;
|
||||
char* _write_base;
|
||||
char* _write_ptr;
|
||||
char* _write_end;
|
||||
char* _buf_base;
|
||||
char* _buf_end;
|
||||
char* _save_base;
|
||||
char* _backup_base;
|
||||
char* _save_end;
|
||||
void* _markers;
|
||||
_iobuf* _chain;
|
||||
int _fileno;
|
||||
int _blksize;
|
||||
int _old_offset;
|
||||
ushort _cur_column;
|
||||
byte _vtable_offset;
|
||||
char[1] _shortbuf;
|
||||
void* _lock;
|
||||
}
|
||||
}
|
||||
|
||||
alias _iobuf FILE; ///
|
||||
|
||||
enum
|
||||
{
|
||||
_F_RDWR = 0x0003,
|
||||
_F_READ = 0x0001,
|
||||
_F_WRIT = 0x0002,
|
||||
_F_BUF = 0x0004,
|
||||
_F_LBUF = 0x0008,
|
||||
_F_ERR = 0x0010,
|
||||
_F_EOF = 0x0020,
|
||||
_F_BIN = 0x0040,
|
||||
_F_IN = 0x0080,
|
||||
_F_OUT = 0x0100,
|
||||
_F_TERM = 0x0200,
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
extern FILE _iob[_NFILE];
|
||||
extern void function() _fcloseallp;
|
||||
extern ubyte __fhnd_info[_NFILE];
|
||||
|
||||
enum
|
||||
{
|
||||
FHND_APPEND = 0x04,
|
||||
FHND_DEVICE = 0x08,
|
||||
FHND_TEXT = 0x10,
|
||||
FHND_BYTE = 0x20,
|
||||
FHND_WCHAR = 0x40,
|
||||
}
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
enum
|
||||
{
|
||||
_IOREAD = 1,
|
||||
_IOWRT = 2,
|
||||
_IONBF = 4,
|
||||
_IOMYBUF = 8,
|
||||
_IOEOF = 0x10,
|
||||
_IOERR = 0x20,
|
||||
_IOLBF = 0x40,
|
||||
_IOSTRG = 0x40,
|
||||
_IORW = 0x80,
|
||||
_IOFBF = 0,
|
||||
_IOAPP = 0x200,
|
||||
_IOTRAN = 0x100,
|
||||
}
|
||||
}
|
||||
|
||||
version (linux)
|
||||
{
|
||||
enum
|
||||
{
|
||||
_IOFBF = 0,
|
||||
_IOLBF = 1,
|
||||
_IONBF = 2,
|
||||
}
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
const FILE *stdin = &_iob[0]; ///
|
||||
const FILE *stdout = &_iob[1]; ///
|
||||
const FILE *stderr = &_iob[2]; ///
|
||||
const FILE *stdaux = &_iob[3]; ///
|
||||
const FILE *stdprn = &_iob[4]; ///
|
||||
}
|
||||
|
||||
version (linux)
|
||||
{
|
||||
extern FILE *stdin;
|
||||
extern FILE *stdout;
|
||||
extern FILE *stderr;
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
const char[] _P_tmpdir = "\\";
|
||||
const wchar[] _wP_tmpdir = "\\";
|
||||
const int L_tmpnam = _P_tmpdir.length + 12;
|
||||
}
|
||||
|
||||
alias int fpos_t; ///
|
||||
|
||||
char * tmpnam(char *); ///
|
||||
FILE * fopen(char *,char *); ///
|
||||
FILE * _fsopen(char *,char *,int ); ///
|
||||
FILE * freopen(char *,char *,FILE *); ///
|
||||
int fseek(FILE *,int,int); ///
|
||||
int ftell(FILE *); ///
|
||||
char * fgets(char *,int,FILE *); ///
|
||||
int fgetc(FILE *); ///
|
||||
int _fgetchar(); ///
|
||||
int fflush(FILE *); ///
|
||||
int fclose(FILE *); ///
|
||||
int fputs(char *,FILE *); ///
|
||||
char * gets(char *); ///
|
||||
int fputc(int,FILE *); ///
|
||||
int _fputchar(int); ///
|
||||
int puts(char *); ///
|
||||
int ungetc(int,FILE *); ///
|
||||
size_t fread(void *,size_t,size_t,FILE *); ///
|
||||
size_t fwrite(void *,size_t,size_t,FILE *); ///
|
||||
//int printf(char *,...); ///
|
||||
int fprintf(FILE *,char *,...); ///
|
||||
int vfprintf(FILE *,char *,va_list); ///
|
||||
int vprintf(char *,va_list); ///
|
||||
int sprintf(char *,char *,...); ///
|
||||
int vsprintf(char *,char *,va_list); ///
|
||||
int scanf(char *,...); ///
|
||||
int fscanf(FILE *,char *,...); ///
|
||||
int sscanf(char *,char *,...); ///
|
||||
void setbuf(FILE *,char *); ///
|
||||
int setvbuf(FILE *,char *,int,size_t); ///
|
||||
int remove(char *); ///
|
||||
int rename(char *,char *); ///
|
||||
void perror(char *); ///
|
||||
int fgetpos(FILE *,fpos_t *); ///
|
||||
int fsetpos(FILE *,fpos_t *); ///
|
||||
FILE * tmpfile(); ///
|
||||
int _rmtmp();
|
||||
int _fillbuf(FILE *);
|
||||
int _flushbu(int, FILE *);
|
||||
|
||||
int getw(FILE *FHdl); ///
|
||||
int putw(int Word, FILE *FilePtr); ///
|
||||
|
||||
///
|
||||
int getchar() { return getc(stdin); }
|
||||
///
|
||||
int putchar(int c) { return putc(c,stdout); }
|
||||
///
|
||||
int getc(FILE *fp) { return fgetc(fp); }
|
||||
///
|
||||
int putc(int c,FILE *fp) { return fputc(c,fp); }
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
///
|
||||
int ferror(FILE *fp) { return fp._flag&_IOERR; }
|
||||
///
|
||||
int feof(FILE *fp) { return fp._flag&_IOEOF; }
|
||||
///
|
||||
void clearerr(FILE *fp) { fp._flag &= ~(_IOERR|_IOEOF); }
|
||||
///
|
||||
void rewind(FILE *fp) { fseek(fp,0L,SEEK_SET); fp._flag&=~_IOERR; }
|
||||
int _bufsize(FILE *fp) { return fp._bufsiz; }
|
||||
///
|
||||
int fileno(FILE *fp) { return fp._file; }
|
||||
int _snprintf(char *,size_t,char *,...);
|
||||
int _vsnprintf(char *,size_t,char *,va_list);
|
||||
}
|
||||
|
||||
version (linux)
|
||||
{
|
||||
int ferror(FILE *fp);
|
||||
int feof(FILE *fp);
|
||||
void clearerr(FILE *fp);
|
||||
void rewind(FILE *fp);
|
||||
int _bufsize(FILE *fp);
|
||||
int fileno(FILE *fp);
|
||||
int snprintf(char *,size_t,char *,...);
|
||||
int vsnprintf(char *,size_t,char *,va_list);
|
||||
}
|
||||
|
||||
int unlink(char *); ///
|
||||
FILE * fdopen(int, char *); ///
|
||||
int fgetchar(); ///
|
||||
int fputchar(int); ///
|
||||
int fcloseall(); ///
|
||||
int filesize(char *); ///
|
||||
int flushall(); ///
|
||||
int getch(); ///
|
||||
int getche(); ///
|
||||
int kbhit(); ///
|
||||
char * tempnam (char *dir, char *pfx); ///
|
||||
|
||||
wchar_t * _wtmpnam(wchar_t *); ///
|
||||
FILE * _wfopen(wchar_t *, wchar_t *);
|
||||
FILE * _wfsopen(wchar_t *, wchar_t *, int);
|
||||
FILE * _wfreopen(wchar_t *, wchar_t *, FILE *);
|
||||
wchar_t * fgetws(wchar_t *, int, FILE *); ///
|
||||
int fputws(wchar_t *, FILE *); ///
|
||||
wchar_t * _getws(wchar_t *);
|
||||
int _putws(wchar_t *);
|
||||
int wprintf(wchar_t *, ...); ///
|
||||
int fwprintf(FILE *, wchar_t *, ...); ///
|
||||
int vwprintf(wchar_t *, va_list); ///
|
||||
int vfwprintf(FILE *, wchar_t *, va_list); ///
|
||||
int swprintf(wchar_t *, wchar_t *, ...); ///
|
||||
int vswprintf(wchar_t *, wchar_t *, va_list); ///
|
||||
int _snwprintf(wchar_t *, size_t, wchar_t *, ...);
|
||||
int _vsnwprintf(wchar_t *, size_t, wchar_t *, va_list);
|
||||
int wscanf(wchar_t *, ...); ///
|
||||
int fwscanf(FILE *, wchar_t *, ...); ///
|
||||
int swscanf(wchar_t *, wchar_t *, ...); ///
|
||||
int _wremove(wchar_t *);
|
||||
void _wperror(wchar_t *);
|
||||
FILE * _wfdopen(int, wchar_t *);
|
||||
wchar_t * _wtempnam(wchar_t *, wchar_t *);
|
||||
wchar_t fgetwc(FILE *); ///
|
||||
wchar_t _fgetwchar_t();
|
||||
wchar_t fputwc(wchar_t, FILE *); ///
|
||||
wchar_t _fputwchar_t(wchar_t);
|
||||
wchar_t ungetwc(wchar_t, FILE *); ///
|
||||
|
||||
///
|
||||
wchar_t getwchar_t() { return fgetwc(stdin); }
|
||||
///
|
||||
wchar_t putwchar_t(wchar_t c) { return fputwc(c,stdout); }
|
||||
///
|
||||
wchar_t getwc(FILE *fp) { return fgetwc(fp); }
|
||||
///
|
||||
wchar_t putwc(wchar_t c, FILE *fp) { return fputwc(c, fp); }
|
||||
|
||||
int fwide(FILE* fp, int mode); ///
|
||||
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
* C's <stdlib.h>
|
||||
* Authors: Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCStdlib
|
||||
*/
|
||||
|
||||
|
||||
module std.c.stdlib;
|
||||
|
||||
private import std.c.stddef;
|
||||
|
||||
extern (C):
|
||||
|
||||
enum
|
||||
{
|
||||
_MAX_PATH = 260,
|
||||
_MAX_DRIVE = 3,
|
||||
_MAX_DIR = 256,
|
||||
_MAX_FNAME = 256,
|
||||
_MAX_EXT = 256,
|
||||
}
|
||||
|
||||
///
|
||||
struct div_t { int quot,rem; }
|
||||
///
|
||||
struct ldiv_t { int quot,rem; }
|
||||
///
|
||||
struct lldiv_t { long quot,rem; }
|
||||
|
||||
div_t div(int,int); ///
|
||||
ldiv_t ldiv(int,int); /// ditto
|
||||
lldiv_t lldiv(long, long); /// ditto
|
||||
|
||||
const int EXIT_SUCCESS = 0; ///
|
||||
const int EXIT_FAILURE = 1; /// ditto
|
||||
|
||||
int atexit(void (*)()); ///
|
||||
void exit(int); /// ditto
|
||||
void _exit(int); /// ditto
|
||||
|
||||
int system(char *);
|
||||
|
||||
pragma(alloca)
|
||||
void *alloca(uint); ///
|
||||
|
||||
void *calloc(size_t, size_t); ///
|
||||
void *malloc(size_t); /// ditto
|
||||
void *realloc(void *, size_t); /// ditto
|
||||
void free(void *); /// ditto
|
||||
|
||||
void *bsearch(void *,void *,size_t,size_t,
|
||||
int function(void *,void *)); ///
|
||||
void qsort(void *base, size_t nelems, size_t elemsize,
|
||||
int (*compare)(void *elem1, void *elem2)); /// ditto
|
||||
|
||||
char* getenv(char*); ///
|
||||
int setenv(char*, char*, int); /// extension to ISO C standard, not available on all platforms
|
||||
void unsetenv(char*); /// extension to ISO C standard, not available on all platforms
|
||||
|
||||
int rand(); ///
|
||||
void srand(uint); /// ditto
|
||||
int random(int num); /// ditto
|
||||
void randomize(); /// 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
|
||||
|
||||
double atof(char *); ///
|
||||
int atoi(char *); /// ditto
|
||||
int atol(char *); /// ditto
|
||||
float strtof(char *,char **); /// ditto
|
||||
double strtod(char *,char **); /// ditto
|
||||
real strtold(char *,char **); /// ditto
|
||||
long strtol(char *,char **,int); /// ditto
|
||||
uint strtoul(char *,char **,int); /// ditto
|
||||
long atoll(char *); /// ditto
|
||||
long strtoll(char *,char **,int); /// ditto
|
||||
ulong strtoull(char *,char **,int); /// ditto
|
||||
|
||||
char* itoa(int, char*, int); ///
|
||||
char* ultoa(uint, char*, int); /// ditto
|
||||
|
||||
int mblen(char *s, size_t n); ///
|
||||
int mbtowc(wchar_t *pwc, char *s, size_t n); /// ditto
|
||||
int wctomb(char *s, wchar_t wc); /// ditto
|
||||
size_t mbstowcs(wchar_t *pwcs, char *s, size_t n); /// ditto
|
||||
size_t wcstombs(char *s, wchar_t *pwcs, size_t n); /// ditto
|
||||
@@ -1,40 +0,0 @@
|
||||
|
||||
/**
|
||||
* C's <string.h>
|
||||
* Authors: Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCString
|
||||
*/
|
||||
|
||||
module std.c.string;
|
||||
|
||||
extern (C):
|
||||
|
||||
void* memcpy(void* s1, void* s2, size_t n); ///
|
||||
void* memmove(void* s1, void* s2, size_t n); ///
|
||||
char* strcpy(char* s1, char* s2); ///
|
||||
char* strncpy(char* s1, char* s2, size_t n); ///
|
||||
char* strncat(char* s1, char* s2, size_t n); ///
|
||||
int strcoll(char* s1, char* s2); ///
|
||||
int strncmp(char* s1, char* s2, size_t n); ///
|
||||
size_t strxfrm(char* s1, char* s2, size_t n); ///
|
||||
void* memchr(void* s, int c, size_t n); ///
|
||||
char* strchr(char* s, int c); ///
|
||||
size_t strcspn(char* s1, char* s2); ///
|
||||
char* strpbrk(char* s1, char* s2); ///
|
||||
char* strrchr(char* s, int c); ///
|
||||
size_t strspn(char* s1, char* s2); ///
|
||||
char* strstr(char* s1, char* s2); ///
|
||||
char* strtok(char* s1, char* s2); ///
|
||||
void* memset(void* s, int c, size_t n); ///
|
||||
char* strerror(int errnum); ///
|
||||
size_t strlen(char* s); ///
|
||||
int strcmp(char* s1, char* s2); ///
|
||||
char* strcat(char* s1, char* s2); ///
|
||||
int memcmp(void* s1, void* s2, size_t n); ///
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
int memicmp(char* s1, char* s2, size_t n); ///
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
|
||||
/**
|
||||
* C's <time.h>
|
||||
* Authors: Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCTime
|
||||
*/
|
||||
|
||||
module std.c.time;
|
||||
|
||||
private import std.c.stddef;
|
||||
|
||||
extern (C):
|
||||
|
||||
alias int clock_t;
|
||||
|
||||
version (Windows)
|
||||
{ const clock_t CLOCKS_PER_SEC = 1000;
|
||||
}
|
||||
else version (linux)
|
||||
{ const clock_t CLOCKS_PER_SEC = 1000000;
|
||||
}
|
||||
else version (darwin)
|
||||
{
|
||||
const clock_t CLOCKS_PER_SEC = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
const clock_t CLK_TCK = 1000;
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
extern (C) int sysconf(int);
|
||||
extern clock_t CLK_TCK;
|
||||
/*static this()
|
||||
{
|
||||
CLK_TCK = cast(clock_t) sysconf(2);
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
|
||||
const uint TIMEOFFSET = 315558000;
|
||||
|
||||
alias int time_t;
|
||||
|
||||
extern int daylight;
|
||||
extern int timezone;
|
||||
extern int altzone;
|
||||
extern char *tzname[2];
|
||||
|
||||
struct tm
|
||||
{ int tm_sec,
|
||||
tm_min,
|
||||
tm_hour,
|
||||
tm_mday,
|
||||
tm_mon,
|
||||
tm_year,
|
||||
tm_wday,
|
||||
tm_yday,
|
||||
tm_isdst;
|
||||
}
|
||||
|
||||
clock_t clock();
|
||||
time_t time(time_t *);
|
||||
time_t mktime(tm *);
|
||||
char *asctime(tm *);
|
||||
char *ctime(time_t *);
|
||||
tm *localtime(time_t *);
|
||||
tm *gmtime(time_t *);
|
||||
size_t strftime(char *, size_t, char *, tm *);
|
||||
char *_strdate(char *dstring);
|
||||
char *_strtime(char *timestr);
|
||||
double difftime(time_t t1, time_t t2);
|
||||
void _tzset();
|
||||
void tzset();
|
||||
|
||||
void sleep(time_t);
|
||||
void usleep(uint);
|
||||
void msleep(uint);
|
||||
|
||||
wchar_t *_wasctime(tm *);
|
||||
wchar_t *_wctime(time_t *);
|
||||
size_t wcsftime(wchar_t *, size_t, wchar_t *, tm *);
|
||||
wchar_t *_wstrdate(wchar_t *);
|
||||
wchar_t *_wstrtime(wchar_t *);
|
||||
@@ -1,246 +0,0 @@
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
|
||||
/// Placed into public domain
|
||||
/// Author: Walter Bright
|
||||
|
||||
module std.c.windows.stat;
|
||||
|
||||
extern (C):
|
||||
|
||||
// linux version is in std.c.linux.linux
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
const S_IFMT = 0xF000;
|
||||
const S_IFDIR = 0x4000;
|
||||
const S_IFCHR = 0x2000;
|
||||
const S_IFIFO = 0x1000;
|
||||
const S_IFREG = 0x8000;
|
||||
const S_IREAD = 0x0100;
|
||||
const S_IWRITE = 0x0080;
|
||||
const S_IEXEC = 0x0040;
|
||||
const S_IFBLK = 0x6000;
|
||||
const S_IFNAM = 0x5000;
|
||||
|
||||
int S_ISREG(int m) { return (m & S_IFMT) == S_IFREG; }
|
||||
int S_ISBLK(int m) { return (m & S_IFMT) == S_IFBLK; }
|
||||
int S_ISNAM(int m) { return (m & S_IFMT) == S_IFNAM; }
|
||||
int S_ISDIR(int m) { return (m & S_IFMT) == S_IFDIR; }
|
||||
int S_ISCHR(int m) { return (m & S_IFMT) == S_IFCHR; }
|
||||
|
||||
struct struct_stat
|
||||
{
|
||||
short st_dev;
|
||||
ushort st_ino;
|
||||
ushort st_mode;
|
||||
short st_nlink;
|
||||
ushort st_uid;
|
||||
ushort st_gid;
|
||||
short st_rdev;
|
||||
short dummy;
|
||||
int st_size;
|
||||
int st_atime;
|
||||
int st_mtime;
|
||||
int st_ctime;
|
||||
}
|
||||
|
||||
int stat(char *, struct_stat *);
|
||||
int fstat(int, struct_stat *);
|
||||
int _wstat(wchar *, struct_stat *);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,540 +0,0 @@
|
||||
/*
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
1578
lphobos/std/conv.d
1578
lphobos/std/conv.d
File diff suppressed because it is too large
Load Diff
@@ -1,228 +0,0 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Placed into the Public Domain.
|
||||
* Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*/
|
||||
|
||||
/**
|
||||
* Simple ASCII character classification functions.
|
||||
* For Unicode classification, see $(LINK2 std_uni.html, std.uni).
|
||||
* References:
|
||||
* $(LINK2 http://www.digitalmars.com/d/ascii-table.html, ASCII Table),
|
||||
* $(LINK2 http://en.wikipedia.org/wiki/Ascii, Wikipedia)
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdCtype
|
||||
*/
|
||||
|
||||
module std.ctype;
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a letter in the range (0..9, a..z, A..Z).
|
||||
*/
|
||||
int isalnum(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is an ascii upper or lower case letter.
|
||||
*/
|
||||
int isalpha(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a control character.
|
||||
*/
|
||||
int iscntrl(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_CTL) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a digit.
|
||||
*/
|
||||
int isdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_DIG) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is lower case ascii letter.
|
||||
*/
|
||||
int islower(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_LC) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a punctuation character.
|
||||
*/
|
||||
int ispunct(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_PNC) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a space, tab, vertical tab, form feed,
|
||||
* carriage return, or linefeed.
|
||||
*/
|
||||
int isspace(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_SPC) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is an upper case ascii character.
|
||||
*/
|
||||
int isupper(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_UC) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a hex digit (0..9, a..f, A..F).
|
||||
*/
|
||||
int isxdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_HEX) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a printing character except for the space character.
|
||||
*/
|
||||
int isgraph(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a printing character including the space character.
|
||||
*/
|
||||
int isprint(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC|_BLK) : 0; }
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is in the ascii character set, i.e. in the range 0..0x7F.
|
||||
*/
|
||||
int isascii(dchar c) { return c <= 0x7F; }
|
||||
|
||||
|
||||
/**
|
||||
* If c is an upper case ascii character,
|
||||
* return the lower case equivalent, otherwise return c.
|
||||
*/
|
||||
dchar tolower(dchar c)
|
||||
out (result)
|
||||
{
|
||||
assert(!isupper(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
return isupper(c) ? c + (cast(dchar)'a' - 'A') : c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If c is a lower case ascii character,
|
||||
* return the upper case equivalent, otherwise return c.
|
||||
*/
|
||||
dchar toupper(dchar c)
|
||||
out (result)
|
||||
{
|
||||
assert(!islower(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
return islower(c) ? c - (cast(dchar)'a' - 'A') : c;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
_SPC = 8,
|
||||
_CTL = 0x20,
|
||||
_BLK = 0x40,
|
||||
_HEX = 0x80,
|
||||
_UC = 1,
|
||||
_LC = 2,
|
||||
_PNC = 0x10,
|
||||
_DIG = 4,
|
||||
_ALP = _UC|_LC,
|
||||
}
|
||||
|
||||
ubyte _ctype[128] =
|
||||
[
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL
|
||||
];
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
assert(isspace(' '));
|
||||
assert(!isspace('z'));
|
||||
assert(toupper('a') == 'A');
|
||||
assert(tolower('Q') == 'q');
|
||||
assert(!isxdigit('G'));
|
||||
}
|
||||
1074
lphobos/std/date.d
1074
lphobos/std/date.d
File diff suppressed because it is too large
Load Diff
1074
lphobos/std/date.d~
1074
lphobos/std/date.d~
File diff suppressed because it is too large
Load Diff
@@ -1,788 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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*/malloc(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);
|
||||
}
|
||||
|
||||
1590
lphobos/std/file.d
1590
lphobos/std/file.d
File diff suppressed because it is too large
Load Diff
1570
lphobos/std/format.d
1570
lphobos/std/format.d
File diff suppressed because it is too large
Load Diff
@@ -1,193 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 1999-2006 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.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* The garbage collector normally works behind the scenes without needing any
|
||||
* specific interaction. These functions are for advanced applications that
|
||||
* benefit from tuning the operation of the collector.
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdGc
|
||||
*/
|
||||
|
||||
module std.gc;
|
||||
|
||||
import gcstats;
|
||||
|
||||
/**
|
||||
* Add p to list of roots. Roots are references to memory allocated by the
|
||||
collector that are maintained in memory outside the collector pool. The garbage
|
||||
collector will by default look for roots in the stacks of each thread, the
|
||||
registers, and the default static data segment. If roots are held elsewhere,
|
||||
use addRoot() or addRange() to tell the collector not to free the memory it
|
||||
points to.
|
||||
*/
|
||||
void addRoot(void *p); // add p to list of roots
|
||||
|
||||
/**
|
||||
* Remove p from list of roots.
|
||||
*/
|
||||
void removeRoot(void *p); // remove p from list of roots
|
||||
|
||||
/**
|
||||
* Add range to scan for roots.
|
||||
*/
|
||||
void addRange(void *pbot, void *ptop); // add range to scan for roots
|
||||
|
||||
/**
|
||||
* Remove range.
|
||||
*/
|
||||
void removeRange(void *pbot); // remove range
|
||||
|
||||
/**
|
||||
* Mark a gc allocated block of memory as possibly containing pointers.
|
||||
*/
|
||||
void hasPointers(void* p);
|
||||
|
||||
/**
|
||||
* Mark a gc allocated block of memory as definitely NOT containing pointers.
|
||||
*/
|
||||
void hasNoPointers(void* p);
|
||||
|
||||
/**
|
||||
* Mark a gc allocated block of memory pointed to by p as being populated with
|
||||
* an array of TypeInfo ti (as many as will fit).
|
||||
*/
|
||||
void setTypeInfo(TypeInfo ti, void* p);
|
||||
|
||||
/**
|
||||
* Allocate nbytes of uninitialized data.
|
||||
* The allocated memory will be scanned for pointers during
|
||||
* a gc collection cycle, unless
|
||||
* it is followed by a call to hasNoPointers().
|
||||
*/
|
||||
void[] malloc(size_t nbytes);
|
||||
|
||||
/**
|
||||
* Resize allocated memory block pointed to by p to be at least nbytes long.
|
||||
* It will try to resize the memory block in place.
|
||||
* If nbytes is 0, the memory block is free'd.
|
||||
* If p is null, the memory block is allocated using malloc.
|
||||
* The returned array may not be at the same location as the original
|
||||
* memory block.
|
||||
* The allocated memory will be scanned for pointers during
|
||||
* a gc collection cycle, unless
|
||||
* it is followed by a call to hasNoPointers().
|
||||
*/
|
||||
void[] realloc(void* p, size_t nbytes);
|
||||
|
||||
/**
|
||||
* Attempt to enlarge the memory block pointed to by p
|
||||
* by at least minbytes beyond its current capacity,
|
||||
* up to a maximum of maxbytes.
|
||||
* Returns:
|
||||
* 0 if could not extend p,
|
||||
* total size of entire memory block if successful.
|
||||
*/
|
||||
size_t extend(void* p, size_t minbytes, size_t maxbytes);
|
||||
|
||||
/**
|
||||
* Returns capacity (size of the memory block) that p
|
||||
* points to the beginning of.
|
||||
* If p does not point into the gc memory pool, or does
|
||||
* not point to the beginning of an allocated memory block,
|
||||
* 0 is returned.
|
||||
*/
|
||||
size_t capacity(void* p);
|
||||
|
||||
/**
|
||||
* Set gc behavior to match that of 1.0.
|
||||
*/
|
||||
void setV1_0();
|
||||
|
||||
/***********************************
|
||||
* Run a full garbage collection cycle.
|
||||
*
|
||||
* The collector normally runs synchronously with a storage allocation request
|
||||
(i.e. it never happens when in code that does not allocate memory). In some
|
||||
circumstances, for example when a particular task is finished, it is convenient
|
||||
to explicitly run the collector and free up all memory used by that task. It
|
||||
can also be helpful to run a collection before starting a new task that would
|
||||
be annoying if it ran a collection in the middle of that task. Explicitly
|
||||
running a collection can also be done in a separate very low priority thread,
|
||||
so that if the program is idly waiting for input, memory can be cleaned up.
|
||||
*/
|
||||
|
||||
void fullCollect();
|
||||
|
||||
/***********************************
|
||||
* Run a generational garbage collection cycle.
|
||||
* Takes less time than a fullcollect(), but isn't
|
||||
* as effective.
|
||||
*/
|
||||
|
||||
void genCollect();
|
||||
|
||||
void genCollectNoStack();
|
||||
|
||||
/**
|
||||
* Minimizes physical memory usage
|
||||
*/
|
||||
void minimize();
|
||||
|
||||
/***************************************
|
||||
* disable() temporarily disables garbage collection cycle, enable()
|
||||
* then reenables them.
|
||||
*
|
||||
* This is used for brief time critical sections of code, so the amount of time
|
||||
* it will take is predictable.
|
||||
* If the collector runs out of memory while it is disabled, it will throw an
|
||||
* std.outofmemory.OutOfMemoryException.
|
||||
* The disable() function calls can be nested, but must be
|
||||
* matched with corresponding enable() calls.
|
||||
* By default collections are enabled.
|
||||
*/
|
||||
|
||||
void disable();
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
void enable();
|
||||
|
||||
void getStats(out GCStats stats);
|
||||
|
||||
/***************************************
|
||||
* Get handle to the collector.
|
||||
*/
|
||||
|
||||
void* getGCHandle();
|
||||
|
||||
/***************************************
|
||||
* Set handle to the collector.
|
||||
*/
|
||||
|
||||
void setGCHandle(void* p);
|
||||
|
||||
void endGCHandle();
|
||||
|
||||
extern (C)
|
||||
{
|
||||
void gc_init();
|
||||
void gc_term();
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
|
||||
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
// Placed into the public domain
|
||||
|
||||
/* NOTE: This file has been patched from the original DMD distribution to
|
||||
work with the GDC compiler.
|
||||
NOTE: This file has been patched from the original GDC distribution to
|
||||
work with the LDC compiler.
|
||||
|
||||
Modified by David Friedman, May 2006
|
||||
Modified by Tomas Lindquist Olsen, August 2007
|
||||
*/
|
||||
|
||||
/** These functions are built-in intrinsics to the compiler.
|
||||
*
|
||||
Intrinsic functions are functions built in to the compiler,
|
||||
usually to take advantage of specific CPU features that
|
||||
are inefficient to handle via external functions.
|
||||
The compiler's optimizer and code generator are fully
|
||||
integrated in with intrinsic functions, bringing to bear
|
||||
their full power on them.
|
||||
This can result in some surprising speedups.
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdIntrinsic
|
||||
*/
|
||||
|
||||
module std.intrinsic;
|
||||
|
||||
/**
|
||||
* Scans the bits in v starting with bit 0, looking
|
||||
* for the first set bit.
|
||||
* Returns:
|
||||
* The bit number of the first bit set.
|
||||
* The return value is undefined if v is zero.
|
||||
*/
|
||||
version (LLVM)
|
||||
int bsf(uint v)
|
||||
{
|
||||
uint m = 1;
|
||||
uint i;
|
||||
for (i = 0; i < 32; i++,m<<=1) {
|
||||
if (v&m)
|
||||
return i;
|
||||
}
|
||||
return i; // supposed to be undefined
|
||||
}
|
||||
else
|
||||
int bsf(uint v);
|
||||
|
||||
/**
|
||||
* Scans the bits in v from the most significant bit
|
||||
* to the least significant bit, looking
|
||||
* for the first set bit.
|
||||
* Returns:
|
||||
* The bit number of the first bit set.
|
||||
* The return value is undefined if v is zero.
|
||||
* Example:
|
||||
* ---
|
||||
* import std.intrinsic;
|
||||
*
|
||||
* int main()
|
||||
* {
|
||||
* uint v;
|
||||
* int x;
|
||||
*
|
||||
* v = 0x21;
|
||||
* x = bsf(v);
|
||||
* printf("bsf(x%x) = %d\n", v, x);
|
||||
* x = bsr(v);
|
||||
* printf("bsr(x%x) = %d\n", v, x);
|
||||
* return 0;
|
||||
* }
|
||||
* ---
|
||||
* Output:
|
||||
* bsf(x21) = 0<br>
|
||||
* bsr(x21) = 5
|
||||
*/
|
||||
version (LLVM)
|
||||
int bsr(uint v)
|
||||
{
|
||||
uint m = 0x80000000;
|
||||
uint i;
|
||||
for (i = 32; i ; i--,m>>>=1) {
|
||||
if (v&m)
|
||||
return i-1;
|
||||
}
|
||||
return i; // supposed to be undefined
|
||||
}
|
||||
else
|
||||
int bsr(uint v);
|
||||
|
||||
/**
|
||||
* Tests the bit.
|
||||
*/
|
||||
version (LLVM)
|
||||
int bt(uint *p, uint bitnum)
|
||||
{
|
||||
return (p[bitnum / (uint.sizeof*8)] & (1<<(bitnum & ((uint.sizeof*8)-1)))) ? -1 : 0 ;
|
||||
}
|
||||
else
|
||||
int bt(uint *p, uint bitnum);
|
||||
|
||||
/**
|
||||
* Tests and complements the bit.
|
||||
*/
|
||||
version (LLVM)
|
||||
int btc(uint *p, uint bitnum)
|
||||
{
|
||||
uint * q = p + (bitnum / (uint.sizeof*8));
|
||||
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
|
||||
int result = *q & mask;
|
||||
*q ^= mask;
|
||||
return result ? -1 : 0;
|
||||
}
|
||||
else
|
||||
int btc(uint *p, uint bitnum);
|
||||
|
||||
/**
|
||||
* Tests and resets (sets to 0) the bit.
|
||||
*/
|
||||
version (LLVM)
|
||||
int btr(uint *p, uint bitnum)
|
||||
{
|
||||
uint * q = p + (bitnum / (uint.sizeof*8));
|
||||
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
|
||||
int result = *q & mask;
|
||||
*q &= ~mask;
|
||||
return result ? -1 : 0;
|
||||
}
|
||||
else
|
||||
int btr(uint *p, uint bitnum);
|
||||
|
||||
/**
|
||||
* Tests and sets the bit.
|
||||
* Params:
|
||||
* p = a non-NULL pointer to an array of uints.
|
||||
* index = a bit number, starting with bit 0 of p[0],
|
||||
* and progressing. It addresses bits like the expression:
|
||||
---
|
||||
p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)))
|
||||
---
|
||||
* Returns:
|
||||
* A non-zero value if the bit was set, and a zero
|
||||
* if it was clear.
|
||||
*
|
||||
* Example:
|
||||
* ---
|
||||
import std.intrinsic;
|
||||
|
||||
int main()
|
||||
{
|
||||
uint array[2];
|
||||
|
||||
array[0] = 2;
|
||||
array[1] = 0x100;
|
||||
|
||||
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
* ---
|
||||
* Output:
|
||||
<pre>
|
||||
btc(array, 35) = 0
|
||||
array = [0]:x2, [1]:x108
|
||||
btc(array, 35) = -1
|
||||
array = [0]:x2, [1]:x100
|
||||
bts(array, 35) = 0
|
||||
array = [0]:x2, [1]:x108
|
||||
btr(array, 35) = -1
|
||||
array = [0]:x2, [1]:x100
|
||||
bt(array, 1) = -1
|
||||
array = [0]:x2, [1]:x100
|
||||
</pre>
|
||||
*/
|
||||
version (LLVM)
|
||||
int bts(uint *p, uint bitnum)
|
||||
{
|
||||
uint * q = p + (bitnum / (uint.sizeof*8));
|
||||
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
|
||||
int result = *q & mask;
|
||||
*q |= mask;
|
||||
return result ? -1 : 0;
|
||||
}
|
||||
else
|
||||
int bts(uint *p, uint bitnum);
|
||||
|
||||
|
||||
/**
|
||||
* Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes
|
||||
byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
|
||||
becomes byte 0.
|
||||
*/
|
||||
version (LLVM)
|
||||
pragma(intrinsic, "llvm.bswap.i32")
|
||||
uint bswap(uint val);
|
||||
else
|
||||
uint bswap(uint v);
|
||||
|
||||
|
||||
/**
|
||||
* Reads I/O port at port_address.
|
||||
*/
|
||||
version (LLVM)
|
||||
ubyte inp(uint p) { return 0; }
|
||||
else
|
||||
ubyte inp(uint port_address);
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
version (LLVM)
|
||||
ushort inpw(uint p) { return 0; }
|
||||
else
|
||||
ushort inpw(uint port_address);
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
version (LLVM)
|
||||
uint inpl(uint p) { return 0; }
|
||||
else
|
||||
uint inpl(uint port_address);
|
||||
|
||||
|
||||
/**
|
||||
* Writes and returns value to I/O port at port_address.
|
||||
*/
|
||||
version (LLVM)
|
||||
ubyte outp(uint p, ubyte v) { return v; }
|
||||
else
|
||||
ubyte outp(uint port_address, ubyte value);
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
version (LLVM)
|
||||
ushort outpw(uint p, ushort v) { return v; }
|
||||
else
|
||||
ushort outpw(uint port_address, ushort value);
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
version (LLVM)
|
||||
uint outpl(uint p, uint v) { return v; }
|
||||
else
|
||||
uint outpl(uint port_address, uint value);
|
||||
|
||||
|
||||
1959
lphobos/std/math.d
1959
lphobos/std/math.d
File diff suppressed because it is too large
Load Diff
@@ -1,504 +0,0 @@
|
||||
/* 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");
|
||||
}
|
||||
|
||||
@@ -1,650 +0,0 @@
|
||||
/* 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;
|
||||
|
||||
version(linux) version = Unix;
|
||||
|
||||
//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");
|
||||
}
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
// Modified for LDC
|
||||
|
||||
module std.moduleinit;
|
||||
|
||||
//debug = 1;
|
||||
|
||||
private
|
||||
{
|
||||
import object;
|
||||
import std.c.stdio;
|
||||
import std.c.stdlib;
|
||||
}
|
||||
|
||||
enum
|
||||
{ MIctorstart = 1, // we've started constructing it
|
||||
MIctordone = 2, // finished construction
|
||||
MIstandalone = 4, // module ctor does not depend on other module
|
||||
// ctors being done first
|
||||
}
|
||||
|
||||
// had to move the class to object.d, as its declaration is needed in the compiler code,
|
||||
// otherwise the DMDFE Module::moduleinfo member is NULL
|
||||
|
||||
class ModuleCtorError : Exception
|
||||
{
|
||||
this(ModuleInfo m)
|
||||
{
|
||||
super("circular initialization dependency with module " ~ m.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this gets initialized in _moduleCtor()
|
||||
extern (C) ModuleInfo[] _moduleinfo_array;
|
||||
|
||||
// this method returns the linker constructed, null terminated, array of moduleinfos
|
||||
extern (C) void** _d_get_moduleinfo_array();
|
||||
|
||||
ModuleInfo[] _moduleinfo_dtors;
|
||||
uint _moduleinfo_dtors_i;
|
||||
|
||||
// Register termination function pointers
|
||||
extern (C) int _fatexit(void *);
|
||||
|
||||
/*************************************
|
||||
* Initialize the modules.
|
||||
*/
|
||||
|
||||
extern (C) void _moduleCtor()
|
||||
{
|
||||
debug printf("_moduleCtor()\n");
|
||||
int len = 0;
|
||||
|
||||
for (auto mr = _Dmodule_ref; mr; mr=mr.next)
|
||||
len++;
|
||||
_moduleinfo_array = new ModuleInfo[len];
|
||||
len = 0;
|
||||
for (auto mr = _Dmodule_ref; mr; mr=mr.next)
|
||||
{ _moduleinfo_array[len] = mr.mod;
|
||||
len++;
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
// Ensure module destructors also get called on program termination
|
||||
//_fatexit(&_STD_moduleDtor);
|
||||
}
|
||||
|
||||
_moduleinfo_dtors = new ModuleInfo[len];
|
||||
debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
|
||||
_moduleCtor2(_moduleinfo_array, 0);
|
||||
|
||||
version (none)
|
||||
{
|
||||
foreach (m; _moduleinfo_array)
|
||||
{
|
||||
writefln("module %s, %d", m.name, m.localClasses.length);
|
||||
foreach (c; m.localClasses)
|
||||
{
|
||||
writefln("\tclass %s", c.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _moduleCtor2(ModuleInfo[] mi, int skip)
|
||||
{
|
||||
debug printf("_moduleCtor2(): %d modules\n", mi.length);
|
||||
for (uint i = 0; i < mi.length; i++)
|
||||
{
|
||||
ModuleInfo m = mi[i];
|
||||
|
||||
debug printf("\tmodule[%d] = '%p'\n", i, m);
|
||||
if (!m)
|
||||
continue;
|
||||
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name.length, m.name.ptr);
|
||||
if (m.flags & MIctordone)
|
||||
continue;
|
||||
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);
|
||||
}
|
||||
|
||||
m.flags |= MIctorstart;
|
||||
_moduleCtor2(m.importedModules, 0);
|
||||
if (m.ctor)
|
||||
(*m.ctor)();
|
||||
m.flags &= ~MIctorstart;
|
||||
m.flags |= MIctordone;
|
||||
|
||||
// Now that construction is done, register the destructor
|
||||
//printf("\tadding module dtor x%x\n", m);
|
||||
assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
|
||||
_moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
m.flags |= MIctordone;
|
||||
_moduleCtor2(m.importedModules, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
* Destruct the modules.
|
||||
*/
|
||||
|
||||
// Starting the name with "_STD" means under linux a pointer to the
|
||||
// function gets put in the .dtors segment.
|
||||
|
||||
extern (C) void _moduleDtor()
|
||||
{
|
||||
debug printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
|
||||
for (uint i = _moduleinfo_dtors_i; i-- != 0;)
|
||||
{
|
||||
ModuleInfo m = _moduleinfo_dtors[i];
|
||||
|
||||
debug printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
|
||||
if (m.dtor)
|
||||
{
|
||||
(*m.dtor)();
|
||||
}
|
||||
}
|
||||
debug printf("_moduleDtor() done\n");
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Run unit tests.
|
||||
*/
|
||||
|
||||
extern (C) void _moduleUnitTests()
|
||||
{
|
||||
debug printf("_moduleUnitTests() %i\n", _moduleinfo_array.length);
|
||||
for (uint i = 0; i < _moduleinfo_array.length; i++)
|
||||
{
|
||||
ModuleInfo m = _moduleinfo_array[i];
|
||||
|
||||
if (!m)
|
||||
continue;
|
||||
|
||||
debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
||||
if (m.unitTest)
|
||||
{
|
||||
(*m.unitTest)();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,368 +0,0 @@
|
||||
// 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*/malloc(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*/std.gc.malloc(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*/std.gc.malloc(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);
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdOutOfMemory
|
||||
* Copyright:
|
||||
* Placed into public domain.
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
|
||||
module std.outofmemory;
|
||||
|
||||
/******
|
||||
* This exception is thrown when out of memory errors happen.
|
||||
*/
|
||||
|
||||
class OutOfMemoryException : Exception
|
||||
{
|
||||
static char[] s = "Out of memory";
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
this()
|
||||
{
|
||||
super(s);
|
||||
}
|
||||
|
||||
char[] toString()
|
||||
{
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
extern (C) void _d_OutOfMemory()
|
||||
{
|
||||
printf("Out of memory!\n");
|
||||
*(cast(int*) 0) = 0;
|
||||
throw cast(OutOfMemoryException)
|
||||
cast(void *)
|
||||
OutOfMemoryException.classinfo.init;
|
||||
}
|
||||
|
||||
static this()
|
||||
{
|
||||
}
|
||||
1254
lphobos/std/path.d
1254
lphobos/std/path.d
File diff suppressed because it is too large
Load Diff
@@ -1,295 +0,0 @@
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
version(linux) version = Unix;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ////////////////////////////////////////////////////////////////////////// */
|
||||
@@ -1,163 +0,0 @@
|
||||
/**
|
||||
* 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(linux) version = Unix;
|
||||
|
||||
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
3208
lphobos/std/regexp.d
File diff suppressed because it is too large
Load Diff
1666
lphobos/std/socket.d
1666
lphobos/std/socket.d
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
|
||||
/*
|
||||
* Placed in public domain.
|
||||
* Written by Hauke Duden and Walter Bright
|
||||
*/
|
||||
|
||||
/* This is for use with variable argument lists with extern(D) linkage. */
|
||||
|
||||
/* Modified for LDC (LLVM D Compiler) by Tomas Lindquist Olsen, 2007 */
|
||||
|
||||
module std.stdarg;
|
||||
|
||||
alias void* va_list;
|
||||
|
||||
T va_arg(T)(ref va_list vp)
|
||||
{
|
||||
size_t size = T.sizeof > size_t.sizeof ? size_t.sizeof : T.sizeof;
|
||||
va_list vptmp = cast(va_list)((cast(size_t)vp + size - 1) & ~(size - 1));
|
||||
vp = vptmp + T.sizeof;
|
||||
return *cast(T*)vptmp;
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
|
||||
/**
|
||||
*
|
||||
D constrains integral types to specific sizes. But efficiency
|
||||
of different sizes varies from machine to machine,
|
||||
pointer sizes vary, and the maximum integer size varies.
|
||||
<b>stdint</b> offers a portable way of trading off size
|
||||
vs efficiency, in a manner compatible with the <tt>stdint.h</tt>
|
||||
definitions in C.
|
||||
|
||||
The exact aliases are types of exactly the specified number of bits.
|
||||
The at least aliases are at least the specified number of bits
|
||||
large, and can be larger.
|
||||
The fast aliases are the fastest integral type supported by the
|
||||
processor that is at least as wide as the specified number of bits.
|
||||
|
||||
The aliases are:
|
||||
|
||||
<table border=1 cellspacing=0 cellpadding=5>
|
||||
<th>Exact Alias
|
||||
<th>Description
|
||||
<th>At Least Alias
|
||||
<th>Description
|
||||
<th>Fast Alias
|
||||
<th>Description
|
||||
<tr>
|
||||
<td>int8_t
|
||||
<td>exactly 8 bits signed
|
||||
<td>int_least8_t
|
||||
<td>at least 8 bits signed
|
||||
<td>int_fast8_t
|
||||
<td>fast 8 bits signed
|
||||
<tr>
|
||||
<td>uint8_t
|
||||
<td>exactly 8 bits unsigned
|
||||
<td>uint_least8_t
|
||||
<td>at least 8 bits unsigned
|
||||
<td>uint_fast8_t
|
||||
<td>fast 8 bits unsigned
|
||||
|
||||
<tr>
|
||||
<td>int16_t
|
||||
<td>exactly 16 bits signed
|
||||
<td>int_least16_t
|
||||
<td>at least 16 bits signed
|
||||
<td>int_fast16_t
|
||||
<td>fast 16 bits signed
|
||||
<tr>
|
||||
<td>uint16_t
|
||||
<td>exactly 16 bits unsigned
|
||||
<td>uint_least16_t
|
||||
<td>at least 16 bits unsigned
|
||||
<td>uint_fast16_t
|
||||
<td>fast 16 bits unsigned
|
||||
|
||||
<tr>
|
||||
<td>int32_t
|
||||
<td>exactly 32 bits signed
|
||||
<td>int_least32_t
|
||||
<td>at least 32 bits signed
|
||||
<td>int_fast32_t
|
||||
<td>fast 32 bits signed
|
||||
<tr>
|
||||
<td>uint32_t
|
||||
<td>exactly 32 bits unsigned
|
||||
<td>uint_least32_t
|
||||
<td>at least 32 bits unsigned
|
||||
<td>uint_fast32_t
|
||||
<td>fast 32 bits unsigned
|
||||
|
||||
<tr>
|
||||
<td>int64_t
|
||||
<td>exactly 64 bits signed
|
||||
<td>int_least64_t
|
||||
<td>at least 64 bits signed
|
||||
<td>int_fast64_t
|
||||
<td>fast 64 bits signed
|
||||
<tr>
|
||||
<td>uint64_t
|
||||
<td>exactly 64 bits unsigned
|
||||
<td>uint_least64_t
|
||||
<td>at least 64 bits unsigned
|
||||
<td>uint_fast64_t
|
||||
<td>fast 64 bits unsigned
|
||||
</table>
|
||||
|
||||
The ptr aliases are integral types guaranteed to be large enough
|
||||
to hold a pointer without losing bits:
|
||||
|
||||
<table border=1 cellspacing=0 cellpadding=5>
|
||||
<th>Alias
|
||||
<th>Description
|
||||
<tr>
|
||||
<td>intptr_t
|
||||
<td>signed integral type large enough to hold a pointer
|
||||
<tr>
|
||||
<td>uintptr_t
|
||||
<td>unsigned integral type large enough to hold a pointer
|
||||
</table>
|
||||
|
||||
The max aliases are the largest integral types:
|
||||
|
||||
<table border=1 cellspacing=0 cellpadding=5>
|
||||
<th>Alias
|
||||
<th>Description
|
||||
<tr>
|
||||
<td>intmax_t
|
||||
<td>the largest signed integral type
|
||||
<tr>
|
||||
<td>uintmax_t
|
||||
<td>the largest unsigned integral type
|
||||
</table>
|
||||
|
||||
* Authors: Walter Bright, www.digitalmars.com
|
||||
* License: Public Domain
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdStdint
|
||||
*/
|
||||
|
||||
/*
|
||||
NOTE: This file has been patched from the original DMD distribution to
|
||||
work with the LDC compiler.
|
||||
|
||||
Modified by Tomas Lindquist Olsen, August 2007
|
||||
*/
|
||||
|
||||
module std.stdint;
|
||||
|
||||
/* Exact sizes */
|
||||
|
||||
alias byte int8_t;
|
||||
alias ubyte uint8_t;
|
||||
alias short int16_t;
|
||||
alias ushort uint16_t;
|
||||
alias int int32_t;
|
||||
alias uint uint32_t;
|
||||
alias long int64_t;
|
||||
alias ulong uint64_t;
|
||||
|
||||
/* At least sizes */
|
||||
|
||||
alias byte int_least8_t;
|
||||
alias ubyte uint_least8_t;
|
||||
alias short int_least16_t;
|
||||
alias ushort uint_least16_t;
|
||||
alias int int_least32_t;
|
||||
alias uint uint_least32_t;
|
||||
alias long int_least64_t;
|
||||
alias ulong uint_least64_t;
|
||||
|
||||
/* Fastest minimum width sizes */
|
||||
|
||||
alias byte int_fast8_t;
|
||||
alias ubyte uint_fast8_t;
|
||||
alias int int_fast16_t;
|
||||
alias uint uint_fast16_t;
|
||||
alias int int_fast32_t;
|
||||
alias uint uint_fast32_t;
|
||||
alias long int_fast64_t;
|
||||
alias ulong uint_fast64_t;
|
||||
|
||||
/* Integer pointer holders */
|
||||
|
||||
version(LLVM64) {
|
||||
alias long intptr_t;
|
||||
alias ulong uintptr_t;
|
||||
}
|
||||
else {
|
||||
alias int intptr_t;
|
||||
alias uint uintptr_t;
|
||||
}
|
||||
|
||||
/* Greatest width integer types */
|
||||
|
||||
alias long intmax_t;
|
||||
alias ulong uintmax_t;
|
||||
|
||||
@@ -1,548 +0,0 @@
|
||||
|
||||
// Written in the D programming language.
|
||||
|
||||
/* Written by Walter Bright and Andrei Alexandrescu
|
||||
* www.digitalmars.com
|
||||
* Placed in the Public Domain.
|
||||
*/
|
||||
|
||||
/********************************
|
||||
* Standard I/O functions that extend $(B std.c.stdio).
|
||||
* $(B std.c.stdio) is automatically imported when importing
|
||||
* $(B std.stdio).
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdStdio
|
||||
*/
|
||||
|
||||
module std.stdio;
|
||||
|
||||
public import std.c.stdio;
|
||||
|
||||
import std.format;
|
||||
import std.utf;
|
||||
import std.string;
|
||||
import std.gc;
|
||||
import std.c.stdlib;
|
||||
import std.c.string;
|
||||
import std.c.stddef;
|
||||
|
||||
|
||||
version (DigitalMars)
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
// Specific to the way Digital Mars C does stdio
|
||||
version = DIGITAL_MARS_STDIO;
|
||||
}
|
||||
}
|
||||
|
||||
version (DIGITAL_MARS_STDIO)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
// Specific to the way Gnu C does stdio
|
||||
version = GCC_IO;
|
||||
import std.c.linux.linux;
|
||||
}
|
||||
|
||||
version (DIGITAL_MARS_STDIO)
|
||||
{
|
||||
extern (C)
|
||||
{
|
||||
/* **
|
||||
* Digital Mars under-the-hood C I/O functions
|
||||
*/
|
||||
int _fputc_nlock(int, FILE*);
|
||||
int _fputwc_nlock(int, FILE*);
|
||||
int _fgetc_nlock(FILE*);
|
||||
int _fgetwc_nlock(FILE*);
|
||||
int __fp_lock(FILE*);
|
||||
void __fp_unlock(FILE*);
|
||||
}
|
||||
alias _fputc_nlock FPUTC;
|
||||
alias _fputwc_nlock FPUTWC;
|
||||
alias _fgetc_nlock FGETC;
|
||||
alias _fgetwc_nlock FGETWC;
|
||||
|
||||
alias __fp_lock FLOCK;
|
||||
alias __fp_unlock FUNLOCK;
|
||||
}
|
||||
else version (GCC_IO)
|
||||
{
|
||||
/* **
|
||||
* Gnu under-the-hood C I/O functions; see
|
||||
* http://www.gnu.org/software/libc/manual/html_node/I_002fO-on-Streams.html#I_002fO-on-Streams
|
||||
*/
|
||||
extern (C)
|
||||
{
|
||||
int fputc_unlocked(int, FILE*);
|
||||
int fputwc_unlocked(wchar_t, FILE*);
|
||||
int fgetc_unlocked(FILE*);
|
||||
int fgetwc_unlocked(FILE*);
|
||||
void flockfile(FILE*);
|
||||
void funlockfile(FILE*);
|
||||
ssize_t getline(char**, size_t*, FILE*);
|
||||
ssize_t getdelim (char**, size_t*, int, FILE*);
|
||||
}
|
||||
|
||||
alias fputc_unlocked FPUTC;
|
||||
alias fputwc_unlocked FPUTWC;
|
||||
alias fgetc_unlocked FGETC;
|
||||
alias fgetwc_unlocked FGETWC;
|
||||
|
||||
alias flockfile FLOCK;
|
||||
alias funlockfile FUNLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0, "unsupported C I/O system");
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
* Thrown if I/O errors happen.
|
||||
*/
|
||||
class StdioException : Exception
|
||||
{
|
||||
uint errno; // operating system error code
|
||||
|
||||
this(char[] msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
|
||||
this(uint errno)
|
||||
{ char* s = strerror(errno);
|
||||
super(std.string.toString(s).dup);
|
||||
}
|
||||
|
||||
static void opCall(char[] msg)
|
||||
{
|
||||
throw new StdioException(msg);
|
||||
}
|
||||
|
||||
static void opCall()
|
||||
{
|
||||
throw new StdioException(getErrno());
|
||||
}
|
||||
}
|
||||
|
||||
private
|
||||
void writefx(FILE* fp, TypeInfo[] arguments, void* argptr, int newline=false)
|
||||
{ int orientation;
|
||||
|
||||
orientation = fwide(fp, 0);
|
||||
|
||||
/* Do the file stream locking at the outermost level
|
||||
* rather than character by character.
|
||||
*/
|
||||
FLOCK(fp);
|
||||
scope(exit) FUNLOCK(fp);
|
||||
|
||||
if (orientation <= 0) // byte orientation or no orientation
|
||||
{
|
||||
void putc(dchar c)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
FPUTC(c, fp);
|
||||
}
|
||||
else
|
||||
{ char[4] buf;
|
||||
char[] b;
|
||||
|
||||
b = std.utf.toUTF8(buf, c);
|
||||
for (size_t i = 0; i < b.length; i++)
|
||||
FPUTC(b[i], fp);
|
||||
}
|
||||
}
|
||||
|
||||
std.format.doFormat(&putc, arguments, argptr);
|
||||
if (newline)
|
||||
FPUTC('\n', fp);
|
||||
}
|
||||
else if (orientation > 0) // wide orientation
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
void putcw(dchar c)
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
FPUTWC(c, fp);
|
||||
}
|
||||
else
|
||||
{ wchar[2] buf;
|
||||
|
||||
buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
|
||||
FPUTWC(buf[0], fp);
|
||||
FPUTWC(buf[1], fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
void putcw(dchar c)
|
||||
{
|
||||
FPUTWC(c, fp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
|
||||
std.format.doFormat(&putcw, arguments, argptr);
|
||||
if (newline)
|
||||
FPUTWC('\n', fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Arguments are formatted per the
|
||||
* $(LINK2 std_format.html#format-string, format strings)
|
||||
* and written to $(B stdout).
|
||||
*/
|
||||
|
||||
void writef(...)
|
||||
{
|
||||
writefx(stdout, _arguments, _argptr, 0);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Same as $(B writef), but a newline is appended
|
||||
* to the output.
|
||||
*/
|
||||
|
||||
void writefln(...)
|
||||
{
|
||||
writefx(stdout, _arguments, _argptr, 1);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Same as $(B writef), but output is sent to the
|
||||
* stream fp instead of $(B stdout).
|
||||
*/
|
||||
|
||||
void fwritef(FILE* fp, ...)
|
||||
{
|
||||
writefx(fp, _arguments, _argptr, 0);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Same as $(B writefln), but output is sent to the
|
||||
* stream fp instead of $(B stdout).
|
||||
*/
|
||||
|
||||
void fwritefln(FILE* fp, ...)
|
||||
{
|
||||
writefx(fp, _arguments, _argptr, 1);
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Read line from stream fp.
|
||||
* Returns:
|
||||
* null for end of file,
|
||||
* char[] for line read from fp, including terminating '\n'
|
||||
* Params:
|
||||
* fp = input stream
|
||||
* Throws:
|
||||
* $(B StdioException) on error
|
||||
* Example:
|
||||
* Reads $(B stdin) and writes it to $(B stdout).
|
||||
---
|
||||
import std.stdio;
|
||||
|
||||
int main()
|
||||
{
|
||||
char[] buf;
|
||||
while ((buf = readln()) != null)
|
||||
writef("%s", buf);
|
||||
return 0;
|
||||
}
|
||||
---
|
||||
*/
|
||||
char[] readln(FILE* fp = stdin)
|
||||
{
|
||||
char[] buf;
|
||||
readln(fp, buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Read line from stream fp and write it to buf[],
|
||||
* including terminating '\n'.
|
||||
*
|
||||
* This is often faster than readln(FILE*) because the buffer
|
||||
* is reused each call. Note that reusing the buffer means that
|
||||
* the previous contents of it need to be copied if needed.
|
||||
* Params:
|
||||
* fp = input stream
|
||||
* buf = buffer used to store the resulting line data. buf
|
||||
* is resized as necessary.
|
||||
* Returns:
|
||||
* 0 for end of file, otherwise
|
||||
* number of characters read
|
||||
* Throws:
|
||||
* $(B StdioException) on error
|
||||
* Example:
|
||||
* Reads $(B stdin) and writes it to $(B stdout).
|
||||
---
|
||||
import std.stdio;
|
||||
|
||||
int main()
|
||||
{
|
||||
char[] buf;
|
||||
while (readln(stdin, buf))
|
||||
writef("%s", buf);
|
||||
return 0;
|
||||
}
|
||||
---
|
||||
*/
|
||||
size_t readln(FILE* fp, inout char[] buf)
|
||||
{
|
||||
version (DIGITAL_MARS_STDIO)
|
||||
{
|
||||
FLOCK(fp);
|
||||
scope(exit) FUNLOCK(fp);
|
||||
|
||||
if (__fhnd_info[fp._file] & FHND_WCHAR)
|
||||
{ /* Stream is in wide characters.
|
||||
* Read them and convert to chars.
|
||||
*/
|
||||
static assert(wchar_t.sizeof == 2);
|
||||
buf.length = 0;
|
||||
int c2;
|
||||
for (int c; (c = FGETWC(fp)) != -1; )
|
||||
{
|
||||
if ((c & ~0x7F) == 0)
|
||||
{ buf ~= c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c >= 0xD800 && c <= 0xDBFF)
|
||||
{
|
||||
if ((c2 = FGETWC(fp)) != -1 ||
|
||||
c2 < 0xDC00 && c2 > 0xDFFF)
|
||||
{
|
||||
StdioException("unpaired UTF-16 surrogate");
|
||||
}
|
||||
c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
|
||||
}
|
||||
std.utf.encode(buf, c);
|
||||
}
|
||||
}
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
return buf.length;
|
||||
}
|
||||
|
||||
auto sz = std.gc.capacity(buf.ptr);
|
||||
//auto sz = buf.length;
|
||||
buf = buf.ptr[0 .. sz];
|
||||
if (fp._flag & _IONBF)
|
||||
{
|
||||
/* Use this for unbuffered I/O, when running
|
||||
* across buffer boundaries, or for any but the common
|
||||
* cases.
|
||||
*/
|
||||
L1:
|
||||
char *p;
|
||||
|
||||
if (sz)
|
||||
{
|
||||
p = buf.ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
sz = 64;
|
||||
p = cast(char*) std.gc.malloc(sz);
|
||||
std.gc.hasNoPointers(p);
|
||||
buf = p[0 .. sz];
|
||||
}
|
||||
size_t i = 0;
|
||||
for (int c; (c = FGETC(fp)) != -1; )
|
||||
{
|
||||
if ((p[i] = c) != '\n')
|
||||
{
|
||||
i++;
|
||||
if (i < sz)
|
||||
continue;
|
||||
buf = p[0 .. i] ~ readln(fp);
|
||||
return buf.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = p[0 .. i + 1];
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
buf = p[0 .. i];
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
int u = fp._cnt;
|
||||
char* p = fp._ptr;
|
||||
int i;
|
||||
if (fp._flag & _IOTRAN)
|
||||
{ /* Translated mode ignores \r and treats ^Z as end-of-file
|
||||
*/
|
||||
char c;
|
||||
while (1)
|
||||
{
|
||||
if (i == u) // if end of buffer
|
||||
goto L1; // give up
|
||||
c = p[i];
|
||||
i++;
|
||||
if (c != '\r')
|
||||
{
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c != 0x1A)
|
||||
continue;
|
||||
goto L1;
|
||||
}
|
||||
else
|
||||
{ if (i != u && p[i] == '\n')
|
||||
break;
|
||||
goto L1;
|
||||
}
|
||||
}
|
||||
if (i > sz)
|
||||
{
|
||||
buf = cast(char[])std.gc.malloc(i);
|
||||
std.gc.hasNoPointers(buf.ptr);
|
||||
}
|
||||
if (i - 1)
|
||||
memcpy(buf.ptr, p, i - 1);
|
||||
buf[i - 1] = '\n';
|
||||
if (c == '\r')
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (i == u) // if end of buffer
|
||||
goto L1; // give up
|
||||
auto c = p[i];
|
||||
i++;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
if (i > sz)
|
||||
{
|
||||
buf = cast(char[])std.gc.malloc(i);
|
||||
std.gc.hasNoPointers(buf.ptr);
|
||||
}
|
||||
memcpy(buf.ptr, p, i);
|
||||
}
|
||||
fp._cnt -= i;
|
||||
fp._ptr += i;
|
||||
buf = buf[0 .. i];
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else version (GCC_IO)
|
||||
{
|
||||
if (fwide(fp, 0) > 0)
|
||||
{ /* Stream is in wide characters.
|
||||
* Read them and convert to chars.
|
||||
*/
|
||||
FLOCK(fp);
|
||||
scope(exit) FUNLOCK(fp);
|
||||
version (Windows)
|
||||
{
|
||||
buf.length = 0;
|
||||
int c2;
|
||||
for (int c; (c = FGETWC(fp)) != -1; )
|
||||
{
|
||||
if ((c & ~0x7F) == 0)
|
||||
{ buf ~= c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c >= 0xD800 && c <= 0xDBFF)
|
||||
{
|
||||
if ((c2 = FGETWC(fp)) != -1 ||
|
||||
c2 < 0xDC00 && c2 > 0xDFFF)
|
||||
{
|
||||
StdioException("unpaired UTF-16 surrogate");
|
||||
}
|
||||
c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00);
|
||||
}
|
||||
std.utf.encode(buf, c);
|
||||
}
|
||||
}
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
return buf.length;
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
buf.length = 0;
|
||||
for (int c; (c = FGETWC(fp)) != -1; )
|
||||
{
|
||||
if ((c & ~0x7F) == 0)
|
||||
buf ~= c;
|
||||
else
|
||||
std.utf.encode(buf, cast(dchar)c);
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
return buf.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
char *lineptr = null;
|
||||
size_t n = 0;
|
||||
auto s = getdelim(&lineptr, &n, '\n', fp);
|
||||
scope(exit) free(lineptr);
|
||||
if (s < 0)
|
||||
{
|
||||
if (ferror(fp))
|
||||
StdioException();
|
||||
buf.length = 0; // end of file
|
||||
return 0;
|
||||
}
|
||||
buf = buf.ptr[0 .. std.gc.capacity(buf.ptr)];
|
||||
if (s <= buf.length)
|
||||
{
|
||||
buf.length = s;
|
||||
buf[] = lineptr[0 .. s];
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = lineptr[0 .. s].dup;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t readln(inout char[] buf)
|
||||
{
|
||||
return readln(stdin, buf);
|
||||
}
|
||||
|
||||
2965
lphobos/std/stream.d
2965
lphobos/std/stream.d
File diff suppressed because it is too large
Load Diff
4085
lphobos/std/string.d
4085
lphobos/std/string.d
File diff suppressed because it is too large
Load Diff
@@ -1,95 +0,0 @@
|
||||
// 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;
|
||||
|
||||
|
||||
1127
lphobos/std/thread.d
1127
lphobos/std/thread.d
File diff suppressed because it is too large
Load Diff
@@ -1,166 +0,0 @@
|
||||
|
||||
// Written in the D programming language.
|
||||
|
||||
/**
|
||||
* Templates with which to extract information about
|
||||
* types at compile time.
|
||||
*
|
||||
* Macros:
|
||||
* WIKI = Phobos/StdTraits
|
||||
* Copyright:
|
||||
* Public Domain
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Walter Bright, Digital Mars, www.digitalmars.com
|
||||
* Tomasz Stachowiak (isStaticArray, isExpressionTuple)
|
||||
*/
|
||||
|
||||
module std.traits;
|
||||
|
||||
/***
|
||||
* Get the type of the return value from a function,
|
||||
* a pointer to function, or a delegate.
|
||||
* Example:
|
||||
* ---
|
||||
* import std.traits;
|
||||
* int foo();
|
||||
* ReturnType!(foo) x; // x is declared as int
|
||||
* ---
|
||||
*/
|
||||
template ReturnType(alias dg)
|
||||
{
|
||||
alias ReturnType!(typeof(dg)) ReturnType;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
template ReturnType(dg)
|
||||
{
|
||||
static if (is(dg R == return))
|
||||
alias R ReturnType;
|
||||
else
|
||||
static assert(0, "argument has no return type");
|
||||
}
|
||||
|
||||
/***
|
||||
* Get the types of the paramters to a function,
|
||||
* a pointer to function, or a delegate as a tuple.
|
||||
* Example:
|
||||
* ---
|
||||
* import std.traits;
|
||||
* int foo(int, long);
|
||||
* void bar(ParameterTypeTuple!(foo)); // declares void bar(int, long);
|
||||
* void abc(ParameterTypeTuple!(foo)[1]); // declares void abc(long);
|
||||
* ---
|
||||
*/
|
||||
template ParameterTypeTuple(alias dg)
|
||||
{
|
||||
alias ParameterTypeTuple!(typeof(dg)) ParameterTypeTuple;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
template ParameterTypeTuple(dg)
|
||||
{
|
||||
static if (is(dg P == function))
|
||||
alias P ParameterTypeTuple;
|
||||
else static if (is(dg P == delegate))
|
||||
alias ParameterTypeTuple!(P) ParameterTypeTuple;
|
||||
else static if (is(dg P == P*))
|
||||
alias ParameterTypeTuple!(P) ParameterTypeTuple;
|
||||
else
|
||||
static assert(0, "argument has no parameters");
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Get the types of the fields of a struct or class.
|
||||
* This consists of the fields that take up memory space,
|
||||
* excluding the hidden fields like the virtual function
|
||||
* table pointer.
|
||||
*/
|
||||
|
||||
template FieldTypeTuple(S)
|
||||
{
|
||||
static if (is(S == struct) || is(S == class))
|
||||
alias typeof(S.tupleof) FieldTypeTuple;
|
||||
else
|
||||
static assert(0, "argument is not struct or class");
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Get a TypeTuple of the base class and base interfaces of
|
||||
* this class or interface.
|
||||
* Example:
|
||||
* ---
|
||||
* import std.traits, std.typetuple, std.stdio;
|
||||
* interface I { }
|
||||
* class A { }
|
||||
* class B : A, I { }
|
||||
*
|
||||
* void main()
|
||||
* {
|
||||
* alias BaseTypeTuple!(B) TL;
|
||||
* writefln(typeid(TL)); // prints: (A,I)
|
||||
* }
|
||||
* ---
|
||||
*/
|
||||
|
||||
template BaseTypeTuple(A)
|
||||
{
|
||||
static if (is(A P == super))
|
||||
alias P BaseTypeTuple;
|
||||
else
|
||||
static assert(0, "argument is not a class or interface");
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
interface I { }
|
||||
class A { }
|
||||
class B : A, I { }
|
||||
|
||||
alias BaseTypeTuple!(B) TL;
|
||||
assert(TL.length == 2);
|
||||
assert(is (TL[0] == A));
|
||||
assert(is (TL[1] == I));
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect whether type T is a static array.
|
||||
*/
|
||||
template isStaticArray(T)
|
||||
{
|
||||
static if (isArray!(T))
|
||||
const bool isStaticArray = !is(T == typeof(T[0])[]);
|
||||
else const bool isStaticArray = false;
|
||||
}
|
||||
|
||||
|
||||
static assert (isStaticArray!(int[51]));
|
||||
static assert (isStaticArray!(int[][2]));
|
||||
//static assert (isStaticArray!(char[][int][11]));
|
||||
static assert (!isStaticArray!(int[]));
|
||||
//static assert (!isStaticArray!(int[char]));
|
||||
static assert (!isStaticArray!(int[1][]));
|
||||
|
||||
template isArray(T)
|
||||
{
|
||||
const bool isArray=false;
|
||||
}
|
||||
template isArray(T: T[])
|
||||
{
|
||||
const bool isArray=true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the tuple T is an expression tuple.
|
||||
*/
|
||||
template isExpressionTuple(T ...)
|
||||
{
|
||||
static if (is(void function(T)))
|
||||
const bool isExpressionTuple = false;
|
||||
else
|
||||
const bool isExpressionTuple = true;
|
||||
}
|
||||
@@ -1,630 +0,0 @@
|
||||
|
||||
// Written in the D programming language.
|
||||
|
||||
/*
|
||||
* Placed into the Public Domain.
|
||||
* Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*/
|
||||
|
||||
/**
|
||||
* Simple Unicode character classification functions.
|
||||
* For ASCII classification, see $(LINK2 std_ctype.html, std.ctype).
|
||||
* Macros:
|
||||
* WIKI=Phobos/StdUni
|
||||
* References:
|
||||
* $(LINK2 http://www.digitalmars.com/d/ascii-table.html, ASCII Table),
|
||||
* $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia),
|
||||
* $(LINK2 http://www.unicode.org, The Unicode Consortium)
|
||||
* Trademarks:
|
||||
* Unicode(tm) is a trademark of Unicode, Inc.
|
||||
*/
|
||||
|
||||
|
||||
module std.uni;
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a Unicode lower case character.
|
||||
*/
|
||||
int isUniLower(dchar c)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
return (c >= 'a' && c <= 'z');
|
||||
|
||||
return isUniAlpha(c) && c == toUniLower(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a Unicode upper case character.
|
||||
*/
|
||||
int isUniUpper(dchar c)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
return (c >= 'A' && c <= 'Z');
|
||||
|
||||
return isUniAlpha(c) && c == toUniUpper(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* If c is a Unicode upper case character, return the lower case
|
||||
* equivalent, otherwise return c.
|
||||
*/
|
||||
dchar toUniLower(dchar c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
{
|
||||
c += 32;
|
||||
}
|
||||
else if (c >= 0x00C0)
|
||||
{
|
||||
if ((c >= 0x00C0 && c <= 0x00D6) || (c >= 0x00D8 && c<=0x00DE))
|
||||
{
|
||||
c += 32;
|
||||
}
|
||||
else if ((c >= 0x0100 && c < 0x0138) || (c > 0x0149 && c < 0x0178))
|
||||
{
|
||||
if (c == 0x0130)
|
||||
c = 0x0069;
|
||||
else if ((c & 1) == 0)
|
||||
c += 1;
|
||||
}
|
||||
else if (c == 0x0178)
|
||||
{
|
||||
c = 0x00FF;
|
||||
}
|
||||
else if ((c >= 0x0139 && c < 0x0149) || (c > 0x0178 && c < 0x017F))
|
||||
{
|
||||
if (c & 1)
|
||||
c += 1;
|
||||
}
|
||||
else if (c >= 0x0200 && c <= 0x0217)
|
||||
{
|
||||
if ((c & 1) == 0)
|
||||
c += 1;
|
||||
}
|
||||
else if ((c >= 0x0401 && c <= 0x040C) || (c>= 0x040E && c <= 0x040F))
|
||||
{
|
||||
c += 80;
|
||||
}
|
||||
else if (c >= 0x0410 && c <= 0x042F)
|
||||
{
|
||||
c += 32;
|
||||
}
|
||||
else if (c >= 0x0460 && c <= 0x047F)
|
||||
{
|
||||
if ((c & 1) == 0)
|
||||
c += 1;
|
||||
}
|
||||
else if (c >= 0x0531 && c <= 0x0556)
|
||||
{
|
||||
c += 48;
|
||||
}
|
||||
else if (c >= 0x10A0 && c <= 0x10C5)
|
||||
{
|
||||
c += 48;
|
||||
}
|
||||
else if (c >= 0xFF21 && c <= 0xFF3A)
|
||||
{
|
||||
c += 32;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* If c is a Unicode lower case character, return the upper case
|
||||
* equivalent, otherwise return c.
|
||||
*/
|
||||
dchar toUniUpper(dchar c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
{
|
||||
c -= 32;
|
||||
}
|
||||
else if (c >= 0x00E0)
|
||||
{
|
||||
if ((c >= 0x00E0 && c <= 0x00F6) || (c >= 0x00F8 && c <= 0x00FE))
|
||||
{
|
||||
c -= 32;
|
||||
}
|
||||
else if (c == 0x00FF)
|
||||
{
|
||||
c = 0x0178;
|
||||
}
|
||||
else if ((c >= 0x0100 && c < 0x0138) || (c > 0x0149 && c < 0x0178))
|
||||
{
|
||||
if (c == 0x0131)
|
||||
c = 0x0049;
|
||||
else if (c & 1)
|
||||
c -= 1;
|
||||
}
|
||||
else if ((c >= 0x0139 && c < 0x0149) || (c > 0x0178 && c < 0x017F))
|
||||
{
|
||||
if ((c & 1) == 0)
|
||||
c = c-1;
|
||||
}
|
||||
else if (c == 0x017F)
|
||||
{
|
||||
c = 0x0053;
|
||||
}
|
||||
else if (c >= 0x0200 && c <= 0x0217)
|
||||
{
|
||||
if (c & 1)
|
||||
c = c-1;
|
||||
}
|
||||
else if (c >= 0x0430 && c<= 0x044F)
|
||||
{
|
||||
c -= 32;
|
||||
}
|
||||
else if ((c >= 0x0451 && c <= 0x045C) || (c >=0x045E && c<= 0x045F))
|
||||
{
|
||||
c -= 80;
|
||||
}
|
||||
else if (c >= 0x0460 && c <= 0x047F)
|
||||
{
|
||||
if (c & 1)
|
||||
c -= 1;
|
||||
}
|
||||
else if (c >= 0x0561 && c < 0x0587)
|
||||
{
|
||||
c -= 48;
|
||||
}
|
||||
else if (c >= 0xFF41 && c <= 0xFF5A)
|
||||
{
|
||||
c -= 32;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
* Return !=0 if u is a Unicode alpha character.
|
||||
* (general Unicode category: Lu, Ll, Lt, Lm and Lo)
|
||||
*
|
||||
* Standards: Unicode 5.0.0
|
||||
*/
|
||||
|
||||
int isUniAlpha(dchar u)
|
||||
{
|
||||
static dchar table[][2] =
|
||||
[
|
||||
[ 'A', 'Z' ],
|
||||
[ 'a', 'z' ],
|
||||
[ 0x00AA, 0x00AA ],
|
||||
[ 0x00B5, 0x00B5 ],
|
||||
[ 0x00BA, 0x00BA ],
|
||||
[ 0x00C0, 0x00D6 ],
|
||||
[ 0x00D8, 0x00F6 ],
|
||||
[ 0x00F8, 0x02C1 ],
|
||||
[ 0x02C6, 0x02D1 ],
|
||||
[ 0x02E0, 0x02E4 ],
|
||||
[ 0x02EE, 0x02EE ],
|
||||
[ 0x037A, 0x037D ],
|
||||
[ 0x0386, 0x0386 ],
|
||||
[ 0x0388, 0x038A ],
|
||||
[ 0x038C, 0x038C ],
|
||||
[ 0x038E, 0x03A1 ],
|
||||
[ 0x03A3, 0x03CE ],
|
||||
[ 0x03D0, 0x03F5 ],
|
||||
[ 0x03F7, 0x0481 ],
|
||||
[ 0x048A, 0x0513 ],
|
||||
[ 0x0531, 0x0556 ],
|
||||
[ 0x0559, 0x0559 ],
|
||||
[ 0x0561, 0x0587 ],
|
||||
[ 0x05D0, 0x05EA ],
|
||||
[ 0x05F0, 0x05F2 ],
|
||||
[ 0x0621, 0x063A ],
|
||||
[ 0x0640, 0x064A ],
|
||||
[ 0x066E, 0x066F ],
|
||||
[ 0x0671, 0x06D3 ],
|
||||
[ 0x06D5, 0x06D5 ],
|
||||
[ 0x06E5, 0x06E6 ],
|
||||
[ 0x06EE, 0x06EF ],
|
||||
[ 0x06FA, 0x06FC ],
|
||||
[ 0x06FF, 0x06FF ],
|
||||
[ 0x0710, 0x0710 ],
|
||||
[ 0x0712, 0x072F ],
|
||||
[ 0x074D, 0x076D ],
|
||||
[ 0x0780, 0x07A5 ],
|
||||
[ 0x07B1, 0x07B1 ],
|
||||
[ 0x07CA, 0x07EA ],
|
||||
[ 0x07F4, 0x07F5 ],
|
||||
[ 0x07FA, 0x07FA ],
|
||||
[ 0x0904, 0x0939 ],
|
||||
[ 0x093D, 0x093D ],
|
||||
[ 0x0950, 0x0950 ],
|
||||
[ 0x0958, 0x0961 ],
|
||||
[ 0x097B, 0x097F ],
|
||||
[ 0x0985, 0x098C ],
|
||||
[ 0x098F, 0x0990 ],
|
||||
[ 0x0993, 0x09A8 ],
|
||||
[ 0x09AA, 0x09B0 ],
|
||||
[ 0x09B2, 0x09B2 ],
|
||||
[ 0x09B6, 0x09B9 ],
|
||||
[ 0x09BD, 0x09BD ],
|
||||
[ 0x09CE, 0x09CE ],
|
||||
[ 0x09DC, 0x09DD ],
|
||||
[ 0x09DF, 0x09E1 ],
|
||||
[ 0x09F0, 0x09F1 ],
|
||||
[ 0x0A05, 0x0A0A ],
|
||||
[ 0x0A0F, 0x0A10 ],
|
||||
[ 0x0A13, 0x0A28 ],
|
||||
[ 0x0A2A, 0x0A30 ],
|
||||
[ 0x0A32, 0x0A33 ],
|
||||
[ 0x0A35, 0x0A36 ],
|
||||
[ 0x0A38, 0x0A39 ],
|
||||
[ 0x0A59, 0x0A5C ],
|
||||
[ 0x0A5E, 0x0A5E ],
|
||||
[ 0x0A72, 0x0A74 ],
|
||||
[ 0x0A85, 0x0A8D ],
|
||||
[ 0x0A8F, 0x0A91 ],
|
||||
[ 0x0A93, 0x0AA8 ],
|
||||
[ 0x0AAA, 0x0AB0 ],
|
||||
[ 0x0AB2, 0x0AB3 ],
|
||||
[ 0x0AB5, 0x0AB9 ],
|
||||
[ 0x0ABD, 0x0ABD ],
|
||||
[ 0x0AD0, 0x0AD0 ],
|
||||
[ 0x0AE0, 0x0AE1 ],
|
||||
[ 0x0B05, 0x0B0C ],
|
||||
[ 0x0B0F, 0x0B10 ],
|
||||
[ 0x0B13, 0x0B28 ],
|
||||
[ 0x0B2A, 0x0B30 ],
|
||||
[ 0x0B32, 0x0B33 ],
|
||||
[ 0x0B35, 0x0B39 ],
|
||||
[ 0x0B3D, 0x0B3D ],
|
||||
[ 0x0B5C, 0x0B5D ],
|
||||
[ 0x0B5F, 0x0B61 ],
|
||||
[ 0x0B71, 0x0B71 ],
|
||||
[ 0x0B83, 0x0B83 ],
|
||||
[ 0x0B85, 0x0B8A ],
|
||||
[ 0x0B8E, 0x0B90 ],
|
||||
[ 0x0B92, 0x0B95 ],
|
||||
[ 0x0B99, 0x0B9A ],
|
||||
[ 0x0B9C, 0x0B9C ],
|
||||
[ 0x0B9E, 0x0B9F ],
|
||||
[ 0x0BA3, 0x0BA4 ],
|
||||
[ 0x0BA8, 0x0BAA ],
|
||||
[ 0x0BAE, 0x0BB9 ],
|
||||
[ 0x0C05, 0x0C0C ],
|
||||
[ 0x0C0E, 0x0C10 ],
|
||||
[ 0x0C12, 0x0C28 ],
|
||||
[ 0x0C2A, 0x0C33 ],
|
||||
[ 0x0C35, 0x0C39 ],
|
||||
[ 0x0C60, 0x0C61 ],
|
||||
[ 0x0C85, 0x0C8C ],
|
||||
[ 0x0C8E, 0x0C90 ],
|
||||
[ 0x0C92, 0x0CA8 ],
|
||||
[ 0x0CAA, 0x0CB3 ],
|
||||
[ 0x0CB5, 0x0CB9 ],
|
||||
[ 0x0CBD, 0x0CBD ],
|
||||
[ 0x0CDE, 0x0CDE ],
|
||||
[ 0x0CE0, 0x0CE1 ],
|
||||
[ 0x0D05, 0x0D0C ],
|
||||
[ 0x0D0E, 0x0D10 ],
|
||||
[ 0x0D12, 0x0D28 ],
|
||||
[ 0x0D2A, 0x0D39 ],
|
||||
[ 0x0D60, 0x0D61 ],
|
||||
[ 0x0D85, 0x0D96 ],
|
||||
[ 0x0D9A, 0x0DB1 ],
|
||||
[ 0x0DB3, 0x0DBB ],
|
||||
[ 0x0DBD, 0x0DBD ],
|
||||
[ 0x0DC0, 0x0DC6 ],
|
||||
[ 0x0E01, 0x0E30 ],
|
||||
[ 0x0E32, 0x0E33 ],
|
||||
[ 0x0E40, 0x0E46 ],
|
||||
[ 0x0E81, 0x0E82 ],
|
||||
[ 0x0E84, 0x0E84 ],
|
||||
[ 0x0E87, 0x0E88 ],
|
||||
[ 0x0E8A, 0x0E8A ],
|
||||
[ 0x0E8D, 0x0E8D ],
|
||||
[ 0x0E94, 0x0E97 ],
|
||||
[ 0x0E99, 0x0E9F ],
|
||||
[ 0x0EA1, 0x0EA3 ],
|
||||
[ 0x0EA5, 0x0EA5 ],
|
||||
[ 0x0EA7, 0x0EA7 ],
|
||||
[ 0x0EAA, 0x0EAB ],
|
||||
[ 0x0EAD, 0x0EB0 ],
|
||||
[ 0x0EB2, 0x0EB3 ],
|
||||
[ 0x0EBD, 0x0EBD ],
|
||||
[ 0x0EC0, 0x0EC4 ],
|
||||
[ 0x0EC6, 0x0EC6 ],
|
||||
[ 0x0EDC, 0x0EDD ],
|
||||
[ 0x0F00, 0x0F00 ],
|
||||
[ 0x0F40, 0x0F47 ],
|
||||
[ 0x0F49, 0x0F6A ],
|
||||
[ 0x0F88, 0x0F8B ],
|
||||
[ 0x1000, 0x1021 ],
|
||||
[ 0x1023, 0x1027 ],
|
||||
[ 0x1029, 0x102A ],
|
||||
[ 0x1050, 0x1055 ],
|
||||
[ 0x10A0, 0x10C5 ],
|
||||
[ 0x10D0, 0x10FA ],
|
||||
[ 0x10FC, 0x10FC ],
|
||||
[ 0x1100, 0x1159 ],
|
||||
[ 0x115F, 0x11A2 ],
|
||||
[ 0x11A8, 0x11F9 ],
|
||||
[ 0x1200, 0x1248 ],
|
||||
[ 0x124A, 0x124D ],
|
||||
[ 0x1250, 0x1256 ],
|
||||
[ 0x1258, 0x1258 ],
|
||||
[ 0x125A, 0x125D ],
|
||||
[ 0x1260, 0x1288 ],
|
||||
[ 0x128A, 0x128D ],
|
||||
[ 0x1290, 0x12B0 ],
|
||||
[ 0x12B2, 0x12B5 ],
|
||||
[ 0x12B8, 0x12BE ],
|
||||
[ 0x12C0, 0x12C0 ],
|
||||
[ 0x12C2, 0x12C5 ],
|
||||
[ 0x12C8, 0x12D6 ],
|
||||
[ 0x12D8, 0x1310 ],
|
||||
[ 0x1312, 0x1315 ],
|
||||
[ 0x1318, 0x135A ],
|
||||
[ 0x1380, 0x138F ],
|
||||
[ 0x13A0, 0x13F4 ],
|
||||
[ 0x1401, 0x166C ],
|
||||
[ 0x166F, 0x1676 ],
|
||||
[ 0x1681, 0x169A ],
|
||||
[ 0x16A0, 0x16EA ],
|
||||
[ 0x1700, 0x170C ],
|
||||
[ 0x170E, 0x1711 ],
|
||||
[ 0x1720, 0x1731 ],
|
||||
[ 0x1740, 0x1751 ],
|
||||
[ 0x1760, 0x176C ],
|
||||
[ 0x176E, 0x1770 ],
|
||||
[ 0x1780, 0x17B3 ],
|
||||
[ 0x17D7, 0x17D7 ],
|
||||
[ 0x17DC, 0x17DC ],
|
||||
[ 0x1820, 0x1877 ],
|
||||
[ 0x1880, 0x18A8 ],
|
||||
[ 0x1900, 0x191C ],
|
||||
[ 0x1950, 0x196D ],
|
||||
[ 0x1970, 0x1974 ],
|
||||
[ 0x1980, 0x19A9 ],
|
||||
[ 0x19C1, 0x19C7 ],
|
||||
[ 0x1A00, 0x1A16 ],
|
||||
[ 0x1B05, 0x1B33 ],
|
||||
[ 0x1B45, 0x1B4B ],
|
||||
[ 0x1D00, 0x1DBF ],
|
||||
[ 0x1E00, 0x1E9B ],
|
||||
[ 0x1EA0, 0x1EF9 ],
|
||||
[ 0x1F00, 0x1F15 ],
|
||||
[ 0x1F18, 0x1F1D ],
|
||||
[ 0x1F20, 0x1F45 ],
|
||||
[ 0x1F48, 0x1F4D ],
|
||||
[ 0x1F50, 0x1F57 ],
|
||||
[ 0x1F59, 0x1F59 ],
|
||||
[ 0x1F5B, 0x1F5B ],
|
||||
[ 0x1F5D, 0x1F5D ],
|
||||
[ 0x1F5F, 0x1F7D ],
|
||||
[ 0x1F80, 0x1FB4 ],
|
||||
[ 0x1FB6, 0x1FBC ],
|
||||
[ 0x1FBE, 0x1FBE ],
|
||||
[ 0x1FC2, 0x1FC4 ],
|
||||
[ 0x1FC6, 0x1FCC ],
|
||||
[ 0x1FD0, 0x1FD3 ],
|
||||
[ 0x1FD6, 0x1FDB ],
|
||||
[ 0x1FE0, 0x1FEC ],
|
||||
[ 0x1FF2, 0x1FF4 ],
|
||||
[ 0x1FF6, 0x1FFC ],
|
||||
[ 0x2071, 0x2071 ],
|
||||
[ 0x207F, 0x207F ],
|
||||
[ 0x2090, 0x2094 ],
|
||||
[ 0x2102, 0x2102 ],
|
||||
[ 0x2107, 0x2107 ],
|
||||
[ 0x210A, 0x2113 ],
|
||||
[ 0x2115, 0x2115 ],
|
||||
[ 0x2119, 0x211D ],
|
||||
[ 0x2124, 0x2124 ],
|
||||
[ 0x2126, 0x2126 ],
|
||||
[ 0x2128, 0x2128 ],
|
||||
[ 0x212A, 0x212D ],
|
||||
[ 0x212F, 0x2139 ],
|
||||
[ 0x213C, 0x213F ],
|
||||
[ 0x2145, 0x2149 ],
|
||||
[ 0x214E, 0x214E ],
|
||||
[ 0x2183, 0x2184 ],
|
||||
[ 0x2C00, 0x2C2E ],
|
||||
[ 0x2C30, 0x2C5E ],
|
||||
[ 0x2C60, 0x2C6C ],
|
||||
[ 0x2C74, 0x2C77 ],
|
||||
[ 0x2C80, 0x2CE4 ],
|
||||
[ 0x2D00, 0x2D25 ],
|
||||
[ 0x2D30, 0x2D65 ],
|
||||
[ 0x2D6F, 0x2D6F ],
|
||||
[ 0x2D80, 0x2D96 ],
|
||||
[ 0x2DA0, 0x2DA6 ],
|
||||
[ 0x2DA8, 0x2DAE ],
|
||||
[ 0x2DB0, 0x2DB6 ],
|
||||
[ 0x2DB8, 0x2DBE ],
|
||||
[ 0x2DC0, 0x2DC6 ],
|
||||
[ 0x2DC8, 0x2DCE ],
|
||||
[ 0x2DD0, 0x2DD6 ],
|
||||
[ 0x2DD8, 0x2DDE ],
|
||||
[ 0x3005, 0x3006 ],
|
||||
[ 0x3031, 0x3035 ],
|
||||
[ 0x303B, 0x303C ],
|
||||
[ 0x3041, 0x3096 ],
|
||||
[ 0x309D, 0x309F ],
|
||||
[ 0x30A1, 0x30FA ],
|
||||
[ 0x30FC, 0x30FF ],
|
||||
[ 0x3105, 0x312C ],
|
||||
[ 0x3131, 0x318E ],
|
||||
[ 0x31A0, 0x31B7 ],
|
||||
[ 0x31F0, 0x31FF ],
|
||||
[ 0x3400, 0x4DB5 ],
|
||||
[ 0x4E00, 0x9FBB ],
|
||||
[ 0xA000, 0xA48C ],
|
||||
[ 0xA717, 0xA71A ],
|
||||
[ 0xA800, 0xA801 ],
|
||||
[ 0xA803, 0xA805 ],
|
||||
[ 0xA807, 0xA80A ],
|
||||
[ 0xA80C, 0xA822 ],
|
||||
[ 0xA840, 0xA873 ],
|
||||
[ 0xAC00, 0xD7A3 ],
|
||||
[ 0xF900, 0xFA2D ],
|
||||
[ 0xFA30, 0xFA6A ],
|
||||
[ 0xFA70, 0xFAD9 ],
|
||||
[ 0xFB00, 0xFB06 ],
|
||||
[ 0xFB13, 0xFB17 ],
|
||||
[ 0xFB1D, 0xFB1D ],
|
||||
[ 0xFB1F, 0xFB28 ],
|
||||
[ 0xFB2A, 0xFB36 ],
|
||||
[ 0xFB38, 0xFB3C ],
|
||||
[ 0xFB3E, 0xFB3E ],
|
||||
[ 0xFB40, 0xFB41 ],
|
||||
[ 0xFB43, 0xFB44 ],
|
||||
[ 0xFB46, 0xFBB1 ],
|
||||
[ 0xFBD3, 0xFD3D ],
|
||||
[ 0xFD50, 0xFD8F ],
|
||||
[ 0xFD92, 0xFDC7 ],
|
||||
[ 0xFDF0, 0xFDFB ],
|
||||
[ 0xFE70, 0xFE74 ],
|
||||
[ 0xFE76, 0xFEFC ],
|
||||
[ 0xFF21, 0xFF3A ],
|
||||
[ 0xFF41, 0xFF5A ],
|
||||
[ 0xFF66, 0xFFBE ],
|
||||
[ 0xFFC2, 0xFFC7 ],
|
||||
[ 0xFFCA, 0xFFCF ],
|
||||
[ 0xFFD2, 0xFFD7 ],
|
||||
[ 0xFFDA, 0xFFDC ],
|
||||
[ 0x10000, 0x1000B ],
|
||||
[ 0x1000D, 0x10026 ],
|
||||
[ 0x10028, 0x1003A ],
|
||||
[ 0x1003C, 0x1003D ],
|
||||
[ 0x1003F, 0x1004D ],
|
||||
[ 0x10050, 0x1005D ],
|
||||
[ 0x10080, 0x100FA ],
|
||||
[ 0x10300, 0x1031E ],
|
||||
[ 0x10330, 0x10340 ],
|
||||
[ 0x10342, 0x10349 ],
|
||||
[ 0x10380, 0x1039D ],
|
||||
[ 0x103A0, 0x103C3 ],
|
||||
[ 0x103C8, 0x103CF ],
|
||||
[ 0x10400, 0x1049D ],
|
||||
[ 0x10800, 0x10805 ],
|
||||
[ 0x10808, 0x10808 ],
|
||||
[ 0x1080A, 0x10835 ],
|
||||
[ 0x10837, 0x10838 ],
|
||||
[ 0x1083C, 0x1083C ],
|
||||
[ 0x1083F, 0x1083F ],
|
||||
[ 0x10900, 0x10915 ],
|
||||
[ 0x10A00, 0x10A00 ],
|
||||
[ 0x10A10, 0x10A13 ],
|
||||
[ 0x10A15, 0x10A17 ],
|
||||
[ 0x10A19, 0x10A33 ],
|
||||
[ 0x12000, 0x1236E ],
|
||||
[ 0x1D400, 0x1D454 ],
|
||||
[ 0x1D456, 0x1D49C ],
|
||||
[ 0x1D49E, 0x1D49F ],
|
||||
[ 0x1D4A2, 0x1D4A2 ],
|
||||
[ 0x1D4A5, 0x1D4A6 ],
|
||||
[ 0x1D4A9, 0x1D4AC ],
|
||||
[ 0x1D4AE, 0x1D4B9 ],
|
||||
[ 0x1D4BB, 0x1D4BB ],
|
||||
[ 0x1D4BD, 0x1D4C3 ],
|
||||
[ 0x1D4C5, 0x1D505 ],
|
||||
[ 0x1D507, 0x1D50A ],
|
||||
[ 0x1D50D, 0x1D514 ],
|
||||
[ 0x1D516, 0x1D51C ],
|
||||
[ 0x1D51E, 0x1D539 ],
|
||||
[ 0x1D53B, 0x1D53E ],
|
||||
[ 0x1D540, 0x1D544 ],
|
||||
[ 0x1D546, 0x1D546 ],
|
||||
[ 0x1D54A, 0x1D550 ],
|
||||
[ 0x1D552, 0x1D6A5 ],
|
||||
[ 0x1D6A8, 0x1D6C0 ],
|
||||
[ 0x1D6C2, 0x1D6DA ],
|
||||
[ 0x1D6DC, 0x1D6FA ],
|
||||
[ 0x1D6FC, 0x1D714 ],
|
||||
[ 0x1D716, 0x1D734 ],
|
||||
[ 0x1D736, 0x1D74E ],
|
||||
[ 0x1D750, 0x1D76E ],
|
||||
[ 0x1D770, 0x1D788 ],
|
||||
[ 0x1D78A, 0x1D7A8 ],
|
||||
[ 0x1D7AA, 0x1D7C2 ],
|
||||
[ 0x1D7C4, 0x1D7CB ],
|
||||
[ 0x20000, 0x2A6D6 ],
|
||||
[ 0x2F800, 0x2FA1D ],
|
||||
];
|
||||
|
||||
debug
|
||||
{
|
||||
for (int i = 0; i < table.length; i++)
|
||||
{
|
||||
assert(table[i][0] <= table[i][1]);
|
||||
if (i < table.length - 1)
|
||||
{
|
||||
if (table[i][1] >= table[i + 1][0])
|
||||
printf("table[%d][1] = x%x, table[%d][0] = x%x\n", i, table[i][1], i + 1, table[i + 1][0]);
|
||||
assert(table[i][1] < table[i + 1][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (u < 0xAA)
|
||||
{
|
||||
if (u < 'A')
|
||||
goto Lisnot;
|
||||
if (u <= 'Z')
|
||||
goto Lis;
|
||||
if (u < 'a')
|
||||
goto Lisnot;
|
||||
if (u <= 'z')
|
||||
goto Lis;
|
||||
goto Lisnot;
|
||||
}
|
||||
|
||||
// Binary search
|
||||
uint mid;
|
||||
uint low;
|
||||
uint high;
|
||||
|
||||
low = 0;
|
||||
high = table.length - 1;
|
||||
while (cast(int)low <= cast(int)high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
if (u < table[mid][0])
|
||||
high = mid - 1;
|
||||
else if (u > table[mid][1])
|
||||
low = mid + 1;
|
||||
else
|
||||
goto Lis;
|
||||
}
|
||||
|
||||
Lisnot:
|
||||
debug
|
||||
{
|
||||
for (int i = 0; i < table.length; i++)
|
||||
{
|
||||
assert(u < table[i][0] || u > table[i][1]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
Lis:
|
||||
debug
|
||||
{
|
||||
for (int i = 0; i < table.length; i++)
|
||||
{
|
||||
if (u >= table[i][0] && u <= table[i][1])
|
||||
return 1;
|
||||
}
|
||||
assert(0); // should have been in table
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
for (uint i = 0; i < 0x80; i++)
|
||||
{
|
||||
if (i >= 'A' && i <= 'Z')
|
||||
assert(isUniAlpha(i));
|
||||
else if (i >= 'a' && i <= 'z')
|
||||
assert(isUniAlpha(i));
|
||||
else
|
||||
assert(!isUniAlpha(i));
|
||||
}
|
||||
}
|
||||
@@ -1,969 +0,0 @@
|
||||
// utf.d
|
||||
|
||||
/*
|
||||
* Copyright (C) 2003-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.
|
||||
*/
|
||||
|
||||
/********************************************
|
||||
* Encode and decode UTF-8, UTF-16 and UTF-32 strings.
|
||||
*
|
||||
* For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D
|
||||
* wchar type.
|
||||
* For linux systems, the C wchar_t type is UTF-32 and corresponds to
|
||||
* the D utf.dchar type.
|
||||
*
|
||||
* UTF character support is restricted to (\u0000 <= character <= \U0010FFFF).
|
||||
*
|
||||
* See_Also:
|
||||
* $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)<br>
|
||||
* $(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)<br>
|
||||
* $(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335)
|
||||
* Macros:
|
||||
* WIKI = Phobos/StdUtf
|
||||
*/
|
||||
|
||||
module std.utf;
|
||||
|
||||
private import std.stdio;
|
||||
|
||||
//debug=utf; // uncomment to turn on debugging printf's
|
||||
|
||||
deprecated class UtfError : Error
|
||||
{
|
||||
size_t idx; // index in string of where error occurred
|
||||
|
||||
this(char[] s, size_t i)
|
||||
{
|
||||
idx = i;
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Exception class that is thrown upon any errors.
|
||||
*/
|
||||
|
||||
class UtfException : Exception
|
||||
{
|
||||
size_t idx; /// index in string of where error occurred
|
||||
|
||||
this(char[] s, size_t i)
|
||||
{
|
||||
idx = i;
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************
|
||||
* Test if c is a valid UTF-32 character.
|
||||
*
|
||||
* \uFFFE and \uFFFF are considered valid by this function,
|
||||
* as they are permitted for internal use by an application,
|
||||
* but they are not allowed for interchange by the Unicode standard.
|
||||
*
|
||||
* Returns: true if it is, false if not.
|
||||
*/
|
||||
|
||||
bool isValidDchar(dchar c)
|
||||
{
|
||||
/* Note: FFFE and FFFF are specifically permitted by the
|
||||
* Unicode standard for application internal use, but are not
|
||||
* allowed for interchange.
|
||||
* (thanks to Arcane Jill)
|
||||
*/
|
||||
|
||||
return c < 0xD800 ||
|
||||
(c > 0xDFFF && c <= 0x10FFFF /*&& c != 0xFFFE && c != 0xFFFF*/);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(utf) printf("utf.isValidDchar.unittest\n");
|
||||
assert(isValidDchar(cast(dchar)'a') == true);
|
||||
assert(isValidDchar(cast(dchar)0x1FFFFF) == false);
|
||||
}
|
||||
|
||||
|
||||
ubyte[256] UTF8stride =
|
||||
[
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF,
|
||||
];
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-8 sequence starting at index i
|
||||
* in string s.
|
||||
* Returns:
|
||||
* The number of bytes in the UTF-8 sequence or
|
||||
* 0xFF meaning s[i] is not the start of of UTF-8 sequence.
|
||||
*/
|
||||
|
||||
uint stride(char[] s, size_t i)
|
||||
{
|
||||
return UTF8stride[s[i]];
|
||||
}
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-16 sequence starting at index i
|
||||
* in string s.
|
||||
*/
|
||||
|
||||
uint stride(wchar[] s, size_t i)
|
||||
{ uint u = s[i];
|
||||
return 1 + (u >= 0xD800 && u <= 0xDBFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-32 sequence starting at index i
|
||||
* in string s.
|
||||
* Returns: The return value will always be 1.
|
||||
*/
|
||||
|
||||
uint stride(dchar[] s, size_t i)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Given an index i into an array of characters s[],
|
||||
* and assuming that index i is at the start of a UTF character,
|
||||
* determine the number of UCS characters up to that index i.
|
||||
*/
|
||||
|
||||
size_t toUCSindex(char[] s, size_t i)
|
||||
{
|
||||
size_t n;
|
||||
size_t j;
|
||||
size_t stride;
|
||||
|
||||
for (j = 0; j < i; j += stride)
|
||||
{
|
||||
stride = UTF8stride[s[j]];
|
||||
if (stride == 0xFF)
|
||||
goto Lerr;
|
||||
n++;
|
||||
}
|
||||
if (j > i)
|
||||
{
|
||||
Lerr:
|
||||
throw new UtfException("1invalid UTF-8 sequence", j);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
size_t toUCSindex(wchar[] s, size_t i)
|
||||
{
|
||||
size_t n;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < i; )
|
||||
{ uint u = s[j];
|
||||
|
||||
j += 1 + (u >= 0xD800 && u <= 0xDBFF);
|
||||
n++;
|
||||
}
|
||||
if (j > i)
|
||||
{
|
||||
Lerr:
|
||||
throw new UtfException("2invalid UTF-16 sequence", j);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
size_t toUCSindex(dchar[] s, size_t i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Given a UCS index n into an array of characters s[], return the UTF index.
|
||||
*/
|
||||
|
||||
size_t toUTFindex(char[] s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
uint j = UTF8stride[s[i]];
|
||||
if (j == 0xFF)
|
||||
throw new UtfException("3invalid UTF-8 sequence", i);
|
||||
i += j;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
size_t toUTFindex(wchar[] s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
while (n--)
|
||||
{ wchar u = s[i];
|
||||
|
||||
i += 1 + (u >= 0xD800 && u <= 0xDBFF);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
size_t toUTFindex(dchar[] s, size_t n)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
/* =================== Decode ======================= */
|
||||
|
||||
/***************
|
||||
* Decodes and returns character starting at s[idx]. idx is advanced past the
|
||||
* decoded character. If the character is not well formed, a UtfException is
|
||||
* thrown and idx remains unchanged.
|
||||
*/
|
||||
|
||||
dchar decode(char[] s, inout size_t idx)
|
||||
in
|
||||
{
|
||||
assert(idx >= 0 && idx < s.length);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(isValidDchar(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t len = s.length;
|
||||
dchar V;
|
||||
size_t i = idx;
|
||||
char u = s[i];
|
||||
|
||||
if (u & 0x80)
|
||||
{ uint n;
|
||||
char u2;
|
||||
|
||||
/* The following encodings are valid, except for the 5 and 6 byte
|
||||
* combinations:
|
||||
* 0xxxxxxx
|
||||
* 110xxxxx 10xxxxxx
|
||||
* 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
for (n = 1; ; n++)
|
||||
{
|
||||
if (n > 4)
|
||||
goto Lerr; // only do the first 4 of 6 encodings
|
||||
if (((u << n) & 0x80) == 0)
|
||||
{
|
||||
if (n == 1)
|
||||
goto Lerr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pick off (7 - n) significant bits of B from first byte of octet
|
||||
V = cast(dchar)(u & ((1 << (7 - n)) - 1));
|
||||
|
||||
if (i + (n - 1) >= len)
|
||||
goto Lerr; // off end of string
|
||||
|
||||
/* The following combinations are overlong, and illegal:
|
||||
* 1100000x (10xxxxxx)
|
||||
* 11100000 100xxxxx (10xxxxxx)
|
||||
* 11110000 1000xxxx (10xxxxxx 10xxxxxx)
|
||||
* 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
* 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
*/
|
||||
u2 = s[i + 1];
|
||||
if ((u & 0xFE) == 0xC0 ||
|
||||
(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
|
||||
(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
|
||||
(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
|
||||
(u == 0xFC && (u2 & 0xFC) == 0x80))
|
||||
goto Lerr; // overlong combination
|
||||
|
||||
for (uint j = 1; j != n; j++)
|
||||
{
|
||||
u = s[i + j];
|
||||
if ((u & 0xC0) != 0x80)
|
||||
goto Lerr; // trailing bytes are 10xxxxxx
|
||||
V = (V << 6) | (u & 0x3F);
|
||||
}
|
||||
if (!isValidDchar(V))
|
||||
goto Lerr;
|
||||
i += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
V = cast(dchar) u;
|
||||
i++;
|
||||
}
|
||||
|
||||
idx = i;
|
||||
return V;
|
||||
|
||||
Lerr:
|
||||
//printf("\ndecode: idx = %d, i = %d, length = %d s = \n'%.*s'\n%x\n'%.*s'\n", idx, i, s.length, s, s[i], s[i .. length]);
|
||||
throw new UtfException("4invalid UTF-8 sequence", i);
|
||||
}
|
||||
|
||||
unittest
|
||||
{ size_t i;
|
||||
dchar c;
|
||||
|
||||
debug(utf) printf("utf.decode.unittest\n");
|
||||
|
||||
static char[] s1 = "abcd";
|
||||
i = 0;
|
||||
c = decode(s1, i);
|
||||
assert(c == cast(dchar)'a');
|
||||
assert(i == 1);
|
||||
c = decode(s1, i);
|
||||
assert(c == cast(dchar)'b');
|
||||
assert(i == 2);
|
||||
|
||||
static char[] s2 = "\xC2\xA9";
|
||||
i = 0;
|
||||
c = decode(s2, i);
|
||||
assert(c == cast(dchar)'\u00A9');
|
||||
assert(i == 2);
|
||||
|
||||
static char[] s3 = "\xE2\x89\xA0";
|
||||
i = 0;
|
||||
c = decode(s3, i);
|
||||
assert(c == cast(dchar)'\u2260');
|
||||
assert(i == 3);
|
||||
|
||||
static char[][] s4 =
|
||||
[ "\xE2\x89", // too short
|
||||
"\xC0\x8A",
|
||||
"\xE0\x80\x8A",
|
||||
"\xF0\x80\x80\x8A",
|
||||
"\xF8\x80\x80\x80\x8A",
|
||||
"\xFC\x80\x80\x80\x80\x8A",
|
||||
];
|
||||
|
||||
for (int j = 0; j < s4.length; j++)
|
||||
{
|
||||
try
|
||||
{
|
||||
i = 0;
|
||||
c = decode(s4[j], i);
|
||||
assert(0);
|
||||
}
|
||||
catch (UtfException u)
|
||||
{
|
||||
i = 23;
|
||||
delete u;
|
||||
}
|
||||
assert(i == 23);
|
||||
}
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
dchar decode(wchar[] s, inout size_t idx)
|
||||
in
|
||||
{
|
||||
assert(idx >= 0 && idx < s.length);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(isValidDchar(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
char[] msg;
|
||||
dchar V;
|
||||
size_t i = idx;
|
||||
uint u = s[i];
|
||||
|
||||
if (u & ~0x7F)
|
||||
{ if (u >= 0xD800 && u <= 0xDBFF)
|
||||
{ uint u2;
|
||||
|
||||
if (i + 1 == s.length)
|
||||
{ msg = "surrogate UTF-16 high value past end of string";
|
||||
goto Lerr;
|
||||
}
|
||||
u2 = s[i + 1];
|
||||
if (u2 < 0xDC00 || u2 > 0xDFFF)
|
||||
{ msg = "surrogate UTF-16 low value out of range";
|
||||
goto Lerr;
|
||||
}
|
||||
u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
|
||||
i += 2;
|
||||
}
|
||||
else if (u >= 0xDC00 && u <= 0xDFFF)
|
||||
{ msg = "unpaired surrogate UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
else if (u == 0xFFFE || u == 0xFFFF)
|
||||
{ msg = "illegal UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
idx = i;
|
||||
return cast(dchar)u;
|
||||
|
||||
Lerr:
|
||||
throw new UtfException(msg, i);
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
dchar decode(dchar[] s, inout size_t idx)
|
||||
in
|
||||
{
|
||||
assert(idx >= 0 && idx < s.length);
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t i = idx;
|
||||
dchar c = s[i];
|
||||
|
||||
if (!isValidDchar(c))
|
||||
goto Lerr;
|
||||
idx = i + 1;
|
||||
return c;
|
||||
|
||||
Lerr:
|
||||
throw new UtfException("5invalid UTF-32 value", i);
|
||||
}
|
||||
|
||||
|
||||
/* =================== Encode ======================= */
|
||||
|
||||
/*******************************
|
||||
* Encodes character c and appends it to array s[].
|
||||
*/
|
||||
|
||||
void encode(inout char[] s, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
char[] r = s;
|
||||
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
r ~= cast(char) c;
|
||||
}
|
||||
else
|
||||
{
|
||||
char[4] buf;
|
||||
uint L;
|
||||
|
||||
if (c <= 0x7FF)
|
||||
{
|
||||
buf[0] = cast(char)(0xC0 | (c >> 6));
|
||||
buf[1] = cast(char)(0x80 | (c & 0x3F));
|
||||
L = 2;
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xE0 | (c >> 12));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | (c & 0x3F));
|
||||
L = 3;
|
||||
}
|
||||
else if (c <= 0x10FFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xF0 | (c >> 18));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[3] = cast(char)(0x80 | (c & 0x3F));
|
||||
L = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
r ~= buf[0 .. L];
|
||||
}
|
||||
s = r;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(utf) printf("utf.encode.unittest\n");
|
||||
|
||||
char[] s = "abcd";
|
||||
encode(s, cast(dchar)'a');
|
||||
assert(s.length == 5);
|
||||
assert(s == "abcda");
|
||||
|
||||
encode(s, cast(dchar)'\u00A9');
|
||||
assert(s.length == 7);
|
||||
assert(s == "abcda\xC2\xA9");
|
||||
//assert(s == "abcda\u00A9"); // BUG: fix compiler
|
||||
|
||||
encode(s, cast(dchar)'\u2260');
|
||||
assert(s.length == 10);
|
||||
assert(s == "abcda\xC2\xA9\xE2\x89\xA0");
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
void encode(inout wchar[] s, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
wchar[] r = s;
|
||||
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
r ~= cast(wchar) c;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar[2] buf;
|
||||
|
||||
buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
|
||||
r ~= buf;
|
||||
}
|
||||
s = r;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
void encode(inout dchar[] s, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
s ~= c;
|
||||
}
|
||||
|
||||
/* =================== Validation ======================= */
|
||||
|
||||
/***********************************
|
||||
* Checks to see if string is well formed or not. Throws a UtfException if it is
|
||||
* not. Use to check all untrusted input for correctness.
|
||||
*/
|
||||
|
||||
void validate(char[] s)
|
||||
{
|
||||
size_t len = s.length;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; )
|
||||
{
|
||||
decode(s, i);
|
||||
}
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
void validate(wchar[] s)
|
||||
{
|
||||
size_t len = s.length;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; )
|
||||
{
|
||||
decode(s, i);
|
||||
}
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
void validate(dchar[] s)
|
||||
{
|
||||
size_t len = s.length;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; )
|
||||
{
|
||||
decode(s, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* =================== Conversion to UTF8 ======================= */
|
||||
|
||||
char[] toUTF8(char[4] buf, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
buf[0] = cast(char) c;
|
||||
return buf[0 .. 1];
|
||||
}
|
||||
else if (c <= 0x7FF)
|
||||
{
|
||||
buf[0] = cast(char)(0xC0 | (c >> 6));
|
||||
buf[1] = cast(char)(0x80 | (c & 0x3F));
|
||||
return buf[0 .. 2];
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xE0 | (c >> 12));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | (c & 0x3F));
|
||||
return buf[0 .. 3];
|
||||
}
|
||||
else if (c <= 0x10FFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xF0 | (c >> 18));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[3] = cast(char)(0x80 | (c & 0x3F));
|
||||
return buf[0 .. 4];
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*******************
|
||||
* Encodes string s into UTF-8 and returns the encoded string.
|
||||
*/
|
||||
|
||||
char[] toUTF8(char[] s)
|
||||
in
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
body
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
char[] toUTF8(wchar[] s)
|
||||
{
|
||||
char[] r;
|
||||
size_t i;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
|
||||
for (i = 0; i < slen; i++)
|
||||
{ wchar c = s[i];
|
||||
|
||||
if (c <= 0x7F)
|
||||
r[i] = cast(char)c; // fast path for ascii
|
||||
else
|
||||
{
|
||||
r.length = i;
|
||||
foreach (dchar c; s[i .. slen])
|
||||
{
|
||||
encode(r, c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
char[] toUTF8(dchar[] s)
|
||||
{
|
||||
char[] r;
|
||||
size_t i;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
|
||||
for (i = 0; i < slen; i++)
|
||||
{ dchar c = s[i];
|
||||
|
||||
if (c <= 0x7F)
|
||||
r[i] = cast(char)c; // fast path for ascii
|
||||
else
|
||||
{
|
||||
r.length = i;
|
||||
foreach (dchar d; s[i .. slen])
|
||||
{
|
||||
encode(r, d);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* =================== Conversion to UTF16 ======================= */
|
||||
|
||||
wchar[] toUTF16(wchar[2] buf, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
buf[0] = cast(wchar) c;
|
||||
return buf[0 .. 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
|
||||
return buf[0 .. 2];
|
||||
}
|
||||
}
|
||||
|
||||
/****************
|
||||
* Encodes string s into UTF-16 and returns the encoded string.
|
||||
* toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take
|
||||
* an LPWSTR or LPCWSTR argument.
|
||||
*/
|
||||
|
||||
wchar[] toUTF16(char[] s)
|
||||
{
|
||||
wchar[] r;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
r.length = 0;
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
i++;
|
||||
r ~= cast(wchar)c;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = decode(s, i);
|
||||
encode(r, c);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
wchar* toUTF16z(char[] s)
|
||||
{
|
||||
wchar[] r;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen + 1;
|
||||
r.length = 0;
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
i++;
|
||||
r ~= cast(wchar)c;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = decode(s, i);
|
||||
encode(r, c);
|
||||
}
|
||||
}
|
||||
r ~= "\000";
|
||||
return r.ptr;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
wchar[] toUTF16(wchar[] s)
|
||||
in
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
body
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
wchar[] toUTF16(dchar[] s)
|
||||
{
|
||||
wchar[] r;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
r.length = 0;
|
||||
for (size_t i = 0; i < slen; i++)
|
||||
{
|
||||
encode(r, s[i]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* =================== Conversion to UTF32 ======================= */
|
||||
|
||||
/*****
|
||||
* Encodes string s into UTF-32 and returns the encoded string.
|
||||
*/
|
||||
|
||||
dchar[] toUTF32(char[] s)
|
||||
{
|
||||
dchar[] r;
|
||||
size_t slen = s.length;
|
||||
size_t j = 0;
|
||||
|
||||
r.length = slen; // r[] will never be longer than s[]
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c >= 0x80)
|
||||
c = decode(s, i);
|
||||
else
|
||||
i++; // c is ascii, no need for decode
|
||||
r[j++] = c;
|
||||
}
|
||||
return r[0 .. j];
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
dchar[] toUTF32(wchar[] s)
|
||||
{
|
||||
dchar[] r;
|
||||
size_t slen = s.length;
|
||||
size_t j = 0;
|
||||
|
||||
r.length = slen; // r[] will never be longer than s[]
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c >= 0x80)
|
||||
c = decode(s, i);
|
||||
else
|
||||
i++; // c is ascii, no need for decode
|
||||
r[j++] = c;
|
||||
}
|
||||
return r[0 .. j];
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
dchar[] toUTF32(dchar[] s)
|
||||
in
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
body
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ================================ tests ================================== */
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(utf) printf("utf.toUTF.unittest\n");
|
||||
|
||||
char[] c;
|
||||
wchar[] w;
|
||||
dchar[] d;
|
||||
|
||||
c = "hello";
|
||||
w = toUTF16(c);
|
||||
assert(w == "hello");
|
||||
d = toUTF32(c);
|
||||
assert(d == "hello");
|
||||
|
||||
c = toUTF8(w);
|
||||
assert(c == "hello");
|
||||
d = toUTF32(w);
|
||||
assert(d == "hello");
|
||||
|
||||
c = toUTF8(d);
|
||||
assert(c == "hello");
|
||||
w = toUTF16(d);
|
||||
assert(w == "hello");
|
||||
|
||||
|
||||
c = "hel\u1234o";
|
||||
w = toUTF16(c);
|
||||
assert(w == "hel\u1234o");
|
||||
d = toUTF32(c);
|
||||
assert(d == "hel\u1234o");
|
||||
|
||||
c = toUTF8(w);
|
||||
assert(c == "hel\u1234o");
|
||||
d = toUTF32(w);
|
||||
assert(d == "hel\u1234o");
|
||||
|
||||
c = toUTF8(d);
|
||||
assert(c == "hel\u1234o");
|
||||
w = toUTF16(d);
|
||||
assert(w == "hel\u1234o");
|
||||
|
||||
|
||||
c = "he\U0010AAAAllo";
|
||||
w = toUTF16(c);
|
||||
//foreach (wchar c; w) printf("c = x%x\n", c);
|
||||
//foreach (wchar c; cast(wchar[])"he\U0010AAAAllo") printf("c = x%x\n", c);
|
||||
assert(w == "he\U0010AAAAllo");
|
||||
d = toUTF32(c);
|
||||
assert(d == "he\U0010AAAAllo");
|
||||
|
||||
c = toUTF8(w);
|
||||
assert(c == "he\U0010AAAAllo");
|
||||
d = toUTF32(w);
|
||||
assert(d == "he\U0010AAAAllo");
|
||||
|
||||
c = toUTF8(d);
|
||||
assert(c == "he\U0010AAAAllo");
|
||||
w = toUTF16(d);
|
||||
assert(w == "he\U0010AAAAllo");
|
||||
}
|
||||
@@ -1,520 +0,0 @@
|
||||
|
||||
/**
|
||||
* 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");
|
||||
}
|
||||
}
|
||||
@@ -1,618 +0,0 @@
|
||||
/**
|
||||
* 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[] );
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
// byte
|
||||
|
||||
module typeinfo1.ti_byte;
|
||||
|
||||
class TypeInfo_g : TypeInfo
|
||||
{
|
||||
char[] toString() { return "byte"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(byte *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(byte *)p1 == *cast(byte *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(byte *)p1 - *cast(byte *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return byte.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
byte t;
|
||||
|
||||
t = *cast(byte *)p1;
|
||||
*cast(byte *)p1 = *cast(byte *)p2;
|
||||
*cast(byte *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
|
||||
// cdouble
|
||||
|
||||
module typeinfo1.ti_cdouble;
|
||||
|
||||
class TypeInfo_r : TypeInfo
|
||||
{
|
||||
char[] toString() { return "cdouble"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
|
||||
(cast(uint *)p)[2] + (cast(uint *)p)[3];
|
||||
}
|
||||
|
||||
static int _equals(cdouble f1, cdouble f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(cdouble f1, cdouble f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return cdouble.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
cdouble t;
|
||||
|
||||
t = *cast(cdouble *)p1;
|
||||
*cast(cdouble *)p1 = *cast(cdouble *)p2;
|
||||
*cast(cdouble *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static cdouble r;
|
||||
|
||||
return (cast(cdouble *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
// cfloat
|
||||
|
||||
module typeinfo1.ti_cfloat;
|
||||
|
||||
class TypeInfo_q : TypeInfo
|
||||
{
|
||||
char[] toString() { return "cfloat"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
static int _equals(cfloat f1, cfloat f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(cfloat f1, cfloat f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return cfloat.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
cfloat t;
|
||||
|
||||
t = *cast(cfloat *)p1;
|
||||
*cast(cfloat *)p1 = *cast(cfloat *)p2;
|
||||
*cast(cfloat *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static cfloat r;
|
||||
|
||||
return (cast(cfloat *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
|
||||
module typeinfo1.ti_char;
|
||||
|
||||
class TypeInfo_a : TypeInfo
|
||||
{
|
||||
char[] toString() { return "char"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(char *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(char *)p1 == *cast(char *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(char *)p1 - *cast(char *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return char.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
char t;
|
||||
|
||||
t = *cast(char *)p1;
|
||||
*cast(char *)p1 = *cast(char *)p2;
|
||||
*cast(char *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static char c;
|
||||
|
||||
return (cast(char *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
|
||||
// creal
|
||||
|
||||
module typeinfo1.ti_creal;
|
||||
|
||||
class TypeInfo_c : TypeInfo
|
||||
{
|
||||
char[] toString() { return "creal"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
|
||||
(cast(uint *)p)[2] + (cast(uint *)p)[3] +
|
||||
(cast(uint *)p)[4];
|
||||
}
|
||||
|
||||
static int _equals(creal f1, creal f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(creal f1, creal f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(creal *)p1, *cast(creal *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(creal *)p1, *cast(creal *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return creal.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
creal t;
|
||||
|
||||
t = *cast(creal *)p1;
|
||||
*cast(creal *)p1 = *cast(creal *)p2;
|
||||
*cast(creal *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static creal r;
|
||||
|
||||
return (cast(creal *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
|
||||
// dchar
|
||||
|
||||
module typeinfo1.ti_dchar;
|
||||
|
||||
class TypeInfo_w : TypeInfo
|
||||
{
|
||||
char[] toString() { return "dchar"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(dchar *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(dchar *)p1 == *cast(dchar *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return *cast(dchar *)p1 - *cast(dchar *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return dchar.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
dchar t;
|
||||
|
||||
t = *cast(dchar *)p1;
|
||||
*cast(dchar *)p1 = *cast(dchar *)p2;
|
||||
*cast(dchar *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static dchar c;
|
||||
|
||||
return (cast(dchar *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
|
||||
// delegate
|
||||
|
||||
module typeinfo1.ti_delegate;
|
||||
|
||||
alias void delegate(int) dg;
|
||||
|
||||
class TypeInfo_D : TypeInfo
|
||||
{
|
||||
hash_t getHash(void *p)
|
||||
{ long l = *cast(long *)p;
|
||||
|
||||
return cast(uint)(l + (l >> 32));
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(dg *)p1 == *cast(dg *)p2;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return dg.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
dg t;
|
||||
|
||||
t = *cast(dg *)p1;
|
||||
*cast(dg *)p1 = *cast(dg *)p2;
|
||||
*cast(dg *)p2 = t;
|
||||
}
|
||||
|
||||
uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
|
||||
// double
|
||||
|
||||
module typeinfo1.ti_double;
|
||||
|
||||
class TypeInfo_d : TypeInfo
|
||||
{
|
||||
char[] toString() { return "double"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
static bool _isnan(double d)
|
||||
{
|
||||
return d !<>= 0;
|
||||
}
|
||||
|
||||
static int _equals(double f1, double f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(_isnan(f1) && _isnan(f2));
|
||||
}
|
||||
|
||||
static int _compare(double d1, double d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (_isnan(d1))
|
||||
{ if (_isnan(d2))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(double *)p1, *cast(double *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(double *)p1, *cast(double *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return double.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
double t;
|
||||
|
||||
t = *cast(double *)p1;
|
||||
*cast(double *)p1 = *cast(double *)p2;
|
||||
*cast(double *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{ static double r;
|
||||
|
||||
return (&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
|
||||
// float
|
||||
|
||||
module typeinfo1.ti_float;
|
||||
|
||||
import std.gc: malloc;
|
||||
class TypeInfo_f : TypeInfo
|
||||
{
|
||||
char[] toString() { return "float"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
static bool _isnan(float f)
|
||||
{
|
||||
return f !<>= 0;
|
||||
}
|
||||
|
||||
static int _equals(float f1, float f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(_isnan(f1) && _isnan(f2));
|
||||
}
|
||||
|
||||
static int _compare(float d1, float d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (_isnan(d1))
|
||||
{ if (_isnan(d2))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return _equals(*cast(float *)p1, *cast(float *)p2);
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
return _compare(*cast(float *)p1, *cast(float *)p2);
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return float.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
float t;
|
||||
|
||||
t = *cast(float *)p1;
|
||||
*cast(float *)p1 = *cast(float *)p2;
|
||||
*cast(float *)p2 = t;
|
||||
}
|
||||
|
||||
void[] init()
|
||||
{
|
||||
return (cast(float*)malloc(float.sizeof))[0..1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
|
||||
// idouble
|
||||
|
||||
module typeinfo1.ti_idouble;
|
||||
|
||||
private import typeinfo1.ti_double;
|
||||
|
||||
class TypeInfo_p : TypeInfo_d
|
||||
{
|
||||
char[] toString() { return "idouble"; }
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
|
||||
// ifloat
|
||||
|
||||
module typeinfo1.ti_ifloat;
|
||||
|
||||
private import typeinfo1.ti_float;
|
||||
|
||||
class TypeInfo_o : TypeInfo_f
|
||||
{
|
||||
char[] toString() { return "ifloat"; }
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
|
||||
// int
|
||||
|
||||
module typeinfo1.ti_int;
|
||||
|
||||
class TypeInfo_i : TypeInfo
|
||||
{
|
||||
char[] toString() { return "int"; }
|
||||
|
||||
hash_t getHash(void *p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
int equals(void *p1, void *p2)
|
||||
{
|
||||
return *cast(uint *)p1 == *cast(uint *)p2;
|
||||
}
|
||||
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
if (*cast(int*) p1 < *cast(int*) p2)
|
||||
return -1;
|
||||
else if (*cast(int*) p1 > *cast(int*) p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t tsize()
|
||||
{
|
||||
return int.sizeof;
|
||||
}
|
||||
|
||||
void swap(void *p1, void *p2)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = *cast(int *)p1;
|
||||
*cast(int *)p1 = *cast(int *)p2;
|
||||
*cast(int *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user