diff --git a/bin/ldc.phobos b/bin/ldc.phobos deleted file mode 100644 index 62f47f7ebf8..00000000000 --- a/bin/ldc.phobos +++ /dev/null @@ -1,4 +0,0 @@ - -[Environment] - -DFLAGS=-I%@P%/../lphobos -L-L%@P%/../lib -R%@P%/../lib diff --git a/lphobos/README.txt b/lphobos/README.txt deleted file mode 100644 index adc3dd52cd5..00000000000 --- a/lphobos/README.txt +++ /dev/null @@ -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. diff --git a/lphobos/build.sh b/lphobos/build.sh deleted file mode 100755 index 6eca5a05784..00000000000 --- a/lphobos/build.sh +++ /dev/null @@ -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" diff --git a/lphobos/crc32.d b/lphobos/crc32.d deleted file mode 100644 index daccbd5a875..00000000000 --- a/lphobos/crc32.d +++ /dev/null @@ -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; -} diff --git a/lphobos/etc/c/zlib.d b/lphobos/etc/c/zlib.d deleted file mode 100644 index 53e11f6444b..00000000000 --- a/lphobos/etc/c/zlib.d +++ /dev/null @@ -1,1215 +0,0 @@ -/* zlib.d: modified from zlib.h by Walter Bright */ -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, February 2007 -*/ - -module etc.c.zlib; - -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.1, November 17th, 2003 - - Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler - - 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. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -private import std.stdint; - -extern (C): -alias uint Culong_t; -alias int Clong_t; - -char[] ZLIB_VERSION = "1.2.1"; - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by the in-memory functions is the zlib - format, which is a zlib wrapper documented in RFC 1950, wrapped around a - deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - This library does not provide any functions to write gzip files in memory. - However such functions could be easily written using zlib's deflate function, - the documentation in the gzip RFC, and the examples in gzio.c. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. -*/ - -alias void* (*alloc_func) (void* opaque, uint items, uint size); -alias void (*free_func) (void* opaque, void* address); - -struct z_stream -{ - ubyte *next_in; /* next input byte */ - uint avail_in; /* number of bytes available at next_in */ - Culong_t total_in; /* total nb of input bytes read so far */ - - ubyte *next_out; /* next output byte should be put there */ - uint avail_out; /* remaining free space at next_out */ - Culong_t total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - void* state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - void* opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: ascii or binary */ - Culong_t adler; /* adler32 value of the uncompressed data */ - Culong_t reserved; /* reserved for future use */ -} - -alias z_stream* z_streamp; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -enum -{ - Z_NO_FLUSH = 0, - Z_PARTIAL_FLUSH = 1, /* will be removed, use Z_SYNC_FLUSH instead */ - Z_SYNC_FLUSH = 2, - Z_FULL_FLUSH = 3, - Z_FINISH = 4, - Z_BLOCK = 5 -} -/* Allowed flush values; see deflate() and inflate() below for details */ - -enum -{ - Z_OK = 0, - Z_STREAM_END = 1, - Z_NEED_DICT = 2, - Z_ERRNO = -1, - Z_STREAM_ERROR = -2, - Z_DATA_ERROR = -3, - Z_MEM_ERROR = -4, - Z_BUF_ERROR = -5, - Z_VERSION_ERROR = -6, -} -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ - -enum -{ - Z_NO_COMPRESSION = 0, - Z_BEST_SPEED = 1, - Z_BEST_COMPRESSION = 9, - Z_DEFAULT_COMPRESSION = -1, -} -/* compression levels */ - -enum -{ - Z_FILTERED = 1, - Z_HUFFMAN_ONLY = 2, - Z_RLE = 3, - Z_DEFAULT_STRATEGY = 0, -} -/* compression strategy; see deflateInit2() below for details */ - -enum -{ - Z_BINARY = 0, - Z_ASCII = 1, - Z_UNKNOWN = 2, -} -/* Possible values of the data_type field (though see inflate()) */ - -enum -{ - Z_DEFLATED = 8, -} -/* The deflate compression method (the only one supported in this version) */ - -const int Z_NULL = 0; /* for initializing zalloc, zfree, opaque */ - - /* basic functions */ - -char* zlibVersion(); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -int deflateInit(z_streamp strm, int level) -{ - return deflateInit_(strm, level, ZLIB_VERSION.ptr, z_stream.sizeof); -} -/* - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ - - -int deflate(z_streamp strm, int flush); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - the compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - the value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update data_type if it can make a good guess about - the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -int deflateEnd(z_streamp strm); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - - -int inflateInit(z_streamp strm) -{ - return inflateInit_(strm, ZLIB_VERSION.ptr, z_stream.sizeof); -} -/* - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) -*/ - - -int inflate(z_streamp strm, int flush); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, - Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() stop - if and when it get to the next deflate block boundary. When decoding the zlib - or gzip format, this will cause inflate() to return immediately after the - header and before the first block. When doing a raw inflate, inflate() will - go ahead and process the first block, and will return when it gets to the end - of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 - if inflate() is currently decoding the last block in the deflate stream, - plus 128 if inflate() returned immediately after decoding an end-of-block - code or decoding the complete header up to just before the first byte of the - deflate stream. The end-of-block will not be indicated until all of the - uncompressed data from that block has been written to strm->next_out. The - number of unused bits may in general be greater than seven, except when - bit 7 of data_type is set, in which case the number of unused bits will be - less than eight. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster approach - may be used for the single inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm-adler to the adler32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() will decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically. Any information - contained in the gzip header is not retained, so applications that need that - information should instead use raw inflate, see inflateInit2() below, or - inflateBack() and perform their own processing of the gzip header and - trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may then - call inflateSync() to look for a good compression block if a partial recovery - of the data is desired. -*/ - - -int inflateEnd(z_streamp strm); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -int deflateInit2(z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy) -{ - return deflateInit2_(strm, level, method, windowBits, memLevel, - strategy, ZLIB_VERSION.ptr, z_stream.sizeof); -} -/* - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), - no header crc, and the operating system will be set to 255 (unknown). - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as - Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy - parameter only affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). -*/ - -int deflateSetDictionary(z_streamp strm, ubyte* dictionary, uint dictLength); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -int deflateCopy(z_streamp dest, z_streamp source); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -int deflateReset(z_streamp strm); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -int deflateParams(z_streamp strm, int level, int strategy); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ - -uint deflateBound(z_streamp strm, uint Culong_t); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() - or deflateInit2(). This would be used to allocate an output buffer - for deflation in a single pass, and so would be called before deflate(). -*/ - -int deflatePrime(z_streamp strm, int bits, int value); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the - bits leftover from a previous deflate stream when appending to it. As such, - this function can only be used for raw deflate, and must be used before the - first deflate() call after a deflateInit2() or deflateReset(). bits must be - less than or equal to 16, and that many of the least significant bits of - value will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -int inflateInit2(z_streamp strm, int windowBits) -{ - return inflateInit2_(strm, windowBits, ZLIB_VERSION.ptr, z_stream.sizeof); -} -/* - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative - memLevel). msg is set to null if there is no error message. inflateInit2 - does not perform any decompression apart from reading the zlib header if - present: this will be done by inflate(). (So next_in and avail_in may be - modified, but next_out and avail_out are unchanged.) -*/ - -int inflateSetDictionary(z_streamp strm, ubyte* dictionary, uint dictLength); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate - if this call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by this call of - inflate. The compressor and decompressor must use exactly the same - dictionary (see deflateSetDictionary). - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -int inflateSync(z_streamp strm); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. -*/ - -int inflateCopy (z_streamp dest, z_streamp source); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -int inflateReset(z_streamp strm); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - - -int inflateBackInit(z_stream* strm, int windowBits, ubyte* window) -{ - return inflateBackInit_(strm, windowBits, window, ZLIB_VERSION.ptr, z_stream.sizeof); -} -/* - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not - be allocated, or Z_VERSION_ERROR if the version of the library does not - match the version of the header file. -*/ - -alias uint function(void*, ubyte**) in_func; -alias int function(void*, ubyte*, uint) out_func; - -int inflateBack(z_stream* strm, - in_func f_in, - void* in_desc, - out_func f_out, - void* out_desc); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free - the allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects - only the raw deflate stream to decompress. This is different from the - normal behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format - error in the deflate stream (in which case strm->msg is set to indicate the - nature of the error), or Z_STREAM_ERROR if the stream was not properly - initialized. In the case of Z_BUF_ERROR, an input or output error can be - distinguished using strm->next_in which will be Z_NULL only if in() returned - an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to - out() returning non-zero. (in() will always be called before out(), so - strm->next_in is assured to be defined if out() returns non-zero.) Note - that inflateBack() cannot return Z_OK. -*/ - -int inflateBackEnd(z_stream* strm); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -uint zlibCompileFlags(); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - /* utility functions */ - -/* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. -*/ - -int compress(ubyte* dest, - Culong_t* destLen, - ubyte* source, - Culong_t sourceLen); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least the value returned - by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -int compress2(ubyte* dest, - Culong_t* destLen, - ubyte* source, - Culong_t sourceLen, - int level); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -uint compressBound(Culong_t sourceLen); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before - a compress() or compress2() call to allocate the destination buffer. -*/ - -int uncompress(ubyte* dest, - uint* Culong_t, - ubyte* source, - uint Culong_t); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. -*/ - - -typedef void* gzFile; -alias int z_off_t; // file offset - -gzFile gzopen(char* path, char* mode); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h", or 'R' for run-length encoding - as in "wb1R". (See the description of deflateInit2 for more information - about the strategy parameter.) - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ - -gzFile gzdopen(int fd, char* mode); -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. -*/ - -int gzsetparams(gzFile file, int level, int strategy); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -int gzread(gzFile file, void* buf, uint len); -/* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ - -int gzwrite(gzFile file, void* buf, uint len); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). -*/ - -int gzprintf(gzFile file, char* format, ...); -/* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). The number of - uncompressed bytes written is limited to 4095. The caller should assure that - this limit is not exceeded. If it is exceeded, then gzprintf() will return - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. -*/ - -int gzputs(gzFile file, char* s); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ - -char* gzgets(gzFile file, char* buf, int len); -/* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ - -int gzputc(gzFile file, int c); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ - -int gzgetc(gzFile file); -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ - -int gzungetc(int c, gzFile file); -/* - Push one character back onto the stream to be read again later. - Only one character of push-back is allowed. gzungetc() returns the - character pushed, or -1 on failure. gzungetc() will fail if a - character has been pushed but not read yet, or if c is -1. The pushed - character will be discarded if the stream is repositioned with gzseek() - or gzrewind(). -*/ - -int gzflush(gzFile file, int flush); -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ - -z_off_t gzseek(gzFile file, z_off_t offset, int whence); -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -int gzrewind(gzFile file); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -z_off_t gztell(gzFile file); -/* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -int gzeof(gzFile file); -/* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ - -int gzclose(gzFile file); -/* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). -*/ - -char* gzerror(gzFile file, int *errnum); -/* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ - -void gzclearerr (gzFile file); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. -*/ - - Culong_t adler32 (Culong_t adler, ubyte *buf, uint len); - -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uint adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -Culong_t crc32(Culong_t crc, ubyte *buf, uint len); -/* - Update a running crc with the bytes buf[0..len-1] and return the updated - crc. If buf is NULL, this function returns the required initial value - for the crc. Pre- and post-conditioning (one's complement) is performed - within this function so it shouldn't be done by the application. - Usage example: - - uint crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -int deflateInit_(z_streamp strm, - int level, - char* versionx, - int stream_size); - -int inflateInit_(z_streamp strm, - char* versionx, - int stream_size); - -int deflateInit2_(z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy, - char* versionx, - int stream_size); - -int inflateBackInit_(z_stream* strm, - int windowBits, - ubyte* window, - char* z_version, - int stream_size); - -int inflateInit2_(z_streamp strm, - int windowBits, - char* versionx, - int stream_size); - -char* zError(int err); -int inflateSyncPoint(z_streamp z); -Culong_t* get_crc_table(); diff --git a/lphobos/gc/gc.d b/lphobos/gc/gc.d deleted file mode 100644 index 4d750ff4e57..00000000000 --- a/lphobos/gc/gc.d +++ /dev/null @@ -1,1034 +0,0 @@ -/** - * Part of the D programming language runtime library. - */ - -/* - * Copyright (C) 2004-2008 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. - */ - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, February 2007 -*/ - - -// Storage allocation - -module std.gc; - -//debug = PRINTF; - -public import std.c.stdarg; -public import std.c.stdlib; -public import std.c.string; -public import gcx; -public import std.outofmemory; -public import gcstats; -public import std.thread; - -version=GCCLASS; - -version (GCCLASS) - alias GC gc_t; -else - alias GC* gc_t; - -gc_t _gc; - -void addRoot(void *p) { _gc.addRoot(p); } -void removeRoot(void *p) { _gc.removeRoot(p); } -void addRange(void *pbot, void *ptop) { _gc.addRange(pbot, ptop); } -void removeRange(void *pbot) { _gc.removeRange(pbot); } -void fullCollect() { _gc.fullCollect(); } -void fullCollectNoStack() { _gc.fullCollectNoStack(); } -void genCollect() { _gc.genCollect(); } -void minimize() { _gc.minimize(); } -void disable() { _gc.disable(); } -void enable() { _gc.enable(); } -void getStats(out GCStats stats) { _gc.getStats(stats); } -void hasPointers(void* p) { _gc.hasPointers(p); } -void hasNoPointers(void* p) { _gc.hasNoPointers(p); } -void setV1_0() { _gc.setV1_0(); } - -void[] malloc(size_t nbytes) -{ - void* p = _gc.malloc(nbytes); - return p[0 .. nbytes]; -} - -void[] realloc(void* p, size_t nbytes) -{ - void* q = _gc.realloc(p, nbytes); - return q[0 .. nbytes]; -} - -size_t extend(void* p, size_t minbytes, size_t maxbytes) -{ - return _gc.extend(p, minbytes, maxbytes); -} - -size_t capacity(void* p) -{ - return _gc.capacity(p); -} - -void setTypeInfo(TypeInfo ti, void* p) -{ - if (ti.flags() & 1) - hasNoPointers(p); - else - hasPointers(p); -} - -void* getGCHandle() -{ - return cast(void*)_gc; -} - -void setGCHandle(void* p) -{ - void* oldp = getGCHandle(); - gc_t g = cast(gc_t)p; - if (g.gcversion != gcx.GCVERSION) - throw new Error("incompatible gc versions"); - - // Add our static data to the new gc - GC.scanStaticData(g); - - _gc = g; -// return oldp; -} - -void endGCHandle() -{ - GC.unscanStaticData(_gc); -} - -extern (C) -{ - -void _d_monitorexit(Object h); - - -void gc_init() -{ - version (GCCLASS) - { void* p; - ClassInfo ci = GC.classinfo; - - p = std.c.stdlib.malloc(ci.init.length); - (cast(byte*)p)[0 .. ci.init.length] = ci.init[]; - _gc = cast(GC)p; - } - else - { - _gc = cast(GC *) std.c.stdlib.calloc(1, GC.sizeof); - } - _gc.initialize(); - GC.scanStaticData(_gc); - std.thread.Thread.thread_init(); -} - -void gc_term() -{ - _gc.fullCollectNoStack(); - _gc.Dtor(); -} - -Object _d_newclass(ClassInfo ci) -{ - void *p; - - debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name); - if (ci.flags & 1) // if COM object - { - p = std.c.stdlib.malloc(ci.init.length); - if (!p) - _d_OutOfMemory(); - debug(PRINTF) printf(" COM object p = %p\n", p); - } - else - { - p = _gc.malloc(ci.init.length); - debug(PRINTF) printf(" p = %p\n", p); - _gc.setFinalizer(p, &new_finalizer); - if (ci.flags & 2) - _gc.hasNoPointers(p); - } - - debug (PRINTF) - { - printf("p = %p\n", p); - printf("ci = %p, ci.init = %p, len = %d\n", ci, ci.init, ci.init.length); - printf("vptr = %p\n", *cast(void **)ci.init); - printf("vtbl[0] = %p\n", (*cast(void ***)ci.init)[0]); - printf("vtbl[1] = %p\n", (*cast(void ***)ci.init)[1]); - printf("init[0] = %x\n", (cast(uint *)ci.init)[0]); - printf("init[1] = %x\n", (cast(uint *)ci.init)[1]); - printf("init[2] = %x\n", (cast(uint *)ci.init)[2]); - printf("init[3] = %x\n", (cast(uint *)ci.init)[3]); - printf("init[4] = %x\n", (cast(uint *)ci.init)[4]); - } - - - // Initialize it - (cast(byte*)p)[0 .. ci.init.length] = ci.init[]; - - //printf("initialization done\n"); - return cast(Object)p; -} - -extern (D) alias void (*fp_t)(Object); // generic function pointer - -void _d_delinterface(void** p) -{ - if (*p) - { - Interface *pi = **cast(Interface ***)*p; - Object o; - - o = cast(Object)(*p - pi.offset); - _d_delclass(&o); - *p = null; - } -} - -void _d_delclass(Object *p) -{ - if (*p) - { - debug (PRINTF) printf("_d_delclass(%p)\n", *p); - version(0) - { - ClassInfo **pc = cast(ClassInfo **)*p; - if (*pc) - { - ClassInfo c = **pc; - - if (c.deallocator) - { - _d_callfinalizer(cast(void *)(*p)); - fp_t fp = cast(fp_t)c.deallocator; - (*fp)(*p); // call deallocator - *p = null; - return; - } - } - } - _gc.free(cast(void*)(*p)); - *p = null; - } -} - -/****************************************** - * Allocate a new array of length elements. - * ti is the type of the resulting array, or pointer to element. - */ - -/* For when the array is initialized to 0 */ -void* _d_newarrayT(TypeInfo ti, size_t length) -{ - void* result; - auto size = ti.next.tsize(); // array element size - - debug(PRINTF) printf("_d_newarrayT(length = x%x, size = %d)\n", length, size); - if (length && size) - { - /*version (D_InlineAsm_X86) - { - asm - { - mov EAX,size ; - mul EAX,length ; - mov size,EAX ; - jc Loverflow ; - } - } - else*/ - size *= length; - result = cast(byte*) _gc.malloc(size + 1); - if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(result); - memset(result, 0, size); - } - return result; - -Loverflow: - _d_OutOfMemory(); -} - -void* _d_newarrayvT(TypeInfo ti, size_t length) { - return _d_newarrayT(ti, length); -} - -/* For when the array has a non-zero initializer. - */ -void* _d_newarrayiT(TypeInfo ti, size_t length) -{ - void* result; - auto size = ti.next.tsize(); // array element size - - debug(PRINTF) - printf("_d_newarrayiT(length = %d, size = %d)\n", length, size); - if (length == 0 || size == 0) - { } - else - { - auto initializer = ti.next.init(); - auto isize = initializer.length; - auto q = initializer.ptr; - /*version (D_InlineAsm_X86) - { - asm - { - mov EAX,size ; - mul EAX,length ; - mov size,EAX ; - jc Loverflow ; - } - } - else*/ - size *= length; - auto p = _gc.malloc(size + 1); - debug(PRINTF) printf(" p = %p\n", p); - if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(p); - if (isize == 1) - memset(p, *cast(ubyte*)q, size); - else if (isize == int.sizeof) - { - int init = *cast(int*)q; - size /= int.sizeof; - for (size_t u = 0; u < size; u++) - { - (cast(int*)p)[u] = init; - } - } - else - { - for (size_t u = 0; u < size; u += isize) - { - memcpy(p + u, q, isize); - } - } - result = cast(byte*) p ; - } - return result; - -Loverflow: - _d_OutOfMemory(); -} - -void[] _d_newarraymTp(TypeInfo ti, int ndims, size_t* pdim) -{ - void[] result = void; - - //debug(PRINTF) - //printf("_d_newarraymT(ndims = %d)\n", ndims); - if (ndims == 0) - result = null; - else - { - - void[] foo(TypeInfo ti, size_t* pdim, int ndims) - { - size_t dim = *pdim; - void[] p; - - //printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, ndims); - if (ndims == 1) - { - auto r = _d_newarrayT(ti, dim); - p = *cast(void[]*)(&r); - } - else - { - p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim]; - for (int i = 0; i < dim; i++) - { - (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1); - } - } - return p; - } - - result = foo(ti, pdim, ndims); - //printf("result = %llx\n", result); - - version (none) - { - for (int i = 0; i < ndims; i++) - { - printf("index %d: %d\n", i, pdim[i]); - } - } - } - return result; -} - -void[] _d_newarraymiTp(TypeInfo ti, int ndims, size_t* pdim) -{ - void[] result = void; - - //debug(PRINTF) - //printf("_d_newarraymi(size = %d, ndims = %d)\n", size, ndims); - if (ndims == 0) - result = null; - else - { - - void[] foo(TypeInfo ti, size_t* pdim, int ndims) - { - size_t dim = *pdim; - void[] p; - - if (ndims == 1) - { - auto r = _d_newarrayiT(ti, dim); - p = *cast(void[]*)(&r); - } - else - { - p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim]; - for (int i = 0; i < dim; i++) - { - (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1); - } - } - return p; - } - - result = foo(ti, pdim, ndims); - //printf("result = %llx\n", result); - - version (none) - { - for (int i = 0; i < ndims; i++) - { - printf("index %d: %d\n", i, pdim[i]); - printf("init = %d\n", *cast(int*)pinit); - } - } - } - return result; -} - -struct Array -{ - size_t length; - byte *data; -}; - -// Perhaps we should get a a size argument like _d_new(), so we -// can zero out the array? - -void _d_delarray(size_t plength, void* pdata) -{ - assert(!plength || pdata); - if (pdata) _gc.free(pdata); -} - - -void _d_delmemory(void* *p) -{ - if (*p) - { - _gc.free(*p); - *p = null; - } -} - - -} - -void new_finalizer(void *p, bool dummy) -{ - //printf("new_finalizer(p = %p)\n", p); - _d_callfinalizer(p); -} - -extern (C) -void _d_callinterfacefinalizer(void *p) -{ - //printf("_d_callinterfacefinalizer(p = %p)\n", p); - if (p) - { - Interface *pi = **cast(Interface ***)p; - Object o = cast(Object)(p - pi.offset); - _d_callfinalizer(cast(void*)o); - } -} - -extern (C) -void _d_callfinalizer(void *p) -{ - //printf("_d_callfinalizer(p = %p)\n", p); - if (p) // not necessary if called from gc - { - ClassInfo **pc = cast(ClassInfo **)p; - if (*pc) - { - ClassInfo c = **pc; - - try - { - do - { - if (c.destructor) - { - fp_t fp = cast(fp_t)c.destructor; - (*fp)(cast(Object)p); // call destructor - } - c = c.base; - } while (c); - if ((cast(void**)p)[1]) // if monitor is not null - _d_monitorexit(cast(Object)p); - } - finally - { - *pc = null; // zero vptr - } - } - } -} - -/+ ------------------------------------------------ +/ - - -/****************************** - * Resize dynamic arrays with 0 initializers. - */ - -extern (C) -byte* _d_arraysetlengthT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata) -in -{ - assert(ti); -} -body -{ - byte* newdata; - size_t sizeelem = ti.next.tsize(); - - debug(PRINTF) - { - printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); - if (p) - printf("\tpdata = %p, plength = %d\n", pdata, plength); - } - - if (newlength) - { - version (GNU) - { - // required to output the label; - static char x = 0; - if (x) - goto Loverflow; - } - - version (D_InlineAsm_X86) - { - size_t newsize = void; - - asm - { - mov EAX,newlength ; - mul EAX,sizeelem ; - mov newsize,EAX ; - jc Loverflow ; - } - } - else - { - size_t newsize = sizeelem * newlength; - - if (newsize / newlength != sizeelem) - goto Loverflow; - } - //printf("newsize = %x, newlength = %x\n", newsize, newlength); - - if (pdata) - { - newdata = pdata; - if (newlength > plength) - { - size_t size = plength * sizeelem; - size_t cap = _gc.capacity(pdata); - - if (cap <= newsize) - { - if (cap >= 4096) - { // Try to extend in-place - auto u = _gc.extend(pdata, (newsize + 1) - cap, (newsize + 1) - cap); - if (u) - { - goto L1; - } - } - newdata = cast(byte *)_gc.malloc(newsize + 1); - newdata[0 .. size] = pdata[0 .. size]; - if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(newdata); - } - L1: - newdata[size .. newsize] = 0; - } - } - else - { - newdata = cast(byte *)_gc.calloc(newsize + 1, 1); - if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(newdata); - } - } - else - { - newdata = pdata; - } - - pdata = newdata; - plength = newlength; - return newdata; - -Loverflow: - _d_OutOfMemory(); -} - -/** - * Resize arrays for non-zero initializers. - * p pointer to array lvalue to be updated - * newlength new .length property of array - * sizeelem size of each element of array - * initsize size of initializer - * ... initializer - */ -extern (C) -byte* _d_arraysetlengthiT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata) -in -{ - assert(!plength || pdata); -} -body -{ - byte* newdata; - size_t sizeelem = ti.next.tsize(); - void[] initializer = ti.next.init(); - size_t initsize = initializer.length; - - assert(sizeelem); - assert(initsize); - assert(initsize <= sizeelem); - assert((sizeelem / initsize) * initsize == sizeelem); - - debug(PRINTF) - { - printf("_d_arraysetlengthiT(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize); - if (p) - printf("\tpdata = %p, plength = %d\n", pdata, plength); - } - - if (newlength) - { - version (GNU) - { - // required to output the label; - static char x = 0; - if (x) - goto Loverflow; - } - - version (D_InlineAsm_X86) - { - size_t newsize = void; - - asm - { - mov EAX,newlength ; - mul EAX,sizeelem ; - mov newsize,EAX ; - jc Loverflow ; - } - } - else - { - size_t newsize = sizeelem * newlength; - - if (newsize / newlength != sizeelem) - goto Loverflow; - } - //printf("newsize = %x, newlength = %x\n", newsize, newlength); - - size_t size = plength * sizeelem; - if (pdata) - { - newdata = pdata; - if (newlength > plength) - { - size_t cap = _gc.capacity(pdata); - - if (cap <= newsize) - { - if (cap >= 4096) - { // Try to extend in-place - auto u = _gc.extend(pdata, (newsize + 1) - cap, (newsize + 1) - cap); - if (u) - { - goto L1; - } - } - newdata = cast(byte *)_gc.malloc(newsize + 1); - newdata[0 .. size] = pdata[0 .. size]; - L1: ; - } - } - } - else - { - newdata = cast(byte *)_gc.malloc(newsize + 1); - if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(newdata); - } - - auto q = initializer.ptr; // pointer to initializer - - if (newsize > size) - { - if (initsize == 1) - { - //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); - newdata[size .. newsize] = *(cast(byte*)q); - } - else - { - for (size_t u = size; u < newsize; u += initsize) - { - memcpy(newdata + u, q, initsize); - } - } - } - } - else - { - newdata = pdata; - } - - pdata = newdata; - plength = newlength; - return newdata; - -Loverflow: - _d_OutOfMemory(); -} - -/**************************************** - * Append y[] to array x[]. - * size is size of each array element. - */ - -extern (C) -Array _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) -{ - auto sizeelem = ti.next.tsize(); // array element size - auto cap = _gc.capacity(px.data); - auto length = px.length; - auto newlength = length + y.length; - auto newsize = newlength * sizeelem; - if (newsize > cap) - { byte* newdata; - - if (cap >= 4096) - { // Try to extend in-place - auto u = _gc.extend(px.data, (newsize + 1) - cap, (newsize + 1) - cap); - if (u) - { - goto L1; - } - } - - newdata = cast(byte *)_gc.malloc(newCapacity(newlength, sizeelem) + 1); - if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(newdata); - memcpy(newdata, px.data, length * sizeelem); - px.data = newdata; - } - L1: - px.length = newlength; - memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem); - return *px; -} - -size_t newCapacity(size_t newlength, size_t size) -{ - version(none) - { - size_t newcap = newlength * size; - } - else - { - /* - * Better version by Dave Fladebo: - * This uses an inverse logorithmic algorithm to pre-allocate a bit more - * space for larger arrays. - * - Arrays smaller than 4096 bytes are left as-is, so for the most - * common cases, memory allocation is 1 to 1. The small overhead added - * doesn't effect small array perf. (it's virtually the same as - * current). - * - Larger arrays have some space pre-allocated. - * - As the arrays grow, the relative pre-allocated space shrinks. - * - The logorithmic algorithm allocates relatively more space for - * mid-size arrays, making it very fast for medium arrays (for - * mid-to-large arrays, this turns out to be quite a bit faster than the - * equivalent realloc() code in C, on Linux at least. Small arrays are - * just as fast as GCC). - * - Perhaps most importantly, overall memory usage and stress on the GC - * is decreased significantly for demanding environments. - */ - size_t newcap = newlength * size; - size_t newext = 0; - - if (newcap > 4096) - { - //double mult2 = 1.0 + (size / log10(pow(newcap * 2.0,2.0))); - - // Redo above line using only integer math - - static int log2plus1(size_t c) - { int i; - - if (c == 0) - i = -1; - else - for (i = 1; c >>= 1; i++) - { } - return i; - } - - /* The following setting for mult sets how much bigger - * the new size will be over what is actually needed. - * 100 means the same size, more means proportionally more. - * More means faster but more memory consumption. - */ - //long mult = 100 + (1000L * size) / (6 * log2plus1(newcap)); - long mult = 100 + (1000L * size) / log2plus1(newcap); - - // testing shows 1.02 for large arrays is about the point of diminishing return - if (mult < 102) - mult = 102; - newext = cast(size_t)((newcap * mult) / 100); - newext -= newext % size; - //printf("mult: %2.2f, mult2: %2.2f, alloc: %2.2f\n",mult/100.0,mult2,newext / cast(double)size); - } - newcap = newext > newcap ? newext : newcap; - //printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size); - } - return newcap; -} - -extern (C) -byte[] _d_arrayappendcTp(TypeInfo ti, inout byte[] x, byte *argp) -{ - auto sizeelem = ti.next.tsize(); // array element size - auto cap = _gc.capacity(x.ptr); - auto length = x.length; - auto newlength = length + 1; - auto newsize = newlength * sizeelem; - - assert(cap == 0 || length * sizeelem <= cap); - - //printf("_d_arrayappendc(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, cap); - - if (newsize >= cap) - { byte* newdata; - - if (cap >= 4096) - { // Try to extend in-place - auto u = _gc.extend(x.ptr, (newsize + 1) - cap, (newsize + 1) - cap); - if (u) - { - goto L1; - } - } - - //printf("_d_arrayappendc(sizeelem = %d, newlength = %d, cap = %d)\n", sizeelem, newlength, cap); - cap = newCapacity(newlength, sizeelem); - assert(cap >= newlength * sizeelem); - newdata = cast(byte *)_gc.malloc(cap + 1); - if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(newdata); - memcpy(newdata, x.ptr, length * sizeelem); - (cast(void **)(&x))[1] = newdata; - } - L1: - - *cast(size_t *)&x = newlength; - x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; - assert((cast(size_t)x.ptr & 15) == 0); - assert(_gc.capacity(x.ptr) >= x.length * sizeelem); - return x; -} - -extern (C) -byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y) -out (result) -{ - auto sizeelem = ti.next.tsize(); // array element size - //printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, sizeelem, result.length, result.ptr); - assert(result.length == x.length + y.length); - for (size_t i = 0; i < x.length * sizeelem; i++) - assert((cast(byte*)result)[i] == (cast(byte*)x)[i]); - for (size_t i = 0; i < y.length * sizeelem; i++) - assert((cast(byte*)result)[x.length * sizeelem + i] == (cast(byte*)y)[i]); - - size_t cap = _gc.capacity(result.ptr); - assert(!cap || cap > result.length * sizeelem); -} -body -{ - version (none) - { - /* Cannot use this optimization because: - * char[] a, b; - * char c = 'a'; - * b = a ~ c; - * c = 'b'; - * will change the contents of b. - */ - if (!y.length) - return x; - if (!x.length) - return y; - } - - //printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr); - auto sizeelem = ti.next.tsize(); // array element size - //printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d)\n", x.length, x.ptr, y.length, y.ptr, sizeelem); - size_t xlen = x.length * sizeelem; - size_t ylen = y.length * sizeelem; - size_t len = xlen + ylen; - if (!len) - return null; - - byte* p = cast(byte*)_gc.malloc(len + 1); - if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(p); - memcpy(p, x.ptr, xlen); - memcpy(p + xlen, y.ptr, ylen); - p[len] = 0; - - return p[0 .. x.length + y.length]; -} - - -extern (C) -byte[] _d_arraycatnT(TypeInfo ti, uint n, ...) -{ void* a; - size_t length; - byte[]* p; - uint i; - byte[] b; - va_list va; - auto sizeelem = ti.next.tsize(); // array element size - - va_start!(typeof(n))(va, n); - - for (i = 0; i < n; i++) - { - b = va_arg!(typeof(b))(va); - length += b.length; - } - if (!length) - return null; - - a = _gc.malloc(length * sizeelem); - if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(a); - va_start!(typeof(n))(va, n); - - uint j = 0; - for (i = 0; i < n; i++) - { - b = va_arg!(typeof(b))(va); - if (b.length) - { - memcpy(a + j, b.ptr, b.length * sizeelem); - j += b.length * sizeelem; - } - } - - return (cast(byte*)a)[0..length]; -} - -version (GNU) { } else -extern (C) -void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) -{ - auto sizeelem = ti.next.tsize(); // array element size - void* result; - - //printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length); - if (length == 0 || sizeelem == 0) - result = null; - else - { - result = _gc.malloc(length * sizeelem); - if (!(ti.next.flags() & 1)) - { - _gc.hasNoPointers(result); - } - - va_list q; - va_start!(size_t)(q, length); - - size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); - - if (stacksize == sizeelem) - { - memcpy(result, q, length * sizeelem); - } - else - { - for (size_t i = 0; i < length; i++) - { - memcpy(result + i * sizeelem, q, sizeelem); - q += stacksize; - } - } - - va_end(q); - } - return result; -} - -/********************************** - * Support for array.dup property. - */ - -/*struct Array2 -{ - size_t length; - void* ptr; -}*/ - -extern(C) void* _d_allocmemoryT(TypeInfo ti) { - return malloc(ti.tsize).ptr; // Tit size :) -} diff --git a/lphobos/gc/gc_guess_stack.d b/lphobos/gc/gc_guess_stack.d deleted file mode 100644 index a2c4c7f30e6..00000000000 --- a/lphobos/gc/gc_guess_stack.d +++ /dev/null @@ -1,3 +0,0 @@ -module gcc.gc_guess_stack; -void * stackOriginGuess; - diff --git a/lphobos/gc/gcbits.d b/lphobos/gc/gcbits.d deleted file mode 100644 index 264bcf71192..00000000000 --- a/lphobos/gc/gcbits.d +++ /dev/null @@ -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() -{ -} -+/ diff --git a/lphobos/gc/gclinux.d b/lphobos/gc/gclinux.d deleted file mode 100644 index 1611d5a8c5a..00000000000 --- a/lphobos/gc/gclinux.d +++ /dev/null @@ -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 - 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 - 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; -} diff --git a/lphobos/gc/gcx.d b/lphobos/gc/gcx.d deleted file mode 100644 index e7dbe7b2ae9..00000000000 --- a/lphobos/gc/gcx.d +++ /dev/null @@ -1,2681 +0,0 @@ -/** - * This module contains the garbage collector implementation. - * - * Copyright: Copyright (C) 2001-2007 Digital Mars, www.digitalmars.com. - * All rights reserved. - * License: - * 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. - * Authors: Walter Bright, David Friedman, Sean Kelly - */ - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, July 2006 -*/ - -module gcx; - -// D Garbage Collector implementation - -/************** Debugging ***************************/ - -//debug = PRINTF; // turn on printf's -//debug = COLLECT_PRINTF; // turn on printf's -//debug = THREADINVARIANT; // check thread integrity -//debug = LOGGING; // log allocations / frees -//debug = MEMSTOMP; // stomp on memory -//debug = SENTINEL; // add underrun/overrrun protection -//debug = PTRCHECK; // more pointer checking -//debug = PTRCHECK2; // thorough but slow pointer checking - -/*************** Configuration *********************/ - -version = STACKGROWSDOWN; // growing the stack means subtracting from the stack pointer - // (use for Intel X86 CPUs) - // else growing the stack means adding to the stack pointer -version = MULTI_THREADED; // produce multithreaded version - -/***************************************************/ - -private import gcbits; -private import gcstats; - -private import cstdlib = std.c.stdlib : calloc, free, malloc, realloc; -private import cstring = std.c.string : memcpy, memmove, memset; - -debug private import std.c.stdio; - -import std.outofmemory; -import std.gc; - -version (GNU) -{ - private import gcc.builtins; -} - -version (Win32) -{ - import win32; - import std.c.windows.windows; -} -else version (GNU) -{ - private import gcgcc; -} -else version (linux) -{ - import gclinux; -} - -/*version (BigEndian) - private import std.intrinsic;*/ - - - -version (MULTI_THREADED) -{ - import std.thread; -} - - -private void onOutOfMemoryError() -{ - _d_OutOfMemory(); -} - -private void* rt_stackBottom() -{ - version (Win32) - { - return win32.os_query_stackBottom(); - } - else version (GNU) - { - return gcgcc.os_query_stackBottom(); - } - else version (linux) - { - return gclinux.os_query_stackBottom(); - } -} - -private bool thread_needLock() -{ - return std.thread.Thread.nthreads != 1; -} - - -alias GC gc_t; - -version (X86) version (D_InlineAsm) { version = Asm86; } - - -/* ======================= Leak Detector =========================== */ - - -debug (LOGGING) -{ - struct Log - { - void* p; - size_t size; - uint line; - char* file; - void* parent; - - void print() - { - printf(" p = %x, size = %d, parent = %x ", p, size, parent); - if (file) - { - printf("%s(%u)", file, line); - } - printf("\n"); - } - } - - - struct LogArray - { - size_t dim; - size_t allocdim; - Log *data; - - void Dtor() - { - if (data) - cstdlib.free(data); - data = null; - } - - void reserve(size_t nentries) - { - assert(dim <= allocdim); - if (allocdim - dim < nentries) - { - allocdim = (dim + nentries) * 2; - assert(dim + nentries <= allocdim); - if (!data) - { - data = cast(Log *)cstdlib.malloc(allocdim * Log.sizeof); - if (!data && allocdim) - onOutOfMemoryError(); - } - else - { Log *newdata; - - newdata = cast(Log *)cstdlib.malloc(allocdim * Log.sizeof); - if (!newdata && allocdim) - onOutOfMemoryError(); - cstring.memcpy(newdata, data, dim * Log.sizeof); - cstdlib.free(data); - data = newdata; - } - } - } - - - void push(Log log) - { - reserve(1); - data[dim++] = log; - } - - void remove(size_t i) - { - cstring.memmove(data + i, data + i + 1, (dim - i) * Log.sizeof); - dim--; - } - - - size_t find(void *p) - { - for (size_t i = 0; i < dim; i++) - { - if (data[i].p == p) - return i; - } - return ~0u; // not found - } - - - void copy(LogArray *from) - { - reserve(from.dim - dim); - assert(from.dim <= allocdim); - cstring.memcpy(data, from.data, from.dim * Log.sizeof); - dim = from.dim; - } - } -} - - -/* ============================ GC =============================== */ - - -alias void (*GC_FINALIZER)(void *p, bool dummy); - -class GCLock { } // just a dummy so we can get a global lock - - -const uint GCVERSION = 1; // increment every time we change interface - // to GC. - -class GC -{ - // For passing to debug code - static size_t line; - static char* file; - - uint gcversion = GCVERSION; - - Gcx *gcx; // implementation - static ClassInfo gcLock; // global lock - - - void initialize() - { - gcLock = GCLock.classinfo; - gcx = cast(Gcx *)cstdlib.calloc(1, Gcx.sizeof); - if (!gcx) - onOutOfMemoryError(); - printf("GCX set to %p\n", gcx); - gcx.initialize(); - setStackBottom(rt_stackBottom()); - } - - - void Dtor() - { - version (linux) - { - //debug(PRINTF) printf("Thread %x ", pthread_self()); - //debug(PRINTF) printf("GC.Dtor()\n"); - } - - if (gcx) - { - gcx.Dtor(); - cstdlib.free(gcx); - gcx = null; - } - } - - - invariant() - { - if (gcx) - { - gcx.thread_Invariant(); - } - } - - - /** - * - */ - void enable() - { - if (!thread_needLock()) - { - assert(gcx.disabled > 0); - gcx.disabled--; - } - else synchronized (gcLock) - { - assert(gcx.disabled > 0); - gcx.disabled--; - } - } - - - /** - * - */ - void disable() - { - if (!thread_needLock()) - { - gcx.disabled++; - } - else synchronized (gcLock) - { - gcx.disabled++; - } - } - - - /** - * - */ - void *malloc(size_t size) - { - if (!size) - { - return null; - } - - if (!thread_needLock()) - { - return mallocNoSync(size); - } - else synchronized (gcLock) - { - return mallocNoSync(size); - } - } - - - // - // - // - private void *mallocNoSync(size_t size) - { - assert(size != 0); - - void *p = null; - Bins bin; - - //debug(PRINTF) printf("GC::malloc(size = %d, gcx = %p)\n", size, gcx); - assert(gcx); - //debug(PRINTF) printf("gcx.self = %x, pthread_self() = %x\n", gcx.self, pthread_self()); - size += SENTINEL_EXTRA; - - // Compute size bin - // Cache previous binsize lookup - Dave Fladebo. - static size_t lastsize = -1; - static Bins lastbin; - if (size == lastsize) - bin = lastbin; - else - { - bin = gcx.findBin(size); - lastsize = size; - lastbin = bin; - } - - if (bin < B_PAGE) - { - p = gcx.bucket[bin]; - if (p == null) - { - if (!gcx.allocPage(bin) && !gcx.disabled) // try to find a new page - { - if (!thread_needLock()) - { - /* Then we haven't locked it yet. Be sure - * and lock for a collection, since a finalizer - * may start a new thread. - */ - synchronized (gcLock) - { - gcx.fullcollectshell(); - } - } - else if (!gcx.fullcollectshell()) // collect to find a new page - { - //gcx.newPool(1); - } - } - if (!gcx.bucket[bin] && !gcx.allocPage(bin)) - { int result; - - gcx.newPool(1); // allocate new pool to find a new page - result = gcx.allocPage(bin); - if (!result) - return null; - } - p = gcx.bucket[bin]; - } - - // Return next item from free list - gcx.bucket[bin] = (cast(List *)p).next; - cstring.memset(p + size, 0, binsize[bin] - size); - //debug(PRINTF) printf("\tmalloc => %x\n", p); - debug (MEMSTOMP) cstring.memset(p, 0xF0, size); - } - else - { - p = gcx.bigAlloc(size); - if (!p) - return null; - } - size -= SENTINEL_EXTRA; - p = sentinel_add(p); - sentinel_init(p, size); - gcx.log_malloc(p, size); - return p; - } - - - /** - * - */ - void *calloc(size_t size, size_t n) - { - size_t len = size * n; - - if (!len) - { - return null; - } - - if (!thread_needLock()) - { - return callocNoSync(len); - } - else synchronized (gcLock) - { - return callocNoSync(len); - } - } - - - // - // - // - private void *callocNoSync(size_t size) - { - assert(size != 0); - - void *p = mallocNoSync(size); - if (p) - { //debug(PRINTF) printf("calloc: %x len %d\n", p, len); - cstring.memset(p, 0, size); - } - return p; - } - - - /** - * - */ - void *realloc(void *p, size_t size) - { - if (!thread_needLock()) - { - return reallocNoSync(p, size); - } - else synchronized (gcLock) - { - return reallocNoSync(p, size); - } - } - - - // - // - // - private void *reallocNoSync(void *p, size_t size) - { - gcx.p_cache = null; - if (!size) - { if (p) - { freeNoSync(p); - p = null; - } - } - else if (!p) - { - p = mallocNoSync(size); - } - else - { void *p2; - size_t psize; - - //debug(PRINTF) printf("GC::realloc(p = %x, size = %u)\n", p, size); - version (SENTINEL) - { - sentinel_Invariant(p); - psize = *sentinel_size(p); - if (psize != size) - { - p2 = mallocNoSync(size); - if (psize < size) - size = psize; - //debug(PRINTF) printf("\tcopying %d bytes\n",size); - cstring.memcpy(p2, p, size); - p = p2; - } - } - else - { - psize = gcx.findSize(p); // find allocated size - if (psize >= PAGESIZE && size >= PAGESIZE) - { - auto psz = psize / PAGESIZE; - auto newsz = (size + PAGESIZE - 1) / PAGESIZE; - if (newsz == psz) - return p; - - auto pool = gcx.findPool(p); - auto pagenum = (p - pool.baseAddr) / PAGESIZE; - - if (newsz < psz) - { // Shrink in place - synchronized (gcLock) - { - debug (MEMSTOMP) cstring.memset(p + size, 0xF2, psize - size); - pool.freePages(pagenum + newsz, psz - newsz); - } - return p; - } - else if (pagenum + newsz <= pool.npages) - { - // Attempt to expand in place - synchronized (gcLock) - { - for (size_t i = pagenum + psz; 1;) - { - if (i == pagenum + newsz) - { - debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, size - psize); - cstring.memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz); - return p; - } - if (i == pool.ncommitted) - { - auto u = pool.extendPages(pagenum + newsz - pool.ncommitted); - if (u == ~0u) - break; - i = pagenum + newsz; - continue; - } - if (pool.pagetable[i] != B_FREE) - break; - i++; - } - } - } - } - if (psize < size || // if new size is bigger - psize > size * 2) // or less than half - { - p2 = mallocNoSync(size); - if (psize < size) - size = psize; - //debug(PRINTF) printf("\tcopying %d bytes\n",size); - cstring.memcpy(p2, p, size); - p = p2; - } - } - } - return p; - } - - - /** - * Attempt to in-place enlarge the memory block pointed to by p by at least - * minbytes beyond its current capacity, up to a maximum of maxsize. This - * does not attempt to move the memory block (like realloc() does). - * - * Returns: - * 0 if could not extend p, - * total size of entire memory block if successful. - */ - size_t extend(void* p, size_t minsize, size_t maxsize) - { - if (!thread_needLock()) - { - return extendNoSync(p, minsize, maxsize); - } - else synchronized (gcLock) - { - return extendNoSync(p, minsize, maxsize); - } - } - - - // - // - // - private size_t extendNoSync(void* p, size_t minsize, size_t maxsize) - in - { - assert( minsize <= maxsize ); - } - body - { - //debug(PRINTF) printf("GC::extend(p = %x, minsize = %u, maxsize = %u)\n", p, minsize, maxsize); - version (SENTINEL) - { - return 0; - } - auto psize = gcx.findSize(p); // find allocated size - if (psize < PAGESIZE) - return 0; // cannot extend buckets - - auto psz = psize / PAGESIZE; - auto minsz = (minsize + PAGESIZE - 1) / PAGESIZE; - auto maxsz = (maxsize + PAGESIZE - 1) / PAGESIZE; - - auto pool = gcx.findPool(p); - auto pagenum = (p - pool.baseAddr) / PAGESIZE; - - size_t sz; - for (sz = 0; sz < maxsz; sz++) - { - auto i = pagenum + psz + sz; - if (i == pool.ncommitted) - break; - if (pool.pagetable[i] != B_FREE) - { if (sz < minsz) - return 0; - break; - } - } - if (sz >= minsz) - { - } - else if (pagenum + psz + sz == pool.ncommitted) - { - auto u = pool.extendPages(minsz - sz); - if (u == ~0u) - return 0; - sz = minsz; - } - else - return 0; - debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize); - cstring.memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz); - gcx.p_cache = null; - gcx.size_cache = 0; - return (psz + sz) * PAGESIZE; - } - - - /** - * - */ - void free(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - return freeNoSync(p); - } - else synchronized (gcLock) - { - return freeNoSync(p); - } - } - - - // - // - // - private void freeNoSync(void *p) - { - assert (p); - - Pool *pool; - uint pagenum; - Bins bin; - uint biti; - - // Find which page it is in - pool = gcx.findPool(p); - if (!pool) // if not one of ours - return; // ignore - sentinel_Invariant(p); - p = sentinel_sub(p); - pagenum = (p - pool.baseAddr) / PAGESIZE; - biti = cast(uint)(p - pool.baseAddr) / 16; - pool.noscan.clear(biti); - if (pool.finals.nbits && pool.finals.testClear(biti)) - gcx.rt_finalize(sentinel_add(p), false); - - gcx.p_cache = null; - bin = cast(Bins)pool.pagetable[pagenum]; - if (bin == B_PAGE) // if large alloc - { int npages; - uint n; - - // Free pages - npages = 1; - n = pagenum; - while (++n < pool.ncommitted && pool.pagetable[n] == B_PAGEPLUS) - npages++; - debug (MEMSTOMP) cstring.memset(p, 0xF2, npages * PAGESIZE); - pool.freePages(pagenum, npages); - } - else - { // Add to free list - List *list = cast(List *)p; - - debug (MEMSTOMP) cstring.memset(p, 0xF2, binsize[bin]); - - list.next = gcx.bucket[bin]; - gcx.bucket[bin] = list; - } - gcx.log_free(sentinel_add(p)); - } - - - /** - * Determine the allocated size of pointer p. If p is an interior pointer - * or not a gc allocated pointer, return 0. - */ - size_t capacity(void *p) - { - if (!p) - { - return 0; - } - - if (!thread_needLock()) - { - return sizeOfNoSync(p); - } - else synchronized (gcLock) - { - return sizeOfNoSync(p); - } - } - - - // - // - // - private size_t sizeOfNoSync(void *p) - { - assert (p); - - version (SENTINEL) - { - p = sentinel_sub(p); - size_t size = gcx.findSize(p); - - // Check for interior pointer - // This depends on: - // 1) size is a power of 2 for less than PAGESIZE values - // 2) base of memory pool is aligned on PAGESIZE boundary - if (cast(size_t)p & (size - 1) & (PAGESIZE - 1)) - size = 0; - return size ? size - SENTINAL_EXTRA : 0; - } - else - { - if (p !is null && p == gcx.p_cache) - return gcx.size_cache; - - size_t size = gcx.findSize(p); - - // Check for interior pointer - // This depends on: - // 1) size is a power of 2 for less than PAGESIZE values - // 2) base of memory pool is aligned on PAGESIZE boundary - if (cast(size_t)p & (size - 1) & (PAGESIZE - 1)) - size = 0; - else - { - gcx.p_cache = p; - gcx.size_cache = size; - } - - return size; - } - } - - - /** - * Verify that pointer p: - * 1) belongs to this memory pool - * 2) points to the start of an allocated piece of memory - * 3) is not on a free list - */ - void check(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - checkNoSync(p); - } - else synchronized (gcLock) - { - checkNoSync(p); - } - } - - // - // - // - private void checkNoSync(void *p) - { - assert(p); - - sentinel_Invariant(p); - debug (PTRCHECK) - { - Pool* pool; - uint pagenum; - Bins bin; - size_t size; - - p = sentinel_sub(p); - pool = gcx.findPool(p); - assert(pool); - pagenum = (p - pool.baseAddr) / PAGESIZE; - bin = cast(Bins)pool.pagetable[pagenum]; - assert(bin <= B_PAGE); - size = binsize[bin]; - assert((cast(size_t)p & (size - 1)) == 0); - - debug (PTRCHECK2) - { - if (bin < B_PAGE) - { - // Check that p is not on a free list - List *list; - - for (list = gcx.bucket[bin]; list; list = list.next) - { - assert(cast(void *)list != p); - } - } - } - } - } - - - // - // - // - private void setStackBottom(void *p) - { - version (STACKGROWSDOWN) - { - //p = (void *)((uint *)p + 4); - if (p > gcx.stackBottom) - { - //debug(PRINTF) printf("setStackBottom(%x)\n", p); - gcx.stackBottom = p; - } - } - else - { - //p = (void *)((uint *)p - 4); - if (p < gcx.stackBottom) - { - //debug(PRINTF) printf("setStackBottom(%x)\n", p); - gcx.stackBottom = cast(char *)p; - } - } - } - - - static void scanStaticData(gc_t g) - { - void *pbot; - void *ptop; - size_t nbytes; - - //debug(PRINTF) printf("+GC.scanStaticData()\n"); - os_query_staticdataseg(&pbot, &nbytes); - ptop = pbot + nbytes; - version (GNU) { - if (pbot) { - g.addRange(pbot, ptop); - } - } else { - g.addRange(pbot, ptop); - } - //debug(PRINTF) printf("-GC.scanStaticData()\n"); - } - - static void unscanStaticData(gc_t g) - { - void *pbot; - size_t nbytes; - - os_query_staticdataseg(&pbot, &nbytes); - version (GNU) { - if (pbot) { - g.removeRange(pbot); - } - } else { - g.removeRange(pbot); - } - } - - - /** - * add p to list of roots - */ - void addRoot(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - gcx.addRoot(p); - } - else synchronized (gcLock) - { - gcx.addRoot(p); - } - } - - - /** - * remove p from list of roots - */ - void removeRoot(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - gcx.removeRoot(p); - } - else synchronized (gcLock) - { - gcx.removeRoot(p); - } - } - - - /** - * add range to scan for roots - */ - void addRange(void *pbot, void *ptop) - { - if (!pbot || !ptop) - { - return; - } - - //debug(PRINTF) printf("+GC.addRange(pbot = x%x, ptop = x%x)\n", pbot, ptop); - if (!thread_needLock()) - { - gcx.addRange(pbot, ptop); - } - else synchronized (gcLock) - { - gcx.addRange(pbot, ptop); - } - //debug(PRINTF) printf("-GC.addRange()\n"); - } - - - /** - * remove range - */ - void removeRange(void *p) - { - if (!p) - { - return; - } - - if (!thread_needLock()) - { - gcx.removeRange(p); - } - else synchronized (gcLock) - { - gcx.removeRange(p); - } - } - - - /** - * do full garbage collection - */ - void fullCollect() - { - debug(PRINTF) printf("GC.fullCollect()\n"); - - if (!thread_needLock()) - { - gcx.fullcollectshell(); - } - else synchronized (gcLock) - { - gcx.fullcollectshell(); - } - - version (none) - { - GCStats stats; - - getStats(stats); - debug(PRINTF) printf("poolsize = %x, usedsize = %x, freelistsize = %x\n", - stats.poolsize, stats.usedsize, stats.freelistsize); - } - - gcx.log_collect(); - } - - - /** - * do full garbage collection ignoring roots - */ - void fullCollectNoStack() - { - if (!thread_needLock()) - { - gcx.noStack++; - gcx.fullcollectshell(); - gcx.noStack--; - } - else synchronized (gcLock) - { - gcx.noStack++; - gcx.fullcollectshell(); - gcx.noStack--; - } - } - - - /** - * do generational garbage collection - */ - void genCollect() - { - synchronized (gcLock) - { - gcx.fullcollectshell(); - } - } - - void minimize() // minimize physical memory usage - { - // Not implemented, ignore - } - - void setFinalizer(void *p, GC_FINALIZER pFn) - { - synchronized (gcLock) - { - gcx.finalizer = pFn; - gcx.doFinalize(p); - } - } - - - void hasPointers(void *p) - { - synchronized (gcLock) - { - gcx.HasPointers(p); - } - } - - - void hasNoPointers(void *p) - { - if (!gcx.conservative) - { synchronized (gcLock) - { - gcx.HasNoPointers(p); - } - } - } - - - void setV1_0() - { - gcx.conservative = 1; - } - - /** - * Retrieve statistics about garbage collection. - * Useful for debugging and tuning. - */ - void getStats(out GCStats stats) - { - if (!thread_needLock()) - { - getStatsNoSync(stats); - } - else synchronized (gcLock) - { - getStatsNoSync(stats); - } - } - - // - // - // - private void getStatsNoSync(out GCStats stats) - { - size_t psize = 0; - size_t usize = 0; - size_t flsize = 0; - - size_t n; - size_t bsize = 0; - - //debug(PRINTF) printf("getStats()\n"); - cstring.memset(&stats, 0, GCStats.sizeof); - - for (n = 0; n < gcx.npools; n++) - { Pool *pool = gcx.pooltable[n]; - - psize += pool.ncommitted * PAGESIZE; - for (uint j = 0; j < pool.ncommitted; j++) - { - Bins bin = cast(Bins)pool.pagetable[j]; - if (bin == B_FREE) - stats.freeblocks++; - else if (bin == B_PAGE) - stats.pageblocks++; - else if (bin < B_PAGE) - bsize += PAGESIZE; - } - } - - for (n = 0; n < B_PAGE; n++) - { - //debug(PRINTF) printf("bin %d\n", n); - for (List *list = gcx.bucket[n]; list; list = list.next) - { - //debug(PRINTF) printf("\tlist %x\n", list); - flsize += binsize[n]; - } - } - - usize = bsize - flsize; - - stats.poolsize = psize; - stats.usedsize = bsize - flsize; - stats.freelistsize = flsize; - } -} - - -/* ============================ Gcx =============================== */ - -enum -{ PAGESIZE = 4096, - COMMITSIZE = (4096*16), - POOLSIZE = (4096*256), -} - - -enum -{ - B_16, - B_32, - B_64, - B_128, - B_256, - B_512, - B_1024, - B_2048, - B_PAGE, // start of large alloc - B_PAGEPLUS, // continuation of large alloc - B_FREE, // free page - B_UNCOMMITTED, // memory not committed for this page - B_MAX -} - - -alias ubyte Bins; - - -struct List -{ - List *next; -} - - -struct Range -{ - void *pbot; - void *ptop; -} - - -const uint binsize[B_MAX] = [ 16,32,64,128,256,512,1024,2048,4096 ]; -const uint notbinsize[B_MAX] = [ ~(16u-1),~(32u-1),~(64u-1),~(128u-1),~(256u-1), - ~(512u-1),~(1024u-1),~(2048u-1),~(4096u-1) ]; - -/* ============================ Gcx =============================== */ - - -struct Gcx -{ - debug (THREADINVARIANT) - { - pthread_t self; - void thread_Invariant() - { - if (self != pthread_self()) - printf("thread_Invariant(): gcx = %x, self = %x, pthread_self() = %x\n", this, self, pthread_self()); - assert(self == pthread_self()); - } - } - else - { - void thread_Invariant() { } - } - - void *p_cache; - size_t size_cache; - - size_t nroots; - size_t rootdim; - void **roots; - - size_t nranges; - size_t rangedim; - Range *ranges; - - uint conservative; // !=0 means conservative behavior - uint noStack; // !=0 means don't scan stack - uint log; // turn on logging - uint anychanges; - void *stackBottom; - uint inited; - int disabled; // turn off collections if >0 - - byte *minAddr; // min(baseAddr) - byte *maxAddr; // max(topAddr) - - uint npools; - Pool **pooltable; - - List *bucket[B_MAX]; // free list for each size - - GC_FINALIZER finalizer; // finalizer function (one per GC) - - private void rt_finalize( void* p, bool dummy ) - { - if (finalizer) - (*finalizer)(p, dummy); - } - - - void initialize() - { int dummy; - - (cast(byte *)this)[0 .. Gcx.sizeof] = 0; - stackBottom = cast(char *)&dummy; - log_init(); - debug (THREADINVARIANT) - self = pthread_self(); - //printf("gcx = %p, self = %x\n", this, self); - inited = 1; - } - - - void Dtor() - { - inited = 0; - - for (uint i = 0; i < npools; i++) - { Pool *pool = pooltable[i]; - - pool.Dtor(); - cstdlib.free(pool); - } - if (pooltable) - cstdlib.free(pooltable); - - if (roots) - cstdlib.free(roots); - - if (ranges) - cstdlib.free(ranges); - } - - - void Invariant() { } - - - invariant() - { - if (inited) - { - //printf("Gcx.invariant(): this = %p\n", this); - uint i; - - // Assure we're called on the right thread - debug (THREADINVARIANT) assert(self == pthread_self()); - - for (i = 0; i < npools; i++) - { Pool *pool = pooltable[i]; - - pool.Invariant(); - if (i == 0) - { - assert(minAddr == pool.baseAddr); - } - if (i + 1 < npools) - { - assert(pool.opCmp(pooltable[i + 1]) < 0); - } - else if (i + 1 == npools) - { - assert(maxAddr == pool.topAddr); - } - } - - if (roots) - { - assert(rootdim != 0); - assert(nroots <= rootdim); - } - - if (ranges) - { - assert(rangedim != 0); - assert(nranges <= rangedim); - - for (i = 0; i < nranges; i++) - { - assert(ranges[i].pbot); - assert(ranges[i].ptop); - assert(ranges[i].pbot <= ranges[i].ptop); - } - } - - for (i = 0; i < B_PAGE; i++) - { - for (List *list = bucket[i]; list; list = list.next) - { - } - } - } - } - - - /** - * - */ - - void addRoot(void *p) - { - if (nroots == rootdim) - { - size_t newdim = rootdim * 2 + 16; - void** newroots; - - newroots = cast(void **)cstdlib.malloc(newdim * newroots[0].sizeof); - if (!newroots) - onOutOfMemoryError(); - if (roots) - { cstring.memcpy(newroots, roots, nroots * newroots[0].sizeof); - cstdlib.free(roots); - } - roots = newroots; - rootdim = newdim; - } - roots[nroots] = p; - nroots++; - } - - - /** - * - */ - void removeRoot(void *p) - { - for (size_t i = nroots; i--;) - { - if (roots[i] == p) - { - nroots--; - cstring.memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof); - return; - } - } - assert(0); - } - - - /** - * - */ - void addRange(void *pbot, void *ptop) - { - debug(THREADINVARIANT) { debug(PRINTF) printf("Thread %x ", pthread_self()); } - debug(PRINTF) printf("%x.Gcx::addRange(%x, %x), nranges = %d\n", this, pbot, ptop, nranges); - if (nranges == rangedim) - { - size_t newdim = rangedim * 2 + 16; - Range *newranges; - - newranges = cast(Range *)cstdlib.malloc(newdim * newranges[0].sizeof); - if (!newranges) - onOutOfMemoryError(); - if (ranges) - { cstring.memcpy(newranges, ranges, nranges * newranges[0].sizeof); - cstdlib.free(ranges); - } - ranges = newranges; - rangedim = newdim; - } - ranges[nranges].pbot = pbot; - ranges[nranges].ptop = ptop; - nranges++; - } - - - /** - * - */ - void removeRange(void *pbot) - { - debug(THREADINVARIANT) { debug(PRINTF) printf("Thread %x ", pthread_self()); } - debug(PRINTF) printf("%x.Gcx.removeRange(%x), nranges = %d\n", this, pbot, nranges); - for (size_t i = nranges; i--;) - { - if (ranges[i].pbot == pbot) - { - nranges--; - cstring.memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof); - return; - } - } - debug(PRINTF) printf("Wrong thread\n"); - - // This is a fatal error, but ignore it. - // The problem is that we can get a Close() call on a thread - // other than the one the range was allocated on. - //assert(zero); - } - - - /** - * Find Pool that pointer is in. - * Return null if not in a Pool. - * Assume pooltable[] is sorted. - */ - Pool *findPool(void *p) - { - if (p >= minAddr && p < maxAddr) - { - if (npools == 1) - { - return pooltable[0]; - } - - for (uint i = 0; i < npools; i++) - { Pool *pool; - - pool = pooltable[i]; - if (p < pool.topAddr) - { if (pool.baseAddr <= p) - return pool; - break; - } - } - } - return null; - } - - - /** - * Find size of pointer p. - * Returns 0 if not a gc'd pointer - */ - size_t findSize(void *p) - { - Pool *pool; - size_t size = 0; - - pool = findPool(p); - if (pool) - { - uint pagenum; - Bins bin; - - pagenum = (cast(uint)(p - pool.baseAddr)) / PAGESIZE; - bin = cast(Bins)pool.pagetable[pagenum]; - size = binsize[bin]; - if (bin == B_PAGE) - { uint npages = pool.ncommitted; - ubyte* pt; - uint i; - - pt = &pool.pagetable[0]; - for (i = pagenum + 1; i < npages; i++) - { - if (pt[i] != B_PAGEPLUS) - break; - } - size = (i - pagenum) * PAGESIZE; - } - } - return size; - } - - - /** - * Compute bin for size. - */ - static Bins findBin(size_t size) - { Bins bin; - - if (size <= 256) - { - if (size <= 64) - { - if (size <= 16) - bin = B_16; - else if (size <= 32) - bin = B_32; - else - bin = B_64; - } - else - { - if (size <= 128) - bin = B_128; - else - bin = B_256; - } - } - else - { - if (size <= 1024) - { - if (size <= 512) - bin = B_512; - else - bin = B_1024; - } - else - { - if (size <= 2048) - bin = B_2048; - else - bin = B_PAGE; - } - } - return bin; - } - - - /** - * Allocate a chunk of memory that is larger than a page. - * Return null if out of memory. - */ - void *bigAlloc(size_t size) - { - Pool *pool; - uint npages; - uint n; - uint pn; - uint freedpages; - void *p; - int state; - - npages = (size + PAGESIZE - 1) / PAGESIZE; - - for (state = 0; ; ) - { - // This code could use some refinement when repeatedly - // allocating very large arrays. - - for (n = 0; n < npools; n++) - { - pool = pooltable[n]; - pn = pool.allocPages(npages); - if (pn != ~0u) - goto L1; - } - - // Failed - switch (state) - { - case 0: - if (disabled) - { state = 1; - continue; - } - // Try collecting - freedpages = fullcollectshell(); - if (freedpages >= npools * ((POOLSIZE / PAGESIZE) / 4)) - { state = 1; - continue; - } - // Allocate new pool - pool = newPool(npages); - if (!pool) - { state = 2; - continue; - } - pn = pool.allocPages(npages); - assert(pn != ~0u); - goto L1; - - case 1: - // Allocate new pool - pool = newPool(npages); - if (!pool) - goto Lnomemory; - pn = pool.allocPages(npages); - assert(pn != ~0u); - goto L1; - - case 2: - goto Lnomemory; - } - } - - L1: - pool.pagetable[pn] = B_PAGE; - if (npages > 1) - cstring.memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1); - p = pool.baseAddr + pn * PAGESIZE; - cstring.memset(cast(char *)p + size, 0, npages * PAGESIZE - size); - debug (MEMSTOMP) cstring.memset(p, 0xF1, size); - //debug(PRINTF) printf("\tp = %x\n", p); - return p; - - Lnomemory: - onOutOfMemoryError(); - return null; - } - - - /** - * Allocate a new pool with at least npages in it. - * Sort it into pooltable[]. - * Return null if failed. - */ - Pool *newPool(uint npages) - { - Pool *pool; - Pool **newpooltable; - uint newnpools; - uint i; - - //debug(PRINTF) printf("************Gcx::newPool(npages = %d)****************\n", npages); - - // Round up to COMMITSIZE pages - npages = (npages + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1); - - // Minimum of POOLSIZE - if (npages < POOLSIZE/PAGESIZE) - npages = POOLSIZE/PAGESIZE; - else if (npages > POOLSIZE/PAGESIZE) - { // Give us 150% of requested size, so there's room to extend - auto n = npages + (npages >> 1); - if (n < size_t.max/PAGESIZE) - npages = n; - } - - // Allocate successively larger pools up to 8 megs - if (npools) - { uint n; - - n = npools; - if (n > 8) - n = 8; // cap pool size at 8 megs - n *= (POOLSIZE / PAGESIZE); - if (npages < n) - npages = n; - } - - pool = cast(Pool *)cstdlib.calloc(1, Pool.sizeof); - if (pool) - { - pool.initialize(npages); - if (!pool.baseAddr) - goto Lerr; - - newnpools = npools + 1; - newpooltable = cast(Pool **)cstdlib.realloc(pooltable, newnpools * (Pool *).sizeof); - if (!newpooltable) - goto Lerr; - - // Sort pool into newpooltable[] - for (i = 0; i < npools; i++) - { - if (pool.opCmp(newpooltable[i]) < 0) - break; - } - cstring.memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof); - newpooltable[i] = pool; - - pooltable = newpooltable; - npools = newnpools; - - minAddr = pooltable[0].baseAddr; - maxAddr = pooltable[npools - 1].topAddr; - } - return pool; - - Lerr: - pool.Dtor(); - cstdlib.free(pool); - return null; - } - - - /** - * Allocate a page of bin's. - * Returns: - * 0 failed - */ - int allocPage(Bins bin) - { - Pool *pool; - uint n; - uint pn; - byte *p; - byte *ptop; - - //debug(PRINTF) printf("Gcx::allocPage(bin = %d)\n", bin); - for (n = 0; n < npools; n++) - { - pool = pooltable[n]; - pn = pool.allocPages(1); - if (pn != ~0u) - goto L1; - } - return 0; // failed - - L1: - pool.pagetable[pn] = cast(ubyte)bin; - - // Convert page to free list - size_t size = binsize[bin]; - List **b = &bucket[bin]; - - p = pool.baseAddr + pn * PAGESIZE; - ptop = p + PAGESIZE; - for (; p < ptop; p += size) - { - (cast(List *)p).next = *b; - *b = cast(List *)p; - } - return 1; - } - - - /** - * Search a range of memory values and mark any pointers into the GC pool. - */ - void mark(void *pbot, void *ptop) - { - void **p1 = cast(void **)pbot; - void **p2 = cast(void **)ptop; - uint changes = 0; - - //printf("marking range: %p -> %p\n", pbot, ptop); - for (; p1 < p2; p1++) - { - Pool *pool; - byte *p = cast(byte *)(*p1); - - //if (log) debug(PRINTF) printf("\tmark %x\n", p); - if (p >= minAddr) - { - pool = findPool(p); - if (pool) - { - size_t offset = cast(size_t)(p - pool.baseAddr); - uint biti; - uint pn = offset / PAGESIZE; - Bins bin = cast(Bins)pool.pagetable[pn]; - - //debug(PRINTF) printf("\t\tfound pool %x, base=%x, pn = %d, bin = %d, biti = x%x\n", pool, pool.baseAddr, pn, bin, biti); - - // Adjust bit to be at start of allocated memory block - if (bin <= B_PAGE) - { - biti = (offset & notbinsize[bin]) >> 4; - //debug(PRINTF) printf("\t\tbiti = x%x\n", biti); - } - else if (bin == B_PAGEPLUS) - { - do - { --pn; - } while (cast(Bins)pool.pagetable[pn] == B_PAGEPLUS); - biti = pn * (PAGESIZE / 16); - } - else - { - // Don't mark bits in B_FREE or B_UNCOMMITTED pages - continue; - } - - //debug(PRINTF) printf("\t\tmark(x%x) = %d\n", biti, pool.mark.test(biti)); - if (!pool.mark.test(biti)) - { - //if (log) debug(PRINTF) printf("\t\tmarking %x\n", p); - pool.mark.set(biti); - if (!pool.noscan.test(biti)) - { - pool.scan.set(biti); - changes = 1; - } - log_parent(sentinel_add(pool.baseAddr + biti * 16), sentinel_add(pbot)); - } - } - } - } - anychanges |= changes; - } - - - /** - * Return number of full pages free'd. - */ - size_t fullcollectshell() - { - // The purpose of the 'shell' is to ensure all the registers - // get put on the stack so they'll be scanned - void *sp; - size_t result; - version (GNU) - { - __builtin_unwind_init(); - sp = & sp; - } - else - { - /*asm - { - pushad ; - mov sp[EBP],ESP ; - }*/ - } - result = fullcollect(sp); - version (GNU) - { - // nothing to do - } - else - { - /*asm - { - popad ; - }*/ - } - return result; - } - - - /** - * - */ - size_t fullcollect(void *stackTop) - { - uint n; - Pool *pool; - - debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n"); - - Thread.pauseAll(); - - p_cache = null; - size_cache = 0; - - anychanges = 0; - for (n = 0; n < npools; n++) - { - pool = pooltable[n]; - pool.mark.zero(); - pool.scan.zero(); - pool.freebits.zero(); - } - - // Mark each free entry, so it doesn't get scanned - for (n = 0; n < B_PAGE; n++) - { - for (List *list = bucket[n]; list; list = list.next) - { - pool = findPool(list); - assert(pool); - pool.freebits.set(cast(uint)(cast(byte *)list - pool.baseAddr) / 16); - } - } - - for (n = 0; n < npools; n++) - { - pool = pooltable[n]; - pool.mark.copy(&pool.freebits); - } - - version (MULTI_THREADED) - { - // Scan stacks and registers for each paused thread - Thread[] threads = Thread.getAll(); - //thread_id id = cast(thread_id) GetCurrentThread(); - for (n = 0; n < threads.length; n++) - { Thread t = threads[n]; - - if (t && t.getState() == Thread.TS.RUNNING) - { - if (noStack && threads.length == 1) - break; - - version (Win32) - { - CONTEXT context; - - context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; - if (!GetThreadContext(t.hdl, &context)) - { - assert(0); - } - debug (PRINTF) printf("mt scan stack bot = %x, top = %x\n", context.Esp, t.stackBottom); - mark(cast(void *)context.Esp, t.stackBottom); - mark(&context.Edi, &context.Eip); - } - else version (GNU) - { - if (t.isSelf()) - t.stackTop = Thread.getESP(); - - //%%fry printf("top=%08x bot=%08x ext=%08x\n", t.stackTop, t.stackBottom, Thread.getESP());//%%try - version (STACKGROWSDOWN) - mark(t.stackTop, t.stackBottom); - else - mark(t.stackBottom, t.stackTop); - } - else version (linux) - { - // The registers are already stored in the stack - //printf("Thread: ESP = x%x, stackBottom = x%x, isSelf = %d\n", Thread.getESP(), t.stackBottom, t.isSelf()); - if (t.isSelf()) - t.stackTop = Thread.getESP(); - - version (STACKGROWSDOWN) - mark(t.stackTop, t.stackBottom); - else - mark(t.stackBottom, t.stackTop); - } - } - } - } - else - { - if (!noStack) - { - // Scan stack for main thread - debug(PRINTF) printf(" scan stack bot = %x, top = %x\n", stackTop, stackBottom); - version (STACKGROWSDOWN) - mark(stackTop, stackBottom); - else - mark(stackBottom, stackTop); - } - } - - // Scan roots[] - debug(COLLECT_PRINTF) printf("scan roots[]\n"); - mark(roots, roots + nroots); - - // Scan ranges[] - debug(COLLECT_PRINTF) printf("scan ranges[]\n"); - //log++; - for (n = 0; n < nranges; n++) - { - debug(COLLECT_PRINTF) printf("\t%x .. %x\n", ranges[n].pbot, ranges[n].ptop); - mark(ranges[n].pbot, ranges[n].ptop); - } - //log--; - - debug(COLLECT_PRINTF) printf("\tscan heap\n"); - while (anychanges) - { - anychanges = 0; - for (n = 0; n < npools; n++) - { - uint *bbase; - uint *b; - uint *btop; - - pool = pooltable[n]; - - bbase = pool.scan.base(); - btop = bbase + pool.scan.nwords; - for (b = bbase; b < btop;) - { Bins bin; - uint pn; - uint u; - uint bitm; - byte *o; - - bitm = *b; - if (!bitm) - { b++; - continue; - } - *b = 0; - - o = pool.baseAddr + (b - bbase) * 32 * 16; - /* version (BigEndian) - bitm = bswap(bitm); - */ - if (!(bitm & 0xFFFF)) - { - bitm >>= 16; - o += 16 * 16; - } - for (; bitm; o += 16, bitm >>= 1) - { - if (!(bitm & 1)) - continue; - - pn = (o - pool.baseAddr) / PAGESIZE; - bin = cast(Bins)pool.pagetable[pn]; - if (bin < B_PAGE) - { - mark(o, o + binsize[bin]); - } - else if (bin == B_PAGE || bin == B_PAGEPLUS) - { - if (bin == B_PAGEPLUS) - { - while (pool.pagetable[pn - 1] != B_PAGE) - pn--; - } - u = 1; - while (pn + u < pool.ncommitted && pool.pagetable[pn + u] == B_PAGEPLUS) - u++; - mark(o, o + u * PAGESIZE); - } - } - } - } - } - - // Free up everything not marked - debug(COLLECT_PRINTF) printf("\tfree'ing\n"); - size_t freedpages = 0; - size_t freed = 0; - for (n = 0; n < npools; n++) - { uint pn; - uint ncommitted; - uint *bbase; - - pool = pooltable[n]; - bbase = pool.mark.base(); - ncommitted = pool.ncommitted; - for (pn = 0; pn < ncommitted; pn++, bbase += PAGESIZE / (32 * 16)) - { - Bins bin = cast(Bins)pool.pagetable[pn]; - - if (bin < B_PAGE) - { byte *p; - byte *ptop; - uint biti; - uint bitstride; - uint size = binsize[bin]; - - p = pool.baseAddr + pn * PAGESIZE; - ptop = p + PAGESIZE; - biti = pn * (PAGESIZE/16); - bitstride = size / 16; - - version(none) // BUG: doesn't work because freebits() must also be cleared - { - // If free'd entire page - if (bbase[0] == 0 && bbase[1] == 0 && bbase[2] == 0 && bbase[3] == 0 && - bbase[4] == 0 && bbase[5] == 0 && bbase[6] == 0 && bbase[7] == 0) - { - for (; p < ptop; p += size, biti += bitstride) - { - if (pool.finals.nbits && pool.finals.testClear(biti)) - rt_finalize(cast(List *)sentinel_add(p), false); - - List *list = cast(List *)p; - //debug(PRINTF) printf("\tcollecting %x\n", list); - log_free(sentinel_add(list)); - - debug (MEMSTOMP) cstring.memset(p, 0xF3, size); - } - pool.pagetable[pn] = B_FREE; - freed += PAGESIZE; - //debug(PRINTF) printf("freeing entire page %d\n", pn); - continue; - } - } - for (; p < ptop; p += size, biti += bitstride) - { - if (!pool.mark.test(biti)) - { - sentinel_Invariant(sentinel_add(p)); - - pool.freebits.set(biti); - pool.noscan.clear(biti); - if (pool.finals.nbits && pool.finals.testClear(biti)) - rt_finalize(cast(List *)sentinel_add(p), false); - - List *list = cast(List *)p; - debug(PRINTF) printf("\tcollecting %x\n", list); - log_free(sentinel_add(list)); - - debug (MEMSTOMP) cstring.memset(p, 0xF3, size); - - freed += size; - } - } - } - else if (bin == B_PAGE) - { uint biti = pn * (PAGESIZE / 16); - - if (!pool.mark.test(biti)) - { byte *p = pool.baseAddr + pn * PAGESIZE; - - sentinel_Invariant(sentinel_add(p)); - pool.noscan.clear(biti); - if (pool.finals.nbits && pool.finals.testClear(biti)) - rt_finalize(sentinel_add(p), false); - - debug(COLLECT_PRINTF) printf("\tcollecting big %x\n", p); - log_free(sentinel_add(p)); - pool.pagetable[pn] = B_FREE; - freedpages++; - debug (MEMSTOMP) cstring.memset(p, 0xF3, PAGESIZE); - while (pn + 1 < ncommitted && pool.pagetable[pn + 1] == B_PAGEPLUS) - { - pn++; - pool.pagetable[pn] = B_FREE; - freedpages++; - - debug (MEMSTOMP) - { p += PAGESIZE; - cstring.memset(p, 0xF3, PAGESIZE); - } - } - } - } - } - } - - // Zero buckets - bucket[] = null; - - // Free complete pages, rebuild free list - debug(COLLECT_PRINTF) printf("\tfree complete pages\n"); - size_t recoveredpages = 0; - for (n = 0; n < npools; n++) - { uint pn; - uint ncommitted; - - pool = pooltable[n]; - ncommitted = pool.ncommitted; - for (pn = 0; pn < ncommitted; pn++) - { - Bins bin = cast(Bins)pool.pagetable[pn]; - uint biti; - uint u; - - if (bin < B_PAGE) - { - uint size = binsize[bin]; - uint bitstride = size / 16; - uint bitbase = pn * (PAGESIZE / 16); - uint bittop = bitbase + (PAGESIZE / 16); - byte *p; - - biti = bitbase; - for (biti = bitbase; biti < bittop; biti += bitstride) - { if (!pool.freebits.test(biti)) - goto Lnotfree; - } - pool.pagetable[pn] = B_FREE; - recoveredpages++; - continue; - - Lnotfree: - p = pool.baseAddr + pn * PAGESIZE; - for (u = 0; u < PAGESIZE; u += size) - { biti = bitbase + u / 16; - if (pool.freebits.test(biti)) - { List *list; - - list = cast(List *)(p + u); - if (list.next != bucket[bin]) // avoid unnecessary writes - list.next = bucket[bin]; - bucket[bin] = list; - } - } - } - } - } - - debug(COLLECT_PRINTF) printf("recovered pages = %d\n", recoveredpages); - debug(COLLECT_PRINTF) printf("\tfree'd %u bytes, %u pages from %u pools\n", freed, freedpages, npools); - - Thread.resumeAll(); - - return freedpages + recoveredpages; - } - - - /** - * Run finalizer on p when it is free'd. - */ - void doFinalize(void *p) - { - Pool *pool = findPool(p); - assert(pool); - - // Only allocate finals[] if we actually need it - if (!pool.finals.nbits) - pool.finals.alloc(pool.mark.nbits); - - pool.finals.set((p - pool.baseAddr) / 16); - } - - - /** - * Indicate that block pointed to by p has possible pointers - * to GC allocated memory in it. - */ - - void HasPointers(void *p) - { - Pool *pool = findPool(p); - assert(pool); - - pool.noscan.clear((p - pool.baseAddr) / 16); - } - - - /** - * Indicate that block pointed to by p has no possible pointers - * to GC allocated memory in it. - */ - void HasNoPointers(void *p) - { - //printf("HasNoPointers(%p)\n", p); - Pool *pool = findPool(p); - assert(pool); - - pool.noscan.set((p - pool.baseAddr) / 16); - } - - - /***** Leak Detector ******/ - - - debug (LOGGING) - { - LogArray current; - LogArray prev; - - - void log_init() - { - //debug(PRINTF) printf("+log_init()\n"); - current.reserve(1000); - prev.reserve(1000); - //debug(PRINTF) printf("-log_init()\n"); - } - - - void log_malloc(void *p, size_t size) - { - //debug(PRINTF) printf("+log_malloc(p = %x, size = %d)\n", p, size); - Log log; - - log.p = p; - log.size = size; - log.line = GC.line; - log.file = GC.file; - log.parent = null; - - GC.line = 0; - GC.file = null; - - current.push(log); - //debug(PRINTF) printf("-log_malloc()\n"); - } - - - void log_free(void *p) - { - //debug(PRINTF) printf("+log_free(%x)\n", p); - size_t i; - - i = current.find(p); - if (i == ~0u) - { - debug(PRINTF) printf("free'ing unallocated memory %x\n", p); - } - else - current.remove(i); - //debug(PRINTF) printf("-log_free()\n"); - } - - void log_collect() - { - //debug(PRINTF) printf("+log_collect()\n"); - // Print everything in current that is not in prev - - debug(PRINTF) printf("New pointers this cycle: --------------------------------\n"); - size_t used = 0; - for (size_t i = 0; i < current.dim; i++) - { - size_t j; - - j = prev.find(current.data[i].p); - if (j == ~0u) - current.data[i].print(); - else - used++; - } - - debug(PRINTF) printf("All roots this cycle: --------------------------------\n"); - for (size_t i = 0; i < current.dim; i++) - { - void *p; - size_t j; - - p = current.data[i].p; - if (!findPool(current.data[i].parent)) - { - j = prev.find(current.data[i].p); - if (j == ~0u) - debug(PRINTF) printf("N"); - else - debug(PRINTF) printf(" ");; - current.data[i].print(); - } - } - - debug(PRINTF) printf("Used = %d-------------------------------------------------\n", used); - prev.copy(¤t); - - debug(PRINTF) printf("-log_collect()\n"); - } - - - void log_parent(void *p, void *parent) - { - //debug(PRINTF) printf("+log_parent()\n"); - size_t i; - - i = current.find(p); - if (i == ~0u) - { - debug(PRINTF) printf("parent'ing unallocated memory %x, parent = %x\n", p, parent); - Pool *pool; - pool = findPool(p); - assert(pool); - size_t offset = cast(uint)(p - pool.baseAddr); - size_t biti; - uint pn = offset / PAGESIZE; - Bins bin = cast(Bins)pool.pagetable[pn]; - biti = (offset & notbinsize[bin]); - debug(PRINTF) printf("\tbin = %d, offset = x%x, biti = x%x\n", bin, offset, biti); - } - else - { - current.data[i].parent = parent; - } - //debug(PRINTF) printf("-log_parent()\n"); - } - - } - else - { - void log_init() { } - void log_malloc(void *p, size_t size) { } - void log_free(void *p) { } - void log_collect() { } - void log_parent(void *p, void *parent) { } - } -} - - -/* ============================ Pool =============================== */ - - -struct Pool -{ - byte* baseAddr; - byte* topAddr; - GCBits mark; // entries already scanned, or should not be scanned - GCBits scan; // entries that need to be scanned - GCBits freebits; // entries that are on the free list - GCBits finals; // entries that need finalizer run on them - GCBits noscan; // entries that should not be scanned - - uint npages; - uint ncommitted; // ncommitted <= npages - ubyte* pagetable; - - - void initialize(uint npages) - { - size_t poolsize; - - //debug(PRINTF) printf("Pool::Pool(%u)\n", npages); - poolsize = npages * PAGESIZE; - assert(poolsize >= POOLSIZE); - baseAddr = cast(byte *)os_mem_map(poolsize); - - // Some of the code depends on page alignment of memory pools - assert((cast(uint)baseAddr & (PAGESIZE - 1)) == 0); - - if (!baseAddr) - { - //debug(PRINTF) printf("GC fail: poolsize = x%x, errno = %d\n", poolsize, errno); - //debug(PRINTF) printf("message = '%s'\n", sys_errlist[errno]); - - npages = 0; - poolsize = 0; - } - //assert(baseAddr); - topAddr = baseAddr + poolsize; - - mark.alloc(poolsize / 16); - scan.alloc(poolsize / 16); - freebits.alloc(poolsize / 16); - noscan.alloc(poolsize / 16); - - pagetable = cast(ubyte*)cstdlib.malloc(npages); - if (!pagetable) - onOutOfMemoryError(); - cstring.memset(pagetable, B_UNCOMMITTED, npages); - - this.npages = npages; - ncommitted = 0; - } - - - void Dtor() - { - if (baseAddr) - { - int result; - - if (ncommitted) - { - result = os_mem_decommit(baseAddr, 0, ncommitted * PAGESIZE); - assert(result == 0); - ncommitted = 0; - } - - if (npages) - { - result = os_mem_unmap(baseAddr, npages * PAGESIZE); - assert(result == 0); - npages = 0; - } - - baseAddr = null; - topAddr = null; - } - if (pagetable) - cstdlib.free(pagetable); - - mark.Dtor(); - scan.Dtor(); - freebits.Dtor(); - finals.Dtor(); - noscan.Dtor(); - } - - - void Invariant() { } - - - invariant() - { - //mark.Invariant(); - //scan.Invariant(); - //freebits.Invariant(); - //finals.Invariant(); - //noscan.Invariant(); - - if (baseAddr) - { - //if (baseAddr + npages * PAGESIZE != topAddr) - //printf("baseAddr = %p, npages = %d, topAddr = %p\n", baseAddr, npages, topAddr); - assert(baseAddr + npages * PAGESIZE == topAddr); - assert(ncommitted <= npages); - } - - for (uint i = 0; i < npages; i++) - { Bins bin = cast(Bins)pagetable[i]; - - assert(bin < B_MAX); - } - } - - - /** - * Allocate n pages from Pool. - * Returns ~0u on failure. - */ - uint allocPages(uint n) - { - uint i; - uint n2; - - //debug(PRINTF) printf("Pool::allocPages(n = %d)\n", n); - n2 = n; - for (i = 0; i < ncommitted; i++) - { - if (pagetable[i] == B_FREE) - { - if (--n2 == 0) - { //debug(PRINTF) printf("\texisting pn = %d\n", i - n + 1); - return i - n + 1; - } - } - else - n2 = n; - } - return extendPages(n); - } - - /** - * Extend Pool by n pages. - * Returns ~0u on failure. - */ - uint extendPages(uint n) - { - //debug(PRINTF) printf("Pool::extendPages(n = %d)\n", n); - if (ncommitted + n <= npages) - { - uint tocommit; - - tocommit = (n + (COMMITSIZE/PAGESIZE) - 1) & ~(COMMITSIZE/PAGESIZE - 1); - if (ncommitted + tocommit > npages) - tocommit = npages - ncommitted; - //debug(PRINTF) printf("\tlooking to commit %d more pages\n", tocommit); - //fflush(stdout); - if (os_mem_commit(baseAddr, ncommitted * PAGESIZE, tocommit * PAGESIZE) == 0) - { - cstring.memset(pagetable + ncommitted, B_FREE, tocommit); - auto i = ncommitted; - ncommitted += tocommit; - - while (i && pagetable[i - 1] == B_FREE) - i--; - - return i; - } - //debug(PRINTF) printf("\tfailed to commit %d pages\n", tocommit); - } - - return ~0u; - } - - - /** - * Free npages pages starting with pagenum. - */ - void freePages(uint pagenum, uint npages) - { - cstring.memset(&pagetable[pagenum], B_FREE, npages); - } - - - /** - * Used for sorting pooltable[] - */ - int opCmp(Pool *p2) - { - if (baseAddr < p2.baseAddr) - return -1; - else - return cast(int)(baseAddr > p2.baseAddr); - } -} - - -/* ============================ SENTINEL =============================== */ - - -version (SENTINEL) -{ - const size_t SENTINEL_PRE = cast(size_t) 0xF4F4F4F4F4F4F4F4UL; // 32 or 64 bits - const ubyte SENTINEL_POST = 0xF5; // 8 bits - const uint SENTINEL_EXTRA = 2 * size_t.sizeof + 1; - - - size_t* sentinel_size(void *p) { return &(cast(size_t *)p)[-2]; } - size_t* sentinel_pre(void *p) { return &(cast(size_t *)p)[-1]; } - ubyte* sentinel_post(void *p) { return &(cast(ubyte *)p)[sentinel_size(p)]; } - - - void sentinel_init(void *p, size_t size) - { - *sentinel_size(p) = size; - *sentinel_pre(p) = SENTINEL_PRE; - *sentinel_post(p) = SENTINEL_POST; - } - - - void sentinel_Invariant(void *p) - { - assert(*sentinel_pre(p) == SENTINEL_PRE); - assert(*sentinel_post(p) == SENTINEL_POST); - } - - - void *sentinel_add(void *p) - { - return p + 2 * size_t.sizeof; - } - - - void *sentinel_sub(void *p) - { - return p - 2 * size_t.sizeof; - } -} -else -{ - const uint SENTINEL_EXTRA = 0; - - - void sentinel_init(void *p, size_t size) - { - } - - - void sentinel_Invariant(void *p) - { - } - - - void *sentinel_add(void *p) - { - return p; - } - - - void *sentinel_sub(void *p) - { - return p; - } -} - - diff --git a/lphobos/gc/win32.d b/lphobos/gc/win32.d deleted file mode 100644 index b0480fbd40e..00000000000 --- a/lphobos/gc/win32.d +++ /dev/null @@ -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; -} - -++++/ diff --git a/lphobos/gcstats.d b/lphobos/gcstats.d deleted file mode 100644 index 6f515545119..00000000000 --- a/lphobos/gcstats.d +++ /dev/null @@ -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 -} - - diff --git a/lphobos/hello.d b/lphobos/hello.d deleted file mode 100644 index 6516c0ffaef..00000000000 --- a/lphobos/hello.d +++ /dev/null @@ -1,5 +0,0 @@ -module hello; - -import std.stdio; - -void main() { writefln("Hello World"); } diff --git a/lphobos/internal/aApply.d b/lphobos/internal/aApply.d deleted file mode 100644 index 019b4781742..00000000000 --- a/lphobos/internal/aApply.d +++ /dev/null @@ -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; -} - - diff --git a/lphobos/internal/aApplyR.d b/lphobos/internal/aApplyR.d deleted file mode 100644 index c419ab8438d..00000000000 --- a/lphobos/internal/aApplyR.d +++ /dev/null @@ -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); -} - - diff --git a/lphobos/internal/aaA.d b/lphobos/internal/aaA.d deleted file mode 100644 index a0b98201c93..00000000000 --- a/lphobos/internal/aaA.d +++ /dev/null @@ -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; -} -} - diff --git a/lphobos/internal/adi.d b/lphobos/internal/adi.d deleted file mode 100644 index 617ac6fe9a0..00000000000 --- a/lphobos/internal/adi.d +++ /dev/null @@ -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); -} diff --git a/lphobos/internal/arrays.d b/lphobos/internal/arrays.d deleted file mode 100644 index db9120a3f44..00000000000 --- a/lphobos/internal/arrays.d +++ /dev/null @@ -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)]; - } -} diff --git a/lphobos/internal/cast.d b/lphobos/internal/cast.d deleted file mode 100644 index 29ebd234ff7..00000000000 --- a/lphobos/internal/cast.d +++ /dev/null @@ -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); -} diff --git a/lphobos/internal/contract.d b/lphobos/internal/contract.d deleted file mode 100644 index 2920d434200..00000000000 --- a/lphobos/internal/contract.d +++ /dev/null @@ -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~"\""); -} diff --git a/lphobos/internal/critical.d b/lphobos/internal/critical.d deleted file mode 100644 index 464c93751a3..00000000000 --- a/lphobos/internal/critical.d +++ /dev/null @@ -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() { } diff --git a/lphobos/internal/dmain2.d b/lphobos/internal/dmain2.d deleted file mode 100644 index d5d9dfa247f..00000000000 --- a/lphobos/internal/dmain2.d +++ /dev/null @@ -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; -} - diff --git a/lphobos/internal/eh.d b/lphobos/internal/eh.d deleted file mode 100644 index a6fca4ace62..00000000000 --- a/lphobos/internal/eh.d +++ /dev/null @@ -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); -} diff --git a/lphobos/internal/mem.d b/lphobos/internal/mem.d deleted file mode 100644 index 7b851634a62..00000000000 --- a/lphobos/internal/mem.d +++ /dev/null @@ -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); -} diff --git a/lphobos/internal/objectimpl.d b/lphobos/internal/objectimpl.d deleted file mode 100644 index 6efbe19db0d..00000000000 --- a/lphobos/internal/objectimpl.d +++ /dev/null @@ -1,1202 +0,0 @@ - -/** - * Part of the D programming language runtime library. - * Forms the symbols available to all D programs. Includes - * Object, which is the root of the class object hierarchy. - * - * This module is implicitly imported. - * Macros: - * WIKI = Phobos/Object - */ - -/* - * 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. - */ - -/* - * This copy is modified to work with LDC - * by Tomas Lindquist Olsen, September 2007 - */ - -module object; - -import std.outofmemory; - -/** - * An unsigned integral type large enough to span the memory space. Use for - * array indices and pointer offsets for maximal portability to - * architectures that have different memory address ranges. This is - * analogous to C's size_t. - */ -alias typeof(int.sizeof) size_t; - -/** - * A signed integral type large enough to span the memory space. Use for - * pointer differences and for size_t differences for maximal portability to - * architectures that have different memory address ranges. This is - * analogous to C's ptrdiff_t. - */ -alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; - -alias size_t hash_t; - -extern (C) -{ /// C's printf function. - int printf(char *, ...); - void trace_term(); - - int memcmp(void *, void *, size_t); - void* memcpy(void *, void *, size_t); - void* calloc(size_t, size_t); - void* realloc(void*, size_t); - void free(void*); - - //Object _d_newclass(ClassInfo ci); -} - -/// Standard boolean type. -alias bool bit; - -alias char[] string; -alias wchar[] wstring; -alias dchar[] dstring; - -/+ - -/* ************************* - * Internal struct pointed to by the hidden .monitor member. - */ -struct Monitor -{ - void delegate(Object)[] delegates; - - /* More stuff goes here defined by internal/monitor.c */ -} - -+/ - -/****************** - * All D class objects inherit from Object. - */ -class Object -{ - void print() - { - char[] s = toString(); - printf("%.*s\n", s.length, s.ptr); - } - - /** - * Convert Object to a human readable string. - */ - char[] toString() - { - return this.classinfo.name; - } - - /** - * Compute hash function for Object. - */ - hash_t toHash() - { - // BUG: this prevents a compacting GC from working, needs to be fixed - return cast(hash_t)cast(void *)this; - } - - /** - * Compare with another Object obj. - * Returns: - * $(TABLE - * $(TR $(TD this < obj) $(TD < 0)) - * $(TR $(TD this == obj) $(TD 0)) - * $(TR $(TD this > obj) $(TD > 0)) - * ) - */ - int opCmp(Object o) - { - // BUG: this prevents a compacting GC from working, needs to be fixed - //return cast(int)cast(void *)this - cast(int)cast(void *)o; - - throw new Error("need opCmp for class " ~ this.classinfo.name); - } - - /** - * Returns !=0 if this object does have the same contents as obj. - */ - int opEquals(Object o) - { - return cast(int)(this is o); - } - - /* ** - * Call delegate dg, passing this to it, when this object gets destroyed. - * Use extreme caution, as the list of delegates is stored in a place - * not known to the gc. Thus, if any objects pointed to by one of these - * delegates gets freed by the gc, calling the delegate will cause a - * crash. - * This is only for use by library developers, as it will need to be - * redone if weak pointers are added or a moving gc is developed. - */ - final void notifyRegister(void delegate(Object) dg) - { - /+ - //printf("notifyRegister(dg = %llx, o = %p)\n", dg, this); - synchronized (this) - { - Monitor* m = cast(Monitor*)(cast(void**)this)[1]; - foreach (inout x; m.delegates) - { - if (!x || x == dg) - { x = dg; - return; - } - } - - // Increase size of delegates[] - auto len = m.delegates.length; - auto startlen = len; - if (len == 0) - { - len = 4; - auto p = calloc((void delegate(Object)).sizeof, len); - if (!p) - _d_OutOfMemory(); - m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; - } - else - { - len += len + 4; - auto p = realloc(m.delegates.ptr, (void delegate(Object)).sizeof * len); - if (!p) - _d_OutOfMemory(); - m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; - m.delegates[startlen .. len] = null; - } - m.delegates[startlen] = dg; - } - +/ - } - - /* ** - * Remove delegate dg from the notify list. - * This is only for use by library developers, as it will need to be - * redone if weak pointers are added or a moving gc is developed. - */ - final void notifyUnRegister(void delegate(Object) dg) - { - /+ - synchronized (this) - { - Monitor* m = cast(Monitor*)(cast(void**)this)[1]; - foreach (inout x; m.delegates) - { - if (x == dg) - x = null; - } - } - +/ - } - - /****** - * Create instance of class specified by classname. - * The class must either have no constructors or have - * a default constructor. - * Returns: - * null if failed - */ - static Object factory(char[] classname) - { - /+ - auto ci = ClassInfo.find(classname); - if (ci) - { - return ci.create(); - } - +/ - return null; - } -} - -/+ -extern (C) void _d_notify_release(Object o) -{ - //printf("_d_notify_release(o = %p)\n", o); - Monitor* m = cast(Monitor*)(cast(void**)o)[1]; - if (m.delegates.length) - { - auto dgs = m.delegates; - synchronized (o) - { - dgs = m.delegates; - m.delegates = null; - } - - foreach (dg; dgs) - { - if (dg) - { //printf("calling dg = %llx (%p)\n", dg, o); - dg(o); - } - } - - free(dgs.ptr); - } -} - -+/ - -/** - * Information about an interface. - * A pointer to this appears as the first entry in the interface's vtbl[]. - */ -struct Interface -{ - ClassInfo classinfo; /// .classinfo for this interface (not for containing class) - void *[] vtbl; - int offset; /// offset to Interface 'this' from Object 'this' -} - -import std.moduleinit; - -/** - * Runtime type information about a class. Can be retrieved for any class type - * or instance by using the .classinfo property. - * A pointer to this appears as the first entry in the class's vtbl[]. - */ -class ClassInfo : Object -{ - byte[] init; /** class static initializer - * (init.length gives size in bytes of class) - */ - char[] name; /// class name - void *[] vtbl; /// virtual function pointer table - Interface[] interfaces; /// interfaces this class implements - ClassInfo base; /// base class - void *destructor; - void function(Object) classInvariant; - uint flags; - // 1: // IUnknown - // 2: // has no possible pointers into GC memory - // 4: // has offTi[] member - // 8: // has constructors - void *deallocator; - OffsetTypeInfo[] offTi; - void function(Object) defaultConstructor; // default Constructor - - /************* - * Search all modules for ClassInfo corresponding to classname. - * Returns: null if not found - */ - static ClassInfo find(char[] classname) - { - /+foreach (m; ModuleInfo.modules()) - { - //writefln("module %s, %d", m.name, m.localClasses.length); - foreach (c; m.localClasses) - { - //writefln("\tclass %s", c.name); - if (c.name == classname) - return c; - } - }+/ - return null; - } - - /******************** - * Create instance of Object represented by 'this'. - */ - Object create() - { - /+if (flags & 8 && !defaultConstructor) - return null; - Object o = _d_newclass(this); - if (flags & 8 && defaultConstructor) - { - defaultConstructor(o); - } - return o; - +/ - return null; - } -} - -//private import std.string; - - -/** - * Array of pairs giving the offset and type information for each - * member in an aggregate. - */ -struct OffsetTypeInfo -{ - size_t offset; /// Offset of member from start of object - TypeInfo ti; /// TypeInfo for this member -} - -private int string_cmp(char[] s1, char[] s2) -{ - auto len = s1.length; - if (s2.length < len) - len = s2.length; - int result = memcmp(s1.ptr, s2.ptr, len); - if (result == 0) - result = cast(int)(cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length); - return result; -} - -/** - * Runtime type information about a type. - * Can be retrieved for any type using a - * TypeidExpression. - */ -class TypeInfo -{ - hash_t toHash() - { hash_t hash; - - foreach (char c; this.toString()) - hash = hash * 9 + c; - return hash; - } - - int opCmp(Object o) - { - if (this is o) - return 0; - TypeInfo ti = cast(TypeInfo)o; - if (ti is null) - return 1; - return string_cmp(this.toString(), ti.toString()); - } - - int opEquals(Object o) - { - /* TypeInfo instances are singletons, but duplicates can exist - * across DLL's. Therefore, comparing for a name match is - * sufficient. - */ - if (this is o) - return 1; - TypeInfo ti = cast(TypeInfo)o; - return cast(int)(ti && this.toString() == ti.toString()); - } - - /// Returns a hash of the instance of a type. - hash_t getHash(void *p) { return cast(uint)p; } - - /// Compares two instances for equality. - int equals(void *p1, void *p2) { return cast(int)(p1 == p2); } - - /// Compares two instances for <, ==, or >. - int compare(void *p1, void *p2) { return 0; } - - /// Returns size of the type. - size_t tsize() { return 0; } - - /// Swaps two instances of the type. - void swap(void *p1, void *p2) - { - size_t n = tsize(); - for (size_t i = 0; i < n; i++) - { byte t; - - t = (cast(byte *)p1)[i]; - (cast(byte *)p1)[i] = (cast(byte *)p2)[i]; - (cast(byte *)p2)[i] = t; - } - } - - /// Get TypeInfo for 'next' type, as defined by what kind of type this is, - /// null if none. - TypeInfo next() { return null; } - - /// Return default initializer, null if default initialize to 0 - void[] init() { return null; } - - /// Get flags for type: 1 means GC should scan for pointers - uint flags() { return 0; } - - /// Get type information on the contents of the type; null if not available - OffsetTypeInfo[] offTi() { return null; } -} - -class TypeInfo_Typedef : TypeInfo -{ - char[] toString() { return name; } - - int opEquals(Object o) - { TypeInfo_Typedef c; - - return cast(int) - (this is o || - ((c = cast(TypeInfo_Typedef)o) !is null && - this.name == c.name && - this.base == c.base)); - } - - hash_t getHash(void *p) { return base.getHash(p); } - int equals(void *p1, void *p2) { return base.equals(p1, p2); } - int compare(void *p1, void *p2) { return base.compare(p1, p2); } - size_t tsize() { return base.tsize(); } - void swap(void *p1, void *p2) { return base.swap(p1, p2); } - - TypeInfo next() { return base; } - uint flags() { return base.flags(); } - void[] init() { return m_init.length ? m_init : base.init(); } - - TypeInfo base; - char[] name; - void[] m_init; -} - -class TypeInfo_Enum : TypeInfo_Typedef -{ -} - -class TypeInfo_Pointer : TypeInfo -{ - char[] toString() { return m_next.toString() ~ "*"; } - - int opEquals(Object o) - { TypeInfo_Pointer c; - - return this is o || - ((c = cast(TypeInfo_Pointer)o) !is null && - this.m_next == c.m_next); - } - - hash_t getHash(void *p) - { - return cast(uint)*cast(void* *)p; - } - - int equals(void *p1, void *p2) - { - return cast(int)(*cast(void* *)p1 == *cast(void* *)p2); - } - - int compare(void *p1, void *p2) - { - if (*cast(void* *)p1 < *cast(void* *)p2) - return -1; - else if (*cast(void* *)p1 > *cast(void* *)p2) - return 1; - else - return 0; - } - - size_t tsize() - { - return (void*).sizeof; - } - - void swap(void *p1, void *p2) - { void* tmp; - tmp = *cast(void**)p1; - *cast(void**)p1 = *cast(void**)p2; - *cast(void**)p2 = tmp; - } - - TypeInfo next() { return m_next; } - uint flags() { return 1; } - - TypeInfo m_next; -} - -class TypeInfo_Array : TypeInfo -{ - char[] toString() { return value.toString() ~ "[]"; } - - int opEquals(Object o) - { TypeInfo_Array c; - - return cast(int) - (this is o || - ((c = cast(TypeInfo_Array)o) !is null && - this.value == c.value)); - } - - hash_t getHash(void *p) - { size_t sz = value.tsize(); - hash_t hash = 0; - void[] a = *cast(void[]*)p; - for (size_t i = 0; i < a.length; i++) - hash += value.getHash(a.ptr + i * sz); - return hash; - } - - int equals(void *p1, void *p2) - { - void[] a1 = *cast(void[]*)p1; - void[] a2 = *cast(void[]*)p2; - if (a1.length != a2.length) - return 0; - size_t sz = value.tsize(); - for (size_t i = 0; i < a1.length; i++) - { - if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) - return 0; - } - return 1; - } - - int compare(void *p1, void *p2) - { - void[] a1 = *cast(void[]*)p1; - void[] a2 = *cast(void[]*)p2; - size_t sz = value.tsize(); - size_t len = a1.length; - - if (a2.length < len) - len = a2.length; - for (size_t u = 0; u < len; u++) - { - int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); - if (result) - return result; - } - return cast(int)a1.length - cast(int)a2.length; - } - - size_t tsize() - { - return (void[]).sizeof; - } - - void swap(void *p1, void *p2) - { void[] tmp; - tmp = *cast(void[]*)p1; - *cast(void[]*)p1 = *cast(void[]*)p2; - *cast(void[]*)p2 = tmp; - } - - TypeInfo value; - - TypeInfo next() - { - return value; - } - - uint flags() { return 1; } -} - -private const char[10] digits = "0123456789"; /// 0..9 - -private char[] lengthToString(uint u) -{ char[uint.sizeof * 3] buffer = void; - int ndigits; - char[] result; - - ndigits = 0; - if (u < 10) - // Avoid storage allocation for simple stuff - result = digits[u .. u + 1]; - else - { - while (u) - { - uint c = (u % 10) + '0'; - u /= 10; - ndigits++; - buffer[buffer.length - ndigits] = cast(char)c; - } - result = new char[ndigits]; - result[] = buffer[buffer.length - ndigits .. buffer.length]; - } - return result; -} - -private char[] lengthToString(ulong u) -{ char[ulong.sizeof * 3] buffer; - int ndigits; - char[] result; - - if (u < 0x1_0000_0000) - return lengthToString(cast(uint)u); - ndigits = 0; - while (u) - { - char c = cast(char)((u % 10) + '0'); - u /= 10; - ndigits++; - buffer[buffer.length - ndigits] = c; - } - result = new char[ndigits]; - result[] = buffer[buffer.length - ndigits .. buffer.length]; - return result; -} - -class TypeInfo_StaticArray : TypeInfo -{ - char[] toString() - { - return value.toString() ~ "[" ~ lengthToString(len) ~ "]"; - } - - int opEquals(Object o) - { TypeInfo_StaticArray c; - - return cast(int) - (this is o || - ((c = cast(TypeInfo_StaticArray)o) !is null && - this.len == c.len && - this.value == c.value)); - } - - hash_t getHash(void *p) - { size_t sz = value.tsize(); - hash_t hash = 0; - for (size_t i = 0; i < len; i++) - hash += value.getHash(p + i * sz); - return hash; - } - - int equals(void *p1, void *p2) - { - size_t sz = value.tsize(); - - for (size_t u = 0; u < len; u++) - { - if (!value.equals(p1 + u * sz, p2 + u * sz)) - return 0; - } - return 1; - } - - int compare(void *p1, void *p2) - { - size_t sz = value.tsize(); - - for (size_t u = 0; u < len; u++) - { - int result = value.compare(p1 + u * sz, p2 + u * sz); - if (result) - return result; - } - return 0; - } - - size_t tsize() - { - return len * value.tsize(); - } - - void swap(void *p1, void *p2) - { void* tmp; - size_t sz = value.tsize(); - ubyte[16] buffer; - void* pbuffer; - - if (sz < buffer.sizeof) - tmp = buffer.ptr; - else { - if (value.flags() & 1) - tmp = pbuffer = (new void[sz]).ptr; - else - tmp = pbuffer = (new byte[sz]).ptr; - } - - for (size_t u = 0; u < len; u += sz) - { size_t o = u * sz; - memcpy(tmp, p1 + o, sz); - memcpy(p1 + o, p2 + o, sz); - memcpy(p2 + o, tmp, sz); - } - if (pbuffer) - delete pbuffer; - } - - void[] init() { return value.init(); } - TypeInfo next() { return value; } - uint flags() { return value.flags(); } - - TypeInfo value; - size_t len; -} - -class TypeInfo_AssociativeArray : TypeInfo -{ - char[] toString() - { - return value.toString() ~ "[" ~ key.toString() ~ "]"; - } - - int opEquals(Object o) - { TypeInfo_AssociativeArray c; - - return this is o || - ((c = cast(TypeInfo_AssociativeArray)o) !is null && - this.key == c.key && - this.value == c.value); - } - - // BUG: need to add the rest of the functions - - size_t tsize() - { - return (char[int]).sizeof; - } - - TypeInfo next() { return value; } - uint flags() { return 1; } - - TypeInfo value; - TypeInfo key; -} - -class TypeInfo_Function : TypeInfo -{ - char[] toString() - { - return next.toString() ~ "()"; - } - - int opEquals(Object o) - { TypeInfo_Function c; - - return this is o || - ((c = cast(TypeInfo_Function)o) !is null && - this.next == c.next); - } - - // BUG: need to add the rest of the functions - - size_t tsize() - { - return 0; // no size for functions - } - - TypeInfo next; -} - -class TypeInfo_Delegate : TypeInfo -{ - char[] toString() - { - return next.toString() ~ " delegate()"; - } - - int opEquals(Object o) - { TypeInfo_Delegate c; - - return this is o || - ((c = cast(TypeInfo_Delegate)o) !is null && - this.next == c.next); - } - - // BUG: need to add the rest of the functions - - size_t tsize() - { alias int delegate() dg; - return dg.sizeof; - } - - uint flags() { return 1; } - - TypeInfo next; -} - -class TypeInfo_Class : TypeInfo -{ - char[] toString() { return info.name; } - - int opEquals(Object o) - { TypeInfo_Class c; - - return this is o || - ((c = cast(TypeInfo_Class)o) !is null && - this.info.name == c.classinfo.name); - } - - hash_t getHash(void *p) - { - Object o = *cast(Object*)p; - assert(o); - return o.toHash(); - } - - int equals(void *p1, void *p2) - { - Object o1 = *cast(Object*)p1; - Object o2 = *cast(Object*)p2; - - return (o1 is o2) || (o1 && o1.opEquals(o2)); - } - - int compare(void *p1, void *p2) - { - Object o1 = *cast(Object*)p1; - Object o2 = *cast(Object*)p2; - int c = 0; - - // Regard null references as always being "less than" - if (o1 !is o2) - { - if (o1) - { if (!o2) - c = 1; - else - c = o1.opCmp(o2); - } - else - c = -1; - } - return c; - } - - size_t tsize() - { - return Object.sizeof; - } - - uint flags() { return 1; } - - OffsetTypeInfo[] offTi() - { - return (info.flags & 4) ? info.offTi : null; - } - - ClassInfo info; -} - -class TypeInfo_Interface : TypeInfo -{ - char[] toString() { return info.name; } - - int opEquals(Object o) - { TypeInfo_Interface c; - - return this is o || - ((c = cast(TypeInfo_Interface)o) !is null && - this.info.name == c.classinfo.name); - } - - hash_t getHash(void *p) - { - Interface* pi = **cast(Interface ***)*cast(void**)p; - Object o = cast(Object)(*cast(void**)p - pi.offset); - assert(o); - return o.toHash(); - } - - int equals(void *p1, void *p2) - { - Interface* pi = **cast(Interface ***)*cast(void**)p1; - Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); - pi = **cast(Interface ***)*cast(void**)p2; - Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); - - return o1 == o2 || (o1 && o1.opCmp(o2) == 0); - } - - int compare(void *p1, void *p2) - { - Interface* pi = **cast(Interface ***)*cast(void**)p1; - Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); - pi = **cast(Interface ***)*cast(void**)p2; - Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); - int c = 0; - - // Regard null references as always being "less than" - if (o1 != o2) - { - if (o1) - { if (!o2) - c = 1; - else - c = o1.opCmp(o2); - } - else - c = -1; - } - return c; - } - - size_t tsize() - { - return Object.sizeof; - } - - uint flags() { return 1; } - - ClassInfo info; -} - -class TypeInfo_Struct : TypeInfo -{ - char[] toString() { return name; } - - int opEquals(Object o) - { TypeInfo_Struct s; - - return this is o || - ((s = cast(TypeInfo_Struct)o) !is null && - this.name == s.name && - this.init.length == s.init.length); - } - - hash_t getHash(void *p) - { hash_t h; - - assert(p); - if (xtoHash) - { //printf("getHash() using xtoHash\n"); - h = (*xtoHash)(p); - } - else - { - //printf("getHash() using default hash\n"); - // A sorry hash algorithm. - // Should use the one for strings. - // BUG: relies on the GC not moving objects - for (size_t i = 0; i < init.length; i++) - { h = h * 9 + *cast(ubyte*)p; - p++; - } - } - return h; - } - - int equals(void *p1, void *p2) - { int c; - - if (p1 == p2) - c = 1; - else if (!p1 || !p2) - c = 0; - else if (xopEquals) - c = (*xopEquals)(p1, p2); - else - // BUG: relies on the GC not moving objects - c = (memcmp(p1, p2, init.length) == 0); - return c; - } - - int compare(void *p1, void *p2) - { - int c = 0; - - // Regard null references as always being "less than" - if (p1 != p2) - { - if (p1) - { if (!p2) - c = 1; - else if (xopCmp) - c = (*xopCmp)(p1, p2); - else - // BUG: relies on the GC not moving objects - c = memcmp(p1, p2, init.length); - } - else - c = -1; - } - return c; - } - - size_t tsize() - { - return init.length; - } - - void[] init() { return m_init; } - - uint flags() { return m_flags; } - - char[] name; - void[] m_init; // initializer; init.ptr == null if 0 initialize - - hash_t 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; - - char[] toString() - { - char[] s; - s = "("; - foreach (i, element; elements) - { - if (i) - s ~= ','; - s ~= element.toString(); - } - s ~= ")"; - return s; - } - - int opEquals(Object o) - { - if (this is o) - return 1; - - auto t = cast(TypeInfo_Tuple)o; - if (t && elements.length == t.elements.length) - { - for (size_t i = 0; i < elements.length; i++) - { - if (elements[i] != t.elements[i]) - return 0; - } - return 1; - } - return 0; - } - - hash_t getHash(void *p) - { - assert(0); - } - - int equals(void *p1, void *p2) - { - assert(0); - } - - int compare(void *p1, void *p2) - { - assert(0); - } - - size_t tsize() - { - assert(0); - } - - void swap(void *p1, void *p2) - { - assert(0); - } -} - -class TypeInfo_Const : TypeInfo -{ - char[] toString() { return "const " ~ base.toString(); } - - int opEquals(Object o) { return base.opEquals(o); } - hash_t getHash(void *p) { return base.getHash(p); } - int equals(void *p1, void *p2) { return base.equals(p1, p2); } - int compare(void *p1, void *p2) { return base.compare(p1, p2); } - size_t tsize() { return base.tsize(); } - void swap(void *p1, void *p2) { return base.swap(p1, p2); } - - TypeInfo next() { return base.next(); } - uint flags() { return base.flags(); } - void[] init() { return base.init(); } - - TypeInfo base; -} - -class TypeInfo_Invariant : TypeInfo_Const -{ - char[] toString() { return "invariant " ~ base.toString(); } -} - -/** - * Information about each module. - */ -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) dg) { - foreach (ref mod; std.moduleinit._moduleinfo_array) - if (auto i = dg(mod)) return i; - return 0; - } -} - -struct ModuleReference -{ - ModuleReference* next; - ModuleInfo mod; -} -extern(C) ModuleReference* _Dmodule_ref; - -/** - * All recoverable exceptions should be derived from class Exception. - */ -class Exception : Object -{ - char[] msg; - - /** - * Constructor; msg is a descriptive message for the exception. - */ - this(char[] msg) - { - this.msg = msg; - } - - void print() - { - char[] s = toString(); - printf("%.*s\n", s.length, s.ptr); - } - - char[] toString() { return msg; } -} - -/** - * All irrecoverable exceptions should be derived from class Error. - */ -class Error : Exception -{ - Error next; - - /** - * Constructor; msg is a descriptive message for the exception. - */ - this(char[] msg) - { - super(msg); - } - - this(char[] msg, Error next) - { - super(msg); - this.next = next; - } -} - -//extern (C) int nullext = 0; diff --git a/lphobos/internal/qsort2.d b/lphobos/internal/qsort2.d deleted file mode 100644 index ee3ad31dcac..00000000000 --- a/lphobos/internal/qsort2.d +++ /dev/null @@ -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]); - } -} - diff --git a/lphobos/internal/switch.d b/lphobos/internal/switch.d deleted file mode 100644 index 6e95b61ebc1..00000000000 --- a/lphobos/internal/switch.d +++ /dev/null @@ -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"); -} diff --git a/lphobos/ldc-build b/lphobos/ldc-build deleted file mode 100755 index cce9ecddf73..00000000000 --- a/lphobos/ldc-build +++ /dev/null @@ -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 diff --git a/lphobos/ldc.conf b/lphobos/ldc.conf deleted file mode 100644 index 4b7a9094256..00000000000 --- a/lphobos/ldc.conf +++ /dev/null @@ -1,5 +0,0 @@ - -[Environment] - -DFLAGS=-I%@P%/../lphobos -I%@P%/../import -L-L%@P%/../lib -# -R%@P%/../lib diff --git a/lphobos/llvm/intrinsic.d b/lphobos/llvm/intrinsic.d deleted file mode 100644 index 285f3094c71..00000000000 --- a/lphobos/llvm/intrinsic.d +++ /dev/null @@ -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* , i8 , i8 ) -pragma(intrinsic, "llvm.atomic.lcs.i8.i8p.i8.i8") - ubyte llvm_atomic_lcs_i8(void* ptr, ubyte cmp, ubyte val); - -declare i16 @llvm.atomic.lcs.i16.i16p.i16.i16( i16* , i16 , i16 ) -declare i32 @llvm.atomic.lcs.i32.i32p.i32.i32( i32* , i32 , i32 ) -declare i64 @llvm.atomic.lcs.i64.i64p.i64.i64( i64* , i64 , i64 ) - -declare i8 @llvm.atomic.ls.i8.i8p.i8( i8* , i8 ) -declare i16 @llvm.atomic.ls.i16.i16p.i16( i16* , i16 ) -declare i32 @llvm.atomic.ls.i32.i32p.i32( i32* , i32 ) -declare i64 @llvm.atomic.ls.i64.i64p.i64( i64* , i64 ) - -declare i8 @llvm.atomic.las.i8.i8p.i8( i8* , i8 ) -declare i16 @llvm.atomic.las.i16.i16p.i16( i16* , i16 ) -declare i32 @llvm.atomic.las.i32.i32p.i32( i32* , i32 ) -declare i64 @llvm.atomic.las.i64.i64p.i64( i64* , i64 ) - -declare i8 @llvm.atomic.lss.i8.i8.i8( i8* , i8 ) -declare i16 @llvm.atomic.lss.i16.i16.i16( i16* , i16 ) -declare i32 @llvm.atomic.lss.i32.i32.i32( i32* , i32 ) -declare i64 @llvm.atomic.lss.i64.i64.i64( i64* , i64 ) - -declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 ) -*/ diff --git a/lphobos/llvm/va_list.d b/lphobos/llvm/va_list.d deleted file mode 100644 index f2c6ca2e7d4..00000000000 --- a/lphobos/llvm/va_list.d +++ /dev/null @@ -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"); - -*/ diff --git a/lphobos/llvmsupport.d b/lphobos/llvmsupport.d deleted file mode 100644 index 4d9c7a1762d..00000000000 --- a/lphobos/llvmsupport.d +++ /dev/null @@ -1,5 +0,0 @@ -module llvmsupport; - -import -llvm.intrinsic, -llvm.va_list; diff --git a/lphobos/object.d b/lphobos/object.d deleted file mode 100644 index 15bcef15171..00000000000 --- a/lphobos/object.d +++ /dev/null @@ -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); -} - diff --git a/lphobos/phobos.d b/lphobos/phobos.d deleted file mode 100644 index 53a86a90c68..00000000000 --- a/lphobos/phobos.d +++ /dev/null @@ -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; -} diff --git a/lphobos/std/array.d b/lphobos/std/array.d deleted file mode 100644 index c3af5e44adb..00000000000 --- a/lphobos/std/array.d +++ /dev/null @@ -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; -} diff --git a/lphobos/std/base64.d b/lphobos/std/base64.d deleted file mode 100644 index a907374dc6f..00000000000 --- a/lphobos/std/base64.d +++ /dev/null @@ -1,293 +0,0 @@ -/** - * Encodes/decodes MIME base64 data. - * - * Macros: - * WIKI=Phobos/StdBase64 - * References: - * Wikipedia Base64$(BR) - * RFC 2045$(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!"); -} - diff --git a/lphobos/std/bitarray.d b/lphobos/std/bitarray.d deleted file mode 100644 index 19e135c3939..00000000000 --- a/lphobos/std/bitarray.d +++ /dev/null @@ -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); - } -} diff --git a/lphobos/std/c/fenv.d b/lphobos/std/c/fenv.d deleted file mode 100644 index 45ee8ce0888..00000000000 --- a/lphobos/std/c/fenv.d +++ /dev/null @@ -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); /// - diff --git a/lphobos/std/c/linux/linux.d b/lphobos/std/c/linux/linux.d deleted file mode 100644 index ba9bc44c2ad..00000000000 --- a/lphobos/std/c/linux/linux.d +++ /dev/null @@ -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 and - -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 - * 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 - */ - - 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); -} diff --git a/lphobos/std/c/linux/linuxextern.d b/lphobos/std/c/linux/linuxextern.d deleted file mode 100644 index 08efcc13683..00000000000 --- a/lphobos/std/c/linux/linuxextern.d +++ /dev/null @@ -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; -} - diff --git a/lphobos/std/c/linux/pthread.d b/lphobos/std/c/linux/pthread.d deleted file mode 100644 index 06fd4a7b38d..00000000000 --- a/lphobos/std/c/linux/pthread.d +++ /dev/null @@ -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); -} - diff --git a/lphobos/std/c/linux/socket.d b/lphobos/std/c/linux/socket.d deleted file mode 100644 index 642e5d98f1f..00000000000 --- a/lphobos/std/c/linux/socket.d +++ /dev/null @@ -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]; - } -} - diff --git a/lphobos/std/c/locale.d b/lphobos/std/c/locale.d deleted file mode 100644 index 4739de5be1e..00000000000 --- a/lphobos/std/c/locale.d +++ /dev/null @@ -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(); - diff --git a/lphobos/std/c/math.d b/lphobos/std/c/math.d deleted file mode 100644 index 270b6271dec..00000000000 --- a/lphobos/std/c/math.d +++ /dev/null @@ -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); } - diff --git a/lphobos/std/c/process.d b/lphobos/std/c/process.d deleted file mode 100644 index 018c6eedced..00000000000 --- a/lphobos/std/c/process.d +++ /dev/null @@ -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 **); -} - - diff --git a/lphobos/std/c/stdarg.d b/lphobos/std/c/stdarg.d deleted file mode 100644 index 1cba7acaa63..00000000000 --- a/lphobos/std/c/stdarg.d +++ /dev/null @@ -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); diff --git a/lphobos/std/c/stddef.d b/lphobos/std/c/stddef.d deleted file mode 100644 index a9699071956..00000000000 --- a/lphobos/std/c/stddef.d +++ /dev/null @@ -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); -} diff --git a/lphobos/std/c/stdio.d b/lphobos/std/c/stdio.d deleted file mode 100644 index 90d36a6df9b..00000000000 --- a/lphobos/std/c/stdio.d +++ /dev/null @@ -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); /// diff --git a/lphobos/std/c/stdlib.d b/lphobos/std/c/stdlib.d deleted file mode 100644 index 8032f179c4b..00000000000 --- a/lphobos/std/c/stdlib.d +++ /dev/null @@ -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 diff --git a/lphobos/std/c/string.d b/lphobos/std/c/string.d deleted file mode 100644 index ce0a53be4ad..00000000000 --- a/lphobos/std/c/string.d +++ /dev/null @@ -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); /// -} diff --git a/lphobos/std/c/time.d b/lphobos/std/c/time.d deleted file mode 100644 index 857283c1604..00000000000 --- a/lphobos/std/c/time.d +++ /dev/null @@ -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 *); diff --git a/lphobos/std/c/windows/com.d b/lphobos/std/c/windows/com.d deleted file mode 100644 index 50547dd14f4..00000000000 --- a/lphobos/std/c/windows/com.d +++ /dev/null @@ -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 -} - -} diff --git a/lphobos/std/c/windows/stat.d b/lphobos/std/c/windows/stat.d deleted file mode 100644 index daada90d42f..00000000000 --- a/lphobos/std/c/windows/stat.d +++ /dev/null @@ -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 *); -} diff --git a/lphobos/std/c/windows/windows.d b/lphobos/std/c/windows/windows.d deleted file mode 100644 index e9d054f321c..00000000000 --- a/lphobos/std/c/windows/windows.d +++ /dev/null @@ -1,2722 +0,0 @@ - -/* Windows is a registered trademark of Microsoft Corporation in the United -States and other countries. */ - -module std.c.windows.windows; - -version (Windows) -{ -} -else -{ - static assert(0); // Windows only -} - -extern (Windows) -{ - alias uint ULONG; - alias ULONG *PULONG; - alias ushort USHORT; - alias USHORT *PUSHORT; - alias ubyte UCHAR; - alias UCHAR *PUCHAR; - alias char *PSZ; - alias wchar WCHAR; - - alias void VOID; - alias char CHAR; - alias short SHORT; - alias int LONG; - alias CHAR *LPSTR; - alias CHAR *PSTR; - alias CHAR *LPCSTR; - alias CHAR *PCSTR; - alias LPSTR LPTCH, PTCH; - alias LPSTR PTSTR, LPTSTR; - alias LPCSTR LPCTSTR; - - alias WCHAR* LPWSTR, LPCWSTR, PCWSTR; - - alias uint DWORD; - alias int BOOL; - alias ubyte BYTE; - alias ushort WORD; - alias float FLOAT; - alias FLOAT *PFLOAT; - alias BOOL *PBOOL; - alias BOOL *LPBOOL; - alias BYTE *PBYTE; - alias BYTE *LPBYTE; - alias int *PINT; - alias int *LPINT; - alias WORD *PWORD; - alias WORD *LPWORD; - alias int *LPLONG; - alias DWORD *PDWORD; - alias DWORD *LPDWORD; - alias void *LPVOID; - alias void *LPCVOID; - - alias int INT; - alias uint UINT; - alias uint *PUINT; - - typedef void *HANDLE; - alias void *PVOID; - alias HANDLE HGLOBAL; - alias HANDLE HLOCAL; - alias LONG HRESULT; - alias LONG SCODE; - alias HANDLE HINSTANCE; - alias HINSTANCE HMODULE; - alias HANDLE HWND; - - alias HANDLE HGDIOBJ; - alias HANDLE HACCEL; - alias HANDLE HBITMAP; - alias HANDLE HBRUSH; - alias HANDLE HCOLORSPACE; - alias HANDLE HDC; - alias HANDLE HGLRC; - alias HANDLE HDESK; - alias HANDLE HENHMETAFILE; - alias HANDLE HFONT; - alias HANDLE HICON; - alias HANDLE HMENU; - alias HANDLE HMETAFILE; - alias HANDLE HPALETTE; - alias HANDLE HPEN; - alias HANDLE HRGN; - alias HANDLE HRSRC; - alias HANDLE HSTR; - alias HANDLE HTASK; - alias HANDLE HWINSTA; - alias HANDLE HKL; - alias HICON HCURSOR; - - alias HANDLE HKEY; - alias HKEY *PHKEY; - alias DWORD ACCESS_MASK; - alias ACCESS_MASK *PACCESS_MASK; - alias ACCESS_MASK REGSAM; - - alias int (*FARPROC)(); - - alias UINT WPARAM; - alias LONG LPARAM; - alias LONG LRESULT; - - alias DWORD COLORREF; - alias DWORD *LPCOLORREF; - alias WORD ATOM; - -version (0) -{ // Properly prototyped versions - alias BOOL function(HWND, UINT, WPARAM, LPARAM) DLGPROC; - alias VOID function(HWND, UINT, UINT, DWORD) TIMERPROC; - alias BOOL function(HDC, LPARAM, int) GRAYSTRINGPROC; - alias BOOL function(HWND, LPARAM) WNDENUMPROC; - alias LRESULT function(int code, WPARAM wParam, LPARAM lParam) HOOKPROC; - alias VOID function(HWND, UINT, DWORD, LRESULT) SENDASYNCPROC; - alias BOOL function(HWND, LPCSTR, HANDLE) PROPENUMPROCA; - alias BOOL function(HWND, LPCWSTR, HANDLE) PROPENUMPROCW; - alias BOOL function(HWND, LPSTR, HANDLE, DWORD) PROPENUMPROCEXA; - alias BOOL function(HWND, LPWSTR, HANDLE, DWORD) PROPENUMPROCEXW; - alias int function(LPSTR lpch, int ichCurrent, int cch, int code) - EDITWORDBREAKPROCA; - alias int function(LPWSTR lpch, int ichCurrent, int cch, int code) - EDITWORDBREAKPROCW; - alias BOOL function(HDC hdc, LPARAM lData, WPARAM wData, int cx, int cy) - DRAWSTATEPROC; -} -else -{ - alias FARPROC DLGPROC; - alias FARPROC TIMERPROC; - alias FARPROC GRAYSTRINGPROC; - alias FARPROC WNDENUMPROC; - alias FARPROC HOOKPROC; - alias FARPROC SENDASYNCPROC; - alias FARPROC EDITWORDBREAKPROCA; - alias FARPROC EDITWORDBREAKPROCW; - alias FARPROC PROPENUMPROCA; - alias FARPROC PROPENUMPROCW; - alias FARPROC PROPENUMPROCEXA; - alias FARPROC PROPENUMPROCEXW; - alias FARPROC DRAWSTATEPROC; -} - -WORD HIWORD(int l) { return cast(WORD)((l >> 16) & 0xFFFF); } -WORD LOWORD(int l) { return cast(WORD)l; } -bool FAILED(int status) { return status < 0; } -bool SUCCEEDED(int Status) { return Status >= 0; } - -enum : int -{ - FALSE = 0, - TRUE = 1, -} - -enum : uint -{ - MAX_PATH = 260, - HINSTANCE_ERROR = 32, -} - -enum -{ - ERROR_SUCCESS = 0, - ERROR_INVALID_FUNCTION = 1, - ERROR_FILE_NOT_FOUND = 2, - ERROR_PATH_NOT_FOUND = 3, - ERROR_TOO_MANY_OPEN_FILES = 4, - ERROR_ACCESS_DENIED = 5, - ERROR_INVALID_HANDLE = 6, - ERROR_NO_MORE_FILES = 18, - ERROR_MORE_DATA = 234, - ERROR_NO_MORE_ITEMS = 259, -} - -enum -{ - DLL_PROCESS_ATTACH = 1, - DLL_THREAD_ATTACH = 2, - DLL_THREAD_DETACH = 3, - DLL_PROCESS_DETACH = 0, -} - -enum -{ - FILE_BEGIN = 0, - FILE_CURRENT = 1, - FILE_END = 2, -} - -enum : uint -{ - DELETE = 0x00010000, - READ_CONTROL = 0x00020000, - WRITE_DAC = 0x00040000, - WRITE_OWNER = 0x00080000, - SYNCHRONIZE = 0x00100000, - - STANDARD_RIGHTS_REQUIRED = 0x000F0000, - STANDARD_RIGHTS_READ = READ_CONTROL, - STANDARD_RIGHTS_WRITE = READ_CONTROL, - STANDARD_RIGHTS_EXECUTE = READ_CONTROL, - STANDARD_RIGHTS_ALL = 0x001F0000, - SPECIFIC_RIGHTS_ALL = 0x0000FFFF, - ACCESS_SYSTEM_SECURITY = 0x01000000, - MAXIMUM_ALLOWED = 0x02000000, - - GENERIC_READ = 0x80000000, - GENERIC_WRITE = 0x40000000, - GENERIC_EXECUTE = 0x20000000, - GENERIC_ALL = 0x10000000, -} - -enum -{ - FILE_SHARE_READ = 0x00000001, - FILE_SHARE_WRITE = 0x00000002, - FILE_SHARE_DELETE = 0x00000004, - FILE_ATTRIBUTE_READONLY = 0x00000001, - FILE_ATTRIBUTE_HIDDEN = 0x00000002, - FILE_ATTRIBUTE_SYSTEM = 0x00000004, - FILE_ATTRIBUTE_DIRECTORY = 0x00000010, - FILE_ATTRIBUTE_ARCHIVE = 0x00000020, - FILE_ATTRIBUTE_NORMAL = 0x00000080, - FILE_ATTRIBUTE_TEMPORARY = 0x00000100, - FILE_ATTRIBUTE_COMPRESSED = 0x00000800, - FILE_ATTRIBUTE_OFFLINE = 0x00001000, - FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001, - FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002, - FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x00000004, - FILE_NOTIFY_CHANGE_SIZE = 0x00000008, - FILE_NOTIFY_CHANGE_LAST_WRITE = 0x00000010, - FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x00000020, - FILE_NOTIFY_CHANGE_CREATION = 0x00000040, - FILE_NOTIFY_CHANGE_SECURITY = 0x00000100, - FILE_ACTION_ADDED = 0x00000001, - FILE_ACTION_REMOVED = 0x00000002, - FILE_ACTION_MODIFIED = 0x00000003, - FILE_ACTION_RENAMED_OLD_NAME = 0x00000004, - FILE_ACTION_RENAMED_NEW_NAME = 0x00000005, - FILE_CASE_SENSITIVE_SEARCH = 0x00000001, - FILE_CASE_PRESERVED_NAMES = 0x00000002, - FILE_UNICODE_ON_DISK = 0x00000004, - FILE_PERSISTENT_ACLS = 0x00000008, - FILE_FILE_COMPRESSION = 0x00000010, - FILE_VOLUME_IS_COMPRESSED = 0x00008000, -} - -const DWORD MAILSLOT_NO_MESSAGE = cast(DWORD)-1; -const DWORD MAILSLOT_WAIT_FOREVER = cast(DWORD)-1; - -enum : uint -{ - FILE_FLAG_WRITE_THROUGH = 0x80000000, - FILE_FLAG_OVERLAPPED = 0x40000000, - FILE_FLAG_NO_BUFFERING = 0x20000000, - FILE_FLAG_RANDOM_ACCESS = 0x10000000, - FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000, - FILE_FLAG_DELETE_ON_CLOSE = 0x04000000, - FILE_FLAG_BACKUP_SEMANTICS = 0x02000000, - FILE_FLAG_POSIX_SEMANTICS = 0x01000000, -} - -enum -{ - CREATE_NEW = 1, - CREATE_ALWAYS = 2, - OPEN_EXISTING = 3, - OPEN_ALWAYS = 4, - TRUNCATE_EXISTING = 5, -} - -const HANDLE INVALID_HANDLE_VALUE = cast(HANDLE)-1; -const DWORD INVALID_SET_FILE_POINTER = cast(DWORD)-1; -const DWORD INVALID_FILE_SIZE = cast(DWORD)0xFFFFFFFF; - -struct OVERLAPPED { - DWORD Internal; - DWORD InternalHigh; - DWORD Offset; - DWORD OffsetHigh; - HANDLE hEvent; -} - -struct SECURITY_ATTRIBUTES { - DWORD nLength; - void *lpSecurityDescriptor; - BOOL bInheritHandle; -} - -alias SECURITY_ATTRIBUTES* PSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES; - -struct FILETIME { - DWORD dwLowDateTime; - DWORD dwHighDateTime; -} -alias FILETIME* PFILETIME, LPFILETIME; - -struct WIN32_FIND_DATA { - DWORD dwFileAttributes; - FILETIME ftCreationTime; - FILETIME ftLastAccessTime; - FILETIME ftLastWriteTime; - DWORD nFileSizeHigh; - DWORD nFileSizeLow; - DWORD dwReserved0; - DWORD dwReserved1; - char cFileName[MAX_PATH]; - char cAlternateFileName[ 14 ]; -} - -struct WIN32_FIND_DATAW { - DWORD dwFileAttributes; - FILETIME ftCreationTime; - FILETIME ftLastAccessTime; - FILETIME ftLastWriteTime; - DWORD nFileSizeHigh; - DWORD nFileSizeLow; - DWORD dwReserved0; - DWORD dwReserved1; - wchar cFileName[ 260 ]; - wchar cAlternateFileName[ 14 ]; -} - -export -{ -BOOL SetCurrentDirectoryA(LPCSTR lpPathName); -BOOL SetCurrentDirectoryW(LPCWSTR lpPathName); -DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer); -DWORD GetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer); -BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); -BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); -BOOL CreateDirectoryExA(LPCSTR lpTemplateDirectory, LPCSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes); -BOOL CreateDirectoryExW(LPCWSTR lpTemplateDirectory, LPCWSTR lpNewDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes); -BOOL RemoveDirectoryA(LPCSTR lpPathName); -BOOL RemoveDirectoryW(LPCWSTR lpPathName); - -BOOL CloseHandle(HANDLE hObject); - -HANDLE CreateFileA(char *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, - SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); -HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, - SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); - -BOOL DeleteFileA(char *lpFileName); -BOOL DeleteFileW(LPCWSTR lpFileName); - -BOOL FindClose(HANDLE hFindFile); -HANDLE FindFirstFileA(char *lpFileName, WIN32_FIND_DATA* lpFindFileData); -HANDLE FindFirstFileW(LPCWSTR lpFileName, WIN32_FIND_DATAW* lpFindFileData); -BOOL FindNextFileA(HANDLE hFindFile, WIN32_FIND_DATA* lpFindFileData); -BOOL FindNextFileW(HANDLE hFindFile, WIN32_FIND_DATAW* lpFindFileData); -BOOL GetExitCodeThread(HANDLE hThread, DWORD *lpExitCode); -DWORD GetLastError(); -DWORD GetFileAttributesA(char *lpFileName); -DWORD GetFileAttributesW(wchar *lpFileName); -DWORD GetFileSize(HANDLE hFile, DWORD *lpFileSizeHigh); -BOOL CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, BOOL bFailIfExists); -BOOL CopyFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists); -BOOL MoveFileA(char *from, char *to); -BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName); -BOOL ReadFile(HANDLE hFile, void *lpBuffer, DWORD nNumberOfBytesToRead, - DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped); -DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, - LONG *lpDistanceToMoveHigh, DWORD dwMoveMethod); -BOOL WriteFile(HANDLE hFile, void *lpBuffer, DWORD nNumberOfBytesToWrite, - DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped); -DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize); -} - -struct MEMORYSTATUS { - DWORD dwLength; - DWORD dwMemoryLoad; - DWORD dwTotalPhys; - DWORD dwAvailPhys; - DWORD dwTotalPageFile; - DWORD dwAvailPageFile; - DWORD dwTotalVirtual; - DWORD dwAvailVirtual; -}; -alias MEMORYSTATUS *LPMEMORYSTATUS; - - -export -{ - LONG InterlockedIncrement(LPLONG lpAddend); - LONG InterlockedDecrement(LPLONG lpAddend); - LONG InterlockedExchange(LPLONG Target, LONG Value); - LONG InterlockedExchangeAdd(LPLONG Addend, LONG Value); - PVOID InterlockedCompareExchange(PVOID *Destination, PVOID Exchange, PVOID Comperand); - BOOL FreeResource(HGLOBAL hResData); - LPVOID LockResource(HGLOBAL hResData); -} - -HMODULE LoadLibraryA(LPCSTR lpLibFileName); -FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName); -DWORD GetVersion(); -BOOL FreeLibrary(HMODULE hLibModule); -void FreeLibraryAndExitThread(HMODULE hLibModule, DWORD dwExitCode); -BOOL DisableThreadLibraryCalls(HMODULE hLibModule); - -// -// Registry Specific Access Rights. -// - -enum -{ - KEY_QUERY_VALUE = 0x0001, - KEY_SET_VALUE = 0x0002, - KEY_CREATE_SUB_KEY = 0x0004, - KEY_ENUMERATE_SUB_KEYS = 0x0008, - KEY_NOTIFY = 0x0010, - KEY_CREATE_LINK = 0x0020, - - KEY_READ = cast(int)((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & ~SYNCHRONIZE), - KEY_WRITE = cast(int)((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & ~SYNCHRONIZE), - KEY_EXECUTE = cast(int)(KEY_READ & ~SYNCHRONIZE), - KEY_ALL_ACCESS = cast(int)((STANDARD_RIGHTS_ALL | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_CREATE_LINK) & ~SYNCHRONIZE), -} - -// -// Key creation/open disposition -// - -const int REG_CREATED_NEW_KEY = 0x00000001; // New Registry Key created -const int REG_OPENED_EXISTING_KEY = 0x00000002; // Existing Key opened - - -// -// -// Predefined Value Types. -// -enum -{ - REG_NONE = 0, // No value type - REG_SZ = 1, // Unicode nul terminated string - REG_EXPAND_SZ = 2, // Unicode nul terminated string - // (with environment variable references) - REG_BINARY = 3, // Free form binary - REG_DWORD = 4, // 32-bit number - REG_DWORD_LITTLE_ENDIAN = 4, // 32-bit number (same as REG_DWORD) - REG_DWORD_BIG_ENDIAN = 5, // 32-bit number - REG_LINK = 6, // Symbolic Link (unicode) - REG_MULTI_SZ = 7, // Multiple Unicode strings - REG_RESOURCE_LIST = 8, // Resource list in the resource map - REG_FULL_RESOURCE_DESCRIPTOR = 9, // Resource list in the hardware description - REG_RESOURCE_REQUIREMENTS_LIST = 10, - REG_QWORD = 11, - REG_QWORD_LITTLE_ENDIAN = 11, -} - -/* - * MessageBox() Flags - */ -enum -{ - MB_OK = 0x00000000, - MB_OKCANCEL = 0x00000001, - MB_ABORTRETRYIGNORE = 0x00000002, - MB_YESNOCANCEL = 0x00000003, - MB_YESNO = 0x00000004, - MB_RETRYCANCEL = 0x00000005, - - - MB_ICONHAND = 0x00000010, - MB_ICONQUESTION = 0x00000020, - MB_ICONEXCLAMATION = 0x00000030, - MB_ICONASTERISK = 0x00000040, - - - MB_USERICON = 0x00000080, - MB_ICONWARNING = MB_ICONEXCLAMATION, - MB_ICONERROR = MB_ICONHAND, - - - MB_ICONINFORMATION = MB_ICONASTERISK, - MB_ICONSTOP = MB_ICONHAND, - - MB_DEFBUTTON1 = 0x00000000, - MB_DEFBUTTON2 = 0x00000100, - MB_DEFBUTTON3 = 0x00000200, - - MB_DEFBUTTON4 = 0x00000300, - - - MB_APPLMODAL = 0x00000000, - MB_SYSTEMMODAL = 0x00001000, - MB_TASKMODAL = 0x00002000, - - MB_HELP = 0x00004000, // Help Button - - - MB_NOFOCUS = 0x00008000, - MB_SETFOREGROUND = 0x00010000, - MB_DEFAULT_DESKTOP_ONLY = 0x00020000, - - - MB_TOPMOST = 0x00040000, - MB_RIGHT = 0x00080000, - MB_RTLREADING = 0x00100000, - - - MB_TYPEMASK = 0x0000000F, - MB_ICONMASK = 0x000000F0, - MB_DEFMASK = 0x00000F00, - MB_MODEMASK = 0x00003000, - MB_MISCMASK = 0x0000C000, -} - - -int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType); -int MessageBoxExA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId); - -const HKEY HKEY_CLASSES_ROOT = cast(HKEY)(0x80000000); -const HKEY HKEY_CURRENT_USER = cast(HKEY)(0x80000001); -const HKEY HKEY_LOCAL_MACHINE = cast(HKEY)(0x80000002); -const HKEY HKEY_USERS = cast(HKEY)(0x80000003); -const HKEY HKEY_PERFORMANCE_DATA = cast(HKEY)(0x80000004); -const HKEY HKEY_PERFORMANCE_TEXT = cast(HKEY)(0x80000050); -const HKEY HKEY_PERFORMANCE_NLSTEXT = cast(HKEY)(0x80000060); -const HKEY HKEY_CURRENT_CONFIG = cast(HKEY)(0x80000005); -const HKEY HKEY_DYN_DATA = cast(HKEY)(0x80000006); - -enum -{ - REG_OPTION_RESERVED = (0x00000000), // Parameter is reserved - - REG_OPTION_NON_VOLATILE = (0x00000000), // Key is preserved - // when system is rebooted - - REG_OPTION_VOLATILE = (0x00000001), // Key is not preserved - // when system is rebooted - - REG_OPTION_CREATE_LINK = (0x00000002), // Created key is a - // symbolic link - - REG_OPTION_BACKUP_RESTORE = (0x00000004), // open for backup or restore - // special access rules - // privilege required - - REG_OPTION_OPEN_LINK = (0x00000008), // Open symbolic link - - REG_LEGAL_OPTION = (REG_OPTION_RESERVED | REG_OPTION_NON_VOLATILE | REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK | REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK), -} - -export LONG RegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey); -export LONG RegDeleteValueA(HKEY hKey, LPCSTR lpValueName); - -export LONG RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcbName, LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcbClass, FILETIME* lpftLastWriteTime); -export LONG RegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName, LPDWORD lpcbValueName, LPDWORD lpReserved, - LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); - -export LONG RegCloseKey(HKEY hKey); -export LONG RegFlushKey(HKEY hKey); - -export LONG RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult); -export LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); - -export LONG RegQueryInfoKeyA(HKEY hKey, LPSTR lpClass, LPDWORD lpcbClass, - LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcbMaxSubKeyLen, LPDWORD lpcbMaxClassLen, - LPDWORD lpcValues, LPDWORD lpcbMaxValueNameLen, LPDWORD lpcbMaxValueLen, LPDWORD lpcbSecurityDescriptor, - PFILETIME lpftLastWriteTime); - -export LONG RegQueryValueA(HKEY hKey, LPCSTR lpSubKey, LPSTR lpValue, - LPLONG lpcbValue); - -export LONG RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, - DWORD dwOptions, REGSAM samDesired, SECURITY_ATTRIBUTES* lpSecurityAttributes, - PHKEY phkResult, LPDWORD lpdwDisposition); - -export LONG RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, BYTE* lpData, DWORD cbData); - -struct MEMORY_BASIC_INFORMATION { - PVOID BaseAddress; - PVOID AllocationBase; - DWORD AllocationProtect; - DWORD RegionSize; - DWORD State; - DWORD Protect; - DWORD Type; -} -alias MEMORY_BASIC_INFORMATION* PMEMORY_BASIC_INFORMATION; - -enum -{ - SECTION_QUERY = 0x0001, - SECTION_MAP_WRITE = 0x0002, - SECTION_MAP_READ = 0x0004, - SECTION_MAP_EXECUTE = 0x0008, - SECTION_EXTEND_SIZE = 0x0010, - - SECTION_ALL_ACCESS = cast(int)(STANDARD_RIGHTS_REQUIRED|SECTION_QUERY| SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE), - PAGE_NOACCESS = 0x01, - PAGE_READONLY = 0x02, - PAGE_READWRITE = 0x04, - PAGE_WRITECOPY = 0x08, - PAGE_EXECUTE = 0x10, - PAGE_EXECUTE_READ = 0x20, - PAGE_EXECUTE_READWRITE = 0x40, - PAGE_EXECUTE_WRITECOPY = 0x80, - PAGE_GUARD = 0x100, - PAGE_NOCACHE = 0x200, - MEM_COMMIT = 0x1000, - MEM_RESERVE = 0x2000, - MEM_DECOMMIT = 0x4000, - MEM_RELEASE = 0x8000, - MEM_FREE = 0x10000, - MEM_PRIVATE = 0x20000, - MEM_MAPPED = 0x40000, - MEM_RESET = 0x80000, - MEM_TOP_DOWN = 0x100000, - SEC_FILE = 0x800000, - SEC_IMAGE = 0x1000000, - SEC_RESERVE = 0x4000000, - SEC_COMMIT = 0x8000000, - SEC_NOCACHE = 0x10000000, - MEM_IMAGE = SEC_IMAGE, -} - -enum -{ - FILE_MAP_COPY = SECTION_QUERY, - FILE_MAP_WRITE = SECTION_MAP_WRITE, - FILE_MAP_READ = SECTION_MAP_READ, - FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS, -} - - -// -// Define access rights to files and directories -// - -// -// The FILE_READ_DATA and FILE_WRITE_DATA constants are also defined in -// devioctl.h as FILE_READ_ACCESS and FILE_WRITE_ACCESS. The values for these -// constants *MUST* always be in sync. -// The values are redefined in devioctl.h because they must be available to -// both DOS and NT. -// - -enum -{ - FILE_READ_DATA = ( 0x0001 ), // file & pipe - FILE_LIST_DIRECTORY = ( 0x0001 ), // directory - - FILE_WRITE_DATA = ( 0x0002 ), // file & pipe - FILE_ADD_FILE = ( 0x0002 ), // directory - - FILE_APPEND_DATA = ( 0x0004 ), // file - FILE_ADD_SUBDIRECTORY = ( 0x0004 ), // directory - FILE_CREATE_PIPE_INSTANCE = ( 0x0004 ), // named pipe - - FILE_READ_EA = ( 0x0008 ), // file & directory - - FILE_WRITE_EA = ( 0x0010 ), // file & directory - - FILE_EXECUTE = ( 0x0020 ), // file - FILE_TRAVERSE = ( 0x0020 ), // directory - - FILE_DELETE_CHILD = ( 0x0040 ), // directory - - FILE_READ_ATTRIBUTES = ( 0x0080 ), // all - - FILE_WRITE_ATTRIBUTES = ( 0x0100 ), // all - - FILE_ALL_ACCESS = cast(int)(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF), - - FILE_GENERIC_READ = cast(int)(STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE), - - FILE_GENERIC_WRITE = cast(int)(STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE), - - FILE_GENERIC_EXECUTE = cast(int)(STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE), -} - -export -{ - BOOL GlobalUnlock(HGLOBAL hMem); - HGLOBAL GlobalFree(HGLOBAL hMem); - UINT GlobalCompact(DWORD dwMinFree); - void GlobalFix(HGLOBAL hMem); - void GlobalUnfix(HGLOBAL hMem); - LPVOID GlobalWire(HGLOBAL hMem); - BOOL GlobalUnWire(HGLOBAL hMem); - void GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer); - HLOCAL LocalAlloc(UINT uFlags, UINT uBytes); - HLOCAL LocalReAlloc(HLOCAL hMem, UINT uBytes, UINT uFlags); - LPVOID LocalLock(HLOCAL hMem); - HLOCAL LocalHandle(LPCVOID pMem); - BOOL LocalUnlock(HLOCAL hMem); - UINT LocalSize(HLOCAL hMem); - UINT LocalFlags(HLOCAL hMem); - HLOCAL LocalFree(HLOCAL hMem); - UINT LocalShrink(HLOCAL hMem, UINT cbNewSize); - UINT LocalCompact(UINT uMinFree); - BOOL FlushInstructionCache(HANDLE hProcess, LPCVOID lpBaseAddress, DWORD dwSize); - LPVOID VirtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect); - BOOL VirtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType); - BOOL VirtualProtect(LPVOID lpAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); - DWORD VirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength); - LPVOID VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect); - BOOL VirtualFreeEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType); - BOOL VirtualProtectEx(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); - DWORD VirtualQueryEx(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength); -} - -struct SYSTEMTIME -{ - WORD wYear; - WORD wMonth; - WORD wDayOfWeek; - WORD wDay; - WORD wHour; - WORD wMinute; - WORD wSecond; - WORD wMilliseconds; -} - -struct TIME_ZONE_INFORMATION { - LONG Bias; - WCHAR StandardName[ 32 ]; - SYSTEMTIME StandardDate; - LONG StandardBias; - WCHAR DaylightName[ 32 ]; - SYSTEMTIME DaylightDate; - LONG DaylightBias; -} - -enum -{ - TIME_ZONE_ID_UNKNOWN = 0, - TIME_ZONE_ID_STANDARD = 1, - TIME_ZONE_ID_DAYLIGHT = 2, -} - -export void GetSystemTime(SYSTEMTIME* lpSystemTime); -export void GetSystemTimeAsFileTime(FILETIME* lpSystemTimeAsFileTime); -export BOOL SetSystemTime(SYSTEMTIME* lpSystemTime); -export void GetLocalTime(SYSTEMTIME* lpSystemTime); -export BOOL SetLocalTime(SYSTEMTIME* lpSystemTime); -export BOOL SystemTimeToTzSpecificLocalTime(TIME_ZONE_INFORMATION* lpTimeZoneInformation, SYSTEMTIME* lpUniversalTime, SYSTEMTIME* lpLocalTime); -export DWORD GetTimeZoneInformation(TIME_ZONE_INFORMATION* lpTimeZoneInformation); -export BOOL SetTimeZoneInformation(TIME_ZONE_INFORMATION* lpTimeZoneInformation); - -export BOOL SystemTimeToFileTime(SYSTEMTIME *lpSystemTime, FILETIME* lpFileTime); -export BOOL FileTimeToLocalFileTime(FILETIME *lpFileTime, FILETIME* lpLocalFileTime); -export BOOL LocalFileTimeToFileTime(FILETIME *lpLocalFileTime, FILETIME* lpFileTime); -export BOOL FileTimeToSystemTime(FILETIME *lpFileTime, SYSTEMTIME* lpSystemTime); -export LONG CompareFileTime(FILETIME *lpFileTime1, FILETIME *lpFileTime2); -export BOOL FileTimeToDosDateTime(FILETIME *lpFileTime, WORD* lpFatDate, WORD* lpFatTime); -export BOOL DosDateTimeToFileTime(WORD wFatDate, WORD wFatTime, FILETIME* lpFileTime); -export DWORD GetTickCount(); -export BOOL SetSystemTimeAdjustment(DWORD dwTimeAdjustment, BOOL bTimeAdjustmentDisabled); -export BOOL GetSystemTimeAdjustment(DWORD* lpTimeAdjustment, DWORD* lpTimeIncrement, BOOL* lpTimeAdjustmentDisabled); -export DWORD FormatMessageA(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, void* *Arguments);export DWORD FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, void* *Arguments); - -enum -{ - FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100, - FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200, - FORMAT_MESSAGE_FROM_STRING = 0x00000400, - FORMAT_MESSAGE_FROM_HMODULE = 0x00000800, - FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000, - FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000, - FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF, -}; - - -// -// Language IDs. -// -// The following two combinations of primary language ID and -// sublanguage ID have special semantics: -// -// Primary Language ID Sublanguage ID Result -// ------------------- --------------- ------------------------ -// LANG_NEUTRAL SUBLANG_NEUTRAL Language neutral -// LANG_NEUTRAL SUBLANG_DEFAULT User default language -// LANG_NEUTRAL SUBLANG_SYS_DEFAULT System default language -// - -// -// Primary language IDs. -// - -enum -{ - LANG_NEUTRAL = 0x00, - - LANG_AFRIKAANS = 0x36, - LANG_ALBANIAN = 0x1c, - LANG_ARABIC = 0x01, - LANG_BASQUE = 0x2d, - LANG_BELARUSIAN = 0x23, - LANG_BULGARIAN = 0x02, - LANG_CATALAN = 0x03, - LANG_CHINESE = 0x04, - LANG_CROATIAN = 0x1a, - LANG_CZECH = 0x05, - LANG_DANISH = 0x06, - LANG_DUTCH = 0x13, - LANG_ENGLISH = 0x09, - LANG_ESTONIAN = 0x25, - LANG_FAEROESE = 0x38, - LANG_FARSI = 0x29, - LANG_FINNISH = 0x0b, - LANG_FRENCH = 0x0c, - LANG_GERMAN = 0x07, - LANG_GREEK = 0x08, - LANG_HEBREW = 0x0d, - LANG_HUNGARIAN = 0x0e, - LANG_ICELANDIC = 0x0f, - LANG_INDONESIAN = 0x21, - LANG_ITALIAN = 0x10, - LANG_JAPANESE = 0x11, - LANG_KOREAN = 0x12, - LANG_LATVIAN = 0x26, - LANG_LITHUANIAN = 0x27, - LANG_NORWEGIAN = 0x14, - LANG_POLISH = 0x15, - LANG_PORTUGUESE = 0x16, - LANG_ROMANIAN = 0x18, - LANG_RUSSIAN = 0x19, - LANG_SERBIAN = 0x1a, - LANG_SLOVAK = 0x1b, - LANG_SLOVENIAN = 0x24, - LANG_SPANISH = 0x0a, - LANG_SWEDISH = 0x1d, - LANG_THAI = 0x1e, - LANG_TURKISH = 0x1f, - LANG_UKRAINIAN = 0x22, - LANG_VIETNAMESE = 0x2a, -} -// -// Sublanguage IDs. -// -// The name immediately following SUBLANG_ dictates which primary -// language ID that sublanguage ID can be combined with to form a -// valid language ID. -// -enum -{ - SUBLANG_NEUTRAL = 0x00, // language neutral - SUBLANG_DEFAULT = 0x01, // user default - SUBLANG_SYS_DEFAULT = 0x02, // system default - - SUBLANG_ARABIC_SAUDI_ARABIA = 0x01, // Arabic (Saudi Arabia) - SUBLANG_ARABIC_IRAQ = 0x02, // Arabic (Iraq) - SUBLANG_ARABIC_EGYPT = 0x03, // Arabic (Egypt) - SUBLANG_ARABIC_LIBYA = 0x04, // Arabic (Libya) - SUBLANG_ARABIC_ALGERIA = 0x05, // Arabic (Algeria) - SUBLANG_ARABIC_MOROCCO = 0x06, // Arabic (Morocco) - SUBLANG_ARABIC_TUNISIA = 0x07, // Arabic (Tunisia) - SUBLANG_ARABIC_OMAN = 0x08, // Arabic (Oman) - SUBLANG_ARABIC_YEMEN = 0x09, // Arabic (Yemen) - SUBLANG_ARABIC_SYRIA = 0x0a, // Arabic (Syria) - SUBLANG_ARABIC_JORDAN = 0x0b, // Arabic (Jordan) - SUBLANG_ARABIC_LEBANON = 0x0c, // Arabic (Lebanon) - SUBLANG_ARABIC_KUWAIT = 0x0d, // Arabic (Kuwait) - SUBLANG_ARABIC_UAE = 0x0e, // Arabic (U.A.E) - SUBLANG_ARABIC_BAHRAIN = 0x0f, // Arabic (Bahrain) - SUBLANG_ARABIC_QATAR = 0x10, // Arabic (Qatar) - SUBLANG_CHINESE_TRADITIONAL = 0x01, // Chinese (Taiwan) - SUBLANG_CHINESE_SIMPLIFIED = 0x02, // Chinese (PR China) - SUBLANG_CHINESE_HONGKONG = 0x03, // Chinese (Hong Kong) - SUBLANG_CHINESE_SINGAPORE = 0x04, // Chinese (Singapore) - SUBLANG_DUTCH = 0x01, // Dutch - SUBLANG_DUTCH_BELGIAN = 0x02, // Dutch (Belgian) - SUBLANG_ENGLISH_US = 0x01, // English (USA) - SUBLANG_ENGLISH_UK = 0x02, // English (UK) - SUBLANG_ENGLISH_AUS = 0x03, // English (Australian) - SUBLANG_ENGLISH_CAN = 0x04, // English (Canadian) - SUBLANG_ENGLISH_NZ = 0x05, // English (New Zealand) - SUBLANG_ENGLISH_EIRE = 0x06, // English (Irish) - SUBLANG_ENGLISH_SOUTH_AFRICA = 0x07, // English (South Africa) - SUBLANG_ENGLISH_JAMAICA = 0x08, // English (Jamaica) - SUBLANG_ENGLISH_CARIBBEAN = 0x09, // English (Caribbean) - SUBLANG_ENGLISH_BELIZE = 0x0a, // English (Belize) - SUBLANG_ENGLISH_TRINIDAD = 0x0b, // English (Trinidad) - SUBLANG_FRENCH = 0x01, // French - SUBLANG_FRENCH_BELGIAN = 0x02, // French (Belgian) - SUBLANG_FRENCH_CANADIAN = 0x03, // French (Canadian) - SUBLANG_FRENCH_SWISS = 0x04, // French (Swiss) - SUBLANG_FRENCH_LUXEMBOURG = 0x05, // French (Luxembourg) - SUBLANG_GERMAN = 0x01, // German - SUBLANG_GERMAN_SWISS = 0x02, // German (Swiss) - SUBLANG_GERMAN_AUSTRIAN = 0x03, // German (Austrian) - SUBLANG_GERMAN_LUXEMBOURG = 0x04, // German (Luxembourg) - SUBLANG_GERMAN_LIECHTENSTEIN = 0x05, // German (Liechtenstein) - SUBLANG_ITALIAN = 0x01, // Italian - SUBLANG_ITALIAN_SWISS = 0x02, // Italian (Swiss) - SUBLANG_KOREAN = 0x01, // Korean (Extended Wansung) - SUBLANG_KOREAN_JOHAB = 0x02, // Korean (Johab) - SUBLANG_NORWEGIAN_BOKMAL = 0x01, // Norwegian (Bokmal) - SUBLANG_NORWEGIAN_NYNORSK = 0x02, // Norwegian (Nynorsk) - SUBLANG_PORTUGUESE = 0x02, // Portuguese - SUBLANG_PORTUGUESE_BRAZILIAN = 0x01, // Portuguese (Brazilian) - SUBLANG_SERBIAN_LATIN = 0x02, // Serbian (Latin) - SUBLANG_SERBIAN_CYRILLIC = 0x03, // Serbian (Cyrillic) - SUBLANG_SPANISH = 0x01, // Spanish (Castilian) - SUBLANG_SPANISH_MEXICAN = 0x02, // Spanish (Mexican) - SUBLANG_SPANISH_MODERN = 0x03, // Spanish (Modern) - SUBLANG_SPANISH_GUATEMALA = 0x04, // Spanish (Guatemala) - SUBLANG_SPANISH_COSTA_RICA = 0x05, // Spanish (Costa Rica) - SUBLANG_SPANISH_PANAMA = 0x06, // Spanish (Panama) - SUBLANG_SPANISH_DOMINICAN_REPUBLIC = 0x07, // Spanish (Dominican Republic) - SUBLANG_SPANISH_VENEZUELA = 0x08, // Spanish (Venezuela) - SUBLANG_SPANISH_COLOMBIA = 0x09, // Spanish (Colombia) - SUBLANG_SPANISH_PERU = 0x0a, // Spanish (Peru) - SUBLANG_SPANISH_ARGENTINA = 0x0b, // Spanish (Argentina) - SUBLANG_SPANISH_ECUADOR = 0x0c, // Spanish (Ecuador) - SUBLANG_SPANISH_CHILE = 0x0d, // Spanish (Chile) - SUBLANG_SPANISH_URUGUAY = 0x0e, // Spanish (Uruguay) - SUBLANG_SPANISH_PARAGUAY = 0x0f, // Spanish (Paraguay) - SUBLANG_SPANISH_BOLIVIA = 0x10, // Spanish (Bolivia) - SUBLANG_SPANISH_EL_SALVADOR = 0x11, // Spanish (El Salvador) - SUBLANG_SPANISH_HONDURAS = 0x12, // Spanish (Honduras) - SUBLANG_SPANISH_NICARAGUA = 0x13, // Spanish (Nicaragua) - SUBLANG_SPANISH_PUERTO_RICO = 0x14, // Spanish (Puerto Rico) - SUBLANG_SWEDISH = 0x01, // Swedish - SUBLANG_SWEDISH_FINLAND = 0x02, // Swedish (Finland) -} -// -// Sorting IDs. -// - -enum -{ - SORT_DEFAULT = 0x0, // sorting default - - SORT_JAPANESE_XJIS = 0x0, // Japanese XJIS order - SORT_JAPANESE_UNICODE = 0x1, // Japanese Unicode order - - SORT_CHINESE_BIG5 = 0x0, // Chinese BIG5 order - SORT_CHINESE_PRCP = 0x0, // PRC Chinese Phonetic order - SORT_CHINESE_UNICODE = 0x1, // Chinese Unicode order - SORT_CHINESE_PRC = 0x2, // PRC Chinese Stroke Count order - - SORT_KOREAN_KSC = 0x0, // Korean KSC order - SORT_KOREAN_UNICODE = 0x1, // Korean Unicode order - - SORT_GERMAN_PHONE_BOOK = 0x1, // German Phone Book order -} - -// end_r_winnt - -// -// A language ID is a 16 bit value which is the combination of a -// primary language ID and a secondary language ID. The bits are -// allocated as follows: -// -// +-----------------------+-------------------------+ -// | Sublanguage ID | Primary Language ID | -// +-----------------------+-------------------------+ -// 15 10 9 0 bit -// -// -// Language ID creation/extraction macros: -// -// MAKELANGID - construct language id from a primary language id and -// a sublanguage id. -// PRIMARYLANGID - extract primary language id from a language id. -// SUBLANGID - extract sublanguage id from a language id. -// - -int MAKELANGID(int p, int s) { return ((cast(WORD)s) << 10) | cast(WORD)p; } -WORD PRIMARYLANGID(int lgid) { return cast(WORD)(lgid & 0x3ff); } -WORD SUBLANGID(int lgid) { return cast(WORD)(lgid >> 10); } - - -struct FLOATING_SAVE_AREA { - DWORD ControlWord; - DWORD StatusWord; - DWORD TagWord; - DWORD ErrorOffset; - DWORD ErrorSelector; - DWORD DataOffset; - DWORD DataSelector; - BYTE RegisterArea[80 ]; - DWORD Cr0NpxState; -} - -enum -{ - SIZE_OF_80387_REGISTERS = 80, -// -// The following flags control the contents of the CONTEXT structure. -// - CONTEXT_i386 = 0x00010000, // this assumes that i386 and - CONTEXT_i486 = 0x00010000, // i486 have identical context records - - CONTEXT_CONTROL = (CONTEXT_i386 | 0x00000001), // SS:SP, CS:IP, FLAGS, BP - CONTEXT_INTEGER = (CONTEXT_i386 | 0x00000002), // AX, BX, CX, DX, SI, DI - CONTEXT_SEGMENTS = (CONTEXT_i386 | 0x00000004), // DS, ES, FS, GS - CONTEXT_FLOATING_POINT = (CONTEXT_i386 | 0x00000008), // 387 state - CONTEXT_DEBUG_REGISTERS = (CONTEXT_i386 | 0x00000010), // DB 0-3,6,7 - - CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS), -} - -struct CONTEXT -{ - - // - // The flags values within this flag control the contents of - // a CONTEXT record. - // - // If the context record is used as an input parameter, then - // for each portion of the context record controlled by a flag - // whose value is set, it is assumed that that portion of the - // context record contains valid context. If the context record - // is being used to modify a threads context, then only that - // portion of the threads context will be modified. - // - // If the context record is used as an IN OUT parameter to capture - // the context of a thread, then only those portions of the thread's - // context corresponding to set flags will be returned. - // - // The context record is never used as an OUT only parameter. - // - - DWORD ContextFlags; - - // - // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is - // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT - // included in CONTEXT_FULL. - // - - DWORD Dr0; - DWORD Dr1; - DWORD Dr2; - DWORD Dr3; - DWORD Dr6; - DWORD Dr7; - - // - // This section is specified/returned if the - // ContextFlags word contians the flag CONTEXT_FLOATING_POINT. - // - - FLOATING_SAVE_AREA FloatSave; - - // - // This section is specified/returned if the - // ContextFlags word contians the flag CONTEXT_SEGMENTS. - // - - DWORD SegGs; - DWORD SegFs; - DWORD SegEs; - DWORD SegDs; - - // - // This section is specified/returned if the - // ContextFlags word contians the flag CONTEXT_INTEGER. - // - - DWORD Edi; - DWORD Esi; - DWORD Ebx; - DWORD Edx; - DWORD Ecx; - DWORD Eax; - - // - // This section is specified/returned if the - // ContextFlags word contians the flag CONTEXT_CONTROL. - // - - DWORD Ebp; - DWORD Eip; - DWORD SegCs; // MUST BE SANITIZED - DWORD EFlags; // MUST BE SANITIZED - DWORD Esp; - DWORD SegSs; -} - -enum -{ - THREAD_BASE_PRIORITY_LOWRT = 15, // value that gets a thread to LowRealtime-1 - THREAD_BASE_PRIORITY_MAX = 2, // maximum thread base priority boost - THREAD_BASE_PRIORITY_MIN = -2, // minimum thread base priority boost - THREAD_BASE_PRIORITY_IDLE = -15, // value that gets a thread to idle - - THREAD_PRIORITY_LOWEST = THREAD_BASE_PRIORITY_MIN, - THREAD_PRIORITY_BELOW_NORMAL = (THREAD_PRIORITY_LOWEST+1), - THREAD_PRIORITY_NORMAL = 0, - THREAD_PRIORITY_HIGHEST = THREAD_BASE_PRIORITY_MAX, - THREAD_PRIORITY_ABOVE_NORMAL = (THREAD_PRIORITY_HIGHEST-1), - THREAD_PRIORITY_ERROR_RETURN = int.max, - - THREAD_PRIORITY_TIME_CRITICAL = THREAD_BASE_PRIORITY_LOWRT, - THREAD_PRIORITY_IDLE = THREAD_BASE_PRIORITY_IDLE, -} - -export HANDLE GetCurrentThread(); -export BOOL GetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime); -export HANDLE GetCurrentProcess(); -export BOOL DuplicateHandle (HANDLE sourceProcess, HANDLE sourceThread, - HANDLE targetProcessHandle, HANDLE *targetHandle, DWORD access, - BOOL inheritHandle, DWORD options); -export DWORD GetCurrentThreadId(); -export BOOL SetThreadPriority(HANDLE hThread, int nPriority); -export BOOL SetThreadPriorityBoost(HANDLE hThread, BOOL bDisablePriorityBoost); -export BOOL GetThreadPriorityBoost(HANDLE hThread, PBOOL pDisablePriorityBoost); -export BOOL GetThreadTimes(HANDLE hThread, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime); -export int GetThreadPriority(HANDLE hThread); -export BOOL GetThreadContext(HANDLE hThread, CONTEXT* lpContext); -export BOOL SetThreadContext(HANDLE hThread, CONTEXT* lpContext); -export DWORD SuspendThread(HANDLE hThread); -export DWORD ResumeThread(HANDLE hThread); -export DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); -export DWORD WaitForMultipleObjects(DWORD nCount, HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds); -export void Sleep(DWORD dwMilliseconds); - -export BOOL QueryPerformanceCounter(long* lpPerformanceCount); -export BOOL QueryPerformanceFrequency(long* lpFrequency); - -enum -{ - WM_NOTIFY = 0x004E, - WM_INPUTLANGCHANGEREQUEST = 0x0050, - WM_INPUTLANGCHANGE = 0x0051, - WM_TCARD = 0x0052, - WM_HELP = 0x0053, - WM_USERCHANGED = 0x0054, - WM_NOTIFYFORMAT = 0x0055, - - NFR_ANSI = 1, - NFR_UNICODE = 2, - NF_QUERY = 3, - NF_REQUERY = 4, - - WM_CONTEXTMENU = 0x007B, - WM_STYLECHANGING = 0x007C, - WM_STYLECHANGED = 0x007D, - WM_DISPLAYCHANGE = 0x007E, - WM_GETICON = 0x007F, - WM_SETICON = 0x0080, - - - - WM_NCCREATE = 0x0081, - WM_NCDESTROY = 0x0082, - WM_NCCALCSIZE = 0x0083, - WM_NCHITTEST = 0x0084, - WM_NCPAINT = 0x0085, - WM_NCACTIVATE = 0x0086, - WM_GETDLGCODE = 0x0087, - - WM_NCMOUSEMOVE = 0x00A0, - WM_NCLBUTTONDOWN = 0x00A1, - WM_NCLBUTTONUP = 0x00A2, - WM_NCLBUTTONDBLCLK = 0x00A3, - WM_NCRBUTTONDOWN = 0x00A4, - WM_NCRBUTTONUP = 0x00A5, - WM_NCRBUTTONDBLCLK = 0x00A6, - WM_NCMBUTTONDOWN = 0x00A7, - WM_NCMBUTTONUP = 0x00A8, - WM_NCMBUTTONDBLCLK = 0x00A9, - - WM_KEYFIRST = 0x0100, - WM_KEYDOWN = 0x0100, - WM_KEYUP = 0x0101, - WM_CHAR = 0x0102, - WM_DEADCHAR = 0x0103, - WM_SYSKEYDOWN = 0x0104, - WM_SYSKEYUP = 0x0105, - WM_SYSCHAR = 0x0106, - WM_SYSDEADCHAR = 0x0107, - WM_KEYLAST = 0x0108, - - - WM_IME_STARTCOMPOSITION = 0x010D, - WM_IME_ENDCOMPOSITION = 0x010E, - WM_IME_COMPOSITION = 0x010F, - WM_IME_KEYLAST = 0x010F, - - - WM_INITDIALOG = 0x0110, - WM_COMMAND = 0x0111, - WM_SYSCOMMAND = 0x0112, - WM_TIMER = 0x0113, - WM_HSCROLL = 0x0114, - WM_VSCROLL = 0x0115, - WM_INITMENU = 0x0116, - WM_INITMENUPOPUP = 0x0117, - WM_MENUSELECT = 0x011F, - WM_MENUCHAR = 0x0120, - WM_ENTERIDLE = 0x0121, - - WM_CTLCOLORMSGBOX = 0x0132, - WM_CTLCOLOREDIT = 0x0133, - WM_CTLCOLORLISTBOX = 0x0134, - WM_CTLCOLORBTN = 0x0135, - WM_CTLCOLORDLG = 0x0136, - WM_CTLCOLORSCROLLBAR = 0x0137, - WM_CTLCOLORSTATIC = 0x0138, - - - - WM_MOUSEFIRST = 0x0200, - WM_MOUSEMOVE = 0x0200, - WM_LBUTTONDOWN = 0x0201, - WM_LBUTTONUP = 0x0202, - WM_LBUTTONDBLCLK = 0x0203, - WM_RBUTTONDOWN = 0x0204, - WM_RBUTTONUP = 0x0205, - WM_RBUTTONDBLCLK = 0x0206, - WM_MBUTTONDOWN = 0x0207, - WM_MBUTTONUP = 0x0208, - WM_MBUTTONDBLCLK = 0x0209, - - - - WM_MOUSELAST = 0x0209, - - - - - - - - - WM_PARENTNOTIFY = 0x0210, - MENULOOP_WINDOW = 0, - MENULOOP_POPUP = 1, - WM_ENTERMENULOOP = 0x0211, - WM_EXITMENULOOP = 0x0212, - - - WM_NEXTMENU = 0x0213, -} - -enum -{ -/* - * Dialog Box Command IDs - */ - IDOK = 1, - IDCANCEL = 2, - IDABORT = 3, - IDRETRY = 4, - IDIGNORE = 5, - IDYES = 6, - IDNO = 7, - - IDCLOSE = 8, - IDHELP = 9, - - -// end_r_winuser - - - -/* - * Control Manager Structures and Definitions - */ - - - -// begin_r_winuser - -/* - * Edit Control Styles - */ - ES_LEFT = 0x0000, - ES_CENTER = 0x0001, - ES_RIGHT = 0x0002, - ES_MULTILINE = 0x0004, - ES_UPPERCASE = 0x0008, - ES_LOWERCASE = 0x0010, - ES_PASSWORD = 0x0020, - ES_AUTOVSCROLL = 0x0040, - ES_AUTOHSCROLL = 0x0080, - ES_NOHIDESEL = 0x0100, - ES_OEMCONVERT = 0x0400, - ES_READONLY = 0x0800, - ES_WANTRETURN = 0x1000, - - ES_NUMBER = 0x2000, - - -// end_r_winuser - - - -/* - * Edit Control Notification Codes - */ - EN_SETFOCUS = 0x0100, - EN_KILLFOCUS = 0x0200, - EN_CHANGE = 0x0300, - EN_UPDATE = 0x0400, - EN_ERRSPACE = 0x0500, - EN_MAXTEXT = 0x0501, - EN_HSCROLL = 0x0601, - EN_VSCROLL = 0x0602, - - -/* Edit control EM_SETMARGIN parameters */ - EC_LEFTMARGIN = 0x0001, - EC_RIGHTMARGIN = 0x0002, - EC_USEFONTINFO = 0xffff, - - - - -// begin_r_winuser - -/* - * Edit Control Messages - */ - EM_GETSEL = 0x00B0, - EM_SETSEL = 0x00B1, - EM_GETRECT = 0x00B2, - EM_SETRECT = 0x00B3, - EM_SETRECTNP = 0x00B4, - EM_SCROLL = 0x00B5, - EM_LINESCROLL = 0x00B6, - EM_SCROLLCARET = 0x00B7, - EM_GETMODIFY = 0x00B8, - EM_SETMODIFY = 0x00B9, - EM_GETLINECOUNT = 0x00BA, - EM_LINEINDEX = 0x00BB, - EM_SETHANDLE = 0x00BC, - EM_GETHANDLE = 0x00BD, - EM_GETTHUMB = 0x00BE, - EM_LINELENGTH = 0x00C1, - EM_REPLACESEL = 0x00C2, - EM_GETLINE = 0x00C4, - EM_LIMITTEXT = 0x00C5, - EM_CANUNDO = 0x00C6, - EM_UNDO = 0x00C7, - EM_FMTLINES = 0x00C8, - EM_LINEFROMCHAR = 0x00C9, - EM_SETTABSTOPS = 0x00CB, - EM_SETPASSWORDCHAR = 0x00CC, - EM_EMPTYUNDOBUFFER = 0x00CD, - EM_GETFIRSTVISIBLELINE = 0x00CE, - EM_SETREADONLY = 0x00CF, - EM_SETWORDBREAKPROC = 0x00D0, - EM_GETWORDBREAKPROC = 0x00D1, - EM_GETPASSWORDCHAR = 0x00D2, - - EM_SETMARGINS = 0x00D3, - EM_GETMARGINS = 0x00D4, - EM_SETLIMITTEXT = EM_LIMITTEXT, /* ;win40 Name change */ - EM_GETLIMITTEXT = 0x00D5, - EM_POSFROMCHAR = 0x00D6, - EM_CHARFROMPOS = 0x00D7, - - - -// end_r_winuser - - -/* - * EDITWORDBREAKPROC code values - */ - WB_LEFT = 0, - WB_RIGHT = 1, - WB_ISDELIMITER = 2, - -// begin_r_winuser - -/* - * Button Control Styles - */ - BS_PUSHBUTTON = 0x00000000, - BS_DEFPUSHBUTTON = 0x00000001, - BS_CHECKBOX = 0x00000002, - BS_AUTOCHECKBOX = 0x00000003, - BS_RADIOBUTTON = 0x00000004, - BS_3STATE = 0x00000005, - BS_AUTO3STATE = 0x00000006, - BS_GROUPBOX = 0x00000007, - BS_USERBUTTON = 0x00000008, - BS_AUTORADIOBUTTON = 0x00000009, - BS_OWNERDRAW = 0x0000000B, - BS_LEFTTEXT = 0x00000020, - - BS_TEXT = 0x00000000, - BS_ICON = 0x00000040, - BS_BITMAP = 0x00000080, - BS_LEFT = 0x00000100, - BS_RIGHT = 0x00000200, - BS_CENTER = 0x00000300, - BS_TOP = 0x00000400, - BS_BOTTOM = 0x00000800, - BS_VCENTER = 0x00000C00, - BS_PUSHLIKE = 0x00001000, - BS_MULTILINE = 0x00002000, - BS_NOTIFY = 0x00004000, - BS_FLAT = 0x00008000, - BS_RIGHTBUTTON = BS_LEFTTEXT, - - - -/* - * User Button Notification Codes - */ - BN_CLICKED = 0, - BN_PAINT = 1, - BN_HILITE = 2, - BN_UNHILITE = 3, - BN_DISABLE = 4, - BN_DOUBLECLICKED = 5, - - BN_PUSHED = BN_HILITE, - BN_UNPUSHED = BN_UNHILITE, - BN_DBLCLK = BN_DOUBLECLICKED, - BN_SETFOCUS = 6, - BN_KILLFOCUS = 7, - -/* - * Button Control Messages - */ - BM_GETCHECK = 0x00F0, - BM_SETCHECK = 0x00F1, - BM_GETSTATE = 0x00F2, - BM_SETSTATE = 0x00F3, - BM_SETSTYLE = 0x00F4, - - BM_CLICK = 0x00F5, - BM_GETIMAGE = 0x00F6, - BM_SETIMAGE = 0x00F7, - - BST_UNCHECKED = 0x0000, - BST_CHECKED = 0x0001, - BST_INDETERMINATE = 0x0002, - BST_PUSHED = 0x0004, - BST_FOCUS = 0x0008, - - -/* - * Static Control Constants - */ - SS_LEFT = 0x00000000, - SS_CENTER = 0x00000001, - SS_RIGHT = 0x00000002, - SS_ICON = 0x00000003, - SS_BLACKRECT = 0x00000004, - SS_GRAYRECT = 0x00000005, - SS_WHITERECT = 0x00000006, - SS_BLACKFRAME = 0x00000007, - SS_GRAYFRAME = 0x00000008, - SS_WHITEFRAME = 0x00000009, - SS_USERITEM = 0x0000000A, - SS_SIMPLE = 0x0000000B, - SS_LEFTNOWORDWRAP = 0x0000000C, - - SS_OWNERDRAW = 0x0000000D, - SS_BITMAP = 0x0000000E, - SS_ENHMETAFILE = 0x0000000F, - SS_ETCHEDHORZ = 0x00000010, - SS_ETCHEDVERT = 0x00000011, - SS_ETCHEDFRAME = 0x00000012, - SS_TYPEMASK = 0x0000001F, - - SS_NOPREFIX = 0x00000080, /* Don't do "&" character translation */ - - SS_NOTIFY = 0x00000100, - SS_CENTERIMAGE = 0x00000200, - SS_RIGHTJUST = 0x00000400, - SS_REALSIZEIMAGE = 0x00000800, - SS_SUNKEN = 0x00001000, - SS_ENDELLIPSIS = 0x00004000, - SS_PATHELLIPSIS = 0x00008000, - SS_WORDELLIPSIS = 0x0000C000, - SS_ELLIPSISMASK = 0x0000C000, - - -// end_r_winuser - - -/* - * Static Control Mesages - */ - STM_SETICON = 0x0170, - STM_GETICON = 0x0171, - - STM_SETIMAGE = 0x0172, - STM_GETIMAGE = 0x0173, - STN_CLICKED = 0, - STN_DBLCLK = 1, - STN_ENABLE = 2, - STN_DISABLE = 3, - - STM_MSGMAX = 0x0174, -} - - -enum -{ -/* - * Window Messages - */ - - WM_NULL = 0x0000, - WM_CREATE = 0x0001, - WM_DESTROY = 0x0002, - WM_MOVE = 0x0003, - WM_SIZE = 0x0005, - - WM_ACTIVATE = 0x0006, -/* - * WM_ACTIVATE state values - */ - WA_INACTIVE = 0, - WA_ACTIVE = 1, - WA_CLICKACTIVE = 2, - - WM_SETFOCUS = 0x0007, - WM_KILLFOCUS = 0x0008, - WM_ENABLE = 0x000A, - WM_SETREDRAW = 0x000B, - WM_SETTEXT = 0x000C, - WM_GETTEXT = 0x000D, - WM_GETTEXTLENGTH = 0x000E, - WM_PAINT = 0x000F, - WM_CLOSE = 0x0010, - WM_QUERYENDSESSION = 0x0011, - WM_QUIT = 0x0012, - WM_QUERYOPEN = 0x0013, - WM_ERASEBKGND = 0x0014, - WM_SYSCOLORCHANGE = 0x0015, - WM_ENDSESSION = 0x0016, - WM_SHOWWINDOW = 0x0018, - WM_WININICHANGE = 0x001A, - - WM_SETTINGCHANGE = WM_WININICHANGE, - - - - WM_DEVMODECHANGE = 0x001B, - WM_ACTIVATEAPP = 0x001C, - WM_FONTCHANGE = 0x001D, - WM_TIMECHANGE = 0x001E, - WM_CANCELMODE = 0x001F, - WM_SETCURSOR = 0x0020, - WM_MOUSEACTIVATE = 0x0021, - WM_CHILDACTIVATE = 0x0022, - WM_QUEUESYNC = 0x0023, - - WM_GETMINMAXINFO = 0x0024, -} - -struct RECT -{ - LONG left; - LONG top; - LONG right; - LONG bottom; -} -alias RECT* PRECT, NPRECT, LPRECT; - -struct PAINTSTRUCT { - HDC hdc; - BOOL fErase; - RECT rcPaint; - BOOL fRestore; - BOOL fIncUpdate; - BYTE rgbReserved[32]; -} -alias PAINTSTRUCT* PPAINTSTRUCT, NPPAINTSTRUCT, LPPAINTSTRUCT; - -// flags for GetDCEx() - -enum -{ - DCX_WINDOW = 0x00000001, - DCX_CACHE = 0x00000002, - DCX_NORESETATTRS = 0x00000004, - DCX_CLIPCHILDREN = 0x00000008, - DCX_CLIPSIBLINGS = 0x00000010, - DCX_PARENTCLIP = 0x00000020, - DCX_EXCLUDERGN = 0x00000040, - DCX_INTERSECTRGN = 0x00000080, - DCX_EXCLUDEUPDATE = 0x00000100, - DCX_INTERSECTUPDATE = 0x00000200, - DCX_LOCKWINDOWUPDATE = 0x00000400, - DCX_VALIDATE = 0x00200000, -} - -export -{ - BOOL UpdateWindow(HWND hWnd); - HWND SetActiveWindow(HWND hWnd); - HWND GetForegroundWindow(); - BOOL PaintDesktop(HDC hdc); - BOOL SetForegroundWindow(HWND hWnd); - HWND WindowFromDC(HDC hDC); - HDC GetDC(HWND hWnd); - HDC GetDCEx(HWND hWnd, HRGN hrgnClip, DWORD flags); - HDC GetWindowDC(HWND hWnd); - int ReleaseDC(HWND hWnd, HDC hDC); - HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint); - BOOL EndPaint(HWND hWnd, PAINTSTRUCT *lpPaint); - BOOL GetUpdateRect(HWND hWnd, LPRECT lpRect, BOOL bErase); - int GetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase); - int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw); - int GetWindowRgn(HWND hWnd, HRGN hRgn); - int ExcludeUpdateRgn(HDC hDC, HWND hWnd); - BOOL InvalidateRect(HWND hWnd, RECT *lpRect, BOOL bErase); - BOOL ValidateRect(HWND hWnd, RECT *lpRect); - BOOL InvalidateRgn(HWND hWnd, HRGN hRgn, BOOL bErase); - BOOL ValidateRgn(HWND hWnd, HRGN hRgn); - BOOL RedrawWindow(HWND hWnd, RECT *lprcUpdate, HRGN hrgnUpdate, UINT flags); -} - -// flags for RedrawWindow() -enum -{ - RDW_INVALIDATE = 0x0001, - RDW_INTERNALPAINT = 0x0002, - RDW_ERASE = 0x0004, - RDW_VALIDATE = 0x0008, - RDW_NOINTERNALPAINT = 0x0010, - RDW_NOERASE = 0x0020, - RDW_NOCHILDREN = 0x0040, - RDW_ALLCHILDREN = 0x0080, - RDW_UPDATENOW = 0x0100, - RDW_ERASENOW = 0x0200, - RDW_FRAME = 0x0400, - RDW_NOFRAME = 0x0800, -} - -export -{ - BOOL GetClientRect(HWND hWnd, LPRECT lpRect); - BOOL GetWindowRect(HWND hWnd, LPRECT lpRect); - BOOL AdjustWindowRect(LPRECT lpRect, DWORD dwStyle, BOOL bMenu); - BOOL AdjustWindowRectEx(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle); - HFONT CreateFontA(int, int, int, int, int, DWORD, - DWORD, DWORD, DWORD, DWORD, DWORD, - DWORD, DWORD, LPCSTR); - HFONT CreateFontW(int, int, int, int, int, DWORD, - DWORD, DWORD, DWORD, DWORD, DWORD, - DWORD, DWORD, LPCWSTR); -} - -enum -{ - OUT_DEFAULT_PRECIS = 0, - OUT_STRING_PRECIS = 1, - OUT_CHARACTER_PRECIS = 2, - OUT_STROKE_PRECIS = 3, - OUT_TT_PRECIS = 4, - OUT_DEVICE_PRECIS = 5, - OUT_RASTER_PRECIS = 6, - OUT_TT_ONLY_PRECIS = 7, - OUT_OUTLINE_PRECIS = 8, - OUT_SCREEN_OUTLINE_PRECIS = 9, - - CLIP_DEFAULT_PRECIS = 0, - CLIP_CHARACTER_PRECIS = 1, - CLIP_STROKE_PRECIS = 2, - CLIP_MASK = 0xf, - CLIP_LH_ANGLES = (1<<4), - CLIP_TT_ALWAYS = (2<<4), - CLIP_EMBEDDED = (8<<4), - - DEFAULT_QUALITY = 0, - DRAFT_QUALITY = 1, - PROOF_QUALITY = 2, - - NONANTIALIASED_QUALITY = 3, - ANTIALIASED_QUALITY = 4, - - - DEFAULT_PITCH = 0, - FIXED_PITCH = 1, - VARIABLE_PITCH = 2, - - MONO_FONT = 8, - - - ANSI_CHARSET = 0, - DEFAULT_CHARSET = 1, - SYMBOL_CHARSET = 2, - SHIFTJIS_CHARSET = 128, - HANGEUL_CHARSET = 129, - GB2312_CHARSET = 134, - CHINESEBIG5_CHARSET = 136, - OEM_CHARSET = 255, - - JOHAB_CHARSET = 130, - HEBREW_CHARSET = 177, - ARABIC_CHARSET = 178, - GREEK_CHARSET = 161, - TURKISH_CHARSET = 162, - VIETNAMESE_CHARSET = 163, - THAI_CHARSET = 222, - EASTEUROPE_CHARSET = 238, - RUSSIAN_CHARSET = 204, - - MAC_CHARSET = 77, - BALTIC_CHARSET = 186, - - FS_LATIN1 = 0x00000001L, - FS_LATIN2 = 0x00000002L, - FS_CYRILLIC = 0x00000004L, - FS_GREEK = 0x00000008L, - FS_TURKISH = 0x00000010L, - FS_HEBREW = 0x00000020L, - FS_ARABIC = 0x00000040L, - FS_BALTIC = 0x00000080L, - FS_VIETNAMESE = 0x00000100L, - FS_THAI = 0x00010000L, - FS_JISJAPAN = 0x00020000L, - FS_CHINESESIMP = 0x00040000L, - FS_WANSUNG = 0x00080000L, - FS_CHINESETRAD = 0x00100000L, - FS_JOHAB = 0x00200000L, - FS_SYMBOL = cast(int)0x80000000L, - - -/* Font Families */ - FF_DONTCARE = (0<<4), /* Don't care or don't know. */ - FF_ROMAN = (1<<4), /* Variable stroke width, serifed. */ - /* Times Roman, Century Schoolbook, etc. */ - FF_SWISS = (2<<4), /* Variable stroke width, sans-serifed. */ - /* Helvetica, Swiss, etc. */ - FF_MODERN = (3<<4), /* Constant stroke width, serifed or sans-serifed. */ - /* Pica, Elite, Courier, etc. */ - FF_SCRIPT = (4<<4), /* Cursive, etc. */ - FF_DECORATIVE = (5<<4), /* Old English, etc. */ - -/* Font Weights */ - FW_DONTCARE = 0, - FW_THIN = 100, - FW_EXTRALIGHT = 200, - FW_LIGHT = 300, - FW_NORMAL = 400, - FW_MEDIUM = 500, - FW_SEMIBOLD = 600, - FW_BOLD = 700, - FW_EXTRABOLD = 800, - FW_HEAVY = 900, - - FW_ULTRALIGHT = FW_EXTRALIGHT, - FW_REGULAR = FW_NORMAL, - FW_DEMIBOLD = FW_SEMIBOLD, - FW_ULTRABOLD = FW_EXTRABOLD, - FW_BLACK = FW_HEAVY, - - PANOSE_COUNT = 10, - PAN_FAMILYTYPE_INDEX = 0, - PAN_SERIFSTYLE_INDEX = 1, - PAN_WEIGHT_INDEX = 2, - PAN_PROPORTION_INDEX = 3, - PAN_CONTRAST_INDEX = 4, - PAN_STROKEVARIATION_INDEX = 5, - PAN_ARMSTYLE_INDEX = 6, - PAN_LETTERFORM_INDEX = 7, - PAN_MIDLINE_INDEX = 8, - PAN_XHEIGHT_INDEX = 9, - - PAN_CULTURE_LATIN = 0, -} - -struct RGBQUAD { - BYTE rgbBlue; - BYTE rgbGreen; - BYTE rgbRed; - BYTE rgbReserved; -} -alias RGBQUAD* LPRGBQUAD; - -struct BITMAPINFOHEADER -{ - DWORD biSize; - LONG biWidth; - LONG biHeight; - WORD biPlanes; - WORD biBitCount; - DWORD biCompression; - DWORD biSizeImage; - LONG biXPelsPerMeter; - LONG biYPelsPerMeter; - DWORD biClrUsed; - DWORD biClrImportant; -} -alias BITMAPINFOHEADER* LPBITMAPINFOHEADER, PBITMAPINFOHEADER; - -struct BITMAPINFO { - BITMAPINFOHEADER bmiHeader; - RGBQUAD bmiColors[1]; -} -alias BITMAPINFO* LPBITMAPINFO, PBITMAPINFO; - -struct PALETTEENTRY { - BYTE peRed; - BYTE peGreen; - BYTE peBlue; - BYTE peFlags; -} -alias PALETTEENTRY* PPALETTEENTRY, LPPALETTEENTRY; - -struct LOGPALETTE { - WORD palVersion; - WORD palNumEntries; - PALETTEENTRY palPalEntry[1]; -} -alias LOGPALETTE* PLOGPALETTE, NPLOGPALETTE, LPLOGPALETTE; - -/* Pixel format descriptor */ -struct PIXELFORMATDESCRIPTOR -{ - WORD nSize; - WORD nVersion; - DWORD dwFlags; - BYTE iPixelType; - BYTE cColorBits; - BYTE cRedBits; - BYTE cRedShift; - BYTE cGreenBits; - BYTE cGreenShift; - BYTE cBlueBits; - BYTE cBlueShift; - BYTE cAlphaBits; - BYTE cAlphaShift; - BYTE cAccumBits; - BYTE cAccumRedBits; - BYTE cAccumGreenBits; - BYTE cAccumBlueBits; - BYTE cAccumAlphaBits; - BYTE cDepthBits; - BYTE cStencilBits; - BYTE cAuxBuffers; - BYTE iLayerType; - BYTE bReserved; - DWORD dwLayerMask; - DWORD dwVisibleMask; - DWORD dwDamageMask; -} -alias PIXELFORMATDESCRIPTOR* PPIXELFORMATDESCRIPTOR, LPPIXELFORMATDESCRIPTOR; - - -export -{ - BOOL RoundRect(HDC, int, int, int, int, int, int); - BOOL ResizePalette(HPALETTE, UINT); - int SaveDC(HDC); - int SelectClipRgn(HDC, HRGN); - int ExtSelectClipRgn(HDC, HRGN, int); - int SetMetaRgn(HDC); - HGDIOBJ SelectObject(HDC, HGDIOBJ); - HPALETTE SelectPalette(HDC, HPALETTE, BOOL); - COLORREF SetBkColor(HDC, COLORREF); - int SetBkMode(HDC, int); - LONG SetBitmapBits(HBITMAP, DWORD, void *); - UINT SetBoundsRect(HDC, RECT *, UINT); - int SetDIBits(HDC, HBITMAP, UINT, UINT, void *, BITMAPINFO *, UINT); - int SetDIBitsToDevice(HDC, int, int, DWORD, DWORD, int, - int, UINT, UINT, void *, BITMAPINFO *, UINT); - DWORD SetMapperFlags(HDC, DWORD); - int SetGraphicsMode(HDC hdc, int iMode); - int SetMapMode(HDC, int); - HMETAFILE SetMetaFileBitsEx(UINT, BYTE *); - UINT SetPaletteEntries(HPALETTE, UINT, UINT, PALETTEENTRY *); - COLORREF SetPixel(HDC, int, int, COLORREF); - BOOL SetPixelV(HDC, int, int, COLORREF); - BOOL SetPixelFormat(HDC, int, PIXELFORMATDESCRIPTOR *); - int SetPolyFillMode(HDC, int); - BOOL StretchBlt(HDC, int, int, int, int, HDC, int, int, int, int, DWORD); - BOOL SetRectRgn(HRGN, int, int, int, int); - int StretchDIBits(HDC, int, int, int, int, int, int, int, int, - void *, BITMAPINFO *, UINT, DWORD); - int SetROP2(HDC, int); - int SetStretchBltMode(HDC, int); - UINT SetSystemPaletteUse(HDC, UINT); - int SetTextCharacterExtra(HDC, int); - COLORREF SetTextColor(HDC, COLORREF); - UINT SetTextAlign(HDC, UINT); - BOOL SetTextJustification(HDC, int, int); - BOOL UpdateColors(HDC); -} - -/* Text Alignment Options */ -enum -{ - TA_NOUPDATECP = 0, - TA_UPDATECP = 1, - - TA_LEFT = 0, - TA_RIGHT = 2, - TA_CENTER = 6, - - TA_TOP = 0, - TA_BOTTOM = 8, - TA_BASELINE = 24, - - TA_RTLREADING = 256, - TA_MASK = (TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING), -} - -struct POINT -{ - LONG x; - LONG y; -} -alias POINT* PPOINT, NPPOINT, LPPOINT; - - -export -{ - BOOL MoveToEx(HDC, int, int, LPPOINT); - BOOL TextOutA(HDC, int, int, LPCSTR, int); - BOOL TextOutW(HDC, int, int, LPCWSTR, int); -} - -export void PostQuitMessage(int nExitCode); -export LRESULT DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); -export HMODULE GetModuleHandleA(LPCSTR lpModuleName); - -alias LRESULT (* WNDPROC)(HWND, UINT, WPARAM, LPARAM); - -struct WNDCLASSEXA { - UINT cbSize; - /* Win 3.x */ - UINT style; - WNDPROC lpfnWndProc; - int cbClsExtra; - int cbWndExtra; - HINSTANCE hInstance; - HICON hIcon; - HCURSOR hCursor; - HBRUSH hbrBackground; - LPCSTR lpszMenuName; - LPCSTR lpszClassName; - /* Win 4.0 */ - HICON hIconSm; -} -alias WNDCLASSEXA* PWNDCLASSEXA, NPWNDCLASSEXA, LPWNDCLASSEXA; - - -struct WNDCLASSA { - UINT style; - WNDPROC lpfnWndProc; - int cbClsExtra; - int cbWndExtra; - HINSTANCE hInstance; - HICON hIcon; - HCURSOR hCursor; - HBRUSH hbrBackground; - LPCSTR lpszMenuName; - LPCSTR lpszClassName; -} -alias WNDCLASSA* PWNDCLASSA, NPWNDCLASSA, LPWNDCLASSA; -alias WNDCLASSA WNDCLASS; - -/* - * Window Styles - */ -enum : uint -{ - WS_OVERLAPPED = 0x00000000, - WS_POPUP = 0x80000000, - WS_CHILD = 0x40000000, - WS_MINIMIZE = 0x20000000, - WS_VISIBLE = 0x10000000, - WS_DISABLED = 0x08000000, - WS_CLIPSIBLINGS = 0x04000000, - WS_CLIPCHILDREN = 0x02000000, - WS_MAXIMIZE = 0x01000000, - WS_CAPTION = 0x00C00000, /* WS_BORDER | WS_DLGFRAME */ - WS_BORDER = 0x00800000, - WS_DLGFRAME = 0x00400000, - WS_VSCROLL = 0x00200000, - WS_HSCROLL = 0x00100000, - WS_SYSMENU = 0x00080000, - WS_THICKFRAME = 0x00040000, - WS_GROUP = 0x00020000, - WS_TABSTOP = 0x00010000, - - WS_MINIMIZEBOX = 0x00020000, - WS_MAXIMIZEBOX = 0x00010000, - - WS_TILED = WS_OVERLAPPED, - WS_ICONIC = WS_MINIMIZE, - WS_SIZEBOX = WS_THICKFRAME, - -/* - * Common Window Styles - */ - WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX), - WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW, - WS_POPUPWINDOW = (WS_POPUP | WS_BORDER | WS_SYSMENU), - WS_CHILDWINDOW = (WS_CHILD), -} - -/* - * Class styles - */ -enum -{ - CS_VREDRAW = 0x0001, - CS_HREDRAW = 0x0002, - CS_KEYCVTWINDOW = 0x0004, - CS_DBLCLKS = 0x0008, - CS_OWNDC = 0x0020, - CS_CLASSDC = 0x0040, - CS_PARENTDC = 0x0080, - CS_NOKEYCVT = 0x0100, - CS_NOCLOSE = 0x0200, - CS_SAVEBITS = 0x0800, - CS_BYTEALIGNCLIENT = 0x1000, - CS_BYTEALIGNWINDOW = 0x2000, - CS_GLOBALCLASS = 0x4000, - - - CS_IME = 0x00010000, -} - -export -{ - HICON LoadIconA(HINSTANCE hInstance, LPCSTR lpIconName); - HICON LoadIconW(HINSTANCE hInstance, LPCWSTR lpIconName); - HCURSOR LoadCursorA(HINSTANCE hInstance, LPCSTR lpCursorName); - HCURSOR LoadCursorW(HINSTANCE hInstance, LPCWSTR lpCursorName); -} - -const LPSTR IDI_APPLICATION = cast(LPSTR)(32512); - -const LPSTR IDC_ARROW = cast(LPSTR)(32512); -const LPSTR IDC_CROSS = cast(LPSTR)(32515); - -/* - * Color Types - */ -enum -{ - CTLCOLOR_MSGBOX = 0, - CTLCOLOR_EDIT = 1, - CTLCOLOR_LISTBOX = 2, - CTLCOLOR_BTN = 3, - CTLCOLOR_DLG = 4, - CTLCOLOR_SCROLLBAR = 5, - CTLCOLOR_STATIC = 6, - CTLCOLOR_MAX = 7, - - COLOR_SCROLLBAR = 0, - COLOR_BACKGROUND = 1, - COLOR_ACTIVECAPTION = 2, - COLOR_INACTIVECAPTION = 3, - COLOR_MENU = 4, - COLOR_WINDOW = 5, - COLOR_WINDOWFRAME = 6, - COLOR_MENUTEXT = 7, - COLOR_WINDOWTEXT = 8, - COLOR_CAPTIONTEXT = 9, - COLOR_ACTIVEBORDER = 10, - COLOR_INACTIVEBORDER = 11, - COLOR_APPWORKSPACE = 12, - COLOR_HIGHLIGHT = 13, - COLOR_HIGHLIGHTTEXT = 14, - COLOR_BTNFACE = 15, - COLOR_BTNSHADOW = 16, - COLOR_GRAYTEXT = 17, - COLOR_BTNTEXT = 18, - COLOR_INACTIVECAPTIONTEXT = 19, - COLOR_BTNHIGHLIGHT = 20, - - - COLOR_3DDKSHADOW = 21, - COLOR_3DLIGHT = 22, - COLOR_INFOTEXT = 23, - COLOR_INFOBK = 24, - - COLOR_DESKTOP = COLOR_BACKGROUND, - COLOR_3DFACE = COLOR_BTNFACE, - COLOR_3DSHADOW = COLOR_BTNSHADOW, - COLOR_3DHIGHLIGHT = COLOR_BTNHIGHLIGHT, - COLOR_3DHILIGHT = COLOR_BTNHIGHLIGHT, - COLOR_BTNHILIGHT = COLOR_BTNHIGHLIGHT, -} - -const int CW_USEDEFAULT = cast(int)0x80000000; -/* - * Special value for CreateWindow, et al. - */ -const HWND HWND_DESKTOP = (cast(HWND)0); - - -export ATOM RegisterClassA(WNDCLASSA *lpWndClass); - -export HWND CreateWindowExA( - DWORD dwExStyle, - LPCSTR lpClassName, - LPCSTR lpWindowName, - DWORD dwStyle, - int X, - int Y, - int nWidth, - int nHeight, - HWND hWndParent , - HMENU hMenu, - HINSTANCE hInstance, - LPVOID lpParam); - - -HWND CreateWindowA( - LPCSTR lpClassName, - LPCSTR lpWindowName, - DWORD dwStyle, - int X, - int Y, - int nWidth, - int nHeight, - HWND hWndParent , - HMENU hMenu, - HINSTANCE hInstance, - LPVOID lpParam) -{ - return CreateWindowExA(0, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); -} - -/* - * Message structure - */ -struct MSG { - HWND hwnd; - UINT message; - WPARAM wParam; - LPARAM lParam; - DWORD time; - POINT pt; -} -alias MSG* PMSG, NPMSG, LPMSG; - -export -{ - BOOL GetMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax); - BOOL TranslateMessage(MSG *lpMsg); - LONG DispatchMessageA(MSG *lpMsg); - BOOL PeekMessageA(MSG *lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg); - HWND GetFocus(); -} - -export DWORD ExpandEnvironmentStringsA(LPCSTR lpSrc, LPSTR lpDst, DWORD nSize); - -export -{ - BOOL IsValidCodePage(UINT CodePage); - UINT GetACP(); - UINT GetOEMCP(); - //BOOL GetCPInfo(UINT CodePage, LPCPINFO lpCPInfo); - BOOL IsDBCSLeadByte(BYTE TestChar); - BOOL IsDBCSLeadByteEx(UINT CodePage, BYTE TestChar); - int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar); - int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar); -} - -export HANDLE CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName); -export HANDLE CreateFileMappingW(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCWSTR lpName); - -export BOOL GetMailslotInfo(HANDLE hMailslot, LPDWORD lpMaxMessageSize, LPDWORD lpNextSize, LPDWORD lpMessageCount, LPDWORD lpReadTimeout); -export BOOL SetMailslotInfo(HANDLE hMailslot, DWORD lReadTimeout); -export LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap); -export LPVOID MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress); -export BOOL FlushViewOfFile(LPCVOID lpBaseAddress, DWORD dwNumberOfBytesToFlush); -export BOOL UnmapViewOfFile(LPCVOID lpBaseAddress); - -export HGDIOBJ GetStockObject(int); -export BOOL ShowWindow(HWND hWnd, int nCmdShow); - -/* Stock Logical Objects */ -enum -{ WHITE_BRUSH = 0, - LTGRAY_BRUSH = 1, - GRAY_BRUSH = 2, - DKGRAY_BRUSH = 3, - BLACK_BRUSH = 4, - NULL_BRUSH = 5, - HOLLOW_BRUSH = NULL_BRUSH, - WHITE_PEN = 6, - BLACK_PEN = 7, - NULL_PEN = 8, - OEM_FIXED_FONT = 10, - ANSI_FIXED_FONT = 11, - ANSI_VAR_FONT = 12, - SYSTEM_FONT = 13, - DEVICE_DEFAULT_FONT = 14, - DEFAULT_PALETTE = 15, - SYSTEM_FIXED_FONT = 16, - DEFAULT_GUI_FONT = 17, - STOCK_LAST = 17, -} - -/* - * ShowWindow() Commands - */ -enum -{ SW_HIDE = 0, - SW_SHOWNORMAL = 1, - SW_NORMAL = 1, - SW_SHOWMINIMIZED = 2, - SW_SHOWMAXIMIZED = 3, - SW_MAXIMIZE = 3, - SW_SHOWNOACTIVATE = 4, - SW_SHOW = 5, - SW_MINIMIZE = 6, - SW_SHOWMINNOACTIVE = 7, - SW_SHOWNA = 8, - SW_RESTORE = 9, - SW_SHOWDEFAULT = 10, - SW_MAX = 10, -} - -struct TEXTMETRICA -{ - LONG tmHeight; - LONG tmAscent; - LONG tmDescent; - LONG tmInternalLeading; - LONG tmExternalLeading; - LONG tmAveCharWidth; - LONG tmMaxCharWidth; - LONG tmWeight; - LONG tmOverhang; - LONG tmDigitizedAspectX; - LONG tmDigitizedAspectY; - BYTE tmFirstChar; - BYTE tmLastChar; - BYTE tmDefaultChar; - BYTE tmBreakChar; - BYTE tmItalic; - BYTE tmUnderlined; - BYTE tmStruckOut; - BYTE tmPitchAndFamily; - BYTE tmCharSet; -} - -export BOOL GetTextMetricsA(HDC, TEXTMETRICA*); - -/* - * Scroll Bar Constants - */ -enum -{ SB_HORZ = 0, - SB_VERT = 1, - SB_CTL = 2, - SB_BOTH = 3, -} - -/* - * Scroll Bar Commands - */ -enum -{ SB_LINEUP = 0, - SB_LINELEFT = 0, - SB_LINEDOWN = 1, - SB_LINERIGHT = 1, - SB_PAGEUP = 2, - SB_PAGELEFT = 2, - SB_PAGEDOWN = 3, - SB_PAGERIGHT = 3, - SB_THUMBPOSITION = 4, - SB_THUMBTRACK = 5, - SB_TOP = 6, - SB_LEFT = 6, - SB_BOTTOM = 7, - SB_RIGHT = 7, - SB_ENDSCROLL = 8, -} - -export int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw); -export int GetScrollPos(HWND hWnd, int nBar); -export BOOL SetScrollRange(HWND hWnd, int nBar, int nMinPos, int nMaxPos, BOOL bRedraw); -export BOOL GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos); -export BOOL ShowScrollBar(HWND hWnd, int wBar, BOOL bShow); -export BOOL EnableScrollBar(HWND hWnd, UINT wSBflags, UINT wArrows); - -/* - * LockWindowUpdate API - */ - -export BOOL LockWindowUpdate(HWND hWndLock); -export BOOL ScrollWindow(HWND hWnd, int XAmount, int YAmount, RECT* lpRect, RECT* lpClipRect); -export BOOL ScrollDC(HDC hDC, int dx, int dy, RECT* lprcScroll, RECT* lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate); -export int ScrollWindowEx(HWND hWnd, int dx, int dy, RECT* prcScroll, RECT* prcClip, HRGN hrgnUpdate, LPRECT prcUpdate, UINT flags); - -/* - * Virtual Keys, Standard Set - */ -enum -{ VK_LBUTTON = 0x01, - VK_RBUTTON = 0x02, - VK_CANCEL = 0x03, - VK_MBUTTON = 0x04, /* NOT contiguous with L & RBUTTON */ - - VK_BACK = 0x08, - VK_TAB = 0x09, - - VK_CLEAR = 0x0C, - VK_RETURN = 0x0D, - - VK_SHIFT = 0x10, - VK_CONTROL = 0x11, - VK_MENU = 0x12, - VK_PAUSE = 0x13, - VK_CAPITAL = 0x14, - - - VK_ESCAPE = 0x1B, - - VK_SPACE = 0x20, - VK_PRIOR = 0x21, - VK_NEXT = 0x22, - VK_END = 0x23, - VK_HOME = 0x24, - VK_LEFT = 0x25, - VK_UP = 0x26, - VK_RIGHT = 0x27, - VK_DOWN = 0x28, - VK_SELECT = 0x29, - VK_PRINT = 0x2A, - VK_EXECUTE = 0x2B, - VK_SNAPSHOT = 0x2C, - VK_INSERT = 0x2D, - VK_DELETE = 0x2E, - VK_HELP = 0x2F, - -/* VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */ -/* VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */ - - VK_LWIN = 0x5B, - VK_RWIN = 0x5C, - VK_APPS = 0x5D, - - VK_NUMPAD0 = 0x60, - VK_NUMPAD1 = 0x61, - VK_NUMPAD2 = 0x62, - VK_NUMPAD3 = 0x63, - VK_NUMPAD4 = 0x64, - VK_NUMPAD5 = 0x65, - VK_NUMPAD6 = 0x66, - VK_NUMPAD7 = 0x67, - VK_NUMPAD8 = 0x68, - VK_NUMPAD9 = 0x69, - VK_MULTIPLY = 0x6A, - VK_ADD = 0x6B, - VK_SEPARATOR = 0x6C, - VK_SUBTRACT = 0x6D, - VK_DECIMAL = 0x6E, - VK_DIVIDE = 0x6F, - VK_F1 = 0x70, - VK_F2 = 0x71, - VK_F3 = 0x72, - VK_F4 = 0x73, - VK_F5 = 0x74, - VK_F6 = 0x75, - VK_F7 = 0x76, - VK_F8 = 0x77, - VK_F9 = 0x78, - VK_F10 = 0x79, - VK_F11 = 0x7A, - VK_F12 = 0x7B, - VK_F13 = 0x7C, - VK_F14 = 0x7D, - VK_F15 = 0x7E, - VK_F16 = 0x7F, - VK_F17 = 0x80, - VK_F18 = 0x81, - VK_F19 = 0x82, - VK_F20 = 0x83, - VK_F21 = 0x84, - VK_F22 = 0x85, - VK_F23 = 0x86, - VK_F24 = 0x87, - - VK_NUMLOCK = 0x90, - VK_SCROLL = 0x91, - -/* - * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys. - * Used only as parameters to GetAsyncKeyState() and GetKeyState(). - * No other API or message will distinguish left and right keys in this way. - */ - VK_LSHIFT = 0xA0, - VK_RSHIFT = 0xA1, - VK_LCONTROL = 0xA2, - VK_RCONTROL = 0xA3, - VK_LMENU = 0xA4, - VK_RMENU = 0xA5, - - - VK_PROCESSKEY = 0xE5, - - - VK_ATTN = 0xF6, - VK_CRSEL = 0xF7, - VK_EXSEL = 0xF8, - VK_EREOF = 0xF9, - VK_PLAY = 0xFA, - VK_ZOOM = 0xFB, - VK_NONAME = 0xFC, - VK_PA1 = 0xFD, - VK_OEM_CLEAR = 0xFE, -} - -export LRESULT SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); - -alias UINT (*LPOFNHOOKPROC) (HWND, UINT, WPARAM, LPARAM); - -struct OPENFILENAMEA { - DWORD lStructSize; - HWND hwndOwner; - HINSTANCE hInstance; - LPCSTR lpstrFilter; - LPSTR lpstrCustomFilter; - DWORD nMaxCustFilter; - DWORD nFilterIndex; - LPSTR lpstrFile; - DWORD nMaxFile; - LPSTR lpstrFileTitle; - DWORD nMaxFileTitle; - LPCSTR lpstrInitialDir; - LPCSTR lpstrTitle; - DWORD Flags; - WORD nFileOffset; - WORD nFileExtension; - LPCSTR lpstrDefExt; - LPARAM lCustData; - LPOFNHOOKPROC lpfnHook; - LPCSTR lpTemplateName; -} -alias OPENFILENAMEA *LPOPENFILENAMEA; - -struct OPENFILENAMEW { - DWORD lStructSize; - HWND hwndOwner; - HINSTANCE hInstance; - LPCWSTR lpstrFilter; - LPWSTR lpstrCustomFilter; - DWORD nMaxCustFilter; - DWORD nFilterIndex; - LPWSTR lpstrFile; - DWORD nMaxFile; - LPWSTR lpstrFileTitle; - DWORD nMaxFileTitle; - LPCWSTR lpstrInitialDir; - LPCWSTR lpstrTitle; - DWORD Flags; - WORD nFileOffset; - WORD nFileExtension; - LPCWSTR lpstrDefExt; - LPARAM lCustData; - LPOFNHOOKPROC lpfnHook; - LPCWSTR lpTemplateName; -} -alias OPENFILENAMEW *LPOPENFILENAMEW; - -BOOL GetOpenFileNameA(LPOPENFILENAMEA); -BOOL GetOpenFileNameW(LPOPENFILENAMEW); - -BOOL GetSaveFileNameA(LPOPENFILENAMEA); -BOOL GetSaveFileNameW(LPOPENFILENAMEW); - -short GetFileTitleA(LPCSTR, LPSTR, WORD); -short GetFileTitleW(LPCWSTR, LPWSTR, WORD); - -enum -{ - PM_NOREMOVE = 0x0000, - PM_REMOVE = 0x0001, - PM_NOYIELD = 0x0002, -} - -/* Bitmap Header Definition */ -struct BITMAP -{ - LONG bmType; - LONG bmWidth; - LONG bmHeight; - LONG bmWidthBytes; - WORD bmPlanes; - WORD bmBitsPixel; - LPVOID bmBits; -} -alias BITMAP* PBITMAP, NPBITMAP, LPBITMAP; - - -export HDC CreateCompatibleDC(HDC); - -export int GetObjectA(HGDIOBJ, int, LPVOID); -export int GetObjectW(HGDIOBJ, int, LPVOID); -export BOOL DeleteDC(HDC); - -struct LOGFONTA -{ - LONG lfHeight; - LONG lfWidth; - LONG lfEscapement; - LONG lfOrientation; - LONG lfWeight; - BYTE lfItalic; - BYTE lfUnderline; - BYTE lfStrikeOut; - BYTE lfCharSet; - BYTE lfOutPrecision; - BYTE lfClipPrecision; - BYTE lfQuality; - BYTE lfPitchAndFamily; - CHAR lfFaceName[32 ]; -} -alias LOGFONTA* PLOGFONTA, NPLOGFONTA, LPLOGFONTA; - -export HMENU LoadMenuA(HINSTANCE hInstance, LPCSTR lpMenuName); -export HMENU LoadMenuW(HINSTANCE hInstance, LPCWSTR lpMenuName); - -export HMENU GetSubMenu(HMENU hMenu, int nPos); - -export HBITMAP LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName); -export HBITMAP LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName); - -LPSTR MAKEINTRESOURCEA(int i) { return cast(LPSTR)(cast(DWORD)(cast(WORD)(i))); } - -export HFONT CreateFontIndirectA(LOGFONTA *); - -export BOOL MessageBeep(UINT uType); -export int ShowCursor(BOOL bShow); -export BOOL SetCursorPos(int X, int Y); -export HCURSOR SetCursor(HCURSOR hCursor); -export BOOL GetCursorPos(LPPOINT lpPoint); -export BOOL ClipCursor( RECT *lpRect); -export BOOL GetClipCursor(LPRECT lpRect); -export HCURSOR GetCursor(); -export BOOL CreateCaret(HWND hWnd, HBITMAP hBitmap , int nWidth, int nHeight); -export UINT GetCaretBlinkTime(); -export BOOL SetCaretBlinkTime(UINT uMSeconds); -export BOOL DestroyCaret(); -export BOOL HideCaret(HWND hWnd); -export BOOL ShowCaret(HWND hWnd); -export BOOL SetCaretPos(int X, int Y); -export BOOL GetCaretPos(LPPOINT lpPoint); -export BOOL ClientToScreen(HWND hWnd, LPPOINT lpPoint); -export BOOL ScreenToClient(HWND hWnd, LPPOINT lpPoint); -export int MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints); -export HWND WindowFromPoint(POINT Point); -export HWND ChildWindowFromPoint(HWND hWndParent, POINT Point); - - -export BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, - int nReserved, HWND hWnd, RECT *prcRect); - -align (2) struct DLGTEMPLATE { - DWORD style; - DWORD dwExtendedStyle; - WORD cdit; - short x; - short y; - short cx; - short cy; -} -alias DLGTEMPLATE *LPDLGTEMPLATEA; -alias DLGTEMPLATE *LPDLGTEMPLATEW; - - -alias LPDLGTEMPLATEA LPDLGTEMPLATE; - -alias DLGTEMPLATE *LPCDLGTEMPLATEA; -alias DLGTEMPLATE *LPCDLGTEMPLATEW; - - -alias LPCDLGTEMPLATEA LPCDLGTEMPLATE; - - -export int DialogBoxParamA(HINSTANCE hInstance, LPCSTR lpTemplateName, - HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); -export int DialogBoxIndirectParamA(HINSTANCE hInstance, - LPCDLGTEMPLATEA hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, - LPARAM dwInitParam); - -enum : DWORD -{ - SRCCOPY = cast(DWORD)0x00CC0020, /* dest = source */ - SRCPAINT = cast(DWORD)0x00EE0086, /* dest = source OR dest */ - SRCAND = cast(DWORD)0x008800C6, /* dest = source AND dest */ - SRCINVERT = cast(DWORD)0x00660046, /* dest = source XOR dest */ - SRCERASE = cast(DWORD)0x00440328, /* dest = source AND (NOT dest) */ - NOTSRCCOPY = cast(DWORD)0x00330008, /* dest = (NOT source) */ - NOTSRCERASE = cast(DWORD)0x001100A6, /* dest = (NOT src) AND (NOT dest) */ - MERGECOPY = cast(DWORD)0x00C000CA, /* dest = (source AND pattern) */ - MERGEPAINT = cast(DWORD)0x00BB0226, /* dest = (NOT source) OR dest */ - PATCOPY = cast(DWORD)0x00F00021, /* dest = pattern */ - PATPAINT = cast(DWORD)0x00FB0A09, /* dest = DPSnoo */ - PATINVERT = cast(DWORD)0x005A0049, /* dest = pattern XOR dest */ - DSTINVERT = cast(DWORD)0x00550009, /* dest = (NOT dest) */ - BLACKNESS = cast(DWORD)0x00000042, /* dest = BLACK */ - WHITENESS = cast(DWORD)0x00FF0062, /* dest = WHITE */ -} - -enum -{ - SND_SYNC = 0x0000, /* play synchronously (default) */ - SND_ASYNC = 0x0001, /* play asynchronously */ - SND_NODEFAULT = 0x0002, /* silence (!default) if sound not found */ - SND_MEMORY = 0x0004, /* pszSound points to a memory file */ - SND_LOOP = 0x0008, /* loop the sound until next sndPlaySound */ - SND_NOSTOP = 0x0010, /* don't stop any currently playing sound */ - - SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */ - SND_ALIAS = 0x00010000, /* name is a registry alias */ - SND_ALIAS_ID = 0x00110000, /* alias is a predefined ID */ - SND_FILENAME = 0x00020000, /* name is file name */ - SND_RESOURCE = 0x00040004, /* name is resource name or atom */ - - SND_PURGE = 0x0040, /* purge non-static events for task */ - SND_APPLICATION = 0x0080, /* look for application specific association */ - - - SND_ALIAS_START = 0, /* alias base */ -} - -export BOOL PlaySoundA(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound); -export BOOL PlaySoundW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound); - -export int GetClipBox(HDC, LPRECT); -export int GetClipRgn(HDC, HRGN); -export int GetMetaRgn(HDC, HRGN); -export HGDIOBJ GetCurrentObject(HDC, UINT); -export BOOL GetCurrentPositionEx(HDC, LPPOINT); -export int GetDeviceCaps(HDC, int); - -struct LOGPEN - { - UINT lopnStyle; - POINT lopnWidth; - COLORREF lopnColor; -} -alias LOGPEN* PLOGPEN, NPLOGPEN, LPLOGPEN; - -enum -{ - PS_SOLID = 0, - PS_DASH = 1, /* ------- */ - PS_DOT = 2, /* ....... */ - PS_DASHDOT = 3, /* _._._._ */ - PS_DASHDOTDOT = 4, /* _.._.._ */ - PS_NULL = 5, - PS_INSIDEFRAME = 6, - PS_USERSTYLE = 7, - PS_ALTERNATE = 8, - PS_STYLE_MASK = 0x0000000F, - - PS_ENDCAP_ROUND = 0x00000000, - PS_ENDCAP_SQUARE = 0x00000100, - PS_ENDCAP_FLAT = 0x00000200, - PS_ENDCAP_MASK = 0x00000F00, - - PS_JOIN_ROUND = 0x00000000, - PS_JOIN_BEVEL = 0x00001000, - PS_JOIN_MITER = 0x00002000, - PS_JOIN_MASK = 0x0000F000, - - PS_COSMETIC = 0x00000000, - PS_GEOMETRIC = 0x00010000, - PS_TYPE_MASK = 0x000F0000, -} - -export HPALETTE CreatePalette(LOGPALETTE *); -export HPEN CreatePen(int, int, COLORREF); -export HPEN CreatePenIndirect(LOGPEN *); -export HRGN CreatePolyPolygonRgn(POINT *, INT *, int, int); -export HBRUSH CreatePatternBrush(HBITMAP); -export HRGN CreateRectRgn(int, int, int, int); -export HRGN CreateRectRgnIndirect(RECT *); -export HRGN CreateRoundRectRgn(int, int, int, int, int, int); -export BOOL CreateScalableFontResourceA(DWORD, LPCSTR, LPCSTR, LPCSTR); -export BOOL CreateScalableFontResourceW(DWORD, LPCWSTR, LPCWSTR, LPCWSTR); - -COLORREF RGB(int r, int g, int b) -{ - return cast(COLORREF) - ((cast(BYTE)r|(cast(WORD)(cast(BYTE)g)<<8))|((cast(DWORD)cast(BYTE)b)<<16)); -} - -export BOOL LineTo(HDC, int, int); -export BOOL DeleteObject(HGDIOBJ); -export int FillRect(HDC hDC, RECT *lprc, HBRUSH hbr); - - -export BOOL EndDialog(HWND hDlg, int nResult); -export HWND GetDlgItem(HWND hDlg, int nIDDlgItem); - -export BOOL SetDlgItemInt(HWND hDlg, int nIDDlgItem, UINT uValue, BOOL bSigned); -export UINT GetDlgItemInt(HWND hDlg, int nIDDlgItem, BOOL *lpTranslated, - BOOL bSigned); - -export BOOL SetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPCSTR lpString); -export BOOL SetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPCWSTR lpString); - -export UINT GetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPSTR lpString, int nMaxCount); -export UINT GetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPWSTR lpString, int nMaxCount); - -export BOOL CheckDlgButton(HWND hDlg, int nIDButton, UINT uCheck); -export BOOL CheckRadioButton(HWND hDlg, int nIDFirstButton, int nIDLastButton, - int nIDCheckButton); - -export UINT IsDlgButtonChecked(HWND hDlg, int nIDButton); - -export HWND SetFocus(HWND hWnd); - -export int wsprintfA(LPSTR, LPCSTR, ...); -export int wsprintfW(LPWSTR, LPCWSTR, ...); - -const uint INFINITE = uint.max; -const uint WAIT_OBJECT_0 = 0; - -export HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName); -export HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName); -export BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount); -} diff --git a/lphobos/std/c/windows/winsock.d b/lphobos/std/c/windows/winsock.d deleted file mode 100644 index 178d9b9b1a7..00000000000 --- a/lphobos/std/c/windows/winsock.d +++ /dev/null @@ -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]; - } -} - diff --git a/lphobos/std/conv.d b/lphobos/std/conv.d deleted file mode 100644 index 2ada2848b3f..00000000000 --- a/lphobos/std/conv.d +++ /dev/null @@ -1,1578 +0,0 @@ - -// Written in the D programming language. - -/* - * Copyright (C) 2002-2006 by Digital Mars, www.digitalmars.com - * Written by Walter Bright - * Some parts contributed by David L. Davis - * - * 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. - */ - -/*********** - * Conversion building blocks. These differ from the C equivalents - * atoi() and atol() by - * checking for overflow and not allowing whitespace. - * - * For conversion to signed types, the grammar recognized is: - *
-$(I Integer):
-    $(I Sign UnsignedInteger)
-    $(I UnsignedInteger)
-
-$(I Sign):
-    $(B +)
-    $(B -)
- * 
- * For conversion to signed types, the grammar recognized is: - *
-$(I UnsignedInteger):
-    $(I DecimalDigit)
-    $(I DecimalDigit) $(I UnsignedInteger)
- * 
- * Macros: - * WIKI=Phobos/StdConv - */ - -module std.conv; - -private import std.string; // for atof(), toString() -private import std.c.stdlib; -private import std.math; // for fabs(), isnan() -private import std.stdio; // for writefln() and printf() - - -//debug=conv; // uncomment to turn on debugging printf's - -/* ************* Exceptions *************** */ - -/** - * Thrown on conversion errors, which happens on deviation from the grammar. - */ -class ConvError : Error -{ - this(char[] s) - { - super("conversion " ~ s); - } -} - -private void conv_error(char[] s) -{ - throw new ConvError(s); -} - -/** - * Thrown on conversion overflow errors. - */ -class ConvOverflowError : Error -{ - this(char[] s) - { - super("Error: overflow " ~ s); - } -} - -private void conv_overflow(char[] s) -{ - throw new ConvOverflowError(s); -} - -/*************************************************************** - * Convert character string to the return type. - */ - -int toInt(char[] s) -{ - int length = s.length; - - if (!length) - goto Lerr; - - int sign = 0; - int v = 0; - - for (int i = 0; i < length; i++) - { - char c = s[i]; - if (c >= '0' && c <= '9') - { - if (v < int.max/10 || (v == int.max/10 && c + sign <= '7')) - v = v * 10 + (c - '0'); - else - goto Loverflow; - } - else if (c == '-' && i == 0) - { - sign = -1; - if (length == 1) - goto Lerr; - } - else if (c == '+' && i == 0) - { - if (length == 1) - goto Lerr; - } - else - goto Lerr; - } - if (sign == -1) - { - if (cast(uint)v > 0x80000000) - goto Loverflow; - v = -v; - } - else - { - if (cast(uint)v > 0x7FFFFFFF) - goto Loverflow; - } - return v; - -Loverflow: - conv_overflow(s); - -Lerr: - conv_error(s); - return 0; -} - -unittest -{ - debug(conv) printf("conv.toInt.unittest\n"); - - int i; - - i = toInt("0"); - assert(i == 0); - - i = toInt("+0"); - assert(i == 0); - - i = toInt("-0"); - assert(i == 0); - - i = toInt("6"); - assert(i == 6); - - i = toInt("+23"); - assert(i == 23); - - i = toInt("-468"); - assert(i == -468); - - i = toInt("2147483647"); - assert(i == 0x7FFFFFFF); - - i = toInt("-2147483648"); - assert(i == 0x80000000); - - static char[][] errors = - [ - "", - "-", - "+", - "-+", - " ", - " 0", - "0 ", - "- 0", - "1-", - "xx", - "123h", - "2147483648", - "-2147483649", - "5656566565", - ]; - - for (int j = 0; j < errors.length; j++) - { - i = 47; - try - { - i = toInt(errors[j]); - printf("i = %d\n", i); - } - catch (Error e) - { - debug(conv) e.print(); - i = 3; - } - assert(i == 3); - } -} - - -/******************************************************* - * ditto - */ - -uint toUint(char[] s) -{ - int length = s.length; - - if (!length) - goto Lerr; - - uint v = 0; - - for (int i = 0; i < length; i++) - { - char c = s[i]; - if (c >= '0' && c <= '9') - { - if (v < uint.max/10 || (v == uint.max/10 && c <= '5')) - v = v * 10 + (c - '0'); - else - goto Loverflow; - } - else - goto Lerr; - } - return v; - -Loverflow: - conv_overflow(s); - -Lerr: - conv_error(s); - return 0; -} - -unittest -{ - debug(conv) printf("conv.toUint.unittest\n"); - - uint i; - - i = toUint("0"); - assert(i == 0); - - i = toUint("6"); - assert(i == 6); - - i = toUint("23"); - assert(i == 23); - - i = toUint("468"); - assert(i == 468); - - i = toUint("2147483647"); - assert(i == 0x7FFFFFFF); - - i = toUint("4294967295"); - assert(i == 0xFFFFFFFF); - - static char[][] errors = - [ - "", - "-", - "+", - "-+", - " ", - " 0", - "0 ", - "- 0", - "1-", - "+5", - "-78", - "xx", - "123h", - "4294967296", - ]; - - for (int j = 0; j < errors.length; j++) - { - i = 47; - try - { - i = toUint(errors[j]); - printf("i = %d\n", i); - } - catch (Error e) - { - debug(conv) e.print(); - i = 3; - } - assert(i == 3); - } -} - -/******************************************************* - * ditto - */ - -long toLong(char[] s) -{ - int length = s.length; - - if (!length) - goto Lerr; - - int sign = 0; - long v = 0; - - for (int i = 0; i < length; i++) - { - char c = s[i]; - if (c >= '0' && c <= '9') - { - if (v < long.max/10 || (v == long.max/10 && c + sign <= '7')) - v = v * 10 + (c - '0'); - else - goto Loverflow; - } - else if (c == '-' && i == 0) - { - sign = -1; - if (length == 1) - goto Lerr; - } - else if (c == '+' && i == 0) - { - if (length == 1) - goto Lerr; - } - else - goto Lerr; - } - if (sign == -1) - { - if (cast(ulong)v > 0x8000000000000000) - goto Loverflow; - v = -v; - } - else - { - if (cast(ulong)v > 0x7FFFFFFFFFFFFFFF) - goto Loverflow; - } - return v; - -Loverflow: - conv_overflow(s); - -Lerr: - conv_error(s); - return 0; -} - -unittest -{ - debug(conv) printf("conv.toLong.unittest\n"); - - long i; - - i = toLong("0"); - assert(i == 0); - - i = toLong("+0"); - assert(i == 0); - - i = toLong("-0"); - assert(i == 0); - - i = toLong("6"); - assert(i == 6); - - i = toLong("+23"); - assert(i == 23); - - i = toLong("-468"); - assert(i == -468); - - i = toLong("2147483647"); - assert(i == 0x7FFFFFFF); - - i = toLong("-2147483648"); - assert(i == -0x80000000L); - - i = toLong("9223372036854775807"); - assert(i == 0x7FFFFFFFFFFFFFFF); - - i = toLong("-9223372036854775808"); - assert(i == 0x8000000000000000); - - static char[][] errors = - [ - "", - "-", - "+", - "-+", - " ", - " 0", - "0 ", - "- 0", - "1-", - "xx", - "123h", - "9223372036854775808", - "-9223372036854775809", - ]; - - for (int j = 0; j < errors.length; j++) - { - i = 47; - try - { - i = toLong(errors[j]); - printf("l = %d\n", i); - } - catch (Error e) - { - debug(conv) e.print(); - i = 3; - } - assert(i == 3); - } -} - - -/******************************************************* - * ditto - */ - -ulong toUlong(char[] s) -{ - int length = s.length; - - if (!length) - goto Lerr; - - ulong v = 0; - - for (int i = 0; i < length; i++) - { - char c = s[i]; - if (c >= '0' && c <= '9') - { - if (v < ulong.max/10 || (v == ulong.max/10 && c <= '5')) - v = v * 10 + (c - '0'); - else - goto Loverflow; - } - else - goto Lerr; - } - return v; - -Loverflow: - conv_overflow(s); - -Lerr: - conv_error(s); - return 0; -} - -unittest -{ - debug(conv) printf("conv.toUlong.unittest\n"); - - ulong i; - - i = toUlong("0"); - assert(i == 0); - - i = toUlong("6"); - assert(i == 6); - - i = toUlong("23"); - assert(i == 23); - - i = toUlong("468"); - assert(i == 468); - - i = toUlong("2147483647"); - assert(i == 0x7FFFFFFF); - - i = toUlong("4294967295"); - assert(i == 0xFFFFFFFF); - - i = toUlong("9223372036854775807"); - assert(i == 0x7FFFFFFFFFFFFFFF); - - i = toUlong("18446744073709551615"); - assert(i == 0xFFFFFFFFFFFFFFFF); - - - static char[][] errors = - [ - "", - "-", - "+", - "-+", - " ", - " 0", - "0 ", - "- 0", - "1-", - "+5", - "-78", - "xx", - "123h", - "18446744073709551616", - ]; - - for (int j = 0; j < errors.length; j++) - { - i = 47; - try - { - i = toUlong(errors[j]); - printf("i = %d\n", i); - } - catch (Error e) - { - debug(conv) e.print(); - i = 3; - } - assert(i == 3); - } -} - - -/******************************************************* - * ditto - */ - -short toShort(char[] s) -{ - int v = toInt(s); - - if (v != cast(short)v) - goto Loverflow; - - return cast(short)v; - -Loverflow: - conv_overflow(s); - return 0; -} - -unittest -{ - debug(conv) printf("conv.toShort.unittest\n"); - - short i; - - i = toShort("0"); - assert(i == 0); - - i = toShort("+0"); - assert(i == 0); - - i = toShort("-0"); - assert(i == 0); - - i = toShort("6"); - assert(i == 6); - - i = toShort("+23"); - assert(i == 23); - - i = toShort("-468"); - assert(i == -468); - - i = toShort("32767"); - assert(i == 0x7FFF); - - i = toShort("-32768"); - assert(i == cast(short)0x8000); - - static char[][] errors = - [ - "", - "-", - "+", - "-+", - " ", - " 0", - "0 ", - "- 0", - "1-", - "xx", - "123h", - "32768", - "-32769", - ]; - - for (int j = 0; j < errors.length; j++) - { - i = 47; - try - { - i = toShort(errors[j]); - printf("i = %d\n", i); - } - catch (Error e) - { - debug(conv) e.print(); - i = 3; - } - assert(i == 3); - } -} - - -/******************************************************* - * ditto - */ - -ushort toUshort(char[] s) -{ - uint v = toUint(s); - - if (v != cast(ushort)v) - goto Loverflow; - - return cast(ushort)v; - -Loverflow: - conv_overflow(s); - return 0; -} - -unittest -{ - debug(conv) printf("conv.toUshort.unittest\n"); - - ushort i; - - i = toUshort("0"); - assert(i == 0); - - i = toUshort("6"); - assert(i == 6); - - i = toUshort("23"); - assert(i == 23); - - i = toUshort("468"); - assert(i == 468); - - i = toUshort("32767"); - assert(i == 0x7FFF); - - i = toUshort("65535"); - assert(i == 0xFFFF); - - static char[][] errors = - [ - "", - "-", - "+", - "-+", - " ", - " 0", - "0 ", - "- 0", - "1-", - "+5", - "-78", - "xx", - "123h", - "65536", - ]; - - for (int j = 0; j < errors.length; j++) - { - i = 47; - try - { - i = toUshort(errors[j]); - printf("i = %d\n", i); - } - catch (Error e) - { - debug(conv) e.print(); - i = 3; - } - assert(i == 3); - } -} - - -/******************************************************* - * ditto - */ - -byte toByte(char[] s) -{ - int v = toInt(s); - - if (v != cast(byte)v) - goto Loverflow; - - return cast(byte)v; - -Loverflow: - conv_overflow(s); - return 0; -} - -unittest -{ - debug(conv) printf("conv.toByte.unittest\n"); - - byte i; - - i = toByte("0"); - assert(i == 0); - - i = toByte("+0"); - assert(i == 0); - - i = toByte("-0"); - assert(i == 0); - - i = toByte("6"); - assert(i == 6); - - i = toByte("+23"); - assert(i == 23); - - i = toByte("-68"); - assert(i == -68); - - i = toByte("127"); - assert(i == 0x7F); - - i = toByte("-128"); - assert(i == cast(byte)0x80); - - static char[][] errors = - [ - "", - "-", - "+", - "-+", - " ", - " 0", - "0 ", - "- 0", - "1-", - "xx", - "123h", - "128", - "-129", - ]; - - for (int j = 0; j < errors.length; j++) - { - i = 47; - try - { - i = toByte(errors[j]); - printf("i = %d\n", i); - } - catch (Error e) - { - debug(conv) e.print(); - i = 3; - } - assert(i == 3); - } -} - - -/******************************************************* - * ditto - */ - -ubyte toUbyte(char[] s) -{ - uint v = toUint(s); - - if (v != cast(ubyte)v) - goto Loverflow; - - return cast(ubyte)v; - -Loverflow: - conv_overflow(s); - return 0; -} - -unittest -{ - debug(conv) printf("conv.toUbyte.unittest\n"); - - ubyte i; - - i = toUbyte("0"); - assert(i == 0); - - i = toUbyte("6"); - assert(i == 6); - - i = toUbyte("23"); - assert(i == 23); - - i = toUbyte("68"); - assert(i == 68); - - i = toUbyte("127"); - assert(i == 0x7F); - - i = toUbyte("255"); - assert(i == 0xFF); - - static char[][] errors = - [ - "", - "-", - "+", - "-+", - " ", - " 0", - "0 ", - "- 0", - "1-", - "+5", - "-78", - "xx", - "123h", - "256", - ]; - - for (int j = 0; j < errors.length; j++) - { - i = 47; - try - { - i = toUbyte(errors[j]); - printf("i = %d\n", i); - } - catch (Error e) - { - debug(conv) e.print(); - i = 3; - } - assert(i == 3); - } -} - - -/******************************************************* - * ditto - */ - -float toFloat(in char[] s) -{ - float f; - char* endptr; - char* sz; - - //writefln("toFloat('%s')", s); - sz = toStringz(s); - if (std.ctype.isspace(*sz)) - goto Lerr; - - // BUG: should set __locale_decpoint to "." for DMC - - setErrno(0); - f = strtof(sz, &endptr); - if (getErrno() == ERANGE) - goto Lerr; - if (endptr && (endptr == s.ptr || *endptr != 0)) - goto Lerr; - - return f; - - Lerr: - conv_error(s ~ " not representable as a float"); - assert(0); -} - -unittest -{ - debug( conv ) writefln( "conv.toFloat.unittest" ); - float f; - - f = toFloat( "123" ); - assert( f == 123f ); - f = toFloat( "+123" ); - assert( f == +123f ); - f = toFloat( "-123" ); - assert( f == -123f ); - f = toFloat( "123e+2" ); - assert( f == 123e+2f ); - - f = toFloat( "123e-2" ); - assert( f == 123e-2f ); - f = toFloat( "123." ); - assert( f == 123.f ); - f = toFloat( ".456" ); - assert( f == .456f ); - - // min and max - f = toFloat("1.17549e-38"); - assert(feq(cast(real)f, cast(real)1.17549e-38)); - assert(feq(cast(real)f, cast(real)float.min)); - f = toFloat("3.40282e+38"); - assert(toString(f) == toString(3.40282e+38)); - - // nan - f = toFloat("nan"); - assert(toString(f) == toString(float.nan)); -} - -/******************************************************* - * ditto - */ - -double toDouble(in char[] s) -{ - double f; - char* endptr; - char* sz; - - //writefln("toDouble('%s')", s); - sz = toStringz(s); - if (std.ctype.isspace(*sz)) - goto Lerr; - - // BUG: should set __locale_decpoint to "." for DMC - - setErrno(0); - f = strtod(sz, &endptr); - if (getErrno() == ERANGE) - goto Lerr; - if (endptr && (endptr == s.ptr || *endptr != 0)) - goto Lerr; - - return f; - - Lerr: - conv_error(s ~ " not representable as a double"); - assert(0); -} - -unittest -{ - debug( conv ) writefln( "conv.toDouble.unittest" ); - double d; - - d = toDouble( "123" ); - assert( d == 123 ); - d = toDouble( "+123" ); - assert( d == +123 ); - d = toDouble( "-123" ); - assert( d == -123 ); - d = toDouble( "123e2" ); - assert( d == 123e2); - d = toDouble( "123e-2" ); - assert( d == 123e-2 ); - d = toDouble( "123." ); - assert( d == 123. ); - d = toDouble( ".456" ); - assert( d == .456 ); - d = toDouble( "1.23456E+2" ); - assert( d == 1.23456E+2 ); - - // min and max - d = toDouble("2.22507e-308"); - assert(feq(cast(real)d, cast(real)2.22507e-308)); - assert(feq(cast(real)d, cast(real)double.min)); - d = toDouble("1.79769e+308"); - assert(toString(d) == toString(1.79769e+308)); - assert(toString(d) == toString(double.max)); - - // nan - d = toDouble("nan"); - assert(toString(d) == toString(double.nan)); - //assert(cast(real)d == cast(real)double.nan); -} - -/******************************************************* - * ditto - */ -real toReal(in char[] s) -{ - real f; - char* endptr; - char* sz; - - //writefln("toReal('%s')", s); - sz = toStringz(s); - if (std.ctype.isspace(*sz)) - goto Lerr; - - // BUG: should set __locale_decpoint to "." for DMC - - setErrno(0); - f = strtold(sz, &endptr); - if (getErrno() == ERANGE) - goto Lerr; - if (endptr && (endptr == s.ptr || *endptr != 0)) - goto Lerr; - - return f; - - Lerr: - conv_error(s ~ " not representable as a real"); - assert(0); -} - -unittest -{ - debug(conv) writefln("conv.toReal.unittest"); - real r; - - r = toReal("123"); - assert(r == 123L); - r = toReal("+123"); - assert(r == 123L); - r = toReal("-123"); - assert(r == -123L); - r = toReal("123e2"); - assert(feq(r, 123e2L)); - r = toReal("123e-2"); - assert(feq(r, 1.23L)); - r = toReal("123."); - assert(r == 123L); - r = toReal(".456"); - assert(r == .456L); - - r = toReal("1.23456e+2"); - assert(feq(r, 1.23456e+2L)); - r = toReal(toString(real.max / 2L)); - assert(toString(r) == toString(real.max / 2L)); - - // min and max - r = toReal(toString(real.min)); - assert(toString(r) == toString(real.min)); - r = toReal(toString(real.max)); - assert(toString(r) == toString(real.max)); - - // nan - r = toReal("nan"); - assert(toString(r) == toString(real.nan)); - //assert(r == real.nan); - - r = toReal(toString(real.nan)); - assert(toString(r) == toString(real.nan)); - //assert(r == real.nan); -} - -version (none) -{ /* These are removed for the moment because of concern about - * what to do about the 'i' suffix. Should it be there? - * Should it not? What about 'nan', should it be 'nani'? - * 'infinity' or 'infinityi'? - * Should it match what toString(ifloat) does with the 'i' suffix? - */ - -/******************************************************* - * ditto - */ - -ifloat toIfloat(in char[] s) -{ - return toFloat(s) * 1.0i; -} - -unittest -{ - debug(conv) writefln("conv.toIfloat.unittest"); - ifloat ift; - - ift = toIfloat(toString(123.45)); - assert(toString(ift) == toString(123.45i)); - - ift = toIfloat(toString(456.77i)); - assert(toString(ift) == toString(456.77i)); - - // min and max - ift = toIfloat(toString(ifloat.min)); - assert(toString(ift) == toString(ifloat.min) ); - assert(feq(cast(ireal)ift, cast(ireal)ifloat.min)); - - ift = toIfloat(toString(ifloat.max)); - assert(toString(ift) == toString(ifloat.max)); - assert(feq(cast(ireal)ift, cast(ireal)ifloat.max)); - - // nan - ift = toIfloat("nani"); - assert(cast(real)ift == cast(real)ifloat.nan); - - ift = toIfloat(toString(ifloat.nan)); - assert(toString(ift) == toString(ifloat.nan)); - assert(feq(cast(ireal)ift, cast(ireal)ifloat.nan)); -} - -/******************************************************* - * ditto - */ - -idouble toIdouble(in char[] s) -{ - return toDouble(s) * 1.0i; -} - -unittest -{ - debug(conv) writefln("conv.toIdouble.unittest"); - idouble id; - - id = toIdouble(toString("123.45")); - assert(id == 123.45i); - - id = toIdouble(toString("123.45e+302i")); - assert(id == 123.45e+302i); - - // min and max - id = toIdouble(toString(idouble.min)); - assert(toString( id ) == toString(idouble.min)); - assert(feq(cast(ireal)id.re, cast(ireal)idouble.min.re)); - assert(feq(cast(ireal)id.im, cast(ireal)idouble.min.im)); - - id = toIdouble(toString(idouble.max)); - assert(toString(id) == toString(idouble.max)); - assert(feq(cast(ireal)id.re, cast(ireal)idouble.max.re)); - assert(feq(cast(ireal)id.im, cast(ireal)idouble.max.im)); - - // nan - id = toIdouble("nani"); - assert(cast(real)id == cast(real)idouble.nan); - - id = toIdouble(toString(idouble.nan)); - assert(toString(id) == toString(idouble.nan)); -} - -/******************************************************* - * ditto - */ - -ireal toIreal(in char[] s) -{ - return toReal(s) * 1.0i; -} - -unittest -{ - debug(conv) writefln("conv.toIreal.unittest"); - ireal ir; - - ir = toIreal(toString("123.45")); - assert(feq(cast(real)ir.re, cast(real)123.45i)); - - ir = toIreal(toString("123.45e+82i")); - assert(toString(ir) == toString(123.45e+82i)); - //assert(ir == 123.45e+82i); - - // min and max - ir = toIreal(toString(ireal.min)); - assert(toString(ir) == toString(ireal.min)); - assert(feq(cast(real)ir.re, cast(real)ireal.min.re)); - assert(feq(cast(real)ir.im, cast(real)ireal.min.im)); - - ir = toIreal(toString(ireal.max)); - assert(toString(ir) == toString(ireal.max)); - assert(feq(cast(real)ir.re, cast(real)ireal.max.re)); - //assert(feq(cast(real)ir.im, cast(real)ireal.max.im)); - - // nan - ir = toIreal("nani"); - assert(cast(real)ir == cast(real)ireal.nan); - - ir = toIreal(toString(ireal.nan)); - assert(toString(ir) == toString(ireal.nan)); -} - - -/******************************************************* - * ditto - */ -cfloat toCfloat(in char[] s) -{ - char[] s1; - char[] s2; - real r1; - real r2; - cfloat cf; - bool b = 0; - char* endptr; - - if (!s.length) - goto Lerr; - - b = getComplexStrings(s, s1, s2); - - if (!b) - goto Lerr; - - // atof(s1); - endptr = &s1[s1.length - 1]; - r1 = strtold(s1, &endptr); - - // atof(s2); - endptr = &s2[s2.length - 1]; - r2 = strtold(s2, &endptr); - - cf = cast(cfloat)(r1 + (r2 * 1.0i)); - - //writefln( "toCfloat() r1=%g, r2=%g, cf=%g, max=%g", - // r1, r2, cf, cfloat.max); - // Currently disabled due to a posted bug where a - // complex float greater-than compare to .max compares - // incorrectly. - //if (cf > cfloat.max) - // goto Loverflow; - - return cf; - - Loverflow: - conv_overflow(s); - - Lerr: - conv_error(s); - return cast(cfloat)0.0e-0+0i; -} - -unittest -{ - debug(conv) writefln("conv.toCfloat.unittest"); - cfloat cf; - - cf = toCfloat(toString("1.2345e-5+0i")); - assert(toString(cf) == toString(1.2345e-5+0i)); - assert(feq(cf, 1.2345e-5+0i)); - - // min and max - cf = toCfloat(toString(cfloat.min)); - assert(toString(cf) == toString(cfloat.min)); - - cf = toCfloat(toString(cfloat.max)); - assert(toString(cf) == toString(cfloat.max)); - - // nan ( nan+nani ) - cf = toCfloat("nani"); - //writefln("toCfloat() cf=%g, cf=\"%s\", nan=%s", - // cf, toString(cf), toString(cfloat.nan)); - assert(toString(cf) == toString(cfloat.nan)); - - cf = toCdouble("nan+nani"); - assert(toString(cf) == toString(cfloat.nan)); - - cf = toCfloat(toString(cfloat.nan)); - assert(toString(cf) == toString(cfloat.nan)); - assert(feq(cast(creal)cf, cast(creal)cfloat.nan)); -} - -/******************************************************* - * ditto - */ -cdouble toCdouble(in char[] s) -{ - char[] s1; - char[] s2; - real r1; - real r2; - cdouble cd; - bool b = 0; - char* endptr; - - if (!s.length) - goto Lerr; - - b = getComplexStrings(s, s1, s2); - - if (!b) - goto Lerr; - - // atof(s1); - endptr = &s1[s1.length - 1]; - r1 = strtold(s1, &endptr); - - // atof(s2); - endptr = &s2[s2.length - 1]; - r2 = strtold(s2, &endptr); //atof(s2); - - cd = cast(cdouble)(r1 + (r2 * 1.0i)); - - //Disabled, waiting on a bug fix. - //if (cd > cdouble.max) //same problem the toCfloat() having - // goto Loverflow; - - return cd; - - Loverflow: - conv_overflow(s); - - Lerr: - conv_error(s); - return cast(cdouble)0.0e-0+0i; -} - -unittest -{ - debug(conv) writefln("conv.toCdouble.unittest"); - cdouble cd; - - cd = toCdouble(toString("1.2345e-5+0i")); - assert(toString( cd ) == toString(1.2345e-5+0i)); - assert(feq(cd, 1.2345e-5+0i)); - - // min and max - cd = toCdouble(toString(cdouble.min)); - assert(toString(cd) == toString(cdouble.min)); - assert(feq(cast(creal)cd, cast(creal)cdouble.min)); - - cd = toCdouble(toString(cdouble.max)); - assert(toString( cd ) == toString(cdouble.max)); - assert(feq(cast(creal)cd, cast(creal)cdouble.max)); - - // nan ( nan+nani ) - cd = toCdouble("nani"); - assert(toString(cd) == toString(cdouble.nan)); - - cd = toCdouble("nan+nani"); - assert(toString(cd) == toString(cdouble.nan)); - - cd = toCdouble(toString(cdouble.nan)); - assert(toString(cd) == toString(cdouble.nan)); - assert(feq(cast(creal)cd, cast(creal)cdouble.nan)); -} - -/******************************************************* - * ditto - */ -creal toCreal(in char[] s) -{ - char[] s1; - char[] s2; - real r1; - real r2; - creal cr; - bool b = 0; - char* endptr; - - if (!s.length) - goto Lerr; - - b = getComplexStrings(s, s1, s2); - - if (!b) - goto Lerr; - - // atof(s1); - endptr = &s1[s1.length - 1]; - r1 = strtold(s1, &endptr); - - // atof(s2); - endptr = &s2[s2.length - 1]; - r2 = strtold(s2, &endptr); //atof(s2); - - //writefln("toCreal() r1=%g, r2=%g, s1=\"%s\", s2=\"%s\", nan=%g", - // r1, r2, s1, s2, creal.nan); - - if (s1 =="nan" && s2 == "nani") - cr = creal.nan; - else if (r2 != 0.0) - cr = cast(creal)(r1 + (r2 * 1.0i)); - else - cr = cast(creal)(r1 + 0.0i); - - return cr; - - Lerr: - conv_error(s); - return cast(creal)0.0e-0+0i; -} - -unittest -{ - debug(conv) writefln("conv.toCreal.unittest"); - creal cr; - - cr = toCreal(toString("1.2345e-5+0i")); - assert(toString(cr) == toString(1.2345e-5+0i)); - assert(feq(cr, 1.2345e-5+0i)); - - cr = toCreal(toString("0.0e-0+0i")); - assert(toString(cr) == toString(0.0e-0+0i)); - assert(cr == 0.0e-0+0i); - assert(feq(cr, 0.0e-0+0i)); - - cr = toCreal("123"); - assert(cr == 123); - - cr = toCreal("+5"); - assert(cr == 5); - - cr = toCreal("-78"); - assert(cr == -78); - - // min and max - cr = toCreal(toString(creal.min)); - assert(toString(cr) == toString(creal.min)); - assert(feq(cr, creal.min)); - - cr = toCreal(toString(creal.max)); - assert(toString(cr) == toString(creal.max)); - assert(feq(cr, creal.max)); - - // nan ( nan+nani ) - cr = toCreal("nani"); - assert(toString(cr) == toString(creal.nan)); - - cr = toCreal("nan+nani"); - assert(toString(cr) == toString(creal.nan)); - - cr = toCreal(toString(cdouble.nan)); - assert(toString(cr) == toString(creal.nan)); - assert(feq(cr, creal.nan)); -} - -} - -/* ************************************************************** - * Splits a complex float (cfloat, cdouble, and creal) into two workable strings. - * Grammar: - * ['+'|'-'] string floating-point digit {digit} - */ -private bool getComplexStrings(in char[] s, out char[] s1, out char[] s2) -{ - int len = s.length; - - if (!len) - goto Lerr; - - // When "nan" or "nani" just return them. - if (s == "nan" || s == "nani" || s == "nan+nani") - { - s1 = "nan"; - s2 = "nani"; - return 1; - } - - // Split the original string out into two strings. - for (int i = 1; i < len; i++) - if ((s[i - 1] != 'e' && s[i - 1] != 'E') && s[i] == '+') - { - s1 = s[0..i]; - if (i + 1 < len - 1) - s2 = s[i + 1..len - 1]; - else - s2 = "0e+0i"; - - break; - } - - // Handle the case when there's only a single value - // to work with, and set the other string to zero. - if (!s1.length) - { - s1 = s; - s2 = "0e+0i"; - } - - //writefln( "getComplexStrings() s=\"%s\", s1=\"%s\", s2=\"%s\", len=%d", - // s, s1, s2, len ); - - return 1; - - Lerr: - // Display the original string in the error message. - conv_error("getComplexStrings() \"" ~ s ~ "\"" ~ " s1=\"" ~ s1 ~ "\"" ~ " s2=\"" ~ s2 ~ "\""); - return 0; -} - -// feq() functions now used only in unittesting - -/* *************************************** - * Main function to compare reals with given precision - */ -private bool feq(in real rx, in real ry, in real precision) -{ - if (rx == ry) - return 1; - - if (isnan(rx)) - return cast(bool)isnan(ry); - - if (isnan(ry)) - return 0; - - return cast(bool)(fabs(rx - ry) <= precision); -} - -/* *************************************** - * (Note: Copied here from std.math's mfeq() function for unittesting) - * Simple function to compare two floating point values - * to a specified precision. - * Returns: - * 1 match - * 0 nomatch - */ -private bool feq(in real r1, in real r2) -{ - if (r1 == r2) - return 1; - - if (isnan(r1)) - return cast(bool)isnan(r2); - - if (isnan(r2)) - return 0; - - return cast(bool)(feq(r1, r2, 0.000001L)); -} - -/* *************************************** - * compare ireals with given precision - */ -private bool feq(in ireal r1, in ireal r2) -{ - real rx = cast(real)r1; - real ry = cast(real)r2; - - if (rx == ry) - return 1; - - if (isnan(rx)) - return cast(bool)isnan(ry); - - if (isnan(ry)) - return 0; - - return feq(rx, ry, 0.000001L); -} - -/* *************************************** - * compare creals with given precision - */ -private bool feq(in creal r1, in creal r2) -{ - real r1a = fabs(cast(real)r1.re - cast(real)r2.re); - real r2b = fabs(cast(real)r1.im - cast(real)r2.im); - - if ((cast(real)r1.re == cast(real)r2.re) && - (cast(real)r1.im == cast(real)r2.im)) - return 1; - - if (isnan(r1a)) - return cast(bool)isnan(r2b); - - if (isnan(r2b)) - return 0; - - return feq(r1a, r2b, 0.000001L); -} - diff --git a/lphobos/std/cstream.d b/lphobos/std/cstream.d deleted file mode 100644 index 33e05ed4f35..00000000000 --- a/lphobos/std/cstream.d +++ /dev/null @@ -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); -} - diff --git a/lphobos/std/ctype.d b/lphobos/std/ctype.d deleted file mode 100644 index 6335e950f1d..00000000000 --- a/lphobos/std/ctype.d +++ /dev/null @@ -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')); -} diff --git a/lphobos/std/date.d b/lphobos/std/date.d deleted file mode 100644 index 97572007f30..00000000000 --- a/lphobos/std/date.d +++ /dev/null @@ -1,1074 +0,0 @@ - -// Written in the D programming language. - -/** - * Dates are represented in several formats. The date implementation revolves - * around a central type, d_time, from which other formats are converted to and - * from. - * Dates are calculated using the Gregorian calendar. - * References: - * $(LINK2 http://en.wikipedia.org/wiki/Gregorian_calendar, Gregorian calendar (Wikipedia)) - * Macros: - * WIKI = Phobos/StdDate - */ - -// Copyright (c) 1999-2007 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, May 2005 -*/ - -module std.date; - -private import std.stdio; -private import std.dateparse; - -/** - * d_time is a signed arithmetic type giving the time elapsed since January 1, - * 1970. - * Negative values are for dates preceding 1970. The time unit used is Ticks. - * Ticks are milliseconds or smaller intervals. - * - * The usual arithmetic operations can be performed on d_time, such as adding, - * subtracting, etc. Elapsed time in Ticks can be computed by subtracting a - * starting d_time from an ending d_time. - */ -alias long d_time; - -/** - * A value for d_time that does not represent a valid time. - */ -const d_time d_time_nan = long.min; - -/** - * Time broken down into its components. - */ -struct Date -{ - int year = int.min; /// use int.min as "nan" year value - int month; /// 1..12 - int day; /// 1..31 - int hour; /// 0..23 - int minute; /// 0..59 - int second; /// 0..59 - int ms; /// 0..999 - int weekday; /// 0: not specified, 1..7: Sunday..Saturday - int tzcorrection = int.min; /// -1200..1200 correction in hours - - /// Parse date out of string s[] and store it in this Date instance. - void parse(string s) - { - DateParse dp; - - dp.parse(s, *this); - } -} - -enum -{ - HoursPerDay = 24, - MinutesPerHour = 60, - msPerMinute = 60 * 1000, - msPerHour = 60 * msPerMinute, - msPerDay = 86400000, - TicksPerMs = 1, - TicksPerSecond = 1000, /// Will be at least 1000 - TicksPerMinute = TicksPerSecond * 60, - TicksPerHour = TicksPerMinute * 60, - TicksPerDay = TicksPerHour * 24, -} - -d_time LocalTZA = 0; - - -const char[] daystr = "SunMonTueWedThuFriSat"; -const char[] monstr = "JanFebMarAprMayJunJulAugSepOctNovDec"; - -const int[12] mdays = [ 0,31,59,90,120,151,181,212,243,273,304,334 ]; - -/******************************** - * Compute year and week [1..53] from t. The ISO 8601 week 1 is the first week - * of the year that includes January 4. Monday is the first day of the week. - * References: - * $(LINK2 http://en.wikipedia.org/wiki/ISO_8601, ISO 8601 (Wikipedia)) - */ - -void toISO8601YearWeek(d_time t, out int year, out int week) -{ - year = YearFromTime(t); - - int yday = Day(t) - DayFromYear(year); - int d; - int w; - int ydaybeg; - - /* Determine day of week Jan 4 falls on. - * Weeks begin on a Monday. - */ - - d = DayFromYear(year); - w = (d + 3/*Jan4*/ + 3) % 7; - if (w < 0) - w += 7; - - /* Find yday of beginning of ISO 8601 year - */ - ydaybeg = 3/*Jan4*/ - w; - - /* Check if yday is actually the last week of the previous year - */ - if (yday < ydaybeg) - { - year -= 1; - week = 53; - return; - } - - /* Check if yday is actually the first week of the next year - */ - if (yday >= 362) // possible - { int d2; - int ydaybeg2; - - d2 = DayFromYear(year + 1); - w = (d2 + 3/*Jan4*/ + 3) % 7; - if (w < 0) - w += 7; - //printf("w = %d\n", w); - ydaybeg2 = 3/*Jan4*/ - w; - if (d + yday >= d2 + ydaybeg2) - { - year += 1; - week = 1; - return; - } - } - - week = (yday - ydaybeg) / 7 + 1; -} - -/* *********************************** - * Divide time by divisor. Always round down, even if d is negative. - */ - -d_time floor(d_time d, int divisor) -{ - if (d < 0) - d -= divisor - 1; - return d / divisor; -} - -int dmod(d_time n, d_time d) -{ d_time r; - - r = n % d; - if (r < 0) - r += d; - assert(cast(int)r == r); - return cast(int)r; -} - -int HourFromTime(d_time t) -{ - return dmod(floor(t, msPerHour), HoursPerDay); -} - -int MinFromTime(d_time t) -{ - return dmod(floor(t, msPerMinute), MinutesPerHour); -} - -int SecFromTime(d_time t) -{ - return dmod(floor(t, TicksPerSecond), 60); -} - -int msFromTime(d_time t) -{ - return dmod(t / (TicksPerSecond / 1000), 1000); -} - -int TimeWithinDay(d_time t) -{ - return dmod(t, msPerDay); -} - -d_time toInteger(d_time n) -{ - return n; -} - -int Day(d_time t) -{ - return cast(int)floor(t, msPerDay); -} - -int LeapYear(int y) -{ - return ((y & 3) == 0 && - (y % 100 || (y % 400) == 0)); -} - -int DaysInYear(int y) -{ - return 365 + LeapYear(y); -} - -int DayFromYear(int y) -{ - return cast(int) (365 * (y - 1970) + - floor((y - 1969), 4) - - floor((y - 1901), 100) + - floor((y - 1601), 400)); -} - -d_time TimeFromYear(int y) -{ - return cast(d_time)msPerDay * DayFromYear(y); -} - -/***************************** - * Calculates the year from the d_time t. - */ - -int YearFromTime(d_time t) -{ int y; - - if (t == d_time_nan) - return 0; - - // Hazard a guess - //y = 1970 + cast(int) (t / (365.2425 * msPerDay)); - // Use integer only math - y = 1970 + cast(int) (t / (3652425 * (msPerDay / 10000))); - - if (TimeFromYear(y) <= t) - { - while (TimeFromYear(y + 1) <= t) - y++; - } - else - { - do - { - y--; - } - while (TimeFromYear(y) > t); - } - return y; -} - -/******************************* - * Determines if d_time t is a leap year. - * - * A leap year is every 4 years except years ending in 00 that are not - * divsible by 400. - * - * Returns: !=0 if it is a leap year. - * - * References: - * $(LINK2 http://en.wikipedia.org/wiki/Leap_year, Wikipedia) - */ - -int inLeapYear(d_time t) -{ - return LeapYear(YearFromTime(t)); -} - -/***************************** - * Calculates the month from the d_time t. - * - * Returns: Integer in the range 0..11, where - * 0 represents January and 11 represents December. - */ - -int MonthFromTime(d_time t) -{ - int day; - int month; - int year; - - year = YearFromTime(t); - day = Day(t) - DayFromYear(year); - - if (day < 59) - { - if (day < 31) - { assert(day >= 0); - month = 0; - } - else - month = 1; - } - else - { - day -= LeapYear(year); - if (day < 212) - { - if (day < 59) - month = 1; - else if (day < 90) - month = 2; - else if (day < 120) - month = 3; - else if (day < 151) - month = 4; - else if (day < 181) - month = 5; - else - month = 6; - } - else - { - if (day < 243) - month = 7; - else if (day < 273) - month = 8; - else if (day < 304) - month = 9; - else if (day < 334) - month = 10; - else if (day < 365) - month = 11; - else - assert(0); - } - } - return month; -} - -/******************************* - * Compute which day in a month a d_time t is. - * Returns: - * Integer in the range 1..31 - */ -int DateFromTime(d_time t) -{ - int day; - int leap; - int month; - int year; - int date; - - year = YearFromTime(t); - day = Day(t) - DayFromYear(year); - leap = LeapYear(year); - month = MonthFromTime(t); - switch (month) - { - case 0: date = day + 1; break; - case 1: date = day - 30; break; - case 2: date = day - 58 - leap; break; - case 3: date = day - 89 - leap; break; - case 4: date = day - 119 - leap; break; - case 5: date = day - 150 - leap; break; - case 6: date = day - 180 - leap; break; - case 7: date = day - 211 - leap; break; - case 8: date = day - 242 - leap; break; - case 9: date = day - 272 - leap; break; - case 10: date = day - 303 - leap; break; - case 11: date = day - 333 - leap; break; - default: - assert(0); - } - return date; -} - -/******************************* - * Compute which day of the week a d_time t is. - * Returns: - * Integer in the range 0..6, where 0 represents Sunday - * and 6 represents Saturday. - */ -int WeekDay(d_time t) -{ int w; - - w = (cast(int)Day(t) + 4) % 7; - if (w < 0) - w += 7; - return w; -} - -/*********************************** - * Convert from UTC to local time. - */ - -d_time UTCtoLocalTime(d_time t) -{ - return (t == d_time_nan) - ? d_time_nan - : t + LocalTZA + DaylightSavingTA(t); -} - -/*********************************** - * Convert from local time to UTC. - */ - -d_time LocalTimetoUTC(d_time t) -{ - return (t == d_time_nan) - ? d_time_nan - : t - LocalTZA - DaylightSavingTA(t - LocalTZA); -} - - -d_time MakeTime(d_time hour, d_time min, d_time sec, d_time ms) -{ - return hour * TicksPerHour + - min * TicksPerMinute + - sec * TicksPerSecond + - ms * TicksPerMs; -} - - -d_time MakeDay(d_time year, d_time month, d_time date) -{ d_time t; - int y; - int m; - int leap; - - y = cast(int)(year + floor(month, 12)); - m = dmod(month, 12); - - leap = LeapYear(y); - t = TimeFromYear(y) + cast(d_time)mdays[m] * msPerDay; - if (leap && month >= 2) - t += msPerDay; - - if (YearFromTime(t) != y || - MonthFromTime(t) != m || - DateFromTime(t) != 1) - { - return d_time_nan; - } - - return Day(t) + date - 1; -} - -d_time MakeDate(d_time day, d_time time) -{ - if (day == d_time_nan || time == d_time_nan) - return d_time_nan; - - return day * TicksPerDay + time; -} - -d_time TimeClip(d_time time) -{ - //printf("TimeClip(%g) = %g\n", time, toInteger(time)); - - return toInteger(time); -} - -/************************************* - * Converts UTC time into a text string of the form: - * "Www Mmm dd hh:mm:ss GMT+-TZ yyyy". - * For example, "Tue Apr 02 02:04:57 GMT-0800 1996". - * If time is invalid, i.e. is d_time_nan, - * the string "Invalid date" is returned. - * - * Example: - * ------------------------------------ - d_time lNow; - char[] lNowString; - - // Grab the date and time relative to UTC - lNow = std.date.getUTCtime(); - // Convert this into the local date and time for display. - lNowString = std.date.toString(lNow); - * ------------------------------------ - */ - -string toString(d_time time) -{ - d_time t; - char sign; - int hr; - int mn; - int len; - d_time offset; - d_time dst; - - // Years are supposed to be -285616 .. 285616, or 7 digits - // "Tue Apr 02 02:04:57 GMT-0800 1996" - char[] buffer = new char[29 + 7 + 1]; - - if (time == d_time_nan) - return "Invalid Date"; - - dst = DaylightSavingTA(time); - offset = LocalTZA + dst; - t = time + offset; - sign = '+'; - if (offset < 0) - { sign = '-'; -// offset = -offset; - offset = -(LocalTZA + dst); - } - - mn = cast(int)(offset / msPerMinute); - hr = mn / 60; - mn %= 60; - - //printf("hr = %d, offset = %g, LocalTZA = %g, dst = %g, + = %g\n", hr, offset, LocalTZA, dst, LocalTZA + dst); - - len = sprintf(buffer.ptr, "%.3s %.3s %02d %02d:%02d:%02d GMT%c%02d%02d %d", - &daystr[WeekDay(t) * 3], - &monstr[MonthFromTime(t) * 3], - DateFromTime(t), - HourFromTime(t), MinFromTime(t), SecFromTime(t), - sign, hr, mn, - /*cast(long)*/YearFromTime(t)); - - // Ensure no buggy buffer overflows - //printf("len = %d, buffer.length = %d\n", len, buffer.length); - assert(len < buffer.length); - - return buffer[0 .. len]; -} - -/*********************************** - * Converts t into a text string of the form: "Www, dd Mmm yyyy hh:mm:ss UTC". - * If t is invalid, "Invalid date" is returned. - */ - -string toUTCString(d_time t) -{ - // Years are supposed to be -285616 .. 285616, or 7 digits - // "Tue, 02 Apr 1996 02:04:57 GMT" - char[] buffer = new char[25 + 7 + 1]; - int len; - - if (t == d_time_nan) - return "Invalid Date"; - - len = sprintf(buffer.ptr, "%.3s, %02d %.3s %d %02d:%02d:%02d UTC", - &daystr[WeekDay(t) * 3], DateFromTime(t), - &monstr[MonthFromTime(t) * 3], - YearFromTime(t), - HourFromTime(t), MinFromTime(t), SecFromTime(t)); - - // Ensure no buggy buffer overflows - assert(len < buffer.length); - - return buffer[0 .. len]; -} - -/************************************ - * Converts the date portion of time into a text string of the form: "Www Mmm dd - * yyyy", for example, "Tue Apr 02 1996". - * If time is invalid, "Invalid date" is returned. - */ - -string toDateString(d_time time) -{ - d_time t; - d_time offset; - d_time dst; - int len; - - // Years are supposed to be -285616 .. 285616, or 7 digits - // "Tue Apr 02 1996" - char[] buffer = new char[29 + 7 + 1]; - - if (time == d_time_nan) - return "Invalid Date"; - - dst = DaylightSavingTA(time); - offset = LocalTZA + dst; - t = time + offset; - - len = sprintf(buffer.ptr, "%.3s %.3s %02d %d", - &daystr[WeekDay(t) * 3], - &monstr[MonthFromTime(t) * 3], - DateFromTime(t), - /*cast(long)*/YearFromTime(t)); - - // Ensure no buggy buffer overflows - assert(len < buffer.length); - - return buffer[0 .. len]; -} - -/****************************************** - * Converts the time portion of t into a text string of the form: "hh:mm:ss - * GMT+-TZ", for example, "02:04:57 GMT-0800". - * If t is invalid, "Invalid date" is returned. - * The input must be in UTC, and the output is in local time. - */ - -string toTimeString(d_time time) -{ - d_time t; - char sign; - int hr; - int mn; - int len; - d_time offset; - d_time dst; - - // "02:04:57 GMT-0800" - char[] buffer = new char[17 + 1]; - - if (time == d_time_nan) - return "Invalid Date"; - - dst = DaylightSavingTA(time); - offset = LocalTZA + dst; - t = time + offset; - sign = '+'; - if (offset < 0) - { sign = '-'; -// offset = -offset; - offset = -(LocalTZA + dst); - } - - mn = cast(int)(offset / msPerMinute); - hr = mn / 60; - mn %= 60; - - //printf("hr = %d, offset = %g, LocalTZA = %g, dst = %g, + = %g\n", hr, offset, LocalTZA, dst, LocalTZA + dst); - - len = sprintf(buffer.ptr, "%02d:%02d:%02d GMT%c%02d%02d", - HourFromTime(t), MinFromTime(t), SecFromTime(t), - sign, hr, mn); - - // Ensure no buggy buffer overflows - assert(len < buffer.length); - - // Lop off terminating 0 - return buffer[0 .. len]; -} - - -/****************************************** - * Parses s as a textual date string, and returns it as a d_time. - * If the string is not a valid date, d_time_nan is returned. - */ - -d_time parse(string s) -{ - Date dp; - d_time n; - d_time day; - d_time time; - - try - { - dp.parse(s); - - //writefln("year = %d, month = %d, day = %d", dp.year, dp.month, dp.day); - //writefln("%02d:%02d:%02d.%03d", dp.hour, dp.minute, dp.second, dp.ms); - //writefln("weekday = %d, ampm = %d, tzcorrection = %d", dp.weekday, 1, dp.tzcorrection); - - time = MakeTime(dp.hour, dp.minute, dp.second, dp.ms); - if (dp.tzcorrection == int.min) - time -= LocalTZA; - else - { - time += cast(d_time)(dp.tzcorrection / 100) * msPerHour + - cast(d_time)(dp.tzcorrection % 100) * msPerMinute; - } - day = MakeDay(dp.year, dp.month - 1, dp.day); - n = MakeDate(day,time); - n = TimeClip(n); - } - catch - { - n = d_time_nan; // erroneous date string - } - return n; -} - -static this() -{ - LocalTZA = getLocalTZA(); - //printf("LocalTZA = %g, %g\n", LocalTZA, LocalTZA / msPerHour); -} - -version (Win32) -{ - - private import std.c.windows.windows; - //import c.time; - - /****** - * Get current UTC time. - */ - d_time getUTCtime() - { - SYSTEMTIME st; - d_time n; - - GetSystemTime(&st); // get time in UTC - n = SYSTEMTIME2d_time(&st, 0); - return n; - //return c.time.time(null) * TicksPerSecond; - } - - static d_time FILETIME2d_time(FILETIME *ft) - { SYSTEMTIME st; - - if (!FileTimeToSystemTime(ft, &st)) - return d_time_nan; - return SYSTEMTIME2d_time(&st, 0); - } - - static d_time SYSTEMTIME2d_time(SYSTEMTIME *st, d_time t) - { - d_time n; - d_time day; - d_time time; - - if (st.wYear) - { - time = MakeTime(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); - day = MakeDay(st.wYear, st.wMonth - 1, st.wDay); - } - else - { // wDayOfWeek is weekday, wDay is which week in the month - int year; - int wd; - int mday; - int month; - d_time x; - - year = YearFromTime(t); - month = st.wMonth - 1; - x = MakeDay(year, month, 1); - wd = WeekDay(MakeDate(x, 0)); - - mday = (7 - wd + st.wDayOfWeek); - if (mday >= 7) - mday -= 7; - mday += (st.wDay - 1) * 7 + 1; - //printf("month = %d, wDayOfWeek = %d, wDay = %d, mday = %d\n", st.wMonth, st.wDayOfWeek, st.wDay, mday); - - day = MakeDay(year, month, mday); - time = 0; - } - n = MakeDate(day,time); - n = TimeClip(n); - return n; - } - - d_time getLocalTZA() - { - d_time t; - DWORD r; - TIME_ZONE_INFORMATION tzi; - - /* http://msdn.microsoft.com/library/en-us/sysinfo/base/gettimezoneinformation.asp - * http://msdn2.microsoft.com/en-us/library/ms725481.aspx - */ - r = GetTimeZoneInformation(&tzi); - //printf("bias = %d\n", tzi.Bias); - //printf("standardbias = %d\n", tzi.StandardBias); - //printf("daylightbias = %d\n", tzi.DaylightBias); - switch (r) - { - case TIME_ZONE_ID_STANDARD: - t = -(tzi.Bias + tzi.StandardBias) * cast(d_time)(60 * TicksPerSecond); - break; - case TIME_ZONE_ID_DAYLIGHT: - //t = -(tzi.Bias + tzi.DaylightBias) * cast(d_time)(60 * TicksPerSecond); - //break; - case TIME_ZONE_ID_UNKNOWN: - t = -(tzi.Bias) * cast(d_time)(60 * TicksPerSecond); - break; - - default: - t = 0; - break; - } - - return t; - } - - /* - * Get daylight savings time adjust for time dt. - */ - - int DaylightSavingTA(d_time dt) - { - int t; - DWORD r; - TIME_ZONE_INFORMATION tzi; - d_time ts; - d_time td; - - /* http://msdn.microsoft.com/library/en-us/sysinfo/base/gettimezoneinformation.asp - */ - r = GetTimeZoneInformation(&tzi); - t = 0; - switch (r) - { - case TIME_ZONE_ID_STANDARD: - case TIME_ZONE_ID_DAYLIGHT: - if (tzi.StandardDate.wMonth == 0 || - tzi.DaylightDate.wMonth == 0) - break; - - ts = SYSTEMTIME2d_time(&tzi.StandardDate, dt); - td = SYSTEMTIME2d_time(&tzi.DaylightDate, dt); - - if (td <= dt && dt <= ts) - { - t = -tzi.DaylightBias * (60 * TicksPerSecond); - //printf("DST is in effect, %d\n", t); - } - else - { - //printf("no DST\n"); - } - break; - - case TIME_ZONE_ID_UNKNOWN: - // Daylight savings time not used in this time zone - break; - - default: - assert(0); - } - return t; - } -} -else version (linux) -{ - - private import std.c.linux.linux; - - d_time getUTCtime() - { timeval tv; - - //printf("getUTCtime()\n"); - if (gettimeofday(&tv, null)) - { // Some error happened - try time() instead - return time(null) * TicksPerSecond; - } - - return tv.tv_sec * cast(d_time)TicksPerSecond + - (tv.tv_usec / (1000000 / cast(d_time)TicksPerSecond)); - } - - d_time getLocalTZA() - { - __time_t t; - - time(&t); - localtime(&t); // this will set timezone - return -(timezone * TicksPerSecond); - } - - /* - * Get daylight savings time adjust for time dt. - */ - - int DaylightSavingTA(d_time dt) - { - tm *tmp; - int dst = 0; - - if (dt != d_time_nan) - { - d_time seconds = dt / TicksPerSecond; - int t; - t = cast(int) seconds; - if (t == seconds) // if in range - { - tmp = localtime(cast(__time_t*)&t); - if (tmp.tm_isdst > 0) - dst = TicksPerHour; // BUG: Assume daylight savings time is plus one hour. - } - else // out of range for system time, use our own calculation - { // Daylight savings time goes from 2 AM the first Sunday - // in April through 2 AM the last Sunday in October - - dt -= LocalTZA; - - int year = YearFromTime(dt); - int leap = LeapYear(dt); - //writefln("year = %s, leap = %s, month = %s", year, leap, MonthFromTime(dt)); - - d_time start = TimeFromYear(year); // Jan 1 - d_time end = start; - // Move fwd to Apr 1 - start += cast(d_time)(mdays[3] + leap) * TicksPerDay; - // Advance a day at a time until we find Sunday (0) - while (WeekDay(start) != 0) - start += TicksPerDay; - - // Move fwd to Oct 30 - end += cast(d_time)(mdays[9] + leap + 30) * TicksPerDay; - // Back up a day at a time until we find Sunday (0) - while (WeekDay(end) != 0) // 0 is Sunday - end -= TicksPerDay; - - dt -= 2 * TicksPerHour; // 2 AM - if (dt >= start && dt <= end) - dst = TicksPerHour; - //writefln("start = %s, dt = %s, end = %s, dst = %s", start, dt, end, dst); - } - } - return dst; - } - -} -else version (Unix) -{ - // for now, just copy linux - private import std.c.unix.unix; - - d_time getUTCtime() - { timeval tv; - - if (gettimeofday(&tv, null)) - { // Some error happened - try time() instead - return time(null) * TicksPerSecond; - } - - return tv.tv_sec * cast(d_time)TicksPerSecond + - (tv.tv_usec / (1000000 / cast(d_time)TicksPerSecond)); - } - - private extern (C) time_t _d_gnu_cbridge_tza(); - - d_time getLocalTZA() - { - return _d_gnu_cbridge_tza() * TicksPerSecond; - } - - /* - * Get daylight savings time adjust for time dt. - */ - - int DaylightSavingTA(d_time dt) - { - tm *tmp; - time_t t; - int dst = 0; - - if (dt != d_time_nan) - { - d_time seconds = dt / TicksPerSecond; - t = cast(time_t) seconds; - if (t == seconds) // if in range - { - tmp = localtime(&t); - if (tmp.tm_isdst > 0) - dst = TicksPerHour; // BUG: Assume daylight savings time is plus one hour. - } - else // out of range for system time, use our own calculation - { // Daylight savings time goes from 2 AM the first Sunday - // in April through 2 AM the last Sunday in October - - dt -= LocalTZA; - - int year = YearFromTime(dt); - int leap = LeapYear(cast(int)dt); - //writefln("year = %s, leap = %s, month = %s", year, leap, MonthFromTime(dt)); - - d_time start = TimeFromYear(year); // Jan 1 - d_time end = start; - // Move fwd to Apr 1 - start += cast(d_time)(mdays[3] + leap) * TicksPerDay; - // Advance a day at a time until we find Sunday (0) - while (WeekDay(start) != 0) - start += TicksPerDay; - - // Move fwd to Oct 30 - end += cast(d_time)(mdays[9] + leap + 30) * TicksPerDay; - // Back up a day at a time until we find Sunday (0) - while (WeekDay(end) != 0) // 0 is Sunday - end -= TicksPerDay; - - dt -= 2 * TicksPerHour; // 2 AM - if (dt >= start && dt <= end) - dst = TicksPerHour; - //writefln("start = %s, dt = %s, end = %s, dst = %s", start, dt, end, dst); - } - } - return dst; - } -} -else version (NoSystem) -{ - d_time getLocalTZA() { return 0; } - int DaylightSavingTA(d_time dt) { return 0; } -} - -/+ ====================== DOS File Time =============================== +/ - -/*** - * Type representing the DOS file date/time format. - */ -typedef uint DosFileTime; - -/************************************ - * Convert from DOS file date/time to d_time. - */ - -d_time toDtime(DosFileTime time) -{ - uint dt = cast(uint)time; - - if (dt == 0) - return d_time_nan; - - int year = ((dt >> 25) & 0x7F) + 1980; - int month = ((dt >> 21) & 0x0F) - 1; // 0..12 - int dayofmonth = ((dt >> 16) & 0x1F); // 0..31 - int hour = (dt >> 11) & 0x1F; // 0..23 - int minute = (dt >> 5) & 0x3F; // 0..59 - int second = (dt << 1) & 0x3E; // 0..58 (in 2 second increments) - - d_time t; - - t = std.date.MakeDate(std.date.MakeDay(year, month, dayofmonth), - std.date.MakeTime(hour, minute, second, 0)); - - assert(YearFromTime(t) == year); - assert(MonthFromTime(t) == month); - assert(DateFromTime(t) == dayofmonth); - assert(HourFromTime(t) == hour); - assert(MinFromTime(t) == minute); - assert(SecFromTime(t) == second); - - t -= LocalTZA + DaylightSavingTA(t); - - return t; -} - -/**************************************** - * Convert from d_time to DOS file date/time. - */ - -DosFileTime toDosFileTime(d_time t) -{ uint dt; - - if (t == d_time_nan) - return cast(DosFileTime)0; - - t += LocalTZA + DaylightSavingTA(t); - - uint year = YearFromTime(t); - uint month = MonthFromTime(t); - uint dayofmonth = DateFromTime(t); - uint hour = HourFromTime(t); - uint minute = MinFromTime(t); - uint second = SecFromTime(t); - - dt = (year - 1980) << 25; - dt |= ((month + 1) & 0x0F) << 21; - dt |= (dayofmonth & 0x1F) << 16; - dt |= (hour & 0x1F) << 11; - dt |= (minute & 0x3F) << 5; - dt |= (second >> 1) & 0x1F; - - return cast(DosFileTime)dt; -} diff --git a/lphobos/std/date.d~ b/lphobos/std/date.d~ deleted file mode 100644 index 2e76db863b4..00000000000 --- a/lphobos/std/date.d~ +++ /dev/null @@ -1,1074 +0,0 @@ - -// Written in the D programming language. - -/** - * Dates are represented in several formats. The date implementation revolves - * around a central type, d_time, from which other formats are converted to and - * from. - * Dates are calculated using the Gregorian calendar. - * References: - * $(LINK2 http://en.wikipedia.org/wiki/Gregorian_calendar, Gregorian calendar (Wikipedia)) - * Macros: - * WIKI = Phobos/StdDate - */ - -// Copyright (c) 1999-2007 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, May 2005 -*/ - -module std.date; - -private import std.stdio; -private import std.dateparse; - -/** - * d_time is a signed arithmetic type giving the time elapsed since January 1, - * 1970. - * Negative values are for dates preceding 1970. The time unit used is Ticks. - * Ticks are milliseconds or smaller intervals. - * - * The usual arithmetic operations can be performed on d_time, such as adding, - * subtracting, etc. Elapsed time in Ticks can be computed by subtracting a - * starting d_time from an ending d_time. - */ -alias long d_time; - -/** - * A value for d_time that does not represent a valid time. - */ -const d_time d_time_nan = long.min; - -/** - * Time broken down into its components. - */ -struct Date -{ - int year = int.min; /// use int.min as "nan" year value - int month; /// 1..12 - int day; /// 1..31 - int hour; /// 0..23 - int minute; /// 0..59 - int second; /// 0..59 - int ms; /// 0..999 - int weekday; /// 0: not specified, 1..7: Sunday..Saturday - int tzcorrection = int.min; /// -1200..1200 correction in hours - - /// Parse date out of string s[] and store it in this Date instance. - void parse(string s) - { - DateParse dp; - - dp.parse(s, *this); - } -} - -enum -{ - HoursPerDay = 24, - MinutesPerHour = 60, - msPerMinute = 60 * 1000, - msPerHour = 60 * msPerMinute, - msPerDay = 86400000, - TicksPerMs = 1, - TicksPerSecond = 1000, /// Will be at least 1000 - TicksPerMinute = TicksPerSecond * 60, - TicksPerHour = TicksPerMinute * 60, - TicksPerDay = TicksPerHour * 24, -} - -d_time LocalTZA = 0; - - -const char[] daystr = "SunMonTueWedThuFriSat"; -const char[] monstr = "JanFebMarAprMayJunJulAugSepOctNovDec"; - -const int[12] mdays = [ 0,31,59,90,120,151,181,212,243,273,304,334 ]; - -/******************************** - * Compute year and week [1..53] from t. The ISO 8601 week 1 is the first week - * of the year that includes January 4. Monday is the first day of the week. - * References: - * $(LINK2 http://en.wikipedia.org/wiki/ISO_8601, ISO 8601 (Wikipedia)) - */ - -void toISO8601YearWeek(d_time t, out int year, out int week) -{ - year = YearFromTime(t); - - int yday = Day(t) - DayFromYear(year); - int d; - int w; - int ydaybeg; - - /* Determine day of week Jan 4 falls on. - * Weeks begin on a Monday. - */ - - d = DayFromYear(year); - w = (d + 3/*Jan4*/ + 3) % 7; - if (w < 0) - w += 7; - - /* Find yday of beginning of ISO 8601 year - */ - ydaybeg = 3/*Jan4*/ - w; - - /* Check if yday is actually the last week of the previous year - */ - if (yday < ydaybeg) - { - year -= 1; - week = 53; - return; - } - - /* Check if yday is actually the first week of the next year - */ - if (yday >= 362) // possible - { int d2; - int ydaybeg2; - - d2 = DayFromYear(year + 1); - w = (d2 + 3/*Jan4*/ + 3) % 7; - if (w < 0) - w += 7; - //printf("w = %d\n", w); - ydaybeg2 = 3/*Jan4*/ - w; - if (d + yday >= d2 + ydaybeg2) - { - year += 1; - week = 1; - return; - } - } - - week = (yday - ydaybeg) / 7 + 1; -} - -/* *********************************** - * Divide time by divisor. Always round down, even if d is negative. - */ - -d_time floor(d_time d, int divisor) -{ - if (d < 0) - d -= divisor - 1; - return d / divisor; -} - -int dmod(d_time n, d_time d) -{ d_time r; - - r = n % d; - if (r < 0) - r += d; - assert(cast(int)r == r); - return cast(int)r; -} - -int HourFromTime(d_time t) -{ - return dmod(floor(t, msPerHour), HoursPerDay); -} - -int MinFromTime(d_time t) -{ - return dmod(floor(t, msPerMinute), MinutesPerHour); -} - -int SecFromTime(d_time t) -{ - return dmod(floor(t, TicksPerSecond), 60); -} - -int msFromTime(d_time t) -{ - return dmod(t / (TicksPerSecond / 1000), 1000); -} - -int TimeWithinDay(d_time t) -{ - return dmod(t, msPerDay); -} - -d_time toInteger(d_time n) -{ - return n; -} - -int Day(d_time t) -{ - return cast(int)floor(t, msPerDay); -} - -int LeapYear(int y) -{ - return ((y & 3) == 0 && - (y % 100 || (y % 400) == 0)); -} - -int DaysInYear(int y) -{ - return 365 + LeapYear(y); -} - -int DayFromYear(int y) -{ - return cast(int) (365 * (y - 1970) + - floor((y - 1969), 4) - - floor((y - 1901), 100) + - floor((y - 1601), 400)); -} - -d_time TimeFromYear(int y) -{ - return cast(d_time)msPerDay * DayFromYear(y); -} - -/***************************** - * Calculates the year from the d_time t. - */ - -int YearFromTime(d_time t) -{ int y; - - if (t == d_time_nan) - return 0; - - // Hazard a guess - //y = 1970 + cast(int) (t / (365.2425 * msPerDay)); - // Use integer only math - y = 1970 + cast(int) (t / (3652425 * (msPerDay / 10000))); - - if (TimeFromYear(y) <= t) - { - while (TimeFromYear(y + 1) <= t) - y++; - } - else - { - do - { - y--; - } - while (TimeFromYear(y) > t); - } - return y; -} - -/******************************* - * Determines if d_time t is a leap year. - * - * A leap year is every 4 years except years ending in 00 that are not - * divsible by 400. - * - * Returns: !=0 if it is a leap year. - * - * References: - * $(LINK2 http://en.wikipedia.org/wiki/Leap_year, Wikipedia) - */ - -int inLeapYear(d_time t) -{ - return LeapYear(YearFromTime(t)); -} - -/***************************** - * Calculates the month from the d_time t. - * - * Returns: Integer in the range 0..11, where - * 0 represents January and 11 represents December. - */ - -int MonthFromTime(d_time t) -{ - int day; - int month; - int year; - - year = YearFromTime(t); - day = Day(t) - DayFromYear(year); - - if (day < 59) - { - if (day < 31) - { assert(day >= 0); - month = 0; - } - else - month = 1; - } - else - { - day -= LeapYear(year); - if (day < 212) - { - if (day < 59) - month = 1; - else if (day < 90) - month = 2; - else if (day < 120) - month = 3; - else if (day < 151) - month = 4; - else if (day < 181) - month = 5; - else - month = 6; - } - else - { - if (day < 243) - month = 7; - else if (day < 273) - month = 8; - else if (day < 304) - month = 9; - else if (day < 334) - month = 10; - else if (day < 365) - month = 11; - else - assert(0); - } - } - return month; -} - -/******************************* - * Compute which day in a month a d_time t is. - * Returns: - * Integer in the range 1..31 - */ -int DateFromTime(d_time t) -{ - int day; - int leap; - int month; - int year; - int date; - - year = YearFromTime(t); - day = Day(t) - DayFromYear(year); - leap = LeapYear(year); - month = MonthFromTime(t); - switch (month) - { - case 0: date = day + 1; break; - case 1: date = day - 30; break; - case 2: date = day - 58 - leap; break; - case 3: date = day - 89 - leap; break; - case 4: date = day - 119 - leap; break; - case 5: date = day - 150 - leap; break; - case 6: date = day - 180 - leap; break; - case 7: date = day - 211 - leap; break; - case 8: date = day - 242 - leap; break; - case 9: date = day - 272 - leap; break; - case 10: date = day - 303 - leap; break; - case 11: date = day - 333 - leap; break; - default: - assert(0); - } - return date; -} - -/******************************* - * Compute which day of the week a d_time t is. - * Returns: - * Integer in the range 0..6, where 0 represents Sunday - * and 6 represents Saturday. - */ -int WeekDay(d_time t) -{ int w; - - w = (cast(int)Day(t) + 4) % 7; - if (w < 0) - w += 7; - return w; -} - -/*********************************** - * Convert from UTC to local time. - */ - -d_time UTCtoLocalTime(d_time t) -{ - return (t == d_time_nan) - ? d_time_nan - : t + LocalTZA + DaylightSavingTA(t); -} - -/*********************************** - * Convert from local time to UTC. - */ - -d_time LocalTimetoUTC(d_time t) -{ - return (t == d_time_nan) - ? d_time_nan - : t - LocalTZA - DaylightSavingTA(t - LocalTZA); -} - - -d_time MakeTime(d_time hour, d_time min, d_time sec, d_time ms) -{ - return hour * TicksPerHour + - min * TicksPerMinute + - sec * TicksPerSecond + - ms * TicksPerMs; -} - - -d_time MakeDay(d_time year, d_time month, d_time date) -{ d_time t; - int y; - int m; - int leap; - - y = cast(int)(year + floor(month, 12)); - m = dmod(month, 12); - - leap = LeapYear(y); - t = TimeFromYear(y) + cast(d_time)mdays[m] * msPerDay; - if (leap && month >= 2) - t += msPerDay; - - if (YearFromTime(t) != y || - MonthFromTime(t) != m || - DateFromTime(t) != 1) - { - return d_time_nan; - } - - return Day(t) + date - 1; -} - -d_time MakeDate(d_time day, d_time time) -{ - if (day == d_time_nan || time == d_time_nan) - return d_time_nan; - - return day * TicksPerDay + time; -} - -d_time TimeClip(d_time time) -{ - //printf("TimeClip(%g) = %g\n", time, toInteger(time)); - - return toInteger(time); -} - -/************************************* - * Converts UTC time into a text string of the form: - * "Www Mmm dd hh:mm:ss GMT+-TZ yyyy". - * For example, "Tue Apr 02 02:04:57 GMT-0800 1996". - * If time is invalid, i.e. is d_time_nan, - * the string "Invalid date" is returned. - * - * Example: - * ------------------------------------ - d_time lNow; - char[] lNowString; - - // Grab the date and time relative to UTC - lNow = std.date.getUTCtime(); - // Convert this into the local date and time for display. - lNowString = std.date.toString(lNow); - * ------------------------------------ - */ - -string toString(d_time time) -{ - d_time t; - char sign; - int hr; - int mn; - int len; - d_time offset; - d_time dst; - - // Years are supposed to be -285616 .. 285616, or 7 digits - // "Tue Apr 02 02:04:57 GMT-0800 1996" - char[] buffer = new char[29 + 7 + 1]; - - if (time == d_time_nan) - return "Invalid Date"; - - dst = DaylightSavingTA(time); - offset = LocalTZA + dst; - t = time + offset; - sign = '+'; - if (offset < 0) - { sign = '-'; -// offset = -offset; - offset = -(LocalTZA + dst); - } - - mn = cast(int)(offset / msPerMinute); - hr = mn / 60; - mn %= 60; - - //printf("hr = %d, offset = %g, LocalTZA = %g, dst = %g, + = %g\n", hr, offset, LocalTZA, dst, LocalTZA + dst); - - len = sprintf(buffer.ptr, "%.3s %.3s %02d %02d:%02d:%02d GMT%c%02d%02d %d", - &daystr[WeekDay(t) * 3], - &monstr[MonthFromTime(t) * 3], - DateFromTime(t), - HourFromTime(t), MinFromTime(t), SecFromTime(t), - sign, hr, mn, - /*cast(long)*/YearFromTime(t)); - - // Ensure no buggy buffer overflows - //printf("len = %d, buffer.length = %d\n", len, buffer.length); - assert(len < buffer.length); - - return buffer[0 .. len]; -} - -/*********************************** - * Converts t into a text string of the form: "Www, dd Mmm yyyy hh:mm:ss UTC". - * If t is invalid, "Invalid date" is returned. - */ - -string toUTCString(d_time t) -{ - // Years are supposed to be -285616 .. 285616, or 7 digits - // "Tue, 02 Apr 1996 02:04:57 GMT" - char[] buffer = new char[25 + 7 + 1]; - int len; - - if (t == d_time_nan) - return "Invalid Date"; - - len = sprintf(buffer.ptr, "%.3s, %02d %.3s %d %02d:%02d:%02d UTC", - &daystr[WeekDay(t) * 3], DateFromTime(t), - &monstr[MonthFromTime(t) * 3], - YearFromTime(t), - HourFromTime(t), MinFromTime(t), SecFromTime(t)); - - // Ensure no buggy buffer overflows - assert(len < buffer.length); - - return buffer[0 .. len]; -} - -/************************************ - * Converts the date portion of time into a text string of the form: "Www Mmm dd - * yyyy", for example, "Tue Apr 02 1996". - * If time is invalid, "Invalid date" is returned. - */ - -string toDateString(d_time time) -{ - d_time t; - d_time offset; - d_time dst; - int len; - - // Years are supposed to be -285616 .. 285616, or 7 digits - // "Tue Apr 02 1996" - char[] buffer = new char[29 + 7 + 1]; - - if (time == d_time_nan) - return "Invalid Date"; - - dst = DaylightSavingTA(time); - offset = LocalTZA + dst; - t = time + offset; - - len = sprintf(buffer.ptr, "%.3s %.3s %02d %d", - &daystr[WeekDay(t) * 3], - &monstr[MonthFromTime(t) * 3], - DateFromTime(t), - /*cast(long)*/YearFromTime(t)); - - // Ensure no buggy buffer overflows - assert(len < buffer.length); - - return buffer[0 .. len]; -} - -/****************************************** - * Converts the time portion of t into a text string of the form: "hh:mm:ss - * GMT+-TZ", for example, "02:04:57 GMT-0800". - * If t is invalid, "Invalid date" is returned. - * The input must be in UTC, and the output is in local time. - */ - -string toTimeString(d_time time) -{ - d_time t; - char sign; - int hr; - int mn; - int len; - d_time offset; - d_time dst; - - // "02:04:57 GMT-0800" - char[] buffer = new char[17 + 1]; - - if (time == d_time_nan) - return "Invalid Date"; - - dst = DaylightSavingTA(time); - offset = LocalTZA + dst; - t = time + offset; - sign = '+'; - if (offset < 0) - { sign = '-'; -// offset = -offset; - offset = -(LocalTZA + dst); - } - - mn = cast(int)(offset / msPerMinute); - hr = mn / 60; - mn %= 60; - - //printf("hr = %d, offset = %g, LocalTZA = %g, dst = %g, + = %g\n", hr, offset, LocalTZA, dst, LocalTZA + dst); - - len = sprintf(buffer.ptr, "%02d:%02d:%02d GMT%c%02d%02d", - HourFromTime(t), MinFromTime(t), SecFromTime(t), - sign, hr, mn); - - // Ensure no buggy buffer overflows - assert(len < buffer.length); - - // Lop off terminating 0 - return buffer[0 .. len]; -} - - -/****************************************** - * Parses s as a textual date string, and returns it as a d_time. - * If the string is not a valid date, d_time_nan is returned. - */ - -d_time parse(string s) -{ - Date dp; - d_time n; - d_time day; - d_time time; - - try - { - dp.parse(s); - - //writefln("year = %d, month = %d, day = %d", dp.year, dp.month, dp.day); - //writefln("%02d:%02d:%02d.%03d", dp.hour, dp.minute, dp.second, dp.ms); - //writefln("weekday = %d, ampm = %d, tzcorrection = %d", dp.weekday, 1, dp.tzcorrection); - - time = MakeTime(dp.hour, dp.minute, dp.second, dp.ms); - if (dp.tzcorrection == int.min) - time -= LocalTZA; - else - { - time += cast(d_time)(dp.tzcorrection / 100) * msPerHour + - cast(d_time)(dp.tzcorrection % 100) * msPerMinute; - } - day = MakeDay(dp.year, dp.month - 1, dp.day); - n = MakeDate(day,time); - n = TimeClip(n); - } - catch - { - n = d_time_nan; // erroneous date string - } - return n; -} - -static this() -{ - LocalTZA = getLocalTZA(); - //printf("LocalTZA = %g, %g\n", LocalTZA, LocalTZA / msPerHour); -} - -version (Win32) -{ - - private import std.c.windows.windows; - //import c.time; - - /****** - * Get current UTC time. - */ - d_time getUTCtime() - { - SYSTEMTIME st; - d_time n; - - GetSystemTime(&st); // get time in UTC - n = SYSTEMTIME2d_time(&st, 0); - return n; - //return c.time.time(null) * TicksPerSecond; - } - - static d_time FILETIME2d_time(FILETIME *ft) - { SYSTEMTIME st; - - if (!FileTimeToSystemTime(ft, &st)) - return d_time_nan; - return SYSTEMTIME2d_time(&st, 0); - } - - static d_time SYSTEMTIME2d_time(SYSTEMTIME *st, d_time t) - { - d_time n; - d_time day; - d_time time; - - if (st.wYear) - { - time = MakeTime(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); - day = MakeDay(st.wYear, st.wMonth - 1, st.wDay); - } - else - { // wDayOfWeek is weekday, wDay is which week in the month - int year; - int wd; - int mday; - int month; - d_time x; - - year = YearFromTime(t); - month = st.wMonth - 1; - x = MakeDay(year, month, 1); - wd = WeekDay(MakeDate(x, 0)); - - mday = (7 - wd + st.wDayOfWeek); - if (mday >= 7) - mday -= 7; - mday += (st.wDay - 1) * 7 + 1; - //printf("month = %d, wDayOfWeek = %d, wDay = %d, mday = %d\n", st.wMonth, st.wDayOfWeek, st.wDay, mday); - - day = MakeDay(year, month, mday); - time = 0; - } - n = MakeDate(day,time); - n = TimeClip(n); - return n; - } - - d_time getLocalTZA() - { - d_time t; - DWORD r; - TIME_ZONE_INFORMATION tzi; - - /* http://msdn.microsoft.com/library/en-us/sysinfo/base/gettimezoneinformation.asp - * http://msdn2.microsoft.com/en-us/library/ms725481.aspx - */ - r = GetTimeZoneInformation(&tzi); - //printf("bias = %d\n", tzi.Bias); - //printf("standardbias = %d\n", tzi.StandardBias); - //printf("daylightbias = %d\n", tzi.DaylightBias); - switch (r) - { - case TIME_ZONE_ID_STANDARD: - t = -(tzi.Bias + tzi.StandardBias) * cast(d_time)(60 * TicksPerSecond); - break; - case TIME_ZONE_ID_DAYLIGHT: - //t = -(tzi.Bias + tzi.DaylightBias) * cast(d_time)(60 * TicksPerSecond); - //break; - case TIME_ZONE_ID_UNKNOWN: - t = -(tzi.Bias) * cast(d_time)(60 * TicksPerSecond); - break; - - default: - t = 0; - break; - } - - return t; - } - - /* - * Get daylight savings time adjust for time dt. - */ - - int DaylightSavingTA(d_time dt) - { - int t; - DWORD r; - TIME_ZONE_INFORMATION tzi; - d_time ts; - d_time td; - - /* http://msdn.microsoft.com/library/en-us/sysinfo/base/gettimezoneinformation.asp - */ - r = GetTimeZoneInformation(&tzi); - t = 0; - switch (r) - { - case TIME_ZONE_ID_STANDARD: - case TIME_ZONE_ID_DAYLIGHT: - if (tzi.StandardDate.wMonth == 0 || - tzi.DaylightDate.wMonth == 0) - break; - - ts = SYSTEMTIME2d_time(&tzi.StandardDate, dt); - td = SYSTEMTIME2d_time(&tzi.DaylightDate, dt); - - if (td <= dt && dt <= ts) - { - t = -tzi.DaylightBias * (60 * TicksPerSecond); - //printf("DST is in effect, %d\n", t); - } - else - { - //printf("no DST\n"); - } - break; - - case TIME_ZONE_ID_UNKNOWN: - // Daylight savings time not used in this time zone - break; - - default: - assert(0); - } - return t; - } -} -else version (Unix) -{ - // for now, just copy linux - private import std.c.unix.unix; - - d_time getUTCtime() - { timeval tv; - - if (gettimeofday(&tv, null)) - { // Some error happened - try time() instead - return time(null) * TicksPerSecond; - } - - return tv.tv_sec * cast(d_time)TicksPerSecond + - (tv.tv_usec / (1000000 / cast(d_time)TicksPerSecond)); - } - - private extern (C) time_t _d_gnu_cbridge_tza(); - - d_time getLocalTZA() - { - return _d_gnu_cbridge_tza() * TicksPerSecond; - } - - /* - * Get daylight savings time adjust for time dt. - */ - - int DaylightSavingTA(d_time dt) - { - tm *tmp; - time_t t; - int dst = 0; - - if (dt != d_time_nan) - { - d_time seconds = dt / TicksPerSecond; - t = cast(time_t) seconds; - if (t == seconds) // if in range - { - tmp = localtime(&t); - if (tmp.tm_isdst > 0) - dst = TicksPerHour; // BUG: Assume daylight savings time is plus one hour. - } - else // out of range for system time, use our own calculation - { // Daylight savings time goes from 2 AM the first Sunday - // in April through 2 AM the last Sunday in October - - dt -= LocalTZA; - - int year = YearFromTime(dt); - int leap = LeapYear(cast(int)dt); - //writefln("year = %s, leap = %s, month = %s", year, leap, MonthFromTime(dt)); - - d_time start = TimeFromYear(year); // Jan 1 - d_time end = start; - // Move fwd to Apr 1 - start += cast(d_time)(mdays[3] + leap) * TicksPerDay; - // Advance a day at a time until we find Sunday (0) - while (WeekDay(start) != 0) - start += TicksPerDay; - - // Move fwd to Oct 30 - end += cast(d_time)(mdays[9] + leap + 30) * TicksPerDay; - // Back up a day at a time until we find Sunday (0) - while (WeekDay(end) != 0) // 0 is Sunday - end -= TicksPerDay; - - dt -= 2 * TicksPerHour; // 2 AM - if (dt >= start && dt <= end) - dst = TicksPerHour; - //writefln("start = %s, dt = %s, end = %s, dst = %s", start, dt, end, dst); - } - } - return dst; - } -} -else version (linux) -{ - - private import std.c.linux.linux; - - d_time getUTCtime() - { timeval tv; - - //printf("getUTCtime()\n"); - if (gettimeofday(&tv, null)) - { // Some error happened - try time() instead - return time(null) * TicksPerSecond; - } - - return tv.tv_sec * cast(d_time)TicksPerSecond + - (tv.tv_usec / (1000000 / cast(d_time)TicksPerSecond)); - } - - d_time getLocalTZA() - { - int t; - - time(&t); - localtime(&t); // this will set timezone - return -(timezone * TicksPerSecond); - } - - /* - * Get daylight savings time adjust for time dt. - */ - - int DaylightSavingTA(d_time dt) - { - tm *tmp; - int t; - int dst = 0; - - if (dt != d_time_nan) - { - d_time seconds = dt / TicksPerSecond; - t = cast(int) seconds; - if (t == seconds) // if in range - { - tmp = localtime(&t); - if (tmp.tm_isdst > 0) - dst = TicksPerHour; // BUG: Assume daylight savings time is plus one hour. - } - else // out of range for system time, use our own calculation - { // Daylight savings time goes from 2 AM the first Sunday - // in April through 2 AM the last Sunday in October - - dt -= LocalTZA; - - int year = YearFromTime(dt); - int leap = LeapYear(dt); - //writefln("year = %s, leap = %s, month = %s", year, leap, MonthFromTime(dt)); - - d_time start = TimeFromYear(year); // Jan 1 - d_time end = start; - // Move fwd to Apr 1 - start += cast(d_time)(mdays[3] + leap) * TicksPerDay; - // Advance a day at a time until we find Sunday (0) - while (WeekDay(start) != 0) - start += TicksPerDay; - - // Move fwd to Oct 30 - end += cast(d_time)(mdays[9] + leap + 30) * TicksPerDay; - // Back up a day at a time until we find Sunday (0) - while (WeekDay(end) != 0) // 0 is Sunday - end -= TicksPerDay; - - dt -= 2 * TicksPerHour; // 2 AM - if (dt >= start && dt <= end) - dst = TicksPerHour; - //writefln("start = %s, dt = %s, end = %s, dst = %s", start, dt, end, dst); - } - } - return dst; - } - -} -else version (NoSystem) -{ - d_time getLocalTZA() { return 0; } - int DaylightSavingTA(d_time dt) { return 0; } -} - -/+ ====================== DOS File Time =============================== +/ - -/*** - * Type representing the DOS file date/time format. - */ -typedef uint DosFileTime; - -/************************************ - * Convert from DOS file date/time to d_time. - */ - -d_time toDtime(DosFileTime time) -{ - uint dt = cast(uint)time; - - if (dt == 0) - return d_time_nan; - - int year = ((dt >> 25) & 0x7F) + 1980; - int month = ((dt >> 21) & 0x0F) - 1; // 0..12 - int dayofmonth = ((dt >> 16) & 0x1F); // 0..31 - int hour = (dt >> 11) & 0x1F; // 0..23 - int minute = (dt >> 5) & 0x3F; // 0..59 - int second = (dt << 1) & 0x3E; // 0..58 (in 2 second increments) - - d_time t; - - t = std.date.MakeDate(std.date.MakeDay(year, month, dayofmonth), - std.date.MakeTime(hour, minute, second, 0)); - - assert(YearFromTime(t) == year); - assert(MonthFromTime(t) == month); - assert(DateFromTime(t) == dayofmonth); - assert(HourFromTime(t) == hour); - assert(MinFromTime(t) == minute); - assert(SecFromTime(t) == second); - - t -= LocalTZA + DaylightSavingTA(t); - - return t; -} - -/**************************************** - * Convert from d_time to DOS file date/time. - */ - -DosFileTime toDosFileTime(d_time t) -{ uint dt; - - if (t == d_time_nan) - return cast(DosFileTime)0; - - t += LocalTZA + DaylightSavingTA(t); - - uint year = YearFromTime(t); - uint month = MonthFromTime(t); - uint dayofmonth = DateFromTime(t); - uint hour = HourFromTime(t); - uint minute = MinFromTime(t); - uint second = SecFromTime(t); - - dt = (year - 1980) << 25; - dt |= ((month + 1) & 0x0F) << 21; - dt |= (dayofmonth & 0x1F) << 16; - dt |= (hour & 0x1F) << 11; - dt |= (minute & 0x3F) << 5; - dt |= (second >> 1) & 0x1F; - - return cast(DosFileTime)dt; -} diff --git a/lphobos/std/dateparse.d b/lphobos/std/dateparse.d deleted file mode 100644 index 197fd9300d8..00000000000 --- a/lphobos/std/dateparse.d +++ /dev/null @@ -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); -} - diff --git a/lphobos/std/file.d b/lphobos/std/file.d deleted file mode 100644 index 2ee363b2612..00000000000 --- a/lphobos/std/file.d +++ /dev/null @@ -1,1590 +0,0 @@ -// Written in the D programming language. - -/** - * Macros: - * WIKI = Phobos/StdFile - */ - -/* - * Copyright (C) 2001-2004 by Digital Mars, www.digitalmars.com - * Written by Walter Bright, Christopher E. Miller, Andre Fornacon - * - * 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, March 2006 -*/ - -module std.file; - -private import std.c.stdio; -private import std.c.stdlib; -private import std.c.string; -private import std.path; -private import std.string; -private import std.regexp; -private import std.gc; - -version(linux) version = Unix; - -/* =========================== Win32 ======================= */ - -version (Win32) -{ - -private import std.c.windows.windows; -private import std.utf; -private import std.windows.syserror; -private import std.windows.charset; -private import std.date; - -int useWfuncs = 1; - -static this() -{ - // Win 95, 98, ME do not implement the W functions - useWfuncs = (GetVersion() < 0x80000000); -} - -/*********************************** - * Exception thrown for file I/O errors. - */ - -class FileException : Exception -{ - - uint errno; // operating system error code - - this(char[] name) - { - this(name, "file I/O"); - } - - this(char[] name, char[] message) - { - super(name ~ ": " ~ message); - } - - this(char[] name, uint errno) - { - this(name, sysErrorString(errno)); - this.errno = errno; - } -} - -/* ********************************** - * Basic File operations. - */ - -/******************************************** - * Read file name[], return array of bytes read. - * Throws: - * FileException on error. - */ - -void[] read(char[] name) -{ - DWORD numread; - HANDLE h; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - - if (h == INVALID_HANDLE_VALUE) - goto err1; - - auto size = GetFileSize(h, null); - if (size == INVALID_FILE_SIZE) - goto err2; - - auto buf = std.gc.malloc(size); - if (buf) - std.gc.hasNoPointers(buf.ptr); - - if (ReadFile(h,buf.ptr,size,&numread,null) != 1) - goto err2; - - if (numread != size) - goto err2; - - if (!CloseHandle(h)) - goto err; - - return buf[0 .. size]; - -err2: - CloseHandle(h); -err: - delete buf; -err1: - throw new FileException(name, GetLastError()); -} - -/********************************************* - * Write buffer[] to file name[]. - * Throws: FileException on error. - */ - -void write(char[] name, void[] buffer) -{ - HANDLE h; - DWORD numwritten; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_WRITE,0,null,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - if (h == INVALID_HANDLE_VALUE) - goto err; - - if (WriteFile(h,buffer.ptr,buffer.length,&numwritten,null) != 1) - goto err2; - - if (buffer.length != numwritten) - goto err2; - - if (!CloseHandle(h)) - goto err; - return; - -err2: - CloseHandle(h); -err: - throw new FileException(name, GetLastError()); -} - - -/********************************************* - * Append buffer[] to file name[]. - * Throws: FileException on error. - */ - -void append(char[] name, void[] buffer) -{ - HANDLE h; - DWORD numwritten; - - if (useWfuncs) - { - wchar* namez = std.utf.toUTF16z(name); - h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - else - { - char* namez = toMBSz(name); - h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null); - } - if (h == INVALID_HANDLE_VALUE) - goto err; - - SetFilePointer(h, 0, null, FILE_END); - - if (WriteFile(h,buffer.ptr,buffer.length,&numwritten,null) != 1) - goto err2; - - if (buffer.length != numwritten) - goto err2; - - if (!CloseHandle(h)) - goto err; - return; - -err2: - CloseHandle(h); -err: - throw new FileException(name, GetLastError()); -} - - -/*************************************************** - * Rename file from[] to to[]. - * Throws: FileException on error. - */ - -void rename(char[] from, char[] to) -{ - BOOL result; - - if (useWfuncs) - result = MoveFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to)); - else - result = MoveFileA(toMBSz(from), toMBSz(to)); - if (!result) - throw new FileException(to, GetLastError()); -} - - -/*************************************************** - * Delete file name[]. - * Throws: FileException on error. - */ - -void remove(char[] name) -{ - BOOL result; - - if (useWfuncs) - result = DeleteFileW(std.utf.toUTF16z(name)); - else - result = DeleteFileA(toMBSz(name)); - if (!result) - throw new FileException(name, GetLastError()); -} - - -/*************************************************** - * Get size of file name[]. - * Throws: FileException on error. - */ - -ulong getSize(char[] name) -{ - HANDLE findhndl; - uint resulth; - uint resultl; - - if (useWfuncs) - { - WIN32_FIND_DATAW filefindbuf; - - findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf); - resulth = filefindbuf.nFileSizeHigh; - resultl = filefindbuf.nFileSizeLow; - } - else - { - WIN32_FIND_DATA filefindbuf; - - findhndl = FindFirstFileA(toMBSz(name), &filefindbuf); - resulth = filefindbuf.nFileSizeHigh; - resultl = filefindbuf.nFileSizeLow; - } - - if (findhndl == cast(HANDLE)-1) - { - throw new FileException(name, GetLastError()); - } - FindClose(findhndl); - return (cast(ulong)resulth << 32) + resultl; -} - -/************************* - * Get creation/access/modified times of file name[]. - * Throws: FileException on error. - */ - -void getTimes(char[] name, out d_time ftc, out d_time fta, out d_time ftm) -{ - HANDLE findhndl; - - if (useWfuncs) - { - WIN32_FIND_DATAW filefindbuf; - - findhndl = FindFirstFileW(std.utf.toUTF16z(name), &filefindbuf); - ftc = std.date.FILETIME2d_time(&filefindbuf.ftCreationTime); - fta = std.date.FILETIME2d_time(&filefindbuf.ftLastAccessTime); - ftm = std.date.FILETIME2d_time(&filefindbuf.ftLastWriteTime); - } - else - { - WIN32_FIND_DATA filefindbuf; - - findhndl = FindFirstFileA(toMBSz(name), &filefindbuf); - ftc = std.date.FILETIME2d_time(&filefindbuf.ftCreationTime); - fta = std.date.FILETIME2d_time(&filefindbuf.ftLastAccessTime); - ftm = std.date.FILETIME2d_time(&filefindbuf.ftLastWriteTime); - } - - if (findhndl == cast(HANDLE)-1) - { - throw new FileException(name, GetLastError()); - } - FindClose(findhndl); -} - - -/*************************************************** - * Does file name[] (or directory) exist? - * Return 1 if it does, 0 if not. - */ - -int exists(char[] name) -{ - uint result; - - if (useWfuncs) - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/getfileattributes.asp - result = GetFileAttributesW(std.utf.toUTF16z(name)); - else - result = GetFileAttributesA(toMBSz(name)); - - return (result == 0xFFFFFFFF) ? 0 : 1; -} - -/*************************************************** - * Get file name[] attributes. - * Throws: FileException on error. - */ - -uint getAttributes(char[] name) -{ - uint result; - - if (useWfuncs) - result = GetFileAttributesW(std.utf.toUTF16z(name)); - else - result = GetFileAttributesA(toMBSz(name)); - if (result == 0xFFFFFFFF) - { - throw new FileException(name, GetLastError()); - } - return result; -} - -/**************************************************** - * Is name[] a file? - * Throws: FileException if name[] doesn't exist. - */ - -int isfile(char[] name) -{ - return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) == 0; -} - -/**************************************************** - * Is name[] a directory? - * Throws: FileException if name[] doesn't exist. - */ - -int isdir(char[] name) -{ - return (getAttributes(name) & FILE_ATTRIBUTE_DIRECTORY) != 0; -} - -/**************************************************** - * Change directory to pathname[]. - * Throws: FileException on error. - */ - -void chdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = SetCurrentDirectoryW(std.utf.toUTF16z(pathname)); - else - result = SetCurrentDirectoryA(toMBSz(pathname)); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Make directory pathname[]. - * Throws: FileException on error. - */ - -void mkdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = CreateDirectoryW(std.utf.toUTF16z(pathname), null); - else - result = CreateDirectoryA(toMBSz(pathname), null); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Remove directory pathname[]. - * Throws: FileException on error. - */ - -void rmdir(char[] pathname) -{ BOOL result; - - if (useWfuncs) - result = RemoveDirectoryW(std.utf.toUTF16z(pathname)); - else - result = RemoveDirectoryA(toMBSz(pathname)); - - if (!result) - { - throw new FileException(pathname, GetLastError()); - } -} - -/**************************************************** - * Get current directory. - * Throws: FileException on error. - */ - -char[] getcwd() -{ - if (useWfuncs) - { - wchar c; - - auto len = GetCurrentDirectoryW(0, &c); - if (!len) - goto Lerr; - auto dir = new wchar[len]; - len = GetCurrentDirectoryW(len, dir.ptr); - if (!len) - goto Lerr; - return std.utf.toUTF8(dir[0 .. len]); // leave off terminating 0 - } - else - { - char c; - - auto len = GetCurrentDirectoryA(0, &c); - if (!len) - goto Lerr; - auto dir = new char[len]; - len = GetCurrentDirectoryA(len, dir.ptr); - if (!len) - goto Lerr; - return dir[0 .. len]; // leave off terminating 0 - } - -Lerr: - throw new FileException("getcwd", GetLastError()); -} - -/*************************************************** - * Directory Entry - */ - -struct DirEntry -{ - char[] name; /// file or directory name - ulong size = ~0UL; /// size of file in bytes - d_time creationTime = d_time_nan; /// time of file creation - d_time lastAccessTime = d_time_nan; /// time file was last accessed - d_time lastWriteTime = d_time_nan; /// time file was last written to - uint attributes; // Windows file attributes OR'd together - - void init(char[] path, WIN32_FIND_DATA *fd) - { - wchar[] wbuf; - size_t clength; - size_t wlength; - size_t n; - - clength = std.string.strlen(fd.cFileName.ptr); - - // Convert cFileName[] to unicode - wlength = MultiByteToWideChar(0,0,fd.cFileName.ptr,clength,null,0); - if (wlength > wbuf.length) - wbuf.length = wlength; - n = MultiByteToWideChar(0,0,fd.cFileName.ptr,clength,cast(wchar*)wbuf,wlength); - assert(n == wlength); - // toUTF8() returns a new buffer - name = std.path.join(path, std.utf.toUTF8(wbuf[0 .. wlength])); - - size = (cast(ulong)fd.nFileSizeHigh << 32) | fd.nFileSizeLow; - creationTime = std.date.FILETIME2d_time(&fd.ftCreationTime); - lastAccessTime = std.date.FILETIME2d_time(&fd.ftLastAccessTime); - lastWriteTime = std.date.FILETIME2d_time(&fd.ftLastWriteTime); - attributes = fd.dwFileAttributes; - } - - void init(char[] path, WIN32_FIND_DATAW *fd) - { - size_t clength = std.string.wcslen(fd.cFileName.ptr); - name = std.path.join(path, std.utf.toUTF8(fd.cFileName[0 .. clength])); - size = (cast(ulong)fd.nFileSizeHigh << 32) | fd.nFileSizeLow; - creationTime = std.date.FILETIME2d_time(&fd.ftCreationTime); - lastAccessTime = std.date.FILETIME2d_time(&fd.ftLastAccessTime); - lastWriteTime = std.date.FILETIME2d_time(&fd.ftLastWriteTime); - attributes = fd.dwFileAttributes; - } - - /**** - * Return !=0 if DirEntry is a directory. - */ - uint isdir() - { - return attributes & FILE_ATTRIBUTE_DIRECTORY; - } - - /**** - * Return !=0 if DirEntry is a file. - */ - uint isfile() - { - return !(attributes & FILE_ATTRIBUTE_DIRECTORY); - } -} - - -/*************************************************** - * Return contents of directory pathname[]. - * The names in the contents do not include the pathname. - * Throws: FileException on error - * Example: - * This program lists all the files and subdirectories in its - * path argument. - * ---- - * import std.stdio; - * import std.file; - * - * void main(char[][] args) - * { - * auto dirs = std.file.listdir(args[1]); - * - * foreach (d; dirs) - * writefln(d); - * } - * ---- - */ - -char[][] listdir(char[] pathname) -{ - char[][] result; - - bool listing(char[] filename) - { - result ~= filename; - return true; // continue - } - - listdir(pathname, &listing); - return result; -} - - -/***************************************************** - * Return all the files in the directory and its subdirectories - * that match pattern or regular expression r. - * Params: - * pathname = Directory name - * pattern = String with wildcards, such as $(RED "*.d"). The supported - * wildcard strings are described under fnmatch() in - * $(LINK2 std_path.html, std.path). - * r = Regular expression, for more powerful _pattern matching. - * Example: - * This program lists all the files with a "d" extension in - * the path passed as the first argument. - * ---- - * import std.stdio; - * import std.file; - * - * void main(char[][] args) - * { - * auto d_source_files = std.file.listdir(args[1], "*.d"); - * - * foreach (d; d_source_files) - * writefln(d); - * } - * ---- - * A regular expression version that searches for all files with "d" or - * "obj" extensions: - * ---- - * import std.stdio; - * import std.file; - * import std.regexp; - * - * void main(char[][] args) - * { - * auto d_source_files = std.file.listdir(args[1], RegExp(r"\.(d|obj)$")); - * - * foreach (d; d_source_files) - * writefln(d); - * } - * ---- - */ - -char[][] listdir(char[] pathname, char[] pattern) -{ char[][] result; - - bool callback(DirEntry* de) - { - if (de.isdir) - listdir(de.name, &callback); - else - { if (std.path.fnmatch(de.name, pattern)) - result ~= de.name; - } - return true; // continue - } - - listdir(pathname, &callback); - return result; -} - -/** Ditto */ - -char[][] listdir(char[] pathname, RegExp r) -{ char[][] result; - - bool callback(DirEntry* de) - { - if (de.isdir) - listdir(de.name, &callback); - else - { if (r.test(de.name)) - result ~= de.name; - } - return true; // continue - } - - listdir(pathname, &callback); - return result; -} - -/****************************************************** - * For each file and directory name in pathname[], - * pass it to the callback delegate. - * Params: - * callback = Delegate that processes each - * filename in turn. Returns true to - * continue, false to stop. - * Example: - * This program lists all the files in its - * path argument, including the path. - * ---- - * import std.stdio; - * import std.path; - * import std.file; - * - * void main(char[][] args) - * { - * auto pathname = args[1]; - * char[][] result; - * - * bool listing(char[] filename) - * { - * result ~= std.path.join(pathname, filename); - * return true; // continue - * } - * - * listdir(pathname, &listing); - * - * foreach (name; result) - * writefln("%s", name); - * } - * ---- - */ - -void listdir(char[] pathname, bool delegate(char[] filename) callback) -{ - bool listing(DirEntry* de) - { - return callback(std.path.getBaseName(de.name)); - } - - listdir(pathname, &listing); -} - -/****************************************************** - * For each file and directory DirEntry in pathname[], - * pass it to the callback delegate. - * Params: - * callback = Delegate that processes each - * DirEntry in turn. Returns true to - * continue, false to stop. - * Example: - * This program lists all the files in its - * path argument and all subdirectories thereof. - * ---- - * import std.stdio; - * import std.file; - * - * void main(char[][] args) - * { - * bool callback(DirEntry* de) - * { - * if (de.isdir) - * listdir(de.name, &callback); - * else - * writefln(de.name); - * return true; - * } - * - * listdir(args[1], &callback); - * } - * ---- - */ - -void listdir(char[] pathname, bool delegate(DirEntry* de) callback) -{ - char[] c; - HANDLE h; - DirEntry de; - - c = std.path.join(pathname, "*.*"); - if (useWfuncs) - { - WIN32_FIND_DATAW fileinfo; - - h = FindFirstFileW(std.utf.toUTF16z(c), &fileinfo); - if (h != INVALID_HANDLE_VALUE) - { - try - { - do - { - // Skip "." and ".." - if (std.string.wcscmp(fileinfo.cFileName.ptr, ".") == 0 || - std.string.wcscmp(fileinfo.cFileName.ptr, "..") == 0) - continue; - - de.init(pathname, &fileinfo); - if (!callback(&de)) - break; - } while (FindNextFileW(h,&fileinfo) != FALSE); - } - finally - { - FindClose(h); - } - } - } - else - { - WIN32_FIND_DATA fileinfo; - - h = FindFirstFileA(toMBSz(c), &fileinfo); - if (h != INVALID_HANDLE_VALUE) // should we throw exception if invalid? - { - try - { - do - { - // Skip "." and ".." - if (std.string.strcmp(fileinfo.cFileName.ptr, ".") == 0 || - std.string.strcmp(fileinfo.cFileName.ptr, "..") == 0) - continue; - - de.init(pathname, &fileinfo); - if (!callback(&de)) - break; - } while (FindNextFileA(h,&fileinfo) != FALSE); - } - finally - { - FindClose(h); - } - } - } -} - -/****************************************** - * Since Win 9x does not support the "W" API's, first convert - * to wchar, then convert to multibyte using the current code - * page. - * (Thanks to yaneurao for this) - * Deprecated: use std.windows.charset.toMBSz instead. - */ - -char* toMBSz(char[] s) -{ - return std.windows.charset.toMBSz(s); -} - - -/*************************************************** - * Copy a file from[] to[]. - */ - -void copy(char[] from, char[] to) -{ - BOOL result; - - if (useWfuncs) - result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to), false); - else - result = CopyFileA(toMBSz(from), toMBSz(to), false); - if (!result) - throw new FileException(to, GetLastError()); -} - - -} - -/* =========================== linux ======================= */ - -else version (Unix) -{ - -version(linux) { - import std.c.linux.linux; - alias std.c.linux.linux sys; -} else { - import std.c.unix.unix; - alias std.c.unix.unix sys; -} -import std.date, std.c.string; - -/*********************************** - */ - -extern(C) char* strerror_r(int errnum, char* buf, size_t buflen); -class FileException : Exception -{ - - uint errno; // operating system error code - - this(char[] name) - { - this(name, "file I/O"); - } - - this(char[] name, char[] message) - { - super(name ~ ": " ~ message); - } - - this(char[] name, uint errno) - { char[80] buf = void; - auto s = strerror_r(errno, buf.ptr, buf.length); - this(name, std.string.toString(s).dup); - this.errno = errno; - } -} - -/******************************************** - * Read a file. - * Returns: - * array of bytes read - */ - -void[] read(char[] name) -{ - uint numread; - struct_stat statbuf; - - auto namez = toStringz(name); - //printf("file.read('%s')\n",namez); - auto fd = sys.open(namez, O_RDONLY); - if (fd == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err1; - } - - //printf("\tfile opened\n"); - if (sys.fstat(fd, &statbuf)) - { - //printf("\tfstat error, errno = %d\n",getErrno()); - goto err2; - } - auto size = statbuf.st_size; - if (size > size_t.max) - goto err2; - - auto buf = std.gc.malloc(size); - if (buf.ptr) - std.gc.hasNoPointers(buf.ptr); - - numread = sys.read(fd, buf.ptr, size); - if (numread != size) - { - //printf("\tread error, errno = %d\n",getErrno()); - goto err2; - } - - if (sys.close(fd) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err; - } - - return buf[0 .. size]; - -err2: - sys.close(fd); -err: - delete buf; - -err1: - throw new FileException(name, getErrno()); -} - -/********************************************* - * Write a file. - * Returns: - * 0 success - */ - -void write(char[] name, void[] buffer) -{ - int fd; - char *namez; - - namez = toStringz(name); - fd = sys.open(namez, O_CREAT | O_WRONLY | O_TRUNC, 0660); - if (fd == -1) - goto err; - - auto numwritten = sys.write(fd, buffer.ptr, buffer.length); - if (buffer.length != numwritten) - goto err2; - - if (sys.close(fd) == -1) - goto err; - - return; - -err2: - sys.close(fd); -err: - throw new FileException(name, getErrno()); -} - - -/********************************************* - * Append to a file. - */ - -void append(char[] name, void[] buffer) -{ - int fd; - char *namez; - - namez = toStringz(name); - fd = sys.open(namez, O_APPEND | O_WRONLY | O_CREAT, 0660); - if (fd == -1) - goto err; - - auto numwritten = sys.write(fd, buffer.ptr, buffer.length); - if (buffer.length != numwritten) - goto err2; - - if (sys.close(fd) == -1) - goto err; - - return; - -err2: - sys.close(fd); -err: - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Rename a file. - */ - -void rename(char[] from, char[] to) -{ - char *fromz = toStringz(from); - char *toz = toStringz(to); - - if (std.c.stdio.rename(fromz, toz) == -1) - throw new FileException(to, getErrno()); -} - - -/*************************************************** - * Delete a file. - */ - -void remove(char[] name) -{ - if (std.c.stdio.remove(toStringz(name)) == -1) - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Get file size. - */ - -ulong getSize(char[] name) -{ - uint size; - int fd; - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - //printf("file.getSize('%s')\n",namez); - fd = sys.open(namez, O_RDONLY); - if (fd == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err1; - } - - //printf("\tfile opened\n"); - if (sys.fstat(fd, &statbuf)) - { - //printf("\tfstat error, errno = %d\n",getErrno()); - goto err2; - } - size = statbuf.st_size; - - if (sys.close(fd) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err; - } - - return size; - -err2: - sys.close(fd); -err: -err1: - throw new FileException(name, getErrno()); -} - - -/*************************************************** - * Get file attributes. - */ - -uint getAttributes(char[] name) -{ - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - if (sys.stat(namez, &statbuf)) - { - throw new FileException(name, getErrno()); - } - - return statbuf.st_mode; -} - -/************************* - * Get creation/access/modified times of file name[]. - * Throws: FileException on error. - */ - -void getTimes(char[] name, out d_time ftc, out d_time fta, out d_time ftm) -{ - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - if (sys.stat(namez, &statbuf)) - { - throw new FileException(name, getErrno()); - } - - ftc = cast(d_time)statbuf.st_ctime * std.date.TicksPerSecond; - fta = cast(d_time)statbuf.st_atime * std.date.TicksPerSecond; - ftm = cast(d_time)statbuf.st_mtime * std.date.TicksPerSecond; -} - - -/**************************************************** - * Does file/directory exist? - */ - -int exists(char[] name) -{ - return access(toStringz(name),0) == 0; - -/+ - struct_stat statbuf; - char *namez; - - namez = toStringz(name); - if (sys.stat(namez, &statbuf)) - { - return 0; - } - return 1; -+/ -} - -unittest -{ - assert(exists(".")); -} - -/**************************************************** - * Is name a file? - */ - -int isfile(char[] name) -{ - return (getAttributes(name) & S_IFMT) == S_IFREG; // regular file -} - -/**************************************************** - * Is name a directory? - */ - -int isdir(char[] name) -{ - return (getAttributes(name) & S_IFMT) == S_IFDIR; -} - -/**************************************************** - * Change directory. - */ - -void chdir(char[] pathname) -{ - if (sys.chdir(toStringz(pathname))) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Make directory. - */ - -void mkdir(char[] pathname) -{ - if (sys.mkdir(toStringz(pathname), 0777)) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Remove directory. - */ - -void rmdir(char[] pathname) -{ - if (sys.rmdir(toStringz(pathname))) - { - throw new FileException(pathname, getErrno()); - } -} - -/**************************************************** - * Get current directory. - */ - -char[] getcwd() -{ - version(all) - { - const PATH_MAX=4096; - char buf[PATH_MAX]; - if (! sys.getcwd(buf.ptr, buf.length)) - { - throw new FileException("cannot get cwd", getErrno()); - } - size_t len = strlen(buf.ptr); - char[] result = new char[len]; - result[] = buf[0..len]; - return result; - } - else - { - auto p = sys.getcwd(null, 0); - if (!p) - { - throw new FileException("cannot get cwd", getErrno()); - } - auto len = std.string.strlen(p); - auto buf = new char[len]; - buf[] = p[0 .. len]; - std.c.stdlib.free(p); - return buf; - } - -} - -/*************************************************** - * Directory Entry - */ - -struct DirEntry -{ - char[] name; /// file or directory name - ulong _size = ~0UL; // size of file in bytes - d_time _creationTime = d_time_nan; // time of file creation - d_time _lastAccessTime = d_time_nan; // time file was last accessed - d_time _lastWriteTime = d_time_nan; // time file was last written to - version (GNU) - typeof(struct_stat.st_mode) _st_mode; - else - ubyte d_type; - ubyte didstat; // done lazy evaluation of stat() - - void init(char[] path, dirent *fd) - { size_t len = std.string.strlen(fd.d_name.ptr); - name = std.path.join(path, fd.d_name[0 .. len]); - version(GNU) - { } - else - d_type = fd.d_type; - didstat = 0; - } - - int isdir() - { - version(GNU) - { - if (!didstat) - doStat(); - return (_st_mode & S_IFMT) == S_IFDIR; - } - else - return d_type & DT_DIR; - } - - int isfile() - { - version(GNU) - { - if (!didstat) - doStat(); - return (_st_mode & S_IFMT) == S_IFREG; - } - else - return d_type & DT_REG; - } - - ulong size() - { - if (!didstat) - doStat(); - return _size; - } - - d_time creationTime() - { - if (!didstat) - doStat(); - return _creationTime; - } - - d_time lastAccessTime() - { - if (!didstat) - doStat(); - return _lastAccessTime; - } - - d_time lastWriteTime() - { - if (!didstat) - doStat(); - return _lastWriteTime; - } - - /* This is to support lazy evaluation, because doing stat's is - * expensive and not always needed. - */ - - void doStat() - { - int fd; - struct_stat statbuf; - char* namez; - - namez = toStringz(name); - if (sys.stat(namez, &statbuf)) - { - //printf("\tstat error, errno = %d\n",getErrno()); - return; - } - _size = statbuf.st_size; - _creationTime = cast(d_time)statbuf.st_ctime * std.date.TicksPerSecond; - _lastAccessTime = cast(d_time)statbuf.st_atime * std.date.TicksPerSecond; - _lastWriteTime = cast(d_time)statbuf.st_mtime * std.date.TicksPerSecond; - version(GNU) _st_mode = statbuf.st_mode; - didstat = 1; - } -} - - -/*************************************************** - * Return contents of directory. - */ - -char[][] listdir(char[] pathname) -{ - char[][] result; - - bool listing(char[] filename) - { - result ~= filename; - return true; // continue - } - - listdir(pathname, &listing); - return result; -} - -char[][] listdir(char[] pathname, char[] pattern) -{ char[][] result; - - bool callback(DirEntry* de) - { - if (de.isdir) - listdir(de.name, &callback); - else - { if (std.path.fnmatch(de.name, pattern)) - result ~= de.name; - } - return true; // continue - } - - listdir(pathname, &callback); - return result; -} - -char[][] listdir(char[] pathname, RegExp r) -{ char[][] result; - - bool callback(DirEntry* de) - { - if (de.isdir) - listdir(de.name, &callback); - else - { if (r.test(de.name)) - result ~= de.name; - } - return true; // continue - } - - listdir(pathname, &callback); - return result; -} - -void listdir(char[] pathname, bool delegate(char[] filename) callback) -{ - bool listing(DirEntry* de) - { - return callback(std.path.getBaseName(de.name)); - } - - listdir(pathname, &listing); -} - -void listdir(char[] pathname, bool delegate(DirEntry* de) callback) -{ - DIR* h; - dirent* fdata; - DirEntry de; - - h = opendir(toStringz(pathname)); - if (h) - { - try - { - while((fdata = readdir(h)) != null) - { - // Skip "." and ".." - if (!std.string.strcmp(fdata.d_name.ptr, ".") || - !std.string.strcmp(fdata.d_name.ptr, "..")) - continue; - - de.init(pathname, fdata); - if (!callback(&de)) - break; - } - } - finally - { - closedir(h); - } - } - else - { - throw new FileException(pathname, getErrno()); - } -} - - -/*************************************************** - * Copy a file. File timestamps are preserved. - */ - -void copy(char[] from, char[] to) -{ - version (all) - { - struct_stat statbuf; - - char* fromz = toStringz(from); - char* toz = toStringz(to); - //printf("file.copy(from='%s', to='%s')\n", fromz, toz); - - int fd = sys.open(fromz, O_RDONLY); - if (fd == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err1; - } - - //printf("\tfile opened\n"); - if (sys.fstat(fd, &statbuf)) - { - //printf("\tfstat error, errno = %d\n",getErrno()); - goto err2; - } - - int fdw = sys.open(toz, O_CREAT | O_WRONLY | O_TRUNC, 0660); - if (fdw == -1) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err2; - } - - size_t BUFSIZ = 4096 * 16; - void* buf = std.c.stdlib.malloc(BUFSIZ); - if (!buf) - { BUFSIZ = 4096; - buf = std.c.stdlib.malloc(BUFSIZ); - } - if (!buf) - { - //printf("\topen error, errno = %d\n",getErrno()); - goto err4; - } - - for (auto size = statbuf.st_size; size; ) - { size_t toread = (size > BUFSIZ) ? BUFSIZ : size; - - auto n = sys.read(fd, buf, toread); - if (n != toread) - { - //printf("\tread error, errno = %d\n",getErrno()); - goto err5; - } - n = sys.write(fdw, buf, toread); - if (n != toread) - { - //printf("\twrite error, errno = %d\n",getErrno()); - goto err5; - } - size -= toread; - } - - std.c.stdlib.free(buf); - - if (sys.close(fdw) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err2; - } - - utimbuf utim; - utim.actime = cast(typeof(utim.actime))statbuf.st_atime; - utim.modtime = cast(typeof(utim.modtime))statbuf.st_mtime; - if (utime(toz, &utim) == -1) - { - //printf("\tutime error, errno = %d\n",getErrno()); - goto err3; - } - - if (sys.close(fd) == -1) - { - //printf("\tclose error, errno = %d\n",getErrno()); - goto err1; - } - - return; - -err5: - std.c.stdlib.free(buf); -err4: - sys.close(fdw); -err3: - std.c.stdio.remove(toz); -err2: - sys.close(fd); -err1: - throw new FileException(from, getErrno()); - } - else - { - void[] buffer; - - buffer = read(from); - write(to, buffer); - delete buffer; - } -} - - - -} - -unittest -{ - //printf("std.file.unittest\n"); - void[] buf; - - buf = new void[10]; - (cast(byte[])buf)[] = 3; - write("unittest_write.tmp", buf); - void buf2[] = read("unittest_write.tmp"); - assert(buf == buf2); - - copy("unittest_write.tmp", "unittest_write2.tmp"); - buf2 = read("unittest_write2.tmp"); - assert(buf == buf2); - - remove("unittest_write.tmp"); - if (exists("unittest_write.tmp")) - assert(0); - remove("unittest_write2.tmp"); - if (exists("unittest_write2.tmp")) - assert(0); -} - -unittest -{ - listdir (".", delegate bool (DirEntry * de) - { - auto s = std.string.format("%s : c %s, w %s, a %s", de.name, - toUTCString (de.creationTime), - toUTCString (de.lastWriteTime), - toUTCString (de.lastAccessTime)); - return true; - } - ); -} - - diff --git a/lphobos/std/format.d b/lphobos/std/format.d deleted file mode 100644 index a081912921d..00000000000 --- a/lphobos/std/format.d +++ /dev/null @@ -1,1570 +0,0 @@ - -// Written in the D programming language. - -/** - * This module implements the workhorse functionality for string and I/O formatting. - * It's comparable to C99's vsprintf(). - * - * Macros: - * WIKI = Phobos/StdFormat - */ - -/* - * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com - * Written by Walter Bright - * Modified for LDC by Tomas Lindquist Olsen - * - * 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.format; - -//debug=format; // uncomment to turn on debugging printf's - -import std.stdarg; // caller will need va_list - -private import std.utf; -private import std.c.stdlib; -private import std.c.string; -private import std.string; - -version (Windows) -{ - version (DigitalMars) - { - version = DigitalMarsC; - } -} - -version (DigitalMarsC) -{ - // This is DMC's internal floating point formatting function - extern (C) - { - extern char* function(int c, int flags, int precision, real* pdval, - char* buf, int* psl, int width) __pfloatfmt; - } -} -else -{ - // Use C99 snprintf - extern (C) int snprintf(char* s, size_t n, char* format, ...); -} - -/********************************************************************** - * Signals a mismatch between a format and its corresponding argument. - */ -class FormatError : Error -{ - private: - - this() - { - super("std.format"); - } - - this(char[] msg) - { - super("std.format " ~ msg); - } -} - - -enum Mangle : char -{ - Tvoid = 'v', - Tbool = 'b', - Tbyte = 'g', - Tubyte = 'h', - Tshort = 's', - Tushort = 't', - Tint = 'i', - Tuint = 'k', - Tlong = 'l', - Tulong = 'm', - Tfloat = 'f', - Tdouble = 'd', - Treal = 'e', - - Tifloat = 'o', - Tidouble = 'p', - Tireal = 'j', - Tcfloat = 'q', - Tcdouble = 'r', - Tcreal = 'c', - - Tchar = 'a', - Twchar = 'u', - Tdchar = 'w', - - Tarray = 'A', - Tsarray = 'G', - Taarray = 'H', - Tpointer = 'P', - Tfunction = 'F', - Tident = 'I', - Tclass = 'C', - Tstruct = 'S', - Tenum = 'E', - Ttypedef = 'T', - Tdelegate = 'D', - - Tconst = 'x', - Tinvariant = 'y', -} - -// return the TypeInfo for a primitive type and null otherwise. -// This is required since for arrays of ints we only have the mangled -// char to work from. If arrays always subclassed TypeInfo_Array this -// routine could go away. -private TypeInfo primitiveTypeInfo(Mangle m) -{ - TypeInfo ti; - - switch (m) - { - case Mangle.Tvoid: - ti = typeid(void);break; - case Mangle.Tbool: - ti = typeid(bool);break; - case Mangle.Tbyte: - ti = typeid(byte);break; - case Mangle.Tubyte: - ti = typeid(ubyte);break; - case Mangle.Tshort: - ti = typeid(short);break; - case Mangle.Tushort: - ti = typeid(ushort);break; - case Mangle.Tint: - ti = typeid(int);break; - case Mangle.Tuint: - ti = typeid(uint);break; - case Mangle.Tlong: - ti = typeid(long);break; - case Mangle.Tulong: - ti = typeid(ulong);break; - case Mangle.Tfloat: - ti = typeid(float);break; - case Mangle.Tdouble: - ti = typeid(double);break; - case Mangle.Treal: - ti = typeid(real);break; - case Mangle.Tifloat: - ti = typeid(ifloat);break; - case Mangle.Tidouble: - ti = typeid(idouble);break; - case Mangle.Tireal: - ti = typeid(ireal);break; - case Mangle.Tcfloat: - ti = typeid(cfloat);break; - case Mangle.Tcdouble: - ti = typeid(cdouble);break; - case Mangle.Tcreal: - ti = typeid(creal);break; - case Mangle.Tchar: - ti = typeid(char);break; - case Mangle.Twchar: - ti = typeid(wchar);break; - case Mangle.Tdchar: - ti = typeid(dchar); - default: - ti = null; - } - return ti; -} - -/************************************ - * Interprets variadic argument list pointed to by argptr whose types are given - * by arguments[], formats them according to embedded format strings in the - * variadic argument list, and sends the resulting characters to putc. - * - * The variadic arguments are consumed in order. - * Each is formatted into a sequence of chars, using the default format - * specification for its type, and the - * characters are sequentially passed to putc. - * If a char[], wchar[], or dchar[] - * argument is encountered, it is interpreted as a format string. As many - * arguments as specified in the format string are consumed and formatted - * according to the format specifications in that string and passed to putc. If - * there are too few remaining arguments, a FormatError is thrown. If there are - * more remaining arguments than needed by the format specification, the default - * processing of arguments resumes until they are all consumed. - * - * Params: - * putc = Output is sent do this delegate, character by character. - * arguments = Array of TypeInfo's, one for each argument to be formatted. - * argptr = Points to variadic argument list. - * - * Throws: - * Mismatched arguments and formats result in a FormatError being thrown. - * - * Format_String: - * $(I Format strings) - * consist of characters interspersed with - * $(I format specifications). Characters are simply copied - * to the output (such as putc) after any necessary conversion - * to the corresponding UTF-8 sequence. - * - * A $(I format specification) starts with a '%' character, - * and has the following grammar: - -
-$(I FormatSpecification):
-    $(B '%%')
-    $(B '%') $(I Flags) $(I Width) $(I Precision) $(I FormatChar)
-
-$(I Flags):
-    $(I empty)
-    $(B '-') $(I Flags)
-    $(B '+') $(I Flags)
-    $(B '#') $(I Flags)
-    $(B '0') $(I Flags)
-    $(B ' ') $(I Flags)
-
-$(I Width):
-    $(I empty)
-    $(I Integer)
-    $(B '*')
-
-$(I Precision):
-    $(I empty)
-    $(B '.')
-    $(B '.') $(I Integer)
-    $(B '.*')
-
-$(I Integer):
-    $(I Digit)
-    $(I Digit) $(I Integer)
-
-$(I Digit):
-    $(B '0')
-    $(B '1')
-    $(B '2')
-    $(B '3')
-    $(B '4')
-    $(B '5')
-    $(B '6')
-    $(B '7')
-    $(B '8')
-    $(B '9')
-
-$(I FormatChar):
-    $(B 's')
-    $(B 'b')
-    $(B 'd')
-    $(B 'o')
-    $(B 'x')
-    $(B 'X')
-    $(B 'e')
-    $(B 'E')
-    $(B 'f')
-    $(B 'F')
-    $(B 'g')
-    $(B 'G')
-    $(B 'a')
-    $(B 'A')
-
-
-
$(I Flags) -
-
$(B '-') -
- Left justify the result in the field. - It overrides any $(B 0) flag. - -
$(B '+') -
Prefix positive numbers in a signed conversion with a $(B +). - It overrides any $(I space) flag. - -
$(B '#') -
Use alternative formatting: -
-
For $(B 'o'): -
Add to precision as necessary so that the first digit - of the octal formatting is a '0', even if both the argument - and the $(I Precision) are zero. -
For $(B 'x') ($(B 'X')): -
If non-zero, prefix result with $(B 0x) ($(B 0X)). -
For floating point formatting: -
Always insert the decimal point. -
For $(B 'g') ($(B 'G')): -
Do not elide trailing zeros. -
- -
$(B '0') -
For integer and floating point formatting when not nan or - infinity, use leading zeros - to pad rather than spaces. - Ignore if there's a $(I Precision). - -
$(B ' ') -
Prefix positive numbers in a signed conversion with a space. -
- -
$(I Width) -
- Specifies the minimum field width. - If the width is a $(B *), the next argument, which must be - of type $(B int), is taken as the width. - If the width is negative, it is as if the $(B -) was given - as a $(I Flags) character. - -
$(I Precision) -
Gives the precision for numeric conversions. - If the precision is a $(B *), the next argument, which must be - of type $(B int), is taken as the precision. If it is negative, - it is as if there was no $(I Precision). - -
$(I FormatChar) -
-
-
$(B 's') -
The corresponding argument is formatted in a manner consistent - with its type: -
-
$(B bool) -
The result is 'true' or 'false'. -
integral types -
The $(B %d) format is used. -
floating point types -
The $(B %g) format is used. -
string types -
The result is the string converted to UTF-8. - A $(I Precision) specifies the maximum number of characters - to use in the result. -
classes derived from $(B Object) -
The result is the string returned from the class instance's - $(B .toString()) method. - A $(I Precision) specifies the maximum number of characters - to use in the result. -
non-string static and dynamic arrays -
The result is [s0, s1, ...] - where sk is the kth element - formatted with the default format. -
- -
$(B 'b','d','o','x','X') -
The corresponding argument must be an integral type - and is formatted as an integer. If the argument is a signed type - and the $(I FormatChar) is $(B d) it is converted to - a signed string of characters, otherwise it is treated as - unsigned. An argument of type $(B bool) is formatted as '1' - or '0'. The base used is binary for $(B b), octal for $(B o), - decimal - for $(B d), and hexadecimal for $(B x) or $(B X). - $(B x) formats using lower case letters, $(B X) uppercase. - If there are fewer resulting digits than the $(I Precision), - leading zeros are used as necessary. - If the $(I Precision) is 0 and the number is 0, no digits - result. - -
$(B 'e','E') -
A floating point number is formatted as one digit before - the decimal point, $(I Precision) digits after, the $(I FormatChar), - ±, followed by at least a two digit exponent: $(I d.dddddd)e$(I ±dd). - If there is no $(I Precision), six - digits are generated after the decimal point. - If the $(I Precision) is 0, no decimal point is generated. - -
$(B 'f','F') -
A floating point number is formatted in decimal notation. - The $(I Precision) specifies the number of digits generated - after the decimal point. It defaults to six. At least one digit - is generated before the decimal point. If the $(I Precision) - is zero, no decimal point is generated. - -
$(B 'g','G') -
A floating point number is formatted in either $(B e) or - $(B f) format for $(B g); $(B E) or $(B F) format for - $(B G). - The $(B f) format is used if the exponent for an $(B e) format - is greater than -5 and less than the $(I Precision). - The $(I Precision) specifies the number of significant - digits, and defaults to six. - Trailing zeros are elided after the decimal point, if the fractional - part is zero then no decimal point is generated. - -
$(B 'a','A') -
A floating point number is formatted in hexadecimal - exponential notation 0x$(I h.hhhhhh)p$(I ±d). - There is one hexadecimal digit before the decimal point, and as - many after as specified by the $(I Precision). - If the $(I Precision) is zero, no decimal point is generated. - If there is no $(I Precision), as many hexadecimal digits as - necessary to exactly represent the mantissa are generated. - The exponent is written in as few digits as possible, - but at least one, is in decimal, and represents a power of 2 as in - $(I h.hhhhhh)*2$(I ±d). - The exponent for zero is zero. - The hexadecimal digits, x and p are in upper case if the - $(I FormatChar) is upper case. -
- - Floating point NaN's are formatted as $(B nan) if the - $(I FormatChar) is lower case, or $(B NAN) if upper. - Floating point infinities are formatted as $(B inf) or - $(B infinity) if the - $(I FormatChar) is lower case, or $(B INF) or $(B INFINITY) if upper. -
- -Example: - -------------------------- -import std.c.stdio; -import std.format; - -void formattedPrint(...) -{ - void putc(char c) - { - fputc(c, stdout); - } - - std.format.doFormat(&putc, _arguments, _argptr); -} - -... - -int x = 27; -// prints 'The answer is 27:6' -formattedPrint("The answer is %s:", x, 6); ------------------------- - */ - -void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, void* argptr) -{ //printf("doFormat(...)\n"); - int j; - TypeInfo ti; - Mangle m; - uint flags; - int field_width; - int precision; - - enum : uint - { - FLdash = 1, - FLplus = 2, - FLspace = 4, - FLhash = 8, - FLlngdbl = 0x20, - FL0pad = 0x40, - FLprecision = 0x80, - } - - static TypeInfo skipCI(TypeInfo valti) - { - while (1) - { - if (valti.classinfo.name.length == 18 && - valti.classinfo.name[9..18] == "Invariant") - valti = (cast(TypeInfo_Invariant)valti).next; - else if (valti.classinfo.name.length == 14 && - valti.classinfo.name[9..14] == "Const") - valti = (cast(TypeInfo_Const)valti).next; - else - break; - } - return valti; - } - - void formatArg(char fc) - { - bool vbit; - ulong vnumber; - char vchar; - dchar vdchar; - Object vobject; - real vreal; - creal vcreal; - Mangle m2; - int signed = 0; - uint base = 10; - int uc; - char[ulong.sizeof * 8] tmpbuf; // long enough to print long in binary - char* prefix = ""; - string s; - - void putstr(char[] s) - { - //printf("flags = 0x%x\n", flags); - int prepad = 0; - int postpad = 0; - int padding = field_width - (strlen(prefix) + s.length); - if (padding > 0) - { - if (flags & FLdash) - postpad = padding; - else - prepad = padding; - } - - if (flags & FL0pad) - { - while (*prefix) - putc(*prefix++); - while (prepad--) - putc('0'); - } - else - { - while (prepad--) - putc(' '); - while (*prefix) - putc(*prefix++); - } - - foreach (dchar c; s) - putc(c); - - while (postpad--) - putc(' '); - } - - void putreal(real v) - { - //printf("putreal %Lg\n", vreal); // no 80 bit float - //printf("putreal %g\n", vreal); - - switch (fc) - { - case 's': - fc = 'g'; - break; - - case 'f', 'F', 'e', 'E', 'g', 'G', 'a', 'A': - break; - - default: - //printf("fc = '%c'\n", fc); - Lerror: - throw new FormatError("floating"); - } - version (DigitalMarsC) - { - int sl; - char[] fbuf = tmpbuf; - if (!(flags & FLprecision)) - precision = 6; - while (1) - { - sl = fbuf.length; - prefix = (*__pfloatfmt)(fc, flags | FLlngdbl, - precision, &v, cast(char*)fbuf, &sl, field_width); - if (sl != -1) - break; - sl = fbuf.length * 2; - fbuf = (cast(char*)/*alloca*/malloc(sl * char.sizeof))[0 .. sl]; - } - putstr(fbuf[0 .. sl]); - } - else - { - int sl; - char[] fbuf = tmpbuf; - char[12] format; - format[0] = '%'; - int i = 1; - if (flags & FLdash) - format[i++] = '-'; - if (flags & FLplus) - format[i++] = '+'; - if (flags & FLspace) - format[i++] = ' '; - if (flags & FLhash) - format[i++] = '#'; - if (flags & FL0pad) - format[i++] = '0'; - format[i + 0] = '*'; - format[i + 1] = '.'; - format[i + 2] = '*'; - format[i + 3] = fc; - format[i + 4] = 0; - //format[i + 3] = 'L'; // no 80 bit yet - //format[i + 4] = fc; - //format[i + 5] = 0; - if (!(flags & FLprecision)) - precision = -1; - while (1) - { int n; - - sl = fbuf.length; - n = snprintf(fbuf.ptr, sl, format.ptr, field_width, precision, v); - //printf("format = '%s', n = %d\n", cast(char*)format, n); - if (n >= 0 && n < sl) - { sl = n; - break; - } - if (n < 0) - sl = sl * 2; - else - sl = n + 1; - fbuf = (cast(char*)/*alloca*/malloc(sl * char.sizeof))[0 .. sl]; - } - putstr(fbuf[0 .. sl]); - } - return; - } - - static Mangle getMan(TypeInfo ti) - { - auto m = cast(Mangle)ti.classinfo.name[9]; - if (ti.classinfo.name.length == 20 && - ti.classinfo.name[9..20] == "StaticArray") - m = cast(Mangle)'G'; - return m; - } - - void putArray(void* p, size_t len, TypeInfo valti) - { - //printf("\nputArray(len = %u), tsize = %u\n", len, valti.tsize()); - putc('['); - valti = skipCI(valti); - size_t tsize = valti.tsize(); - auto argptrSave = argptr; - auto tiSave = ti; - auto mSave = m; - ti = valti; - auto className = valti.classinfo.name; - printf("\n%.*s\n", className.length, className.ptr); - m = getMan(valti); - while (len--) - { - //doFormat(putc, (&valti)[0 .. 1], p); - argptr = p; - formatArg('s'); - - p += tsize; - if (len > 0) putc(','); - } - m = mSave; - ti = tiSave; - argptr = argptrSave; - putc(']'); - } - - void putAArray(ubyte[long] vaa, TypeInfo valti, TypeInfo keyti) - { - putc('['); - bool comma=false; - auto argptrSave = argptr; - auto tiSave = ti; - auto mSave = m; - valti = skipCI(valti); - keyti = skipCI(keyti); - foreach(inout fakevalue; vaa) - { - if (comma) putc(','); - comma = true; - // the key comes before the value - ubyte* key = &fakevalue - long.sizeof; - - //doFormat(putc, (&keyti)[0..1], key); - argptr = key; - ti = keyti; - m = getMan(keyti); - formatArg('s'); - - putc(':'); - auto keysize = keyti.tsize; - keysize = (keysize + 3) & ~3; - ubyte* value = key + keysize; - //doFormat(putc, (&valti)[0..1], value); - argptr = value; - ti = valti; - m = getMan(valti); - formatArg('s'); - } - m = mSave; - ti = tiSave; - argptr = argptrSave; - putc(']'); - } - - //printf("formatArg(fc = '%c', m = '%c')\n", fc, m); - switch (m) - { - case Mangle.Tbool: - vbit = va_arg!(bool)(argptr); - if (fc != 's') - { vnumber = vbit; - goto Lnumber; - } - putstr(vbit ? "true" : "false"); - return; - - - case Mangle.Tchar: - vchar = va_arg!(char)(argptr); - if (fc != 's') - { vnumber = vchar; - goto Lnumber; - } - L2: - putstr((&vchar)[0 .. 1]); - return; - - case Mangle.Twchar: - vdchar = va_arg!(wchar)(argptr); - goto L1; - - case Mangle.Tdchar: - vdchar = va_arg!(dchar)(argptr); - L1: - if (fc != 's') - { vnumber = vdchar; - goto Lnumber; - } - if (vdchar <= 0x7F) - { vchar = cast(char)vdchar; - goto L2; - } - else - { if (!isValidDchar(vdchar)) - throw new UtfException("invalid dchar in format", 0); - char[4] vbuf; - putstr(toUTF8(vbuf, vdchar)); - } - return; - - - case Mangle.Tbyte: - signed = 1; - vnumber = va_arg!(byte)(argptr); - goto Lnumber; - - case Mangle.Tubyte: - vnumber = va_arg!(ubyte)(argptr); - goto Lnumber; - - case Mangle.Tshort: - signed = 1; - vnumber = va_arg!(short)(argptr); - goto Lnumber; - - case Mangle.Tushort: - vnumber = va_arg!(ushort)(argptr); - goto Lnumber; - - case Mangle.Tint: - signed = 1; - vnumber = va_arg!(int)(argptr); - goto Lnumber; - - case Mangle.Tuint: - Luint: - vnumber = va_arg!(uint)(argptr); - goto Lnumber; - - case Mangle.Tlong: - signed = 1; - vnumber = cast(ulong)va_arg!(long)(argptr); - goto Lnumber; - - case Mangle.Tulong: - Lulong: - vnumber = va_arg!(ulong)(argptr); - goto Lnumber; - - case Mangle.Tclass: - vobject = va_arg!(Object)(argptr); - if (vobject is null) - s = "null"; - else - s = vobject.toString(); - goto Lputstr; - - case Mangle.Tpointer: - vnumber = cast(ulong)va_arg!(void*)(argptr); - uc = 1; - flags |= FL0pad; - if (!(flags & FLprecision)) - { flags |= FLprecision; - precision = (void*).sizeof; - } - base = 16; - goto Lnumber; - - - case Mangle.Tfloat: - case Mangle.Tifloat: - if (fc == 'x' || fc == 'X') - goto Luint; - vreal = va_arg!(float)(argptr); - goto Lreal; - - case Mangle.Tdouble: - case Mangle.Tidouble: - if (fc == 'x' || fc == 'X') - goto Lulong; - vreal = va_arg!(double)(argptr); - goto Lreal; - - case Mangle.Treal: - case Mangle.Tireal: - vreal = va_arg!(real)(argptr); - goto Lreal; - - - case Mangle.Tcfloat: - vcreal = va_arg!(cfloat)(argptr); - goto Lcomplex; - - case Mangle.Tcdouble: - vcreal = va_arg!(cdouble)(argptr); - goto Lcomplex; - - case Mangle.Tcreal: - vcreal = va_arg!(creal)(argptr); - goto Lcomplex; - - case Mangle.Tsarray: - //printf("static array\n"); - putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); - return; - - case Mangle.Tarray: - //printf("dynamic array\n"); - int mi = 10; - if (ti.classinfo.name.length == 14 && - ti.classinfo.name[9..14] == "Array") - { // array of non-primitive types - TypeInfo tn = (cast(TypeInfo_Array)ti).next; - tn = skipCI(tn); - switch (cast(Mangle)tn.classinfo.name[9]) - { - case Mangle.Tchar: goto LarrayChar; - case Mangle.Twchar: goto LarrayWchar; - case Mangle.Tdchar: goto LarrayDchar; - default: - break; - } - void[] va = va_arg!(void[])(argptr); - putArray(va.ptr, va.length, tn); - return; - } - if (ti.classinfo.name.length == 25 && - ti.classinfo.name[9..25] == "AssociativeArray") - { // associative array - ubyte[long] vaa = va_arg!(ubyte[long])(argptr); - putAArray(vaa, - (cast(TypeInfo_AssociativeArray)ti).next, - (cast(TypeInfo_AssociativeArray)ti).key); - return; - } - - //printf("primitive type\n"); - while (1) - { - m2 = cast(Mangle)ti.classinfo.name[mi]; - switch (m2) - { - case Mangle.Tchar: - LarrayChar: - s = va_arg!(char[])(argptr); - goto Lputstr; - - case Mangle.Twchar: - LarrayWchar: - wchar[] sw = va_arg!(wchar[])(argptr); - s = toUTF8(sw); - goto Lputstr; - - case Mangle.Tdchar: - LarrayDchar: - dchar[] sd = va_arg!(dchar[])(argptr); - s = toUTF8(sd); - Lputstr: - if (fc != 's') - throw new FormatError("string"); - if (flags & FLprecision && precision < s.length) - s = s[0 .. precision]; - putstr(s); - break; - - case Mangle.Tconst: - case Mangle.Tinvariant: - mi++; - continue; - - default: - //printf("primitive type default handling\n"); - TypeInfo ti2 = primitiveTypeInfo(m2); - if (!ti2) - goto Lerror; - void[] va = va_arg!(void[])(argptr); - putArray(va.ptr, va.length, ti2); - } - return; - } - - case Mangle.Ttypedef: - ti = (cast(TypeInfo_Typedef)ti).base; - m = cast(Mangle)ti.classinfo.name[9]; - formatArg(fc); - return; - - case Mangle.Tenum: - ti = (cast(TypeInfo_Enum)ti).base; - m = cast(Mangle)ti.classinfo.name[9]; - formatArg(fc); - return; - - case Mangle.Tstruct: - { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; - if (tis.xtoString is null) - throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); - s = tis.xtoString(argptr); - argptr += (tis.tsize() + 3) & ~3; - goto Lputstr; - } - - default: - goto Lerror; - } - - Lnumber: - switch (fc) - { - case 's': - case 'd': - if (signed) - { if (cast(long)vnumber < 0) - { prefix = "-"; - vnumber = -vnumber; - } - else if (flags & FLplus) - prefix = "+"; - else if (flags & FLspace) - prefix = " "; - } - break; - - case 'b': - signed = 0; - base = 2; - break; - - case 'o': - signed = 0; - base = 8; - break; - - case 'X': - uc = 1; - if (flags & FLhash && vnumber) - prefix = "0X"; - signed = 0; - base = 16; - break; - - case 'x': - if (flags & FLhash && vnumber) - prefix = "0x"; - signed = 0; - base = 16; - break; - - default: - goto Lerror; - } - - if (!signed) - { - switch (m) - { - case Mangle.Tbyte: - vnumber &= 0xFF; - break; - - case Mangle.Tshort: - vnumber &= 0xFFFF; - break; - - case Mangle.Tint: - vnumber &= 0xFFFFFFFF; - break; - - default: - break; - } - } - - if (flags & FLprecision && fc != 'p') - flags &= ~FL0pad; - - if (vnumber < base) - { - if (vnumber == 0 && precision == 0 && flags & FLprecision && - !(fc == 'o' && flags & FLhash)) - { - putstr(null); - return; - } - if (precision == 0 || !(flags & FLprecision)) - { vchar = cast(char)('0' + vnumber); - if (vnumber < 10) - vchar = cast(char)('0' + vnumber); - else - vchar = cast(char)((uc ? 'A' - 10 : 'a' - 10) + vnumber); - goto L2; - } - } - - int n = tmpbuf.length; - char c; - int hexoffset = uc ? ('A' - ('9' + 1)) : ('a' - ('9' + 1)); - - while (vnumber) - { - c = cast(char)((vnumber % base) + '0'); - if (c > '9') - c += hexoffset; - vnumber /= base; - tmpbuf[--n] = c; - } - if (tmpbuf.length - n < precision && precision < tmpbuf.length) - { - int m = tmpbuf.length - precision; - tmpbuf[m .. n] = '0'; - n = m; - } - else if (flags & FLhash && fc == 'o') - prefix = "0"; - putstr(tmpbuf[n .. tmpbuf.length]); - return; - - Lreal: - putreal(vreal); - return; - - Lcomplex: - putreal(vcreal.re); - putc('+'); - putreal(vcreal.im); - putc('i'); - return; - - Lerror: - throw new FormatError("formatArg"); - } - - - //printf("arguments length: %u\n", arguments.length); - for (j = 0; j < arguments.length; ) - { ti = arguments[j++]; - //printf("test1: '%.*s' %d\n", ti.classinfo.name.length, ti.classinfo.name.ptr, ti.classinfo.name.length); - //ti.print(); - - flags = 0; - precision = 0; - field_width = 0; - - ti = skipCI(ti); - int mi = 9; - do - { - if (ti.classinfo.name.length <= mi) - goto Lerror; - m = cast(Mangle)ti.classinfo.name[mi++]; - } while (m == Mangle.Tconst || m == Mangle.Tinvariant); - - if (m == Mangle.Tarray) - { - if (ti.classinfo.name.length == 14 && - ti.classinfo.name[9..14] == "Array") - { - TypeInfo tn = (cast(TypeInfo_Array)ti).next; - tn = skipCI(tn); - switch (cast(Mangle)tn.classinfo.name[9]) - { - case Mangle.Tchar: - case Mangle.Twchar: - case Mangle.Tdchar: - ti = tn; - mi = 9; - break; - default: - break; - } - } - L1: - Mangle m2 = cast(Mangle)ti.classinfo.name[mi]; - string fmt; // format string - wstring wfmt; - dstring dfmt; - - /* For performance reasons, this code takes advantage of the - * fact that most format strings will be ASCII, and that the - * format specifiers are always ASCII. This means we only need - * to deal with UTF in a couple of isolated spots. - */ - - switch (m2) - { - case Mangle.Tchar: - fmt = va_arg!(char[])(argptr); - break; - - case Mangle.Twchar: - wfmt = va_arg!(wchar[])(argptr); - fmt = toUTF8(wfmt); - break; - - case Mangle.Tdchar: - dfmt = va_arg!(dchar[])(argptr); - fmt = toUTF8(dfmt); - break; - - case Mangle.Tconst: - case Mangle.Tinvariant: - mi++; - goto L1; - - default: - formatArg('s'); - continue; - } - - for (size_t i = 0; i < fmt.length; ) - { dchar c = fmt[i++]; - - dchar getFmtChar() - { // Valid format specifier characters will never be UTF - if (i == fmt.length) - throw new FormatError("invalid specifier"); - return fmt[i++]; - } - - int getFmtInt() - { int n; - - while (1) - { - n = n * 10 + (c - '0'); - if (n < 0) // overflow - throw new FormatError("int overflow"); - c = getFmtChar(); - if (c < '0' || c > '9') - break; - } - return n; - } - - int getFmtStar() - { Mangle m; - TypeInfo ti; - - if (j == arguments.length) - throw new FormatError("too few arguments"); - ti = arguments[j++]; - m = cast(Mangle)ti.classinfo.name[9]; - if (m != Mangle.Tint) - throw new FormatError("int argument expected"); - return va_arg!(int)(argptr); - } - - if (c != '%') - { - if (c > 0x7F) // if UTF sequence - { - i--; // back up and decode UTF sequence - c = std.utf.decode(fmt, i); - } - Lputc: - putc(c); - continue; - } - - // Get flags {-+ #} - flags = 0; - while (1) - { - c = getFmtChar(); - switch (c) - { - case '-': flags |= FLdash; continue; - case '+': flags |= FLplus; continue; - case ' ': flags |= FLspace; continue; - case '#': flags |= FLhash; continue; - case '0': flags |= FL0pad; continue; - - case '%': if (flags == 0) - goto Lputc; - default: break; - } - break; - } - - // Get field width - field_width = 0; - if (c == '*') - { - field_width = getFmtStar(); - if (field_width < 0) - { flags |= FLdash; - field_width = -field_width; - } - - c = getFmtChar(); - } - else if (c >= '0' && c <= '9') - field_width = getFmtInt(); - - if (flags & FLplus) - flags &= ~FLspace; - if (flags & FLdash) - flags &= ~FL0pad; - - // Get precision - precision = 0; - if (c == '.') - { flags |= FLprecision; - //flags &= ~FL0pad; - - c = getFmtChar(); - if (c == '*') - { - precision = getFmtStar(); - if (precision < 0) - { precision = 0; - flags &= ~FLprecision; - } - - c = getFmtChar(); - } - else if (c >= '0' && c <= '9') - precision = getFmtInt(); - } - - if (j == arguments.length) - goto Lerror; - ti = arguments[j++]; - ti = skipCI(ti); - mi = 9; - do - { - m = cast(Mangle)ti.classinfo.name[mi++]; - } while (m == Mangle.Tconst || m == Mangle.Tinvariant); - - if (c > 0x7F) // if UTF sequence - goto Lerror; // format specifiers can't be UTF - formatArg(cast(char)c); - } - } - else - { - formatArg('s'); - } - } - return; - -Lerror: - throw new FormatError(); -} - -/* ======================== Unit Tests ====================================== */ - -unittest -{ - int i; - string s; - - debug(format) printf("std.format.format.unittest\n"); - - s = std.string.format("hello world! %s %s ", true, 57, 1_000_000_000, 'x', " foo"); - assert(s == "hello world! true 57 1000000000x foo"); - - s = std.string.format(1.67, " %A ", -1.28, float.nan); - /* The host C library is used to format floats. - * C99 doesn't specify what the hex digit before the decimal point - * is for %A. - */ - version (linux) - assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan"); - else - assert(s == "1.67 -0X1.47AE147AE147BP+0 nan"); - - s = std.string.format("%x %X", 0x1234AF, 0xAFAFAFAF); - assert(s == "1234af AFAFAFAF"); - - s = std.string.format("%b %o", 0x1234AF, 0xAFAFAFAF); - assert(s == "100100011010010101111 25753727657"); - - s = std.string.format("%d %s", 0x1234AF, 0xAFAFAFAF); - assert(s == "1193135 2947526575"); - - s = std.string.format("%s", 1.2 + 3.4i); - assert(s == "1.2+3.4i"); - - s = std.string.format("%x %X", 1.32, 6.78f); - assert(s == "3ff51eb851eb851f 40D8F5C3"); - - s = std.string.format("%#06.*f",2,12.345); - assert(s == "012.35"); - - s = std.string.format("%#0*.*f",6,2,12.345); - assert(s == "012.35"); - - s = std.string.format("%7.4g:", 12.678); - assert(s == " 12.68:"); - - s = std.string.format("%7.4g:", 12.678L); - assert(s == " 12.68:"); - - s = std.string.format("%04f|%05d|%#05x|%#5x",-4.,-10,1,1); - assert(s == "-4.000000|-0010|0x001| 0x1"); - - i = -10; - s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); - assert(s == "-10|-10|-10|-10|-10.0000"); - - i = -5; - s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); - assert(s == "-5| -5|-05|-5|-5.0000"); - - i = 0; - s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); - assert(s == "0| 0|000|0|0.0000"); - - i = 5; - s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); - assert(s == "5| 5|005|5|5.0000"); - - i = 10; - s = std.string.format("%d|%3d|%03d|%1d|%01.4f",i,i,i,i,cast(double) i); - assert(s == "10| 10|010|10|10.0000"); - - s = std.string.format("%.0d", 0); - assert(s == ""); - - s = std.string.format("%.g", .34); - assert(s == "0.3"); - - s = std.string.format("%.0g", .34); - assert(s == "0.3"); - - s = std.string.format("%.2g", .34); - assert(s == "0.34"); - - s = std.string.format("%0.0008f", 1e-08); - assert(s == "0.00000001"); - - s = std.string.format("%0.0008f", 1e-05); - assert(s == "0.00001000"); - - s = "helloworld"; - string r; - r = std.string.format("%.2s", s[0..5]); - assert(r == "he"); - r = std.string.format("%.20s", s[0..5]); - assert(r == "hello"); - r = std.string.format("%8s", s[0..5]); - assert(r == " hello"); - - byte[] arrbyte = new byte[4]; - arrbyte[0] = 100; - arrbyte[1] = -99; - arrbyte[3] = 0; - r = std.string.format(arrbyte); - assert(r == "[100,-99,0,0]"); - - ubyte[] arrubyte = new ubyte[4]; - arrubyte[0] = 100; - arrubyte[1] = 200; - arrubyte[3] = 0; - r = std.string.format(arrubyte); - assert(r == "[100,200,0,0]"); - - short[] arrshort = new short[4]; - arrshort[0] = 100; - arrshort[1] = -999; - arrshort[3] = 0; - r = std.string.format(arrshort); - assert(r == "[100,-999,0,0]"); - r = std.string.format("%s",arrshort); - assert(r == "[100,-999,0,0]"); - - ushort[] arrushort = new ushort[4]; - arrushort[0] = 100; - arrushort[1] = 20_000; - arrushort[3] = 0; - r = std.string.format(arrushort); - assert(r == "[100,20000,0,0]"); - - int[] arrint = new int[4]; - arrint[0] = 100; - arrint[1] = -999; - arrint[3] = 0; - r = std.string.format(arrint); - assert(r == "[100,-999,0,0]"); - r = std.string.format("%s",arrint); - assert(r == "[100,-999,0,0]"); - - long[] arrlong = new long[4]; - arrlong[0] = 100; - arrlong[1] = -999; - arrlong[3] = 0; - r = std.string.format(arrlong); - assert(r == "[100,-999,0,0]"); - r = std.string.format("%s",arrlong); - assert(r == "[100,-999,0,0]"); - - ulong[] arrulong = new ulong[4]; - arrulong[0] = 100; - arrulong[1] = 999; - arrulong[3] = 0; - r = std.string.format(arrulong); - assert(r == "[100,999,0,0]"); - - string[] arr2 = new string[4]; - arr2[0] = "hello"; - arr2[1] = "world"; - arr2[3] = "foo"; - r = std.string.format(arr2); - assert(r == "[hello,world,,foo]"); - - r = std.string.format("%.8d", 7); - assert(r == "00000007"); - r = std.string.format("%.8x", 10); - assert(r == "0000000a"); - - r = std.string.format("%-3d", 7); - assert(r == "7 "); - - r = std.string.format("%*d", -3, 7); - assert(r == "7 "); - - r = std.string.format("%.*d", -3, 7); - assert(r == "7"); - - typedef int myint; - myint m = -7; - r = std.string.format(m); - assert(r == "-7"); - - r = std.string.format("abc"c); - assert(r == "abc"); - r = std.string.format("def"w); - assert(r == "def"); - r = std.string.format("ghi"d); - assert(r == "ghi"); - - void* p = cast(void*)0xDEADBEEF; - r = std.string.format(p); - assert(r == "DEADBEEF"); - - r = std.string.format("%#x", 0xabcd); - assert(r == "0xabcd"); - r = std.string.format("%#X", 0xABCD); - assert(r == "0XABCD"); - - r = std.string.format("%#o", 012345); - assert(r == "012345"); - r = std.string.format("%o", 9); - assert(r == "11"); - - r = std.string.format("%+d", 123); - assert(r == "+123"); - r = std.string.format("%+d", -123); - assert(r == "-123"); - r = std.string.format("% d", 123); - assert(r == " 123"); - r = std.string.format("% d", -123); - assert(r == "-123"); - - r = std.string.format("%%"); - assert(r == "%"); - - r = std.string.format("%d", true); - assert(r == "1"); - r = std.string.format("%d", false); - assert(r == "0"); - - r = std.string.format("%d", 'a'); - assert(r == "97"); - wchar wc = 'a'; - r = std.string.format("%d", wc); - assert(r == "97"); - dchar dc = 'a'; - r = std.string.format("%d", dc); - assert(r == "97"); - - byte b = byte.max; - r = std.string.format("%x", b); - assert(r == "7f"); - r = std.string.format("%x", ++b); - assert(r == "80"); - r = std.string.format("%x", ++b); - assert(r == "81"); - - short sh = short.max; - r = std.string.format("%x", sh); - assert(r == "7fff"); - r = std.string.format("%x", ++sh); - assert(r == "8000"); - r = std.string.format("%x", ++sh); - assert(r == "8001"); - - i = int.max; - r = std.string.format("%x", i); - assert(r == "7fffffff"); - r = std.string.format("%x", ++i); - assert(r == "80000000"); - r = std.string.format("%x", ++i); - assert(r == "80000001"); - - r = std.string.format("%x", 10); - assert(r == "a"); - r = std.string.format("%X", 10); - assert(r == "A"); - r = std.string.format("%x", 15); - assert(r == "f"); - r = std.string.format("%X", 15); - assert(r == "F"); - - Object c = null; - r = std.string.format(c); - assert(r == "null"); - - enum TestEnum - { - Value1, Value2 - } - r = std.string.format("%s", TestEnum.Value2); - assert(r == "1"); - - char[5][int] aa = ([3:"hello", 4:"betty"]); - r = std.string.format("%s", aa.values); - assert(r == "[[h,e,l,l,o],[b,e,t,t,y]]"); - r = std.string.format("%s", aa); - assert(r == "[3:[h,e,l,l,o],4:[b,e,t,t,y]]"); - - static const dchar[] ds = ['a','b']; - for (int j = 0; j < ds.length; ++j) - { - r = std.string.format(" %d", ds[j]); - if (j == 0) - assert(r == " 97"); - else - assert(r == " 98"); - } - - r = std.string.format(">%14d<, ", 15, [1,2,3]); - assert(r == "> 15<, [1,2,3]"); -} - diff --git a/lphobos/std/gc.di b/lphobos/std/gc.di deleted file mode 100644 index 74f56241ad8..00000000000 --- a/lphobos/std/gc.di +++ /dev/null @@ -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(); -} diff --git a/lphobos/std/intrinsic.d b/lphobos/std/intrinsic.d deleted file mode 100644 index eba705fb6ff..00000000000 --- a/lphobos/std/intrinsic.d +++ /dev/null @@ -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
- * 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", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bts(array, 35) = %d\n", bts(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("btr(array, 35) = %d\n", btr(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - printf("bt(array, 1) = %d\n", bt(array, 1)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); - - return 0; -} - * --- - * Output: -
-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
-
- */ -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); - - diff --git a/lphobos/std/math.d b/lphobos/std/math.d deleted file mode 100644 index fc9c5b5ff70..00000000000 --- a/lphobos/std/math.d +++ /dev/null @@ -1,1959 +0,0 @@ -// Written in the D programming language - -/** - * Macros: - * WIKI = Phobos/StdMath - * - * TABLE_SV = - * - * $0
Special Values
- * SVH = $(TR $(TH $1) $(TH $2)) - * SV = $(TR $(TD $1) $(TD $2)) - * - * NAN = $(RED NAN) - * SUP = $0 - * GAMMA = Γ - * INTEGRAL = ∫ - * INTEGRATE = $(BIG ∫$(SMALL $1)$2) - * POWER = $1$2 - * BIGSUM = $(BIG Σ $2$(SMALL $1)) - * CHOOSE = $(BIG () $(SMALL $1)$(SMALL $2) $(BIG )) - * PLUSMN = ± - * INFIN = ∞ - * PI = π - * LT = < - * GT = > - */ - -/* - * Author: - * Walter Bright - * Copyright: - * Copyright (c) 2001-2005 by Digital Mars, - * All Rights Reserved, - * www.digitalmars.com - * Copyright (c) 2007 by Tomas Lindquist Olsen - * License: - * 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: - * - *
    - *
  • 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. - *
  • - *
- */ - - -module std.math; - -//debug=math; // uncomment to turn on debugging printf's - -private import std.c.stdio; -private import std.c.math; - -class NotImplemented : Error -{ - this(string msg) - { - super(msg ~ "not implemented"); - } -} - -const real E = 2.7182818284590452354L; /** e */ -const real LOG2T = 0x1.a934f0979a3715fcp+1; /** log210 */ // 3.32193 fldl2t -const real LOG2E = 0x1.71547652b82fe178p+0; /** log2e */ // 1.4427 fldl2e -const real LOG2 = 0x1.34413509f79fef32p-2; /** log102 */ // 0.30103 fldlg2 -const real LOG10E = 0.43429448190325182765; /** log10e */ -const real LN2 = 0x1.62e42fefa39ef358p-1; /** ln 2 */ // 0.693147 fldln2 -const real LN10 = 2.30258509299404568402; /** ln 10 */ -const real PI = 0x1.921fb54442d1846ap+1; /** $(PI) */ // 3.14159 fldpi -const real PI_2 = 1.57079632679489661923; /** $(PI) / 2 */ -const real PI_4 = 0.78539816339744830962; /** $(PI) / 4 */ -const real M_1_PI = 0.31830988618379067154; /** 1 / $(PI) */ -const real M_2_PI = 0.63661977236758134308; /** 2 / $(PI) */ -const real M_2_SQRTPI = 1.12837916709551257390; /** 2 / √$(PI) */ -const real SQRT2 = 1.41421356237309504880; /** √2 */ -const real SQRT1_2 = 0.70710678118654752440; /** √½ */ - -/* - Octal versions: - PI/64800 0.00001 45530 36176 77347 02143 15351 61441 26767 - PI/180 0.01073 72152 11224 72344 25603 54276 63351 22056 - PI/8 0.31103 75524 21026 43021 51423 06305 05600 67016 - SQRT(1/PI) 0.44067 27240 41233 33210 65616 51051 77327 77303 - 2/PI 0.50574 60333 44710 40522 47741 16537 21752 32335 - PI/4 0.62207 73250 42055 06043 23046 14612 13401 56034 - SQRT(2/PI) 0.63041 05147 52066 24106 41762 63612 00272 56161 - - PI 3.11037 55242 10264 30215 14230 63050 56006 70163 - LOG2 0.23210 11520 47674 77674 61076 11263 26013 37111 - */ - - -/*********************************** - * Calculates the absolute value - * - * For complex numbers, abs(z) = sqrt( $(POWER z.re, 2) + $(POWER z.im, 2) ) - * = hypot(z.re, z.im). - */ -real abs(real x) -{ - return fabs(x); -} - -/** ditto */ -long abs(long x) -{ - return x>=0 ? x : -x; -} - -/** ditto */ -int abs(int x) -{ - return x>=0 ? x : -x; -} - -/** ditto */ -real abs(creal z) -{ - return hypot(z.re, z.im); -} - -/** ditto */ -real abs(ireal y) -{ - return fabs(y.im); -} - - -unittest -{ - assert(isPosZero(abs(-0.0L))); - assert(isnan(abs(real.nan))); - assert(abs(-real.infinity) == real.infinity); - assert(abs(-3.2Li) == 3.2L); - assert(abs(71.6Li) == 71.6L); - assert(abs(-56) == 56); - assert(abs(2321312L) == 2321312L); - assert(abs(-1+1i) == sqrt(2.0)); -} - -/*********************************** - * Complex conjugate - * - * conj(x + iy) = x - iy - * - * Note that z * conj(z) = $(POWER z.re, 2) - $(POWER z.im, 2) - * is always a real number - */ -creal conj(creal z) -{ - return z.re - z.im*1i; -} - -/** ditto */ -ireal conj(ireal y) -{ - return -y; -} - -unittest -{ - assert(conj(7 + 3i) == 7-3i); - ireal z = -3.2Li; - assert(conj(z) == -z); -} - -/*********************************** - * Returns cosine of x. x is in radians. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH cos(x)) $(TH invalid?)) - * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes) ) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes) ) - * ) - * Bugs: - * Results are undefined if |x| >= $(POWER 2,64). - */ - -pragma(intrinsic, "llvm.cos.f32") -float cos(float x); - -pragma(intrinsic, "llvm.cos.f64") -double cos(double x); // ditto - -pragma(intrinsic, "llvm.cos.f80") -real cos(real x); /// ditto - - -/*********************************** - * Returns sine of x. x is in radians. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH sin(x)) $(TH invalid?)) - * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes)) - * ) - * Bugs: - * Results are undefined if |x| >= $(POWER 2,64). - */ - -pragma(intrinsic, "llvm.sin.f32") -float sin(float x); - -pragma(intrinsic, "llvm.sin.f64") -double sin(double x); // ditto - -pragma(intrinsic, "llvm.sin.f80") -real sin(real x); /// ditto - - -/**************************************************************************** - * Returns tangent of x. x is in radians. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH tan(x)) $(TH invalid?)) - * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes)) - * ) - */ - -version(D_InlineAsm_X86) -real tan(real x) -{ - - asm - { - fld x[EBP] ; // load theta - fxam ; // test for oddball values - fstsw AX ; - sahf ; - jc trigerr ; // x is NAN, infinity, or empty - // 387's can handle denormals -SC18: fptan ; - fstp ST(0) ; // dump X, which is always 1 - fstsw AX ; - sahf ; - jnp Lret ; // C2 = 1 (x is out of range) - - // Do argument reduction to bring x into range - fldpi ; - fxch ; -SC17: fprem1 ; - fstsw AX ; - sahf ; - jp SC17 ; - fstp ST(1) ; // remove pi from stack - jmp SC18 ; - -trigerr: - jnp Lret ; // if theta is NAN, return theta - fstp ST(0) ; // dump theta - } - return real.nan; - -Lret: - ; -} -else -{ -real tan(real x) { return std.c.math.atan(x); } -} - - -unittest -{ - static real vals[][2] = // angle,tan - [ - [ 0, 0], - [ .5, .5463024898], - [ 1, 1.557407725], - [ 1.5, 14.10141995], - [ 2, -2.185039863], - [ 2.5,-.7470222972], - [ 3, -.1425465431], - [ 3.5, .3745856402], - [ 4, 1.157821282], - [ 4.5, 4.637332055], - [ 5, -3.380515006], - [ 5.5,-.9955840522], - [ 6, -.2910061914], - [ 6.5, .2202772003], - [ 10, .6483608275], - - // special angles - [ PI_4, 1], - //[ PI_2, real.infinity], - [ 3*PI_4, -1], - [ PI, 0], - [ 5*PI_4, 1], - //[ 3*PI_2, -real.infinity], - [ 7*PI_4, -1], - [ 2*PI, 0], - - // overflow - [ real.infinity, real.nan], - [ real.nan, real.nan], - //[ 1e+100, real.nan], - ]; - int i; - - for (i = 0; i < vals.length; i++) - { - real x = vals[i][0]; - real r = vals[i][1]; - real t = tan(x); - - //printf("tan(%Lg) = %Lg, should be %Lg\n", x, t, r); - assert(mfeq(r, t, .0000001)); - - x = -x; - r = -r; - t = tan(x); - //printf("tan(%Lg) = %Lg, should be %Lg\n", x, t, r); - assert(mfeq(r, t, .0000001)); - } -} - -/*************** - * Calculates the arc cosine of x, - * returning a value ranging from -$(PI)/2 to $(PI)/2. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH acos(x)) $(TH invalid?)) - * $(TR $(TD $(GT)1.0) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD $(LT)-1.0) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes)) - * ) - */ -real acos(real x) { return std.c.math.acos(x); } - -/*************** - * Calculates the arc sine of x, - * returning a value ranging from -$(PI)/2 to $(PI)/2. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH asin(x)) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) - * $(TR $(TD $(GT)1.0) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD $(LT)-1.0) $(TD $(NAN)) $(TD yes)) - * ) - */ -real asin(real x) { return std.c.math.asin(x); } - -/*************** - * Calculates the arc tangent of x, - * returning a value ranging from -$(PI)/2 to $(PI)/2. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH atan(x)) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes)) - * ) - */ -real atan(real x) { return std.c.math.atan(x); } - -/*************** - * Calculates the arc tangent of y / x, - * returning a value ranging from -$(PI)/2 to $(PI)/2. - * - * $(TABLE_SV - * $(TR $(TH y) $(TH x) $(TH atan(y, x))) - * $(TR $(TD $(NAN)) $(TD anything) $(TD $(NAN)) ) - * $(TR $(TD anything) $(TD $(NAN)) $(TD $(NAN)) ) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(GT)0.0) $(TD $(PLUSMN)0.0) ) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) ) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(LT)0.0) $(TD $(PLUSMN)$(PI))) - * $(TR $(TD $(PLUSMN)0.0) $(TD -0.0) $(TD $(PLUSMN)$(PI))) - * $(TR $(TD $(GT)0.0) $(TD $(PLUSMN)0.0) $(TD $(PI)/2) ) - * $(TR $(TD $(LT)0.0) $(TD $(PLUSMN)0.0) $(TD $(PI)/2)) - * $(TR $(TD $(GT)0.0) $(TD $(INFIN)) $(TD $(PLUSMN)0.0) ) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD anything) $(TD $(PLUSMN)$(PI)/2)) - * $(TR $(TD $(GT)0.0) $(TD -$(INFIN)) $(TD $(PLUSMN)$(PI)) ) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(INFIN)) $(TD $(PLUSMN)$(PI)/4)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD -$(INFIN)) $(TD $(PLUSMN)3$(PI)/4)) - * ) - */ -real atan2(real y, real x) { return std.c.math.atan2(y,x); } - -/*********************************** - * Calculates the hyperbolic cosine of x. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH cosh(x)) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)0.0) $(TD no) ) - * ) - */ -real cosh(real x) { return std.c.math.cosh(x); } - -/*********************************** - * Calculates the hyperbolic sine of x. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH sinh(x)) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD no)) - * ) - */ -real sinh(real x) { return std.c.math.sinh(x); } - -/*********************************** - * Calculates the hyperbolic tangent of x. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH tanh(x)) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no) ) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)1.0) $(TD no)) - * ) - */ -real tanh(real x) { return std.c.math.tanh(x); } - -//real acosh(real x) { return std.c.math.acoshl(x); } -//real asinh(real x) { return std.c.math.asinhl(x); } -//real atanh(real x) { return std.c.math.atanhl(x); } - -/*********************************** - * Calculates the inverse hyperbolic cosine of x. - * - * Mathematically, acosh(x) = log(x + sqrt( x*x - 1)) - * - * $(TABLE_DOMRG - * $(DOMAIN 1..$(INFIN)) - * $(RANGE 1..log(real.max), $(INFIN)) ) - * $(TABLE_SV - * $(SVH x, acosh(x) ) - * $(SV $(NAN), $(NAN) ) - * $(SV <1, $(NAN) ) - * $(SV 1, 0 ) - * $(SV +$(INFIN),+$(INFIN)) - * ) - */ -real acosh(real x) -{ - if (x > 1/real.epsilon) - return LN2 + log(x); - else - return log(x + sqrt(x*x - 1)); -} - -unittest -{ - assert(isnan(acosh(0.9))); - assert(isnan(acosh(real.nan))); - assert(acosh(1)==0.0); - assert(acosh(real.infinity) == real.infinity); -} - -/*********************************** - * Calculates the inverse hyperbolic sine of x. - * - * Mathematically, - * --------------- - * asinh(x) = log( x + sqrt( x*x + 1 )) // if x >= +0 - * asinh(x) = -log(-x + sqrt( x*x + 1 )) // if x <= -0 - * ------------- - * - * $(TABLE_SV - * $(SVH x, asinh(x) ) - * $(SV $(NAN), $(NAN) ) - * $(SV $(PLUSMN)0, $(PLUSMN)0 ) - * $(SV $(PLUSMN)$(INFIN),$(PLUSMN)$(INFIN)) - * ) - */ -real asinh(real x) -{ - if (fabs(x) > 1 / real.epsilon) // beyond this point, x*x + 1 == x*x - return copysign(LN2 + log(fabs(x)), x); - else - { - // sqrt(x*x + 1) == 1 + x * x / ( 1 + sqrt(x*x + 1) ) - return copysign(log1p(fabs(x) + x*x / (1 + sqrt(x*x + 1)) ), x); - } -} - -unittest -{ - assert(isPosZero(asinh(0.0))); - assert(isNegZero(asinh(-0.0))); - assert(asinh(real.infinity) == real.infinity); - assert(asinh(-real.infinity) == -real.infinity); - assert(isnan(asinh(real.nan))); -} - -/*********************************** - * Calculates the inverse hyperbolic tangent of x, - * returning a value from ranging from -1 to 1. - * - * Mathematically, atanh(x) = log( (1+x)/(1-x) ) / 2 - * - * - * $(TABLE_DOMRG - * $(DOMAIN -$(INFIN)..$(INFIN)) - * $(RANGE -1..1) ) - * $(TABLE_SV - * $(SVH x, acosh(x) ) - * $(SV $(NAN), $(NAN) ) - * $(SV $(PLUSMN)0, $(PLUSMN)0) - * $(SV -$(INFIN), -0) - * ) - */ -real atanh(real x) -{ - // log( (1+x)/(1-x) ) == log ( 1 + (2*x)/(1-x) ) - return 0.5 * log1p( 2 * x / (1 - x) ); -} - -unittest -{ - assert(isPosZero(atanh(0.0))); - assert(isNegZero(atanh(-0.0))); - assert(isnan(atanh(real.nan))); - assert(isnan(atanh(-real.infinity))); -} - -/***************************************** - * Returns x rounded to a long value using the current rounding mode. - * If the integer value of x is - * greater than long.max, the result is - * indeterminate. - */ -long rndtol(real x); /* intrinsic */ - - -/***************************************** - * Returns x rounded to a long value using the FE_TONEAREST rounding mode. - * If the integer value of x is - * greater than long.max, the result is - * indeterminate. - */ -extern (C) real rndtonl(real x); - -/*************************************** - * Compute square root of x. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH sqrt(x)) $(TH invalid?)) - * $(TR $(TD -0.0) $(TD -0.0) $(TD no)) - * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no)) - * ) - */ - -pragma(intrinsic, "llvm.sqrt.f32") -float sqrt(float x); /* intrinsic */ - -pragma(intrinsic, "llvm.sqrt.f64") -double sqrt(double x); /* intrinsic */ /// ditto - -pragma(intrinsic, "llvm.sqrt.f80") -real sqrt(real x); /* intrinsic */ /// ditto - -creal sqrt(creal z) -{ - creal c; - real x,y,w,r; - - if (z == 0) - { - c = 0 + 0i; - } - else - { real z_re = z.re; - real z_im = z.im; - - x = fabs(z_re); - y = fabs(z_im); - if (x >= y) - { - r = y / x; - w = sqrt(x) * sqrt(0.5 * (1 + sqrt(1 + r * r))); - } - else - { - r = x / y; - w = sqrt(y) * sqrt(0.5 * (r + sqrt(1 + r * r))); - } - - if (z_re >= 0) - { - c = w + (z_im / (w + w)) * 1.0i; - } - else - { - if (z_im < 0) - w = -w; - c = z_im / (w + w) + w * 1.0i; - } - } - return c; -} - -/********************** - * Calculates e$(SUP x). - * - * $(TABLE_SV - * $(TR $(TH x) $(TH exp(x))) - * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) ) - * $(TR $(TD -$(INFIN)) $(TD +0.0) ) - * ) - */ -real exp(real x) { return std.c.math.exp(x); } - -/********************** - * Calculates 2$(SUP x). - * - * $(TABLE_SV - * $(TR $(TH x) $(TH exp2(x))) - * $(TR $(TD +$(INFIN)) $(TD +$(INFIN))) - * $(TR $(TD -$(INFIN)) $(TD +0.0)) - * ) - */ -real exp2(real x) { return std.c.math.exp2(x); } - -/****************************************** - * Calculates the value of the natural logarithm base (e) - * raised to the power of x, minus 1. - * - * For very small x, expm1(x) is more accurate - * than exp(x)-1. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH e$(SUP x)-1)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0)) - * $(TR $(TD +$(INFIN)) $(TD +$(INFIN))) - * $(TR $(TD -$(INFIN)) $(TD -1.0)) - * ) - */ - -real expm1(real x) { return std.c.math.expm1(x); } - - -/********************************************************************* - * Separate floating point value into significand and exponent. - * - * Returns: - * Calculate and return x and exp such that - * value =x*2$(SUP exp) and - * .5 $(LT)= |x| $(LT) 1.0
- * x has same sign as value. - * - * $(TABLE_SV - * $(TR $(TH value) $(TH returns) $(TH exp)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD 0)) - * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD int.max)) - * $(TR $(TD -$(INFIN)) $(TD -$(INFIN)) $(TD int.min)) - * $(TR $(TD $(PLUSMN)$(NAN)) $(TD $(PLUSMN)$(NAN)) $(TD int.min)) - * ) - */ - - -real frexp(real value, out int exp) -{ - ushort* vu = cast(ushort*)&value; - long* vl = cast(long*)&value; - uint ex; - - // If exponent is non-zero - ex = vu[4] & 0x7FFF; - if (ex) - { - if (ex == 0x7FFF) - { // infinity or NaN - if (*vl & 0x7FFFFFFFFFFFFFFF) // if NaN - { *vl |= 0xC000000000000000; // convert $(NAN)S to $(NAN)Q - exp = int.min; - } - else if (vu[4] & 0x8000) - { // negative infinity - exp = int.min; - } - else - { // positive infinity - exp = int.max; - } - } - else - { - exp = ex - 0x3FFE; - vu[4] = cast(ushort)((0x8000 & vu[4]) | 0x3FFE); - } - } - else if (!*vl) - { - // value is +-0.0 - exp = 0; - } - else - { // denormal - int i = -0x3FFD; - - do - { - i--; - *vl <<= 1; - } while (*vl > 0); - exp = i; - vu[4] = cast(ushort)((0x8000 & vu[4]) | 0x3FFE); - } - return value; -} - - -unittest -{ - static real vals[][3] = // x,frexp,exp - [ - [0.0, 0.0, 0], - [-0.0, -0.0, 0], - [1.0, .5, 1], - [-1.0, -.5, 1], - [2.0, .5, 2], - [155.67e20, 0x1.A5F1C2EB3FE4Fp-1, 74], // normal - [1.0e-320, 0.98829225, -1063], - [real.min, .5, -16381], - [real.min/2.0L, .5, -16382], // denormal - - [real.infinity,real.infinity,int.max], - [-real.infinity,-real.infinity,int.min], - [real.nan,real.nan,int.min], - [-real.nan,-real.nan,int.min], - - // Don't really support signalling nan's in D - //[real.nans,real.nan,int.min], - //[-real.nans,-real.nan,int.min], - ]; - int i; - - for (i = 0; i < vals.length; i++) - { - real x = vals[i][0]; - real e = vals[i][1]; - int exp = cast(int)vals[i][2]; - int eptr; - real v = frexp(x, eptr); - - //printf("frexp(%Lg) = %.8Lg, should be %.8Lg, eptr = %d, should be %d\n", x, v, e, eptr, exp); - assert(mfeq(e, v, .0000001)); - assert(exp == eptr); - } -} - - -/****************************************** - * Extracts the exponent of x as a signed integral value. - * - * If x is not a special value, the result is the same as - * cast(int)logb(x). - * - * $(TABLE_SV - * $(TR $(TH x) $(TH ilogb(x)) $(TH Range error?)) - * $(TR $(TD 0) $(TD FP_ILOGB0) $(TD yes)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD int.max) $(TD no)) - * $(TR $(TD $(NAN)) $(TD FP_ILOGBNAN) $(TD no)) - * ) - */ -int ilogb(real x) { return std.c.math.ilogb(x); } - -alias std.c.math.FP_ILOGB0 FP_ILOGB0; -alias std.c.math.FP_ILOGBNAN FP_ILOGBNAN; - - -/******************************************* - * Compute n * 2$(SUP exp) - * References: frexp - */ - -real ldexp(real n, int exp) { return std.c.math.ldexp(n, exp); } - -/************************************** - * Calculate the natural logarithm of x. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH log(x)) $(TH divide by 0?) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD -$(INFIN)) $(TD yes) $(TD no)) - * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD no) $(TD yes)) - * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no)) - * ) - */ - -real log(real x) { return std.c.math.log(x); } - -/************************************** - * Calculate the base-10 logarithm of x. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH log10(x)) $(TH divide by 0?) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD -$(INFIN)) $(TD yes) $(TD no)) - * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD no) $(TD yes)) - * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no)) - * ) - */ - -real log10(real x) { return std.c.math.log10(x); } - -/****************************************** - * Calculates the natural logarithm of 1 + x. - * - * For very small x, log1p(x) will be more accurate than - * log(1 + x). - * - * $(TABLE_SV - * $(TR $(TH x) $(TH log1p(x)) $(TH divide by 0?) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no) $(TD no)) - * $(TR $(TD -1.0) $(TD -$(INFIN)) $(TD yes) $(TD no)) - * $(TR $(TD $(LT)-1.0) $(TD $(NAN)) $(TD no) $(TD yes)) - * $(TR $(TD +$(INFIN)) $(TD -$(INFIN)) $(TD no) $(TD no)) - * ) - */ - -real log1p(real x) { return std.c.math.log1p(x); } - -/*************************************** - * Calculates the base-2 logarithm of x: - * log2x - * - * $(TABLE_SV - * $(TR $(TH x) $(TH log2(x)) $(TH divide by 0?) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD -$(INFIN)) $(TD yes) $(TD no) ) - * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD no) $(TD yes) ) - * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no) ) - * ) - */ -real log2(real x) { return std.c.math.log2(x); } - -/***************************************** - * Extracts the exponent of x as a signed integral value. - * - * If x is subnormal, it is treated as if it were normalized. - * For a positive, finite x: - * - * ----- - * 1 <= $(I x) * FLT_RADIX$(SUP -logb(x)) < FLT_RADIX - * ----- - * - * $(TABLE_SV - * $(TR $(TH x) $(TH logb(x)) $(TH divide by 0?) ) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) $(TD no)) - * $(TR $(TD $(PLUSMN)0.0) $(TD -$(INFIN)) $(TD yes) ) - * ) - */ -real logb(real x) { return std.c.math.logb(x); } - -/************************************ - * Calculates the remainder from the calculation x/y. - * Returns: - * The value of x - i * y, where i is the number of times that y can - * be completely subtracted from x. The result has the same sign as x. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH y) $(TH modf(x, y)) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD no)t 0.0 $(TD $(PLUSMN)0.0) $(TD no)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD anything) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD anything) $(TD $(PLUSMN)0.0) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD !=$(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD x) $(TD no)) - * ) - */ -real modf(real x, inout real y) -{ -double Y = y; -auto tmp = std.c.math.modf(x,&Y); -y = Y; -return tmp; -} - -/************************************* - * Efficiently calculates x * 2$(SUP n). - * - * scalbn handles underflow and overflow in - * the same fashion as the basic arithmetic operators. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH scalb(x))) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) ) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) ) - * ) - */ -real scalbn(real x, int n) -{ - version (linux) - return std.c.math.scalbn(x, n); - else - throw new NotImplemented("scalbn"); -} - -/*************** - * Calculates the cube root x. - * - * $(TABLE_SV - * $(TR $(TH $(I x)) $(TH cbrt(x)) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no) ) - * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes) ) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD no) ) - * ) - */ -real cbrt(real x) { return std.c.math.cbrt(x); } - - -/******************************* - * Returns |x| - * - * $(TABLE_SV - * $(TR $(TH x) $(TH fabs(x))) - * $(TR $(TD $(PLUSMN)0.0) $(TD +0.0) ) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) ) - * ) - */ -real fabs(real x) { return std.c.math.fabs(x); } - - -/*********************************************************************** - * Calculates the length of the - * hypotenuse of a right-angled triangle with sides of length x and y. - * The hypotenuse is the value of the square root of - * the sums of the squares of x and y: - * - * sqrt(x² + y²) - * - * Note that hypot(x, y), hypot(y, x) and - * hypot(x, -y) are equivalent. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH y) $(TH hypot(x, y)) $(TH invalid?)) - * $(TR $(TD x) $(TD $(PLUSMN)0.0) $(TD |x|) $(TD no)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD y) $(TD +$(INFIN)) $(TD no)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD +$(INFIN)) $(TD no)) - * ) - */ - -real hypot(real x, real y) -{ - /* - * This is based on code from: - * Cephes Math Library Release 2.1: January, 1989 - * Copyright 1984, 1987, 1989 by Stephen L. Moshier - * Direct inquiries to 30 Frost Street, Cambridge, MA 02140 - */ - - const int PRECL = 32; - const int MAXEXPL = real.max_exp; //16384; - const int MINEXPL = real.min_exp; //-16384; - - real xx, yy, b, re, im; - int ex, ey, e; - - // Note, hypot(INFINITY, NAN) = INFINITY. - if (isinf(x) || isinf(y)) - return real.infinity; - - if (isnan(x)) - return x; - if (isnan(y)) - return y; - - re = fabs(x); - im = fabs(y); - - if (re == 0.0) - return im; - if (im == 0.0) - return re; - - // Get the exponents of the numbers - xx = frexp(re, ex); - yy = frexp(im, ey); - - // Check if one number is tiny compared to the other - e = ex - ey; - if (e > PRECL) - return re; - if (e < -PRECL) - return im; - - // Find approximate exponent e of the geometric mean. - e = (ex + ey) >> 1; - - // Rescale so mean is about 1 - xx = ldexp(re, -e); - yy = ldexp(im, -e); - - // Hypotenuse of the right triangle - b = sqrt(xx * xx + yy * yy); - - // Compute the exponent of the answer. - yy = frexp(b, ey); - ey = e + ey; - - // Check it for overflow and underflow. - if (ey > MAXEXPL + 2) - { - //return __matherr(_OVERFLOW, INFINITY, x, y, "hypotl"); - return real.infinity; - } - if (ey < MINEXPL - 2) - return 0.0; - - // Undo the scaling - b = ldexp(b, e); - return b; -} - -unittest -{ - static real vals[][3] = // x,y,hypot - [ - [ 0, 0, 0], - [ 0, -0, 0], - [ 3, 4, 5], - [ -300, -400, 500], - [ real.min, real.min, 4.75473e-4932L], - [ real.max/2, real.max/2, 0x1.6a09e667f3bcc908p+16383L /*8.41267e+4931L*/], - [ real.infinity, real.nan, real.infinity], - [ real.nan, real.nan, real.nan], - ]; - int i; - - for (i = 0; i < vals.length; i++) - { - real x = vals[i][0]; - real y = vals[i][1]; - real z = vals[i][2]; - real h = hypot(x, y); - - //printf("hypot(%Lg, %Lg) = %Lg, should be %Lg\n", x, y, h, z); - //if (!mfeq(z, h, .0000001)) - //printf("%La\n", h); - assert(mfeq(z, h, .0000001)); - } -} - -/********************************** - * Returns the error function of x. - * - * error function - */ -real erf(real x) { return std.c.math.erf(x); } - -/********************************** - * Returns the complementary error function of x, which is 1 - erf(x). - * - * complementary error function - */ -real erfc(real x) { return std.c.math.erfc(x); } - -/*********************************** - * Natural logarithm of gamma function. - * - * Returns the base e (2.718...) logarithm of the absolute - * value of the gamma function of the argument. - * - * For reals, lgamma is equivalent to log(fabs(gamma(x))). - * - * $(TABLE_SV - * $(TR $(TH x) $(TH lgamma(x)) $(TH invalid?)) - * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD integer <= 0) $(TD +$(INFIN)) $(TD yes)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) $(TD no)) - * ) - */ -/* Documentation prepared by Don Clugston */ -real lgamma(real x) -{ - return std.c.math.lgamma(x); - - // Use etc.gamma.lgamma for those C systems that are missing it -} - -/*********************************** - * The Gamma function, $(GAMMA)(x) - * - * $(GAMMA)(x) is a generalisation of the factorial function - * to real and complex numbers. - * Like x!, $(GAMMA)(x+1) = x*$(GAMMA)(x). - * - * Mathematically, if z.re > 0 then - * $(GAMMA)(z) =$(INTEGRAL)0$(INFIN)tz-1e-tdt - * - * $(TABLE_SV - * $(TR $(TH x) $(TH $(GAMMA)(x)) $(TH invalid?)) - * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)$(INFIN)) $(TD yes)) - * $(TR $(TD integer $(GT)0) $(TD (x-1)!) $(TD no)) - * $(TR $(TD integer $(LT)0) $(TD $(NAN)) $(TD yes)) - * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no)) - * $(TR $(TD -$(INFIN)) $(TD $(NAN)) $(TD yes)) - * ) - * - * References: - * $(LINK http://en.wikipedia.org/wiki/Gamma_function), - * $(LINK http://www.netlib.org/cephes/ldoubdoc.html#gamma) - */ -/* Documentation prepared by Don Clugston */ -real tgamma(real x) -{ - return std.c.math.tgamma(x); - - // Use etc.gamma.tgamma for those C systems that are missing it -} - -/************************************** - * Returns the value of x rounded upward to the next integer - * (toward positive infinity). - */ -real ceil(real x) { return std.c.math.ceil(x); } - -/************************************** - * Returns the value of x rounded downward to the next integer - * (toward negative infinity). - */ -real floor(real x) { return std.c.math.floor(x); } - -/****************************************** - * Rounds x to the nearest integer value, using the current rounding - * mode. - * - * Unlike the rint functions, nearbyint does not raise the - * FE_INEXACT exception. - */ -real nearbyint(real x) { return std.c.math.nearbyint(x); } - -/********************************** - * Rounds x to the nearest integer value, using the current rounding - * mode. - * If the return value is not equal to x, the FE_INEXACT - * exception is raised. - * nearbyint performs - * the same operation, but does not set the FE_INEXACT exception. - */ -real rint(real x) { return std.c.math.rint(x); } - -/*************************************** - * Rounds x to the nearest integer value, using the current rounding - * mode. - */ -long lrint(real x) -{ - version (linux) - return std.c.math.llrint(x); - else - throw new NotImplemented("lrint"); -} - -/******************************************* - * Return the value of x rounded to the nearest integer. - * If the fractional part of x is exactly 0.5, the return value is rounded to - * the even integer. - */ -real round(real x) { return std.c.math.round(x); } - -/********************************************** - * Return the value of x rounded to the nearest integer. - * - * If the fractional part of x is exactly 0.5, the return value is rounded - * away from zero. - */ -long lround(real x) -{ - version (linux) - return std.c.math.llround(x); - else - throw new NotImplemented("lround"); -} - -/**************************************************** - * Returns the integer portion of x, dropping the fractional portion. - * - * This is also known as "chop" rounding. - */ -real trunc(real x) { return std.c.math.trunc(x); } - -/**************************************************** - * Calculate the remainder x REM y, following IEC 60559. - * - * REM is the value of x - y * n, where n is the integer nearest the exact - * value of x / y. - * If |n - x / y| == 0.5, n is even. - * If the result is zero, it has the same sign as x. - * Otherwise, the sign of the result is the sign of x / y. - * Precision mode has no effect on the remainder functions. - * - * remquo returns n in the parameter n. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH y) $(TH remainder(x, y)) $(TH n) $(TH invalid?)) - * $(TR $(TD $(PLUSMN)0.0) $(TD no)t 0.0 $(TD $(PLUSMN)0.0) $(TD 0.0) $(TD no)) - * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD anything) $(TD $(NAN)) $(TD ?) $(TD yes)) - * $(TR $(TD anything) $(TD $(PLUSMN)0.0) $(TD $(NAN)) $(TD ?) $(TD yes)) - * $(TR $(TD != $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD x) $(TD ?) $(TD no)) - * ) - */ -real remainder(real x, real y) { return std.c.math.remainder(x, y); } - -real remquo(real x, real y, out int n) /// ditto -{ - version (linux) - return std.c.math.remquo(x, y, &n); - else - throw new NotImplemented("remquo"); -} - -/********************************* - * Returns !=0 if e is a NaN. - */ - -int isnan(real e) -{ - ushort* pe = cast(ushort *)&e; - ulong* ps = cast(ulong *)&e; - - return (pe[4] & 0x7FFF) == 0x7FFF && - *ps & 0x7FFFFFFFFFFFFFFF; -} - -unittest -{ - assert(isnan(float.nan)); - assert(isnan(-double.nan)); - assert(isnan(real.nan)); - - assert(!isnan(53.6)); - assert(!isnan(float.infinity)); -} - -/********************************* - * Returns !=0 if e is finite. - */ - -int isfinite(real e) -{ - ushort* pe = cast(ushort *)&e; - - return (pe[4] & 0x7FFF) != 0x7FFF; -} - -unittest -{ - assert(isfinite(1.23)); - assert(!isfinite(double.infinity)); - assert(!isfinite(float.nan)); -} - - -/********************************* - * Returns !=0 if x is normalized. - */ - -/* Need one for each format because subnormal floats might - * be converted to normal reals. - */ - -int isnormal(float x) -{ - uint *p = cast(uint *)&x; - uint e; - - e = *p & 0x7F800000; - //printf("e = x%x, *p = x%x\n", e, *p); - return e && e != 0x7F800000; -} - -/// ditto - -int isnormal(double d) -{ - uint *p = cast(uint *)&d; - uint e; - - e = p[1] & 0x7FF00000; - return e && e != 0x7FF00000; -} - -/// ditto - -int isnormal(real e) -{ - ushort* pe = cast(ushort *)&e; - long* ps = cast(long *)&e; - - return (pe[4] & 0x7FFF) != 0x7FFF && *ps < 0; -} - -unittest -{ - float f = 3; - double d = 500; - real e = 10e+48; - - assert(isnormal(f)); - assert(isnormal(d)); - assert(isnormal(e)); -} - -/********************************* - * Is number subnormal? (Also called "denormal".) - * Subnormals have a 0 exponent and a 0 most significant mantissa bit. - */ - -/* Need one for each format because subnormal floats might - * be converted to normal reals. - */ - -int issubnormal(float f) -{ - uint *p = cast(uint *)&f; - - //printf("*p = x%x\n", *p); - return (*p & 0x7F800000) == 0 && *p & 0x007FFFFF; -} - -unittest -{ - float f = 3.0; - - for (f = 1.0; !issubnormal(f); f /= 2) - assert(f != 0); -} - -/// ditto - -int issubnormal(double d) -{ - uint *p = cast(uint *)&d; - - return (p[1] & 0x7FF00000) == 0 && (p[0] || p[1] & 0x000FFFFF); -} - -unittest -{ - double f; - - for (f = 1; !issubnormal(f); f /= 2) - assert(f != 0); -} - -/// ditto - -int issubnormal(real e) -{ - ushort* pe = cast(ushort *)&e; - long* ps = cast(long *)&e; - - return (pe[4] & 0x7FFF) == 0 && *ps > 0; -} - -unittest -{ - real f; - - for (f = 1; !issubnormal(f); f /= 2) - assert(f != 0); -} - -/********************************* - * Return !=0 if e is $(PLUSMN)$(INFIN). - */ - -int isinf(real e) -{ - ushort* pe = cast(ushort *)&e; - ulong* ps = cast(ulong *)&e; - - return (pe[4] & 0x7FFF) == 0x7FFF && - *ps == 0x8000000000000000; -} - -unittest -{ - assert(isinf(float.infinity)); - assert(!isinf(float.nan)); - assert(isinf(double.infinity)); - assert(isinf(-real.infinity)); - - assert(isinf(-1.0 / 0.0)); -} - -/********************************* - * Return 1 if sign bit of e is set, 0 if not. - */ - -int signbit(real e) -{ - ubyte* pe = cast(ubyte *)&e; - -//printf("e = %Lg\n", e); - return (pe[9] & 0x80) != 0; -} - -unittest -{ - debug (math) printf("math.signbit.unittest\n"); - assert(!signbit(float.nan)); - assert(signbit(-float.nan)); - assert(!signbit(168.1234)); - assert(signbit(-168.1234)); - assert(!signbit(0.0)); - assert(signbit(-0.0)); -} - -/********************************* - * Return a value composed of to with from's sign bit. - */ - -real copysign(real to, real from) -{ - ubyte* pto = cast(ubyte *)&to; - ubyte* pfrom = cast(ubyte *)&from; - - pto[9] &= 0x7F; - pto[9] |= pfrom[9] & 0x80; - - return to; -} - -unittest -{ - real e; - - e = copysign(21, 23.8); - assert(e == 21); - - e = copysign(-21, 23.8); - assert(e == 21); - - e = copysign(21, -23.8); - assert(e == -21); - - e = copysign(-21, -23.8); - assert(e == -21); - - e = copysign(real.nan, -23.8); - assert(isnan(e) && signbit(e)); -} - -/****************************************** - * Creates a quiet NAN with the information from tagp[] embedded in it. - */ -real nan(char[] tagp) { return std.c.math.nan((tagp~\0).ptr); } - -/****************************************** - * Calculates the next representable value after x in the direction of y. - * - * If y $(GT) x, the result will be the next largest floating-point value; - * if y $(LT) x, the result will be the next smallest value. - * If x == y, the result is y. - * The FE_INEXACT and FE_OVERFLOW exceptions will be raised if x is finite and - * the function result is infinite. The FE_INEXACT and FE_UNDERFLOW - * exceptions will be raised if the function value is subnormal, and x is - * not equal to y. - */ -real nextafter(real x, real y) -{ - version (linux) - return std.c.math.nextafterl(x, y); - else - throw new NotImplemented("nextafter"); -} - -//real nexttoward(real x, real y) { return std.c.math.nexttowardl(x, y); } - -/******************************************* - * Returns the positive difference between x and y. - * Returns: - * $(TABLE_SV - * $(TR $(TH x, y) $(TH fdim(x, y))) - * $(TR $(TD x $(GT) y) $(TD x - y)) - * $(TR $(TD x $(LT)= y) $(TD +0.0)) - * ) - */ -real fdim(real x, real y) { return (x > y) ? x - y : +0.0; } - -/**************************************** - * Returns the larger of x and y. - */ -real fmax(real x, real y) { return x > y ? x : y; } - -/**************************************** - * Returns the smaller of x and y. - */ -real fmin(real x, real y) { return x < y ? x : y; } - -/************************************** - * Returns (x * y) + z, rounding only once according to the - * current rounding mode. - */ -real fma(real x, real y, real z) { return (x * y) + z; } - -/******************************************************************* - * Fast integral powers. - */ - -pragma(intrinsic, "llvm.powi.f32") -{ -float pow(float x, uint n); -/// ditto -float pow(float x, int n); -} - -pragma(intrinsic, "llvm.powi.f64") -{ -/// ditto -double pow(double x, uint n); -/// ditto -double pow(double x, int n); -} - -pragma(intrinsic, "llvm.powi.f80") -{ -/// ditto -real pow(real x, uint n); -/// ditto -real pow(real x, int n); -} - -/+ -real pow(real x, uint n); -{ - real p; - - switch (n) - { - case 0: - p = 1.0; - break; - - case 1: - p = x; - break; - - case 2: - p = x * x; - break; - - default: - p = 1.0; - while (1) - { - if (n & 1) - p *= x; - n >>= 1; - if (!n) - break; - x *= x; - } - break; - } - return p; -} - -/// ditto -real pow(real x, int n); -{ - if (n < 0) - return pow(x, cast(real)n); - else - return pow(x, cast(uint)n); -} -+/ - -/********************************************* - * Calculates x$(SUP y). - * - * $(TABLE_SV - * $(TR - * $(TH x) $(TH y) $(TH pow(x, y)) $(TH div 0) $(TH invalid?)) - * $(TR - * $(TD anything) $(TD $(PLUSMN)0.0) $(TD 1.0) $(TD no) $(TD no) ) - * $(TR - * $(TD |x| $(GT) 1) $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no) ) - * $(TR - * $(TD |x| $(LT) 1) $(TD +$(INFIN)) $(TD +0.0) $(TD no) $(TD no) ) - * $(TR - * $(TD |x| $(GT) 1) $(TD -$(INFIN)) $(TD +0.0) $(TD no) $(TD no) ) - * $(TR - * $(TD |x| $(LT) 1) $(TD -$(INFIN)) $(TD +$(INFIN)) $(TD no) $(TD no) ) - * $(TR - * $(TD +$(INFIN)) $(TD $(GT) 0.0) $(TD +$(INFIN)) $(TD no) $(TD no) ) - * $(TR - * $(TD +$(INFIN)) $(TD $(LT) 0.0) $(TD +0.0) $(TD no) $(TD no) ) - * $(TR - * $(TD -$(INFIN)) $(TD odd integer $(GT) 0.0) $(TD -$(INFIN)) $(TD no) $(TD no) ) - * $(TR - * $(TD -$(INFIN)) $(TD $(GT) 0.0, not odd integer) $(TD +$(INFIN)) $(TD no) $(TD no)) - * $(TR - * $(TD -$(INFIN)) $(TD odd integer $(LT) 0.0) $(TD -0.0) $(TD no) $(TD no) ) - * $(TR - * $(TD -$(INFIN)) $(TD $(LT) 0.0, not odd integer) $(TD +0.0) $(TD no) $(TD no) ) - * $(TR - * $(TD $(PLUSMN)1.0) $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD no) $(TD yes) ) - * $(TR - * $(TD $(LT) 0.0) $(TD finite, nonintegral) $(TD $(NAN)) $(TD no) $(TD yes)) - * $(TR - * $(TD $(PLUSMN)0.0) $(TD odd integer $(LT) 0.0) $(TD $(PLUSMN)$(INFIN)) $(TD yes) $(TD no) ) - * $(TR - * $(TD $(PLUSMN)0.0) $(TD $(LT) 0.0, not odd integer) $(TD +$(INFIN)) $(TD yes) $(TD no)) - * $(TR - * $(TD $(PLUSMN)0.0) $(TD odd integer $(GT) 0.0) $(TD $(PLUSMN)0.0) $(TD no) $(TD no) ) - * $(TR - * $(TD $(PLUSMN)0.0) $(TD $(GT) 0.0, not odd integer) $(TD +0.0) $(TD no) $(TD no) ) - * ) - */ - -pragma(intrinsic, "llvm.pow.f32") -float pow(float x, float y); - -pragma(intrinsic, "llvm.pow.f64") -double pow(double x, double y); - -pragma(intrinsic, "llvm.pow.f80") -real pow(real x, real y); - -/+ -real pow(real x, real y); -{ - version (linux) // C pow() often does not handle special values correctly - { - if (isnan(y)) - return y; - - if (y == 0) - return 1; // even if x is $(NAN) - if (isnan(x) && y != 0) - return x; - if (isinf(y)) - { - if (fabs(x) > 1) - { - if (signbit(y)) - return +0.0; - else - return real.infinity; - } - else if (fabs(x) == 1) - { - return real.nan; - } - else // < 1 - { - if (signbit(y)) - return real.infinity; - else - return +0.0; - } - } - if (isinf(x)) - { - if (signbit(x)) - { long i; - - i = cast(long)y; - if (y > 0) - { - if (i == y && i & 1) - return -real.infinity; - else - return real.infinity; - } - else if (y < 0) - { - if (i == y && i & 1) - return -0.0; - else - return +0.0; - } - } - else - { - if (y > 0) - return real.infinity; - else if (y < 0) - return +0.0; - } - } - - if (x == 0.0) - { - if (signbit(x)) - { long i; - - i = cast(long)y; - if (y > 0) - { - if (i == y && i & 1) - return -0.0; - else - return +0.0; - } - else if (y < 0) - { - if (i == y && i & 1) - return -real.infinity; - else - return real.infinity; - } - } - else - { - if (y > 0) - return +0.0; - else if (y < 0) - return real.infinity; - } - } - } - return std.c.math.powl(x, y); -} -+/ - -unittest -{ - real x = 46; - - assert(pow(x,0) == 1.0); - assert(pow(x,1) == x); - assert(pow(x,2) == x * x); - assert(pow(x,3) == x * x * x); - assert(pow(x,8) == (x * x) * (x * x) * (x * x) * (x * x)); -} - -/**************************************** - * Simple function to compare two floating point values - * to a specified precision. - * Returns: - * 1 match - * 0 nomatch - */ - -private int mfeq(real x, real y, real precision) -{ - if (x == y) - return 1; - if (isnan(x)) - return isnan(y); - if (isnan(y)) - return 0; - return fabs(x - y) <= precision; -} - -// Returns true if x is +0.0 (This function is used in unit tests) -bool isPosZero(real x) -{ - return (x == 0) && (signbit(x) == 0); -} - -// Returns true if x is -0.0 (This function is used in unit tests) -bool isNegZero(real x) -{ - return (x == 0) && signbit(x); -} - -/************************************** - * To what precision is x equal to y? - * - * Returns: the number of mantissa bits which are equal in x and y. - * eg, 0x1.F8p+60 and 0x1.F1p+60 are equal to 5 bits of precision. - * - * $(TABLE_SV - * $(TR $(TH x) $(TH y) $(TH feqrel(x, y))) - * $(TR $(TD x) $(TD x) $(TD real.mant_dig)) - * $(TR $(TD x) $(TD $(GT)= 2*x) $(TD 0)) - * $(TR $(TD x) $(TD $(LT)= x/2) $(TD 0)) - * $(TR $(TD $(NAN)) $(TD any) $(TD 0)) - * $(TR $(TD any) $(TD $(NAN)) $(TD 0)) - * ) - */ - -int feqrel(real x, real y) -{ - /* Public Domain. Author: Don Clugston, 18 Aug 2005. - */ - - if (x == y) - return real.mant_dig; // ensure diff!=0, cope with INF. - - real diff = fabs(x - y); - - ushort *pa = cast(ushort *)(&x); - ushort *pb = cast(ushort *)(&y); - ushort *pd = cast(ushort *)(&diff); - - // The difference in abs(exponent) between x or y and abs(x-y) - // is equal to the number of mantissa bits of x which are - // equal to y. If negative, x and y have different exponents. - // If positive, x and y are equal to 'bitsdiff' bits. - // AND with 0x7FFF to form the absolute value. - // To avoid out-by-1 errors, we subtract 1 so it rounds down - // if the exponents were different. This means 'bitsdiff' is - // always 1 lower than we want, except that if bitsdiff==0, - // they could have 0 or 1 bits in common. - int bitsdiff = ( ((pa[4]&0x7FFF) + (pb[4]&0x7FFF)-1)>>1) - pd[4]; - - if (pd[4] == 0) - { // Difference is denormal - // For denormals, we need to add the number of zeros that - // lie at the start of diff's mantissa. - // We do this by multiplying by 2^real.mant_dig - diff *= 0x1p+63; - return bitsdiff + real.mant_dig - pd[4]; - } - - if (bitsdiff > 0) - return bitsdiff + 1; // add the 1 we subtracted before - - // Avoid out-by-1 errors when factor is almost 2. - return (bitsdiff == 0) ? (pa[4] == pb[4]) : 0; -} - -unittest -{ - // Exact equality - assert(feqrel(real.max,real.max)==real.mant_dig); - assert(feqrel(0,0)==real.mant_dig); - assert(feqrel(7.1824,7.1824)==real.mant_dig); - assert(feqrel(real.infinity,real.infinity)==real.mant_dig); - - // a few bits away from exact equality - real w=1; - for (int i=1; i0 + a1x + a2x² + a3x³ ... - * - * Uses Horner's rule A(x) = a0 + x(a1 + x(a2 + x(a3 + ...))) - * Params: - * A = array of coefficients a0, a1, etc. - */ -real poly(real x, real[] A) -in -{ - assert(A.length > 0); -} -body -{ - version (D_InlineAsm_X86) - { - version (Windows) - { - asm // assembler by W. Bright - { - // EDX = (A.length - 1) * real.sizeof - mov ECX,A[EBP] ; // ECX = A.length - dec ECX ; - lea EDX,[ECX][ECX*8] ; - add EDX,ECX ; - add EDX,A+4[EBP] ; - fld real ptr [EDX] ; // ST0 = coeff[ECX] - jecxz return_ST ; - fld x[EBP] ; // ST0 = x - fxch ST(1) ; // ST1 = x, ST0 = r - align 4 ; - L2: fmul ST,ST(1) ; // r *= x - fld real ptr -10[EDX] ; - sub EDX,10 ; // deg-- - faddp ST(1),ST ; - dec ECX ; - jne L2 ; - fxch ST(1) ; // ST1 = r, ST0 = x - fstp ST(0) ; // dump x - align 4 ; - return_ST: ; - ; - } - } - else - { - asm // assembler by W. Bright - { - // EDX = (A.length - 1) * real.sizeof - mov ECX,A[EBP] ; // ECX = A.length - dec ECX ; - lea EDX,[ECX*8] ; - lea EDX,[EDX][ECX*4] ; - add EDX,A+4[EBP] ; - fld real ptr [EDX] ; // ST0 = coeff[ECX] - jecxz return_ST ; - fld x[EBP] ; // ST0 = x - fxch ST(1) ; // ST1 = x, ST0 = r - align 4 ; - L2: fmul ST,ST(1) ; // r *= x - fld real ptr -12[EDX] ; - sub EDX,12 ; // deg-- - faddp ST(1),ST ; - dec ECX ; - jne L2 ; - fxch ST(1) ; // ST1 = r, ST0 = x - fstp ST(0) ; // dump x - align 4 ; - return_ST: ; - ; - } - } - } - else - { - int i = A.length - 1; - real r = A[i]; - while (--i >= 0) - { - r *= x; - r += A[i]; - } - return r; - } -} - -unittest -{ - debug (math) printf("math.poly.unittest\n"); - real x = 3.1; - static real pp[] = [56.1, 32.7, 6]; - - assert( poly(x, pp) == (56.1L + (32.7L + 6L * x) * x) ); -} - - diff --git a/lphobos/std/md5.d b/lphobos/std/md5.d deleted file mode 100644 index 6cf5b8c0ef8..00000000000 --- a/lphobos/std/md5.d +++ /dev/null @@ -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"); -} - diff --git a/lphobos/std/mmfile.d b/lphobos/std/mmfile.d deleted file mode 100644 index 67f496c6c4a..00000000000 --- a/lphobos/std/mmfile.d +++ /dev/null @@ -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 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= 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"); - } -} diff --git a/lphobos/std/moduleinit.d b/lphobos/std/moduleinit.d deleted file mode 100644 index d363d29bd22..00000000000 --- a/lphobos/std/moduleinit.d +++ /dev/null @@ -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)(); - } - } -} - diff --git a/lphobos/std/outbuffer.d b/lphobos/std/outbuffer.d deleted file mode 100644 index e47626283a2..00000000000 --- a/lphobos/std/outbuffer.d +++ /dev/null @@ -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); -} diff --git a/lphobos/std/outofmemory.d b/lphobos/std/outofmemory.d deleted file mode 100644 index 5187b849054..00000000000 --- a/lphobos/std/outofmemory.d +++ /dev/null @@ -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() -{ -} diff --git a/lphobos/std/path.d b/lphobos/std/path.d deleted file mode 100644 index 9bc91a18104..00000000000 --- a/lphobos/std/path.d +++ /dev/null @@ -1,1254 +0,0 @@ - -/** - * Macros: - * WIKI = Phobos/StdPath - * Copyright: - * Placed into public domain. - * www.digitalmars.com - * - * Grzegorz Adam Hankiewicz added some documentation. - * - * This module is used to parse file names. All the operations - * work only on strings; they don't perform any input/output - * operations. This means that if a path contains a directory name - * with a dot, functions like getExt() will work with it just as - * if it was a file. To differentiate these cases, - * use the std.file module first (i.e. std.file.isDir()). - */ - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, March 2006 -*/ - -module std.path; - -//debug=path; // uncomment to turn on debugging printf's -//private import std.stdio; - -import std.string; - -version(linux) version = Unix; - -version(Unix) -{ - import std.c.stdlib; - version(linux) import std.c.linux.linux; - else import std.c.unix.unix; - import std.outofmemory; - /*extern(C) struct passwd - { - char* pw_name, pw_passwd; uint pw_uid, pw_gid; char* pw_gecos, pw_dir, pw_shell; - }*/ -} - -version(Windows) -{ - - /** String used to separate directory names in a path. Under - * Windows this is a backslash, under Linux a slash. */ - const char[1] sep = "\\"; - /** Alternate version of sep[] used in Windows (a slash). Under - * Linux this is empty. */ - const char[1] altsep = "/"; - /** Path separator string. A semi colon under Windows, a colon - * under Linux. */ - const char[1] pathsep = ";"; - /** String used to separate lines, \r\n under Windows and \n - * under Linux. */ - const char[2] linesep = "\r\n"; /// String used to separate lines. - const char[1] curdir = "."; /// String representing the current directory. - const char[2] pardir = ".."; /// String representing the parent directory. -} -else version(Unix) -{ - /** String used to separate directory names in a path. Under - * Windows this is a backslash, under Linux a slash. */ - const char[1] sep = "/"; - /** Alternate version of sep[] used in Windows (a slash). Under - * Linux this is empty. */ - const char[0] altsep; - /** Path separator string. A semi colon under Windows, a colon - * under Linux. */ - const char[1] pathsep = ":"; - /** String used to separate lines, \r\n under Windows and \n - * under Linux. */ - const char[1] linesep = "\n"; - const char[1] curdir = "."; /// String representing the current directory. - const char[2] pardir = ".."; /// String representing the parent directory. -} -else -{ - static assert(0); -} - -/***************************** - * Compare file names. - * Returns: - * - *
< 0 filename1 < filename2 - *
= 0 filename1 == filename2 - *
> 0 filename1 > filename2 - *
- */ - -version (Windows) alias std.string.icmp fcmp; - -version (Unix) alias std.string.cmp fcmp; - -/************************** - * Extracts the extension from a filename or path. - * - * This function will search fullname from the end until the - * first dot, path separator or first character of fullname is - * reached. Under Windows, the drive letter separator (colon) - * also terminates the search. - * - * Returns: If a dot was found, characters to its right are - * returned. If a path separator was found, or fullname didn't - * contain any dots or path separators, returns null. - * - * Throws: Nothing. - * - * Examples: - * ----- - * version(Win32) - * { - * getExt(r"d:\path\foo.bat") // "bat" - * getExt(r"d:\path.two\bar") // null - * } - * version(linux) - * { - * getExt(r"/home/user.name/bar.") // "" - * getExt(r"d:\\path.two\\bar") // "two\\bar" - * getExt(r"/home/user/.resource") // "resource" - * } - * ----- - */ - -char[] getExt(char[] fullname) -{ - size_t i; - - i = fullname.length; - while (i > 0) - { - if (fullname[i - 1] == '.') - return fullname[i .. fullname.length]; - i--; - version(Win32) - { - if (fullname[i] == ':' || fullname[i] == '\\') - break; - } - else version(Unix) - { - if (fullname[i] == '/') - break; - } - } - return null; -} - -unittest -{ - debug(path) printf("path.getExt.unittest\n"); - int i; - char[] result; - - version (Win32) - result = getExt("d:\\path\\foo.bat"); - version (Unix) - result = getExt("/path/foo.bat"); - i = cmp(result, "bat"); - assert(i == 0); - - version (Win32) - result = getExt("d:\\path\\foo."); - version (Unix) - result = getExt("d/path/foo."); - i = cmp(result, ""); - assert(i == 0); - - version (Win32) - result = getExt("d:\\path\\foo"); - version (Unix) - result = getExt("d/path/foo"); - i = cmp(result, ""); - assert(i == 0); - - version (Win32) - result = getExt("d:\\path.bar\\foo"); - version (Unix) - result = getExt("/path.bar/foo"); - - i = cmp(result, ""); - assert(i == 0); - - result = getExt("foo"); - i = cmp(result, ""); - assert(i == 0); -} - -/************************** - * Returns the extensionless version of a filename or path. - * - * This function will search fullname from the end until the - * first dot, path separator or first character of fullname is - * reached. Under Windows, the drive letter separator (colon) - * also terminates the search. - * - * Returns: If a dot was found, characters to its left are - * returned. If a path separator was found, or fullname didn't - * contain any dots or path separators, returns null. - * - * Throws: Nothing. - * - * Examples: - * ----- - * version(Win32) - * { - * getName(r"d:\path\foo.bat") => "d:\path\foo" - * getName(r"d:\path.two\bar") => null - * } - * version(linux) - * { - * getName("/home/user.name/bar.") => "/home/user.name/bar" - * getName(r"d:\path.two\bar") => "d:\path" - * getName("/home/user/.resource") => "/home/user/" - * } - * ----- - */ - -char[] getName(char[] fullname) -{ - size_t i; - - i = fullname.length; - while (i > 0) - { - if (fullname[i - 1] == '.') - return fullname[0 .. i - 1]; - i--; - version(Win32) - { - if (fullname[i] == ':' || fullname[i] == '\\') - break; - } - version(Unix) - { - if (fullname[i] == '/') - break; - } - } - return null; -} - -unittest -{ - debug(path) printf("path.getName.unittest\n"); - int i; - char[] result; - - result = getName("foo.bar"); - i = cmp(result, "foo"); - assert(i == 0); - - result = getName("d:\\path.two\\bar"); - version (Win32) - i = cmp(result, null); - version (linux) - i = cmp(result, "d:\\path"); - assert(i == 0); -} - -/************************** - * Extracts the base name of a path. - * - * This function will search fullname from the end until the - * first path separator or first character of fullname is - * reached. Under Windows, the drive letter separator (colon) - * also terminates the search. - * - * Returns: If a path separator was found, all the characters to its - * right are returned. Otherwise, fullname is returned. - * - * Throws: Nothing. - * - * Examples: - * ----- - * version(Win32) - * { - * getBaseName(r"d:\path\foo.bat") => "foo.bat" - * } - * version(linux) - * { - * getBaseName("/home/user.name/bar.") => "bar." - * } - * ----- - */ - -char[] getBaseName(char[] fullname) - out (result) - { - assert(result.length <= fullname.length); - } - body - { - size_t i; - - for (i = fullname.length; i > 0; i--) - { - version(Win32) - { - if (fullname[i - 1] == ':' || fullname[i - 1] == '\\') - break; - } - else version(Unix) - { - if (fullname[i - 1] == '/') - break; - } - } - return fullname[i .. fullname.length]; - } - -unittest -{ - debug(path) printf("path.getBaseName.unittest\n"); - int i; - char[] result; - - version (Windows) - result = getBaseName("d:\\path\\foo.bat"); - version (Unix) - result = getBaseName("/path/foo.bat"); - //printf("result = '%.*s'\n", result); - i = cmp(result, "foo.bat"); - assert(i == 0); - - version (Windows) - result = getBaseName("a\\b"); - version (Unix) - result = getBaseName("a/b"); - i = cmp(result, "b"); - assert(i == 0); -} - - -/************************** - * Extracts the directory part of a path. - * - * This function will search fullname from the end until the - * first path separator or first character of fullname is - * reached. Under Windows, the drive letter separator (colon) - * also terminates the search. - * - * Returns: If a path separator was found, all the characters to its - * left are returned. Otherwise, fullname is returned. - * - * Under Windows, the found path separator will be included in the - * returned string if it is preceeded by a colon. - * - * Throws: Nothing. - * - * Examples: - * ----- - * version(Win32) - * { - * getDirName(r"d:\path\foo.bat") => "d:\path" - * getDirName(getDirName(r"d:\path\foo.bat")) => "d:\" - * } - * version(linux) - * { - * getDirName("/home/user") => "/home" - * getDirName(getDirName("/home/user")) => "" - * } - * ----- - */ - -char[] getDirName(char[] fullname) - out (result) - { - assert(result.length <= fullname.length); - } - body - { - size_t i; - - for (i = fullname.length; i > 0; i--) - { - version(Win32) - { - if (fullname[i - 1] == ':') - break; - if (fullname[i - 1] == '\\') - { i--; - break; - } - } - else version(Unix) - { - if (fullname[i - 1] == '/') - { i--; - break; - } - } - } - return fullname[0 .. i]; - } - - -/******************************** - * Extracts the drive letter of a path. - * - * This function will search fullname for a colon from the beginning. - * - * Returns: If a colon is found, all the characters to its left - * plus the colon are returned. Otherwise, null is returned. - * - * Under Linux, this function always returns null immediately. - * - * Throws: Nothing. - * - * Examples: - * ----- - * getDrive(r"d:\path\foo.bat") => "d:" - * ----- - */ - -char[] getDrive(char[] fullname) - out (result) - { - assert(result.length <= fullname.length); - } - body - { - version(Win32) - { - size_t i; - - for (i = 0; i < fullname.length; i++) - { - if (fullname[i] == ':') - return fullname[0 .. i + 1]; - } - return null; - } - else version(Unix) - { - return null; - } - } - -/**************************** - * Appends a default extension to a filename. - * - * This function first searches filename for an extension and - * appends ext if there is none. ext should not have any leading - * dots, one will be inserted between filename and ext if filename - * doesn't already end with one. - * - * Returns: filename if it contains an extension, otherwise filename - * + ext. - * - * Throws: Nothing. - * - * Examples: - * ----- - * defaultExt("foo.txt", "raw") => "foo.txt" - * defaultExt("foo.", "raw") => "foo.raw" - * defaultExt("bar", "raw") => "bar.raw" - * ----- - */ - -char[] defaultExt(char[] filename, char[] ext) -{ - char[] existing; - - existing = getExt(filename); - if (existing.length == 0) - { - // Check for filename ending in '.' - if (filename.length && filename[filename.length - 1] == '.') - filename ~= ext; - else - filename = filename ~ "." ~ ext; - } - return filename; -} - - -/**************************** - * Adds or replaces an extension to a filename. - * - * This function first searches filename for an extension and - * replaces it with ext if found. If there is no extension, ext - * will be appended. ext should not have any leading dots, one will - * be inserted between filename and ext if filename doesn't already - * end with one. - * - * Returns: filename + ext if filename is extensionless. Otherwise - * strips filename's extension off, appends ext and returns the - * result. - * - * Throws: Nothing. - * - * Examples: - * ----- - * addExt("foo.txt", "raw") => "foo.raw" - * addExt("foo.", "raw") => "foo.raw" - * addExt("bar", "raw") => "bar.raw" - * ----- - */ - -char[] addExt(char[] filename, char[] ext) -{ - char[] existing; - - existing = getExt(filename); - if (existing.length == 0) - { - // Check for filename ending in '.' - if (filename.length && filename[filename.length - 1] == '.') - filename ~= ext; - else - filename = filename ~ "." ~ ext; - } - else - { - filename = filename[0 .. filename.length - existing.length] ~ ext; - } - return filename; -} - - -/************************************* - * Checks if path is absolute. - * - * Returns: non-zero if the path starts from the root directory (Linux) or - * drive letter and root directory (Windows), - * zero otherwise. - * - * Throws: Nothing. - * - * Examples: - * ----- - * version(Win32) - * { - * isabs(r"relative\path") => 0 - * isabs(r"\relative\path") => 0 - * isabs(r"d:\absolute") => 1 - * } - * version(linux) - * { - * isabs("/home/user") => 1 - * isabs("foo") => 0 - * } - * ----- - */ - -int isabs(char[] path) -{ - char[] d = getDrive(path); - - version (Windows) - { - return d.length && d.length < path.length && path[d.length] == sep[0]; - } - else - return d.length < path.length && path[d.length] == sep[0]; -} - -unittest -{ - debug(path) printf("path.isabs.unittest\n"); - - version (Windows) - { - assert(isabs(r"relative\path") == 0); - assert(isabs(r"\relative\path") == 0); - assert(isabs(r"d:\absolute") == 1); - } - version (linux) - { - assert(isabs("/home/user") == 1); - assert(isabs("foo") == 0); - } -} - -/************************************* - * Joins two path components. - * - * If p1 doesn't have a trailing path separator, one will be appended - * to it before concatting p2. - * - * Returns: p1 ~ p2. However, if p2 is an absolute path, only p2 - * will be returned. - * - * Throws: Nothing. - * - * Examples: - * ----- - * version(Win32) - * { - * join(r"c:\foo", "bar") => "c:\foo\bar" - * join("foo", r"d:\bar") => "d:\bar" - * } - * version(linux) - * { - * join("/foo/", "bar") => "/foo/bar" - * join("/foo", "/bar") => "/bar" - * } - * ----- - */ - -char[] join(char[] p1, char[] p2) -{ - if (!p2.length) - return p1; - if (!p1.length) - return p2; - - char[] p; - char[] d1; - - version(Win32) - { - if (getDrive(p2)) - { - p = p2; - } - else - { - d1 = getDrive(p1); - if (p1.length == d1.length) - { - p = p1 ~ p2; - } - else if (p2[0] == '\\') - { - if (d1.length == 0) - p = p2; - else if (p1[p1.length - 1] == '\\') - p = p1 ~ p2[1 .. p2.length]; - else - p = p1 ~ p2; - } - else if (p1[p1.length - 1] == '\\') - { - p = p1 ~ p2; - } - else - { - p = p1 ~ sep ~ p2; - } - } - } - else version(Unix) - { - if (p2[0] == sep[0]) - { - p = p2; - } - else if (p1[p1.length - 1] == sep[0]) - { - p = p1 ~ p2; - } - else - { - p = p1 ~ sep ~ p2; - } - } - return p; -} - -unittest -{ - debug(path) printf("path.join.unittest\n"); - - char[] p; - int i; - - p = join("foo", "bar"); - version (Win32) - i = cmp(p, "foo\\bar"); - version (Unix) - i = cmp(p, "foo/bar"); - assert(i == 0); - - version (Win32) - { p = join("foo\\", "bar"); - i = cmp(p, "foo\\bar"); - } - version (Unix) - { p = join("foo/", "bar"); - i = cmp(p, "foo/bar"); - } - assert(i == 0); - - version (Win32) - { p = join("foo", "\\bar"); - i = cmp(p, "\\bar"); - } - version (Unix) - { p = join("foo", "/bar"); - i = cmp(p, "/bar"); - } - assert(i == 0); - - version (Win32) - { p = join("foo\\", "\\bar"); - i = cmp(p, "\\bar"); - } - version (Unix) - { p = join("foo/", "/bar"); - i = cmp(p, "/bar"); - } - assert(i == 0); - - version(Win32) - { - p = join("d:", "bar"); - i = cmp(p, "d:bar"); - assert(i == 0); - - p = join("d:\\", "bar"); - i = cmp(p, "d:\\bar"); - assert(i == 0); - - p = join("d:\\", "\\bar"); - i = cmp(p, "d:\\bar"); - assert(i == 0); - - p = join("d:\\foo", "bar"); - i = cmp(p, "d:\\foo\\bar"); - assert(i == 0); - - p = join("d:", "\\bar"); - i = cmp(p, "d:\\bar"); - assert(i == 0); - - p = join("foo", "d:"); - i = cmp(p, "d:"); - assert(i == 0); - - p = join("foo", "d:\\"); - i = cmp(p, "d:\\"); - assert(i == 0); - - p = join("foo", "d:\\bar"); - i = cmp(p, "d:\\bar"); - assert(i == 0); - } -} - - -/********************************* - * Matches filename characters. - * - * Under Windows, the comparison is done ignoring case. Under Linux - * an exact match is performed. - * - * Returns: non zero if c1 matches c2, zero otherwise. - * - * Throws: Nothing. - * - * Examples: - * ----- - * version(Win32) - * { - * fncharmatch('a', 'b') => 0 - * fncharmatch('A', 'a') => 1 - * } - * version(linux) - * { - * fncharmatch('a', 'b') => 0 - * fncharmatch('A', 'a') => 0 - * } - * ----- - */ - -int fncharmatch(dchar c1, dchar c2) -{ - version (Win32) - { - if (c1 != c2) - { - if ('A' <= c1 && c1 <= 'Z') - c1 += cast(char)'a' - 'A'; - if ('A' <= c2 && c2 <= 'Z') - c2 += cast(char)'a' - 'A'; - return c1 == c2; - } - return true; - } - else version (Unix) - { - return c1 == c2; - } - /* this is filesystem-dependent, figure out the filesystem? - else version (GNU) - { - // %% figure out filesystem? - return c1 == c2; - } - */ -} - -/************************************ - * Matches a pattern against a filename. - * - * Some characters of pattern have special a meaning (they are - * meta-characters) and can't be escaped. These are: - *

- * - * - * - * - * - * - * - * - *
*Matches 0 or more instances of any character.
?Matches exactly one instances of any character.
[chars]Matches one instance of any character that appears - * between the brackets.
[!chars]Matches one instance of any character that does not appear - * between the brackets after the exclamation mark.

- * Internally individual character comparisons are done calling - * fncharmatch(), so its rules apply here too. Note that path - * separators and dots don't stop a meta-character from matching - * further portions of the filename. - * - * Returns: non zero if pattern matches filename, zero otherwise. - * - * See_Also: fncharmatch(). - * - * Throws: Nothing. - * - * Examples: - * ----- - * version(Win32) - * { - * fnmatch("foo.bar", "*") => 1 - * fnmatch(r"foo/foo\bar", "f*b*r") => 1 - * fnmatch("foo.bar", "f?bar") => 0 - * fnmatch("Goo.bar", "[fg]???bar") => 1 - * fnmatch(r"d:\foo\bar", "d*foo?bar") => 1 - * } - * version(linux) - * { - * fnmatch("Go*.bar", "[fg]???bar") => 0 - * fnmatch("/foo*home/bar", "?foo*bar") => 1 - * fnmatch("foobar", "foo?bar") => 1 - * } - * ----- - */ - -int fnmatch(char[] filename, char[] pattern) - in - { - // Verify that pattern[] is valid - size_t i; - int inbracket = false; - - for (i = 0; i < pattern.length; i++) - { - switch (pattern[i]) - { - case '[': - assert(!inbracket); - inbracket = true; - break; - - case ']': - assert(inbracket); - inbracket = false; - break; - - default: - break; - } - } - } - body - { - size_t pi; - size_t ni; - char pc; - char nc; - size_t j; - int not; - int anymatch; - - ni = 0; - for (pi = 0; pi < pattern.length; pi++) - { - pc = pattern[pi]; - switch (pc) - { - case '*': - if (pi + 1 == pattern.length) - goto match; - for (j = ni; j < filename.length; j++) - { - if (fnmatch(filename[j .. filename.length], pattern[pi + 1 .. pattern.length])) - goto match; - } - goto nomatch; - - case '?': - if (ni == filename.length) - goto nomatch; - ni++; - break; - - case '[': - if (ni == filename.length) - goto nomatch; - nc = filename[ni]; - ni++; - not = 0; - pi++; - if (pattern[pi] == '!') - { not = 1; - pi++; - } - anymatch = 0; - while (1) - { - pc = pattern[pi]; - if (pc == ']') - break; - if (!anymatch && fncharmatch(nc, pc)) - anymatch = 1; - pi++; - } - if (!(anymatch ^ not)) - goto nomatch; - break; - - default: - if (ni == filename.length) - goto nomatch; - nc = filename[ni]; - if (!fncharmatch(pc, nc)) - goto nomatch; - ni++; - break; - } - } - if (ni < filename.length) - goto nomatch; - - match: - return true; - - nomatch: - return false; - } - -unittest -{ - debug(path) printf("path.fnmatch.unittest\n"); - - version (Win32) - assert(fnmatch("foo", "Foo")); - version (Unix) - assert(!fnmatch("foo", "Foo")); - assert(fnmatch("foo", "*")); - assert(fnmatch("foo.bar", "*")); - assert(fnmatch("foo.bar", "*.*")); - assert(fnmatch("foo.bar", "foo*")); - assert(fnmatch("foo.bar", "f*bar")); - assert(fnmatch("foo.bar", "f*b*r")); - assert(fnmatch("foo.bar", "f???bar")); - assert(fnmatch("foo.bar", "[fg]???bar")); - assert(fnmatch("foo.bar", "[!gh]*bar")); - - assert(!fnmatch("foo", "bar")); - assert(!fnmatch("foo", "*.*")); - assert(!fnmatch("foo.bar", "f*baz")); - assert(!fnmatch("foo.bar", "f*b*x")); - assert(!fnmatch("foo.bar", "[gh]???bar")); - assert(!fnmatch("foo.bar", "[!fg]*bar")); - assert(!fnmatch("foo.bar", "[fg]???baz")); -} - -/** - * Performs tilde expansion in paths. - * - * There are two ways of using tilde expansion in a path. One - * involves using the tilde alone or followed by a path separator. In - * this case, the tilde will be expanded with the value of the - * environment variable HOME. The second way is putting - * a username after the tilde (i.e. ~john/Mail). Here, - * the username will be searched for in the user database - * (i.e. /etc/passwd on Unix systems) and will expand to - * whatever path is stored there. The username is considered the - * string after the tilde ending at the first instance of a path - * separator. - * - * Note that using the ~user syntax may give different - * values from just ~ if the environment variable doesn't - * match the value stored in the user database. - * - * When the environment variable version is used, the path won't - * be modified if the environment variable doesn't exist or it - * is empty. When the database version is used, the path won't be - * modified if the user doesn't exist in the database or there is - * not enough memory to perform the query. - * - * Returns: inputPath with the tilde expanded, or just inputPath - * if it could not be expanded. - * For Windows, expandTilde() merely returns its argument inputPath. - * - * Throws: std.outofmemory.OutOfMemoryException if there is not enough - * memory to perform - * the database lookup for the ~user syntax. - * - * Examples: - * ----- - * import std.path; - * - * void process_file(char[] filename) - * { - * char[] path = expandTilde(filename); - * ... - * } - * ----- - * - * ----- - * import std.path; - * - * const char[] RESOURCE_DIR_TEMPLATE = "~/.applicationrc"; - * char[] RESOURCE_DIR; // This gets expanded in main(). - * - * int main(char[][] args) - * { - * RESOURCE_DIR = expandTilde(RESOURCE_DIR_TEMPLATE); - * ... - * } - * ----- - * Version: Available since v0.143. - * Authors: Grzegorz Adam Hankiewicz, Thomas Kühne. - */ - -char[] expandTilde(char[] inputPath) -{ - version(Unix) - { - static assert(sep.length == 1); - - // Return early if there is no tilde in path. - if (inputPath.length < 1 || inputPath[0] != '~') - return inputPath; - - if (inputPath.length == 1 || inputPath[1] == sep[0]) - return expandFromEnvironment(inputPath); - else - return expandFromDatabase(inputPath); - } - else version(Windows) - { - // Put here real windows implementation. - return inputPath; - } - else - { - static assert(0); // Guard. Implement on other platforms. - } -} - - -unittest -{ - debug(path) printf("path.expandTilde.unittest\n"); - - version (Unix) - { - // Retrieve the current home variable. - char* c_home = getenv("HOME"); - - // Testing when there is no environment variable. - unsetenv("HOME"); - assert(expandTilde("~/") == "~/"); - assert(expandTilde("~") == "~"); - - // Testing when an environment variable is set. - int ret = setenv("HOME", "dmd/test\0", 1); - assert(ret == 0); - assert(expandTilde("~/") == "dmd/test/"); - assert(expandTilde("~") == "dmd/test"); - - // The same, but with a variable ending in a slash. - ret = setenv("HOME", "dmd/test/\0", 1); - assert(ret == 0); - assert(expandTilde("~/") == "dmd/test/"); - assert(expandTilde("~") == "dmd/test"); - - // Recover original HOME variable before continuing. - if (c_home) - setenv("HOME", c_home, 1); - else - unsetenv("HOME"); - - // Test user expansion for root. Are there unices without /root? - /* - assert(expandTilde("~root") == "/root"); - assert(expandTilde("~root/") == "/root/"); - */ - assert(expandTilde("~Idontexist/hey") == "~Idontexist/hey"); - } -} - -version (Unix) -{ - -/** - * Replaces the tilde from path with the environment variable HOME. - */ -private char[] expandFromEnvironment(char[] path) -{ - assert(path.length >= 1); - assert(path[0] == '~'); - - // Get HOME and use that to replace the tilde. - char* home = getenv("HOME"); - if (home == null) - return path; - - return combineCPathWithDPath(home, path, 1); -} - - -/** - * Joins a path from a C string to the remainder of path. - * - * The last path separator from c_path is discarded. The result - * is joined to path[char_pos .. length] if char_pos is smaller - * than length, otherwise path is not appended to c_path. - */ -private char[] combineCPathWithDPath(char* c_path, char[] path, int char_pos) -{ - assert(c_path != null); - assert(path.length > 0); - assert(char_pos >= 0); - - // Search end of C string - size_t end = std.string.strlen(c_path); - - // Remove trailing path separator, if any - if (end && c_path[end - 1] == sep[0]) - end--; - - // Create our own copy, as lifetime of c_path is undocumented - char[] cp = c_path[0 .. end].dup; - - // Do we append something from path? - if (char_pos < path.length) - cp ~= path[char_pos .. length]; - - return cp; -} - - -/** - * Replaces the tilde from path with the path from the user database. - */ -private string expandFromDatabase(string path) -{ - assert(path.length > 2 || (path.length == 2 && path[1] != sep[0])); - assert(path[0] == '~'); - - // Extract username, searching for path separator. - string username; - ptrdiff_t last_char = find(path, sep[0]); - - if (last_char == -1) - { - username = path[1 .. length] ~ '\0'; - last_char = username.length + 1; - } - else - { - username = path[1 .. last_char] ~ '\0'; - } - assert(last_char > 1); - - version (GNU_Unix_Have_getpwnam_r) - { - - // Reserve C memory for the getpwnam_r() function. - passwd result; - int extra_memory_size = 5 * 1024; - void* extra_memory; - - while (1) - { - extra_memory = std.c.stdlib.malloc(extra_memory_size); - if (extra_memory == null) - goto Lerror; - - // Obtain info from database. - passwd *verify; - std.c.stdlib.setErrno(0); - if (getpwnam_r(username.ptr, &result, cast(char*) extra_memory, extra_memory_size, - &verify) == 0) - { - // Failure if verify doesn't point at result. - if (verify != &result) - // username is not found, so return path[] - goto Lnotfound; - break; - } - - switch (std.c.stdlib.getErrno()) { - case 0: - case ENOENT: - case ESRCH: - case EBADF: - case EPERM: - goto Lnotfound; - case ERANGE: - break; - default: - // not just out of memory: EMFILE, ENFILE too - goto Lerror; - } - - // extra_memory isn't large enough - std.c.stdlib.free(extra_memory); - extra_memory_size *= 2; - } - - path = combineCPathWithDPath(result.pw_dir, path, last_char); - -Lnotfound: - std.c.stdlib.free(extra_memory); - return path; - -Lerror: - // Errors are going to be caused by running out of memory - if (extra_memory) - std.c.stdlib.free(extra_memory); - _d_OutOfMemory(); - return null; - - } - else - { - passwd * result; - - /* This does not guarantee another thread will not - use getpwnam at the same time */ - synchronized { - result = getpwnam(username.ptr); - } - - if (result) - path = combineCPathWithDPath(result.pw_dir, path, last_char); - return path; - } -} - -} diff --git a/lphobos/std/process.d b/lphobos/std/process.d deleted file mode 100644 index 98736d02185..00000000000 --- a/lphobos/std/process.d +++ /dev/null @@ -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; - } - } -} - -/* ////////////////////////////////////////////////////////////////////////// */ diff --git a/lphobos/std/random.d b/lphobos/std/random.d deleted file mode 100644 index 1320e209cb0..00000000000 --- a/lphobos/std/random.d +++ /dev/null @@ -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; -} diff --git a/lphobos/std/regexp.d b/lphobos/std/regexp.d deleted file mode 100644 index 450c6cbded8..00000000000 --- a/lphobos/std/regexp.d +++ /dev/null @@ -1,3208 +0,0 @@ - -// Regular Expressions - -/* - * Copyright (C) 2000-2005 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. - */ - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, September 2004 -*/ - -/********************************************** - * $(LINK2 http://www.digitalmars.com/ctg/regular.html, Regular expressions) - * are a powerful method of string pattern matching. - * The regular expression - * language used is the same as that commonly used, however, some of the very - * advanced forms may behave slightly differently. - * - * std.regexp is designed to work only with valid UTF strings as input. - * To validate untrusted input, use std.utf.validate(). - * - * In the following guide, $(I pattern)[] refers to a - * $(LINK2 http://www.digitalmars.com/ctg/regular.html, regular expression). - * The $(I attributes)[] refers to - a string controlling the interpretation - of the regular expression. - It consists of a sequence of one or more - of the following characters: - - - - $(TR $(TH Attribute) $(TH Action)) - - $(TD $(B g)) - $(TD global; repeat over the whole input string) - - - $(TD $(B i)) - $(TD case insensitive) - - - $(TD $(B m)) - $(TD treat as multiple lines separated by newlines) - -
Attribute Characters
- * - * The $(I format)[] string has the formatting characters: - * - * - - $(TR $(TH Format) $(TH Replaced With)) - $(TR - $(TD $(B $$)) $(TD $) - ) - $(TR - $(TD $(B $&)) $(TD The matched substring.) - ) - $(TR - $(TD $(B $`)) $(TD The portion of string that precedes the matched substring.) - ) - $(TR - $(TD $(B $')) $(TD The portion of string that follows the matched substring.) - ) - $(TR - $(TD $(B $(DOLLAR))$(I n)) $(TD The $(I n)th capture, where $(I n) - is a single digit 1-9 - and $$(I n) is not followed by a decimal digit.) - ) - $(TR - $(TD $(B $(DOLLAR))$(I nn)) $(TD The $(I nn)th capture, where $(I nn) - is a two-digit decimal - number 01-99. - If $(I nn)th capture is undefined or more than the number - of parenthesized subexpressions, use the empty - string instead.) - ) -
Formatting Characters
- - * Any other $ are left as is. - * - * References: - * $(LINK2 http://en.wikipedia.org/wiki/Regular_expressions, Wikipedia) - * Macros: - * WIKI = StdRegexp - * DOLLAR = $ - */ - -/* - Escape sequences: - - \nnn starts out a 1, 2 or 3 digit octal sequence, - where n is an octal digit. If nnn is larger than - 0377, then the 3rd digit is not part of the sequence - and is not consumed. - For maximal portability, use exactly 3 digits. - - \xXX starts out a 1 or 2 digit hex sequence. X - is a hex character. If the first character after the \x - is not a hex character, the value of the sequence is 'x' - and the XX are not consumed. - For maximal portability, use exactly 2 digits. - - \uUUUU is a unicode sequence. There are exactly - 4 hex characters after the \u, if any are not, then - the value of the sequence is 'u', and the UUUU are not - consumed. - - Character classes: - - [a-b], where a is greater than b, will produce - an error. - - References: - - http://www.unicode.org/unicode/reports/tr18/ - */ - -module std.regexp; - -//debug = regexp; // uncomment to turn on debugging printf's - -private -{ - import std.c.stdio; - import std.c.stdlib; - import std.c.string; - import std.stdio; - import std.string; - import std.ctype; - import std.outbuffer; - import std.bitarray; - import std.utf; - import std.intrinsic; -} - -/** Regular expression to extract an _email address */ -const char[] email = - r"[a-zA-Z]([.]?([[a-zA-Z0-9_]-]+)*)?@([[a-zA-Z0-9_]\-_]+\.)+[a-zA-Z]{2,6}"; - -/** Regular expression to extract a _url */ -const char[] url = r"(([h|H][t|T]|[f|F])[t|T][p|P]([s|S]?)\:\/\/|~/|/)?([\w]+:\w+@)?(([a-zA-Z]{1}([\w\-]+\.)+([\w]{2,5}))(:[\d]{1,5})?)?((/?\w+/)+|/?)(\w+\.[\w]{3,4})?([,]\w+)*((\?\w+=\w+)?(&\w+=\w+)*([,]\w*)*)?"; - -/************************************ - * One of these gets thrown on compilation errors - */ - -class RegExpException : Exception -{ - this(char[] msg) - { - super(msg); - } -} - -struct regmatch_t -{ - int rm_so; // index of start of match - int rm_eo; // index past end of match -} - -private alias char rchar; // so we can make a wchar version - -/****************************************************** - * Search string for matches with regular expression - * pattern with attributes. - * Replace each match with string generated from format. - * Params: - * string = String to search. - * pattern = Regular expression pattern. - * format = Replacement string format. - * attributes = Regular expression attributes. - * Returns: - * the resulting string - * Example: - * Replace the letters 'a' with the letters 'ZZ'. - * --- - * s = "Strap a rocket engine on a chicken." - * sub(s, "a", "ZZ") // result: StrZZp a rocket engine on a chicken. - * sub(s, "a", "ZZ", "g") // result: StrZZp ZZ rocket engine on ZZ chicken. - * --- - * The replacement format can reference the matches using - * the $&, $$, $', $`, $0 .. $99 notation: - * --- - * sub(s, "[ar]", "[$&]", "g") // result: St[r][a]p [a] [r]ocket engine on [a] chi - * --- - */ - -char[] sub(char[] string, char[] pattern, char[] format, char[] attributes = null) -{ - auto r = new RegExp(pattern, attributes); - auto result = r.replace(string, format); - delete r; - return result; -} - -unittest -{ - debug(regexp) printf("regexp.sub.unittest\n"); - - char[] r = sub("hello", "ll", "ss"); - assert(r == "hesso"); -} - -/******************************************************* - * Search string for matches with regular expression - * pattern with attributes. - * Pass each match to delegate dg. - * Replace each match with the return value from dg. - * Params: - * string = String to search. - * pattern = Regular expression pattern. - * dg = Delegate - * attributes = Regular expression attributes. - * Returns: the resulting string. - * Example: - * Capitalize the letters 'a' and 'r': - * --- - * s = "Strap a rocket engine on a chicken."; - * sub(s, "[ar]", - * delegate char[] (RegExp m) - * { - * return toupper(m.match(0)); - * }, - * "g"); // result: StRAp A Rocket engine on A chicken. - * --- - */ - -char[] sub(char[] string, char[] pattern, char[] delegate(RegExp) dg, char[] attributes = null) -{ - auto r = new RegExp(pattern, attributes); - rchar[] result; - int lastindex; - int offset; - - result = string; - lastindex = 0; - offset = 0; - while (r.test(string, lastindex)) - { - int so = r.pmatch[0].rm_so; - int eo = r.pmatch[0].rm_eo; - - rchar[] replacement = dg(r); - - // Optimize by using std.string.replace if possible - Dave Fladebo - rchar[] slice = result[offset + so .. offset + eo]; - if (r.attributes & RegExp.REA.global && // global, so replace all - !(r.attributes & RegExp.REA.ignoreCase) && // not ignoring case - !(r.attributes & RegExp.REA.multiline) && // not multiline - pattern == slice) // simple pattern (exact match, no special characters) - { - debug(regexp) - printf("pattern: %.*s, slice: %.*s, replacement: %.*s\n", - cast(int) pattern.length, pattern.ptr, - cast(int) (eo-so), result.ptr + offset, - cast(int) replacement.length, replacement.ptr); - result = std.string.replace(result,slice,replacement); - break; - } - - result = replaceSlice(result, result[offset + so .. offset + eo], replacement); - - if (r.attributes & RegExp.REA.global) - { - offset += replacement.length - (eo - so); - - if (lastindex == eo) - lastindex++; // always consume some source - else - lastindex = eo; - } - else - break; - } - delete r; - - return result; -} - -unittest -{ - debug(regexp) printf("regexp.sub.unittest\n"); - - char[] foo(RegExp r) { return "ss"; } - - char[] r = sub("hello", "ll", delegate char[](RegExp r) { return "ss"; }); - assert(r == "hesso"); - - r = sub("hello", "l", delegate char[](RegExp r) { return "l"; }, "g"); - assert(r == "hello"); - - auto s = sub("Strap a rocket engine on a chicken.", - "[ar]", - delegate char[] (RegExp m) - { - return std.string.toupper(m.match(0)); - }, - "g"); - assert(s == "StRAp A Rocket engine on A chicken."); -} - - -/************************************************* - * Search string[] for first match with pattern[] with attributes[]. - * Params: - * string = String to search. - * pattern = Regular expression pattern. - * attributes = Regular expression attributes. - * Returns: - * index into string[] of match if found, -1 if no match. - * Example: - * --- - * auto s = "abcabcabab"; - * std.regexp.find(s, "b"); // match, returns 1 - * std.regexp.find(s, "f"); // no match, returns -1 - * --- - */ - -int find(rchar[] string, char[] pattern, char[] attributes = null) -{ - int i = -1; - - auto r = new RegExp(pattern, attributes); - if (r.test(string)) - { - i = r.pmatch[0].rm_so; - } - delete r; - return i; -} - -unittest -{ - debug(regexp) printf("regexp.find.unittest\n"); - - int i; - i = find("xabcy", "abc"); - assert(i == 1); - i = find("cba", "abc"); - assert(i == -1); -} - - - -/************************************************* - * Search string[] for last match with pattern[] with attributes[]. - * Params: - * string = String to search. - * pattern = Regular expression pattern. - * attributes = Regular expression attributes. - * Returns: - * index into string[] of match if found, -1 if no match. - * Example: - * --- - * auto s = "abcabcabab"; - * std.regexp.find(s, "b"); // match, returns 9 - * std.regexp.find(s, "f"); // no match, returns -1 - * --- - */ - -int rfind(rchar[] string, char[] pattern, char[] attributes = null) -{ - int i = -1; - int lastindex = 0; - - auto r = new RegExp(pattern, attributes); - while (r.test(string, lastindex)) - { int eo = r.pmatch[0].rm_eo; - i = r.pmatch[0].rm_so; - if (lastindex == eo) - lastindex++; // always consume some source - else - lastindex = eo; - } - delete r; - return i; -} - -unittest -{ - int i; - - debug(regexp) printf("regexp.rfind.unittest\n"); - i = rfind("abcdefcdef", "c"); - assert(i == 6); - i = rfind("abcdefcdef", "cd"); - assert(i == 6); - i = rfind("abcdefcdef", "x"); - assert(i == -1); - i = rfind("abcdefcdef", "xy"); - assert(i == -1); - i = rfind("abcdefcdef", ""); - assert(i == 10); -} - - -/******************************************** - * Split string[] into an array of strings, using the regular - * expression pattern[] with attributes[] as the separator. - * Params: - * string = String to search. - * pattern = Regular expression pattern. - * attributes = Regular expression attributes. - * Returns: - * array of slices into string[] - * Example: - * --- - * foreach (s; split("abcabcabab", "C.", "i")) - * { - * writefln("s = '%s'", s); - * } - * // Prints: - * // s = 'ab' - * // s = 'b' - * // s = 'bab' - * --- - */ - -char[][] split(char[] string, char[] pattern, char[] attributes = null) -{ - auto r = new RegExp(pattern, attributes); - auto result = r.split(string); - delete r; - return result; -} - -unittest -{ - debug(regexp) printf("regexp.split.unittest()\n"); - char[][] result; - - result = split("ab", "a*"); - assert(result.length == 2); - assert(result[0] == ""); - assert(result[1] == "b"); - - foreach (i, s; split("abcabcabab", "C.", "i")) - { - writefln("s[%d] = '%s'", i, s); - if (i == 0) assert(s == "ab"); - else if (i == 1) assert(s == "b"); - else if (i == 2) assert(s == "bab"); - else assert(0); - } -} - -/**************************************************** - * Search string[] for first match with pattern[] with attributes[]. - * Params: - * string = String to search. - * pattern = Regular expression pattern. - * attributes = Regular expression attributes. - * Returns: - * corresponding RegExp if found, null if not. - * Example: - * --- - * import std.stdio; - * import std.regexp; - * - * void main() - * { - * if (auto m = std.regexp.search("abcdef", "c")) - * { - * writefln("%s[%s]%s", m.pre, m.match(0), m.post); - * } - * } - * // Prints: - * // ab[c]def - * --- - */ - -RegExp search(char[] string, char[] pattern, char[] attributes = null) -{ - auto r = new RegExp(pattern, attributes); - - if (r.test(string)) - { - } - else - { delete r; - r = null; - } - return r; -} - -unittest -{ - debug(regexp) printf("regexp.string.unittest()\n"); - - if (auto m = std.regexp.search("abcdef", "c()")) - { - auto result = std.string.format("%s[%s]%s", m.pre, m.match(0), m.post); - assert(result == "ab[c]def"); - assert(m.match(1) == null); - assert(m.match(2) == null); - } - else - assert(0); - - if (auto n = std.regexp.search("abcdef", "g")) - { - assert(0); - } -} - - -/* ********************************* RegExp ******************************** */ - -/***************************** - * RegExp is a class to handle regular expressions. - * - * It is the core foundation for adding powerful string pattern matching - * capabilities to programs like grep, text editors, awk, sed, etc. - */ -class RegExp -{ - /***** - * Construct a RegExp object. Compile pattern - * with attributes into - * an internal form for fast execution. - * Params: - * pattern = regular expression - * attributes = _attributes - * Throws: RegExpException if there are any compilation errors. - * Example: - * Declare two variables and assign to them a RegExp object: - * --- - * auto r = new RegExp("pattern"); - * auto s = new RegExp(r"p[1-5]\s*"); - * --- - */ - public this(rchar[] pattern, rchar[] attributes = null) - { - pmatch = (&gmatch)[0 .. 1]; - compile(pattern, attributes); - } - - /***** - * Generate instance of RegExp. - * Params: - * pattern = regular expression - * attributes = _attributes - * Throws: RegExpException if there are any compilation errors. - * Example: - * Declare two variables and assign to them a RegExp object: - * --- - * auto r = RegExp("pattern"); - * auto s = RegExp(r"p[1-5]\s*"); - * --- - */ - public static RegExp opCall(rchar[] pattern, rchar[] attributes = null) - { - return new RegExp(pattern, attributes); - } - - unittest - { - debug(regexp) printf("regexp.opCall.unittest()\n"); - auto r1 = RegExp("hello", "m"); - char[] msg; - try - { - auto r2 = RegExp("hello", "q"); - assert(0); - } - catch (RegExpException ree) - { - msg = ree.toString(); - //writefln("message: %s", ree); - } - assert(msg == "unrecognized attribute"); - } - - /************************************ - * Set up for start of foreach loop. - * Returns: - * search() returns instance of RegExp set up to _search string[]. - * Example: - * --- - * import std.stdio; - * import std.regexp; - * - * void main() - * { - * foreach(m; RegExp("ab").search("abcabcabab")) - * { - * writefln("%s[%s]%s", m.pre, m.match(0), m.post); - * } - * } - * // Prints: - * // [ab]cabcabab - * // abc[ab]cabab - * // abcabc[ab]ab - * // abcabcab[ab] - * --- - */ - - public RegExp search(rchar[] string) - { - input = string; - pmatch[0].rm_eo = 0; - return this; - } - - /** ditto */ - public int opApply(int delegate(inout RegExp) dg) - { - int result; - RegExp r = this; - - while (test()) - { - result = dg(r); - if (result) - break; - } - - return result; - } - - unittest - { - debug(regexp) printf("regexp.search.unittest()\n"); - - int i; - foreach(m; RegExp("ab").search("abcabcabab")) - { - auto s = std.string.format("%s[%s]%s", m.pre, m.match(0), m.post); - if (i == 0) assert(s == "[ab]cabcabab"); - else if (i == 1) assert(s == "abc[ab]cabab"); - else if (i == 2) assert(s == "abcabc[ab]ab"); - else if (i == 3) assert(s == "abcabcab[ab]"); - else assert(0); - i++; - } - } - - /****************** - * Retrieve match n. - * - * n==0 means the matched substring, n>0 means the - * n'th parenthesized subexpression. - * if n is larger than the number of parenthesized subexpressions, - * null is returned. - */ - public char[] match(size_t n) - { - if (n >= pmatch.length) - return null; - else - { size_t rm_so, rm_eo; - rm_so = pmatch[n].rm_so; - rm_eo = pmatch[n].rm_eo; - if (rm_so == rm_eo) - return null; - return input[rm_so .. rm_eo]; - } - } - - /******************* - * Return the slice of the input that precedes the matched substring. - */ - public char[] pre() - { - return input[0 .. pmatch[0].rm_so]; - } - - /******************* - * Return the slice of the input that follows the matched substring. - */ - public char[] post() - { - return input[pmatch[0].rm_eo .. $]; - } - - uint re_nsub; // number of parenthesized subexpression matches - regmatch_t[] pmatch; // array [re_nsub + 1] - - rchar[] input; // the string to search - - // per instance: - - rchar[] pattern; // source text of the regular expression - - rchar[] flags; // source text of the attributes parameter - - int errors; - - uint attributes; - - enum REA - { - global = 1, // has the g attribute - ignoreCase = 2, // has the i attribute - multiline = 4, // if treat as multiple lines separated - // by newlines, or as a single line - dotmatchlf = 8, // if . matches \n - } - - -private: - size_t src; // current source index in input[] - size_t src_start; // starting index for match in input[] - size_t p; // position of parser in pattern[] - regmatch_t gmatch; // match for the entire regular expression - // (serves as storage for pmatch[0]) - - ubyte[] program; // pattern[] compiled into regular expression program - OutBuffer buf; - - - - -/******************************************/ - -// Opcodes - -enum : ubyte -{ - REend, // end of program - REchar, // single character - REichar, // single character, case insensitive - REdchar, // single UCS character - REidchar, // single wide character, case insensitive - REanychar, // any character - REanystar, // ".*" - REstring, // string of characters - REistring, // string of characters, case insensitive - REtestbit, // any in bitmap, non-consuming - REbit, // any in the bit map - REnotbit, // any not in the bit map - RErange, // any in the string - REnotrange, // any not in the string - REor, // a | b - REplus, // 1 or more - REstar, // 0 or more - REquest, // 0 or 1 - REnm, // n..m - REnmq, // n..m, non-greedy version - REbol, // beginning of line - REeol, // end of line - REparen, // parenthesized subexpression - REgoto, // goto offset - - REwordboundary, - REnotwordboundary, - REdigit, - REnotdigit, - REspace, - REnotspace, - REword, - REnotword, - REbackref, -}; - -// BUG: should this include '$'? -private int isword(dchar c) { return isalnum(c) || c == '_'; } - -private uint inf = ~0u; - -/* ******************************** - * Throws RegExpException on error - */ - -public void compile(rchar[] pattern, rchar[] attributes) -{ - //printf("RegExp.compile('%.*s', '%.*s')\n", pattern, attributes); - - this.attributes = 0; - foreach (rchar c; attributes) - { REA att; - - switch (c) - { - case 'g': att = REA.global; break; - case 'i': att = REA.ignoreCase; break; - case 'm': att = REA.multiline; break; - default: - error("unrecognized attribute"); - return; - } - if (this.attributes & att) - { error("redundant attribute"); - return; - } - this.attributes |= att; - } - - input = null; - - this.pattern = pattern; - this.flags = attributes; - - uint oldre_nsub = re_nsub; - re_nsub = 0; - errors = 0; - - buf = new OutBuffer(); - buf.reserve(pattern.length * 8); - p = 0; - parseRegexp(); - if (p < pattern.length) - { error("unmatched ')'"); - } - optimize(); - program = buf.data; - buf.data = null; - delete buf; - - if (re_nsub > oldre_nsub) - { - if (pmatch.ptr is &gmatch) - pmatch = null; - pmatch.length = re_nsub + 1; - } - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = 0; -} - -/******************************************** - * Split string[] into an array of strings, using the regular - * expression as the separator. - * Returns: - * array of slices into string[] - */ - -public rchar[][] split(rchar[] string) -{ - debug(regexp) printf("regexp.split()\n"); - - rchar[][] result; - - if (string.length) - { - int p = 0; - int q; - for (q = p; q != string.length;) - { - if (test(string, q)) - { int e; - - q = pmatch[0].rm_so; - e = pmatch[0].rm_eo; - if (e != p) - { - result ~= string[p .. q]; - for (int i = 1; i < pmatch.length; i++) - { - int so = pmatch[i].rm_so; - int eo = pmatch[i].rm_eo; - if (so == eo) - { so = 0; // -1 gives array bounds error - eo = 0; - } - result ~= string[so .. eo]; - } - q = p = e; - continue; - } - } - q++; - } - result ~= string[p .. string.length]; - } - else if (!test(string)) - result ~= string; - return result; -} - -unittest -{ - debug(regexp) printf("regexp.split.unittest()\n"); - - auto r = new RegExp("a*?", null); - rchar[][] result; - rchar[] j; - int i; - - result = r.split("ab"); - - assert(result.length == 2); - i = std.string.cmp(result[0], "a"); - assert(i == 0); - i = std.string.cmp(result[1], "b"); - assert(i == 0); - - r = new RegExp("a*", null); - result = r.split("ab"); - assert(result.length == 2); - i = std.string.cmp(result[0], ""); - assert(i == 0); - i = std.string.cmp(result[1], "b"); - assert(i == 0); - - r = new RegExp("<(\\/)?([^<>]+)>", null); - result = r.split("afontbarhello"); - - for (i = 0; i < result.length; i++) - { - //debug(regexp) printf("result[%d] = '%.*s'\n", i, result[i]); - } - - j = join(result, ","); - //printf("j = '%.*s'\n", j); - i = std.string.cmp(j, "a,,b,font,/,b,bar,,TAG,hello,/,TAG,"); - assert(i == 0); - - r = new RegExp("a[bc]", null); - result = r.match("123ab"); - j = join(result, ","); - i = std.string.cmp(j, "ab"); - assert(i == 0); - - result = r.match("ac"); - j = join(result, ","); - i = std.string.cmp(j, "ac"); - assert(i == 0); -} - -/************************************************* - * Search string[] for match with regular expression. - * Returns: - * index of match if successful, -1 if not found - */ - -public int find(rchar[] string) -{ - int i; - - i = test(string); - if (i) - i = pmatch[0].rm_so; - else - i = -1; // no match - return i; -} - -//deprecated alias find search; - -unittest -{ - debug(regexp) printf("regexp.find.unittest()\n"); - - int i; - RegExp r = new RegExp("abc", null); - i = r.find("xabcy"); - assert(i == 1); - i = r.find("cba"); - assert(i == -1); -} - - -/************************************************* - * Search string[] for match. - * Returns: - * If global attribute, return same value as exec(string). - * If not global attribute, return array of all matches. - */ - -public rchar[][] match(rchar[] string) -{ - rchar[][] result; - - if (attributes & REA.global) - { - int lastindex = 0; - - while (test(string, lastindex)) - { int eo = pmatch[0].rm_eo; - - result ~= input[pmatch[0].rm_so .. eo]; - if (lastindex == eo) - lastindex++; // always consume some source - else - lastindex = eo; - } - } - else - { - result = exec(string); - } - return result; -} - -unittest -{ - debug(regexp) printf("regexp.match.unittest()\n"); - - int i; - rchar[][] result; - rchar[] j; - RegExp r; - - r = new RegExp("a[bc]", null); - result = r.match("1ab2ac3"); - j = join(result, ","); - i = std.string.cmp(j, "ab"); - assert(i == 0); - - r = new RegExp("a[bc]", "g"); - result = r.match("1ab2ac3"); - j = join(result, ","); - i = std.string.cmp(j, "ab,ac"); - assert(i == 0); -} - - -/************************************************* - * Find regular expression matches in string[]. Replace those matches - * with a new _string composed of format[] merged with the result of the - * matches. - * If global, replace all matches. Otherwise, replace first match. - * Returns: the new _string - */ - -public rchar[] replace(rchar[] string, rchar[] format) -{ - rchar[] result; - int lastindex; - int offset; - - result = string; - lastindex = 0; - offset = 0; - for (;;) - { - if (!test(string, lastindex)) - break; - - int so = pmatch[0].rm_so; - int eo = pmatch[0].rm_eo; - - rchar[] replacement = replace(format); - - // Optimize by using std.string.replace if possible - Dave Fladebo - rchar[] slice = result[offset + so .. offset + eo]; - if (attributes & REA.global && // global, so replace all - !(attributes & REA.ignoreCase) && // not ignoring case - !(attributes & REA.multiline) && // not multiline - pattern == slice && // simple pattern (exact match, no special characters) - format == replacement) // simple format, not $ formats - { - debug(regexp) - printf("pattern: %.*s, slice: %.*s, format: %.*s, replacement: %.*s\n", - cast(int) pattern.length, pattern.ptr, - cast(int) (eo-so), result.ptr + offset, - cast(int) format.length, format.ptr, - cast(int) replacement.length, replacement.ptr); - result = std.string.replace(result,slice,replacement); - break; - } - - result = replaceSlice(result, result[offset + so .. offset + eo], replacement); - - if (attributes & REA.global) - { - offset += replacement.length - (eo - so); - - if (lastindex == eo) - lastindex++; // always consume some source - else - lastindex = eo; - } - else - break; - } - - return result; -} - -unittest -{ - debug(regexp) printf("regexp.replace.unittest()\n"); - - int i; - rchar[] result; - RegExp r; - - r = new RegExp("a[bc]", "g"); - result = r.replace("1ab2ac3", "x$&y"); - i = std.string.cmp(result, "1xaby2xacy3"); - assert(i == 0); - - r = new RegExp("ab", "g"); - result = r.replace("1ab2ac3", "xy"); - i = std.string.cmp(result, "1xy2ac3"); - assert(i == 0); -} - - -/************************************************* - * Search string[] for match. - * Returns: - * array of slices into string[] representing matches - */ - -public rchar[][] exec(rchar[] string) -{ - debug(regexp) printf("regexp.exec(string = '%.*s')\n", - cast(int) string.length, string.ptr); - input = string; - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = 0; - return exec(); -} - -/************************************************* - * Pick up where last exec(string) or exec() left off, - * searching string[] for next match. - * Returns: - * array of slices into string[] representing matches - */ - -public rchar[][] exec() -{ - if (!test()) - return null; - - auto result = new rchar[][pmatch.length]; - for (int i = 0; i < pmatch.length; i++) - { - if (pmatch[i].rm_so == pmatch[i].rm_eo) - result[i] = null; - else - result[i] = input[pmatch[i].rm_so .. pmatch[i].rm_eo]; - } - - return result; -} - -/************************************************ - * Search string[] for match. - * Returns: 0 for no match, !=0 for match - * Example: ---- -import std.stdio; -import std.regexp; -import std.string; - -int grep(int delegate(char[]) pred, char[][] list) -{ - int count; - foreach (s; list) - { if (pred(s)) - ++count; - } - return count; -} - -void main() -{ - auto x = grep(&RegExp("[Ff]oo").test, - std.string.split("mary had a foo lamb")); - writefln(x); -} ---- - * which prints: 1 - */ - -public int test(rchar[] string) -{ - return test(string, 0 /*pmatch[0].rm_eo*/); -} - -/************************************************ - * Pick up where last test(string) or test() left off, and search again. - * Returns: 0 for no match, !=0 for match - */ - -public int test() -{ - return test(input, pmatch[0].rm_eo); -} - -/************************************************ - * Test string[] starting at startindex against regular expression. - * Returns: 0 for no match, !=0 for match - */ - -public int test(char[] string, int startindex) -{ - char firstc; - uint si; - - input = string; - debug (regexp) printf("RegExp.test(input[] = '%.*s', startindex = %d)\n", - cast(int) input.length, input.ptr, startindex); - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = 0; - if (startindex < 0 || startindex > input.length) - { - return 0; // fail - } - //debug(regexp) printProgram(program); - - // First character optimization - firstc = 0; - if (program[0] == REchar) - { - firstc = program[1]; - if (attributes & REA.ignoreCase && isalpha(firstc)) - firstc = 0; - } - - for (si = startindex; ; si++) - { - if (firstc) - { - if (si == input.length) - break; // no match - if (input[si] != firstc) - { - si++; - if (!chr(si, firstc)) // if first character not found - break; // no match - } - } - for (int i = 0; i < re_nsub + 1; i++) - { - pmatch[i].rm_so = -1; - pmatch[i].rm_eo = -1; - } - src_start = src = si; - if (trymatch(0, program.length)) - { - pmatch[0].rm_so = si; - pmatch[0].rm_eo = src; - //debug(regexp) printf("start = %d, end = %d\n", gmatch.rm_so, gmatch.rm_eo); - return 1; - } - // If possible match must start at beginning, we are done - if (program[0] == REbol || program[0] == REanystar) - { - if (attributes & REA.multiline) - { - // Scan for the next \n - if (!chr(si, '\n')) - break; // no match if '\n' not found - } - else - break; - } - if (si == input.length) - break; - //debug(regexp) printf("Starting new try: '%.*s'\n", input[si + 1 .. input.length]); - } - return 0; // no match -} - -int chr(inout uint si, rchar c) -{ - for (; si < input.length; si++) - { - if (input[si] == c) - return 1; - } - return 0; -} - - -void printProgram(ubyte[] prog) -{ - //debug(regexp) - { - uint pc; - uint len; - uint n; - uint m; - ushort *pu; - uint *puint; - ubyte[] s; - - printf("printProgram()\n"); - for (pc = 0; pc < prog.length; ) - { - printf("%3d: ", pc); - - //printf("prog[pc] = %d, REchar = %d, REnmq = %d\n", prog[pc], REchar, REnmq); - switch (prog[pc]) - { - case REchar: - printf("\tREchar '%c'\n", prog[pc + 1]); - pc += 1 + char.sizeof; - break; - - case REichar: - printf("\tREichar '%c'\n", prog[pc + 1]); - pc += 1 + char.sizeof; - break; - - case REdchar: - printf("\tREdchar '%c'\n", *cast(dchar *)&prog[pc + 1]); - pc += 1 + dchar.sizeof; - break; - - case REidchar: - printf("\tREidchar '%c'\n", *cast(dchar *)&prog[pc + 1]); - pc += 1 + dchar.sizeof; - break; - - case REanychar: - printf("\tREanychar\n"); - pc++; - break; - - case REstring: - len = *cast(uint *)&prog[pc + 1]; - s = (&prog[pc + 1 + uint.sizeof])[0 .. len]; - printf("\tREstring x%x, '%.*s'\n", len, - cast(int) s.length, s.ptr); - pc += 1 + uint.sizeof + len * rchar.sizeof; - break; - - case REistring: - len = *cast(uint *)&prog[pc + 1]; - s = (&prog[pc + 1 + uint.sizeof])[0 .. len]; - printf("\tREistring x%x, '%.*s'\n", len, - cast(int) s.length, s.ptr); - pc += 1 + uint.sizeof + len * rchar.sizeof; - break; - - case REtestbit: - pu = cast(ushort *)&prog[pc + 1]; - printf("\tREtestbit %d, %d\n", pu[0], pu[1]); - len = pu[1]; - pc += 1 + 2 * ushort.sizeof + len; - break; - - case REbit: - pu = cast(ushort *)&prog[pc + 1]; - len = pu[1]; - printf("\tREbit cmax=%02x, len=%d:", pu[0], len); - for (n = 0; n < len; n++) - printf(" %02x", prog[pc + 1 + 2 * ushort.sizeof + n]); - printf("\n"); - pc += 1 + 2 * ushort.sizeof + len; - break; - - case REnotbit: - pu = cast(ushort *)&prog[pc + 1]; - printf("\tREnotbit %d, %d\n", pu[0], pu[1]); - len = pu[1]; - pc += 1 + 2 * ushort.sizeof + len; - break; - - case RErange: - len = *cast(uint *)&prog[pc + 1]; - printf("\tRErange %d\n", len); - // BUG: REAignoreCase? - pc += 1 + uint.sizeof + len; - break; - - case REnotrange: - len = *cast(uint *)&prog[pc + 1]; - printf("\tREnotrange %d\n", len); - // BUG: REAignoreCase? - pc += 1 + uint.sizeof + len; - break; - - case REbol: - printf("\tREbol\n"); - pc++; - break; - - case REeol: - printf("\tREeol\n"); - pc++; - break; - - case REor: - len = *cast(uint *)&prog[pc + 1]; - printf("\tREor %d, pc=>%d\n", len, pc + 1 + uint.sizeof + len); - pc += 1 + uint.sizeof; - break; - - case REgoto: - len = *cast(uint *)&prog[pc + 1]; - printf("\tREgoto %d, pc=>%d\n", len, pc + 1 + uint.sizeof + len); - pc += 1 + uint.sizeof; - break; - - case REanystar: - printf("\tREanystar\n"); - pc++; - break; - - case REnm: - case REnmq: - // len, n, m, () - puint = cast(uint *)&prog[pc + 1]; - len = puint[0]; - n = puint[1]; - m = puint[2]; - printf("\tREnm%s len=%d, n=%u, m=%u, pc=>%d\n", - (prog[pc] == REnmq) ? cast(char*)"q" : cast(char*)" ", - len, n, m, pc + 1 + uint.sizeof * 3 + len); - pc += 1 + uint.sizeof * 3; - break; - - case REparen: - // len, n, () - puint = cast(uint *)&prog[pc + 1]; - len = puint[0]; - n = puint[1]; - printf("\tREparen len=%d n=%d, pc=>%d\n", len, n, pc + 1 + uint.sizeof * 2 + len); - pc += 1 + uint.sizeof * 2; - break; - - case REend: - printf("\tREend\n"); - return; - - case REwordboundary: - printf("\tREwordboundary\n"); - pc++; - break; - - case REnotwordboundary: - printf("\tREnotwordboundary\n"); - pc++; - break; - - case REdigit: - printf("\tREdigit\n"); - pc++; - break; - - case REnotdigit: - printf("\tREnotdigit\n"); - pc++; - break; - - case REspace: - printf("\tREspace\n"); - pc++; - break; - - case REnotspace: - printf("\tREnotspace\n"); - pc++; - break; - - case REword: - printf("\tREword\n"); - pc++; - break; - - case REnotword: - printf("\tREnotword\n"); - pc++; - break; - - case REbackref: - printf("\tREbackref %d\n", prog[1]); - pc += 2; - break; - - default: - assert(0); - } - } - } -} - - -/************************************************** - * Match input against a section of the program[]. - * Returns: - * 1 if successful match - * 0 no match - */ - -int trymatch(int pc, int pcend) -{ int srcsave; - uint len; - uint n; - uint m; - uint count; - uint pop; - uint ss; - regmatch_t *psave; - uint c1; - uint c2; - ushort* pu; - uint* puint; - - debug(regexp) - { - char[] s = input[src .. input.length]; - printf("RegExp.trymatch(pc = %d, src = '%.*s', pcend = %d)\n", - pc, cast(int) s.length, s.ptr, pcend); - } - srcsave = src; - psave = null; - for (;;) - { - if (pc == pcend) // if done matching - { debug(regex) printf("\tprogend\n"); - return 1; - } - - //printf("\top = %d\n", program[pc]); - switch (program[pc]) - { - case REchar: - if (src == input.length) - goto Lnomatch; - debug(regexp) printf("\tREchar '%c', src = '%c'\n", program[pc + 1], input[src]); - if (program[pc + 1] != input[src]) - goto Lnomatch; - src++; - pc += 1 + char.sizeof; - break; - - case REichar: - if (src == input.length) - goto Lnomatch; - debug(regexp) printf("\tREichar '%c', src = '%c'\n", program[pc + 1], input[src]); - c1 = program[pc + 1]; - c2 = input[src]; - if (c1 != c2) - { - if (islower(cast(rchar)c2)) - c2 = std.ctype.toupper(cast(rchar)c2); - else - goto Lnomatch; - if (c1 != c2) - goto Lnomatch; - } - src++; - pc += 1 + char.sizeof; - break; - - case REdchar: - debug(regexp) printf("\tREdchar '%c', src = '%c'\n", *(cast(dchar *)&program[pc + 1]), input[src]); - if (src == input.length) - goto Lnomatch; - if (*(cast(dchar *)&program[pc + 1]) != input[src]) - goto Lnomatch; - src++; - pc += 1 + dchar.sizeof; - break; - - case REidchar: - debug(regexp) printf("\tREidchar '%c', src = '%c'\n", *(cast(dchar *)&program[pc + 1]), input[src]); - if (src == input.length) - goto Lnomatch; - c1 = *(cast(dchar *)&program[pc + 1]); - c2 = input[src]; - if (c1 != c2) - { - if (islower(cast(rchar)c2)) - c2 = std.ctype.toupper(cast(rchar)c2); - else - goto Lnomatch; - if (c1 != c2) - goto Lnomatch; - } - src++; - pc += 1 + dchar.sizeof; - break; - - case REanychar: - debug(regexp) printf("\tREanychar\n"); - if (src == input.length) - goto Lnomatch; - if (!(attributes & REA.dotmatchlf) && input[src] == cast(rchar)'\n') - goto Lnomatch; - src += std.utf.stride(input, src); - //src++; - pc++; - break; - - case REstring: - len = *cast(uint *)&program[pc + 1]; - debug(regexp) - { - char[] s = (&program[pc + 1 + uint.sizeof])[0 .. len]; - printf("\tREstring x%x, '%.*s'\n", len, - cast(int) s.length, s.ptr); - } - if (src + len > input.length) - goto Lnomatch; - if (memcmp(&program[pc + 1 + uint.sizeof], &input[src], len * rchar.sizeof)) - goto Lnomatch; - src += len; - pc += 1 + uint.sizeof + len * rchar.sizeof; - break; - - case REistring: - len = *cast(uint *)&program[pc + 1]; - debug(regexp) - { - char[] s = (&program[pc + 1 + uint.sizeof])[0 .. len]; - printf("\tREistring x%x, '%.*s'\n", len, - cast(int) s.length, s.ptr); - } - if (src + len > input.length) - goto Lnomatch; - version (Win32) - { - if (memicmp(cast(char*)&program[pc + 1 + uint.sizeof], &input[src], len * rchar.sizeof)) - goto Lnomatch; - } - else - { - if (icmp((cast(char*)&program[pc + 1 + uint.sizeof])[0..len], - input[src .. src + len])) - goto Lnomatch; - } - src += len; - pc += 1 + uint.sizeof + len * rchar.sizeof; - break; - - case REtestbit: - pu = (cast(ushort *)&program[pc + 1]); - debug(regexp) printf("\tREtestbit %d, %d, '%c', x%02x\n", - pu[0], pu[1], input[src], input[src]); - if (src == input.length) - goto Lnomatch; - len = pu[1]; - c1 = input[src]; - //printf("[x%02x]=x%02x, x%02x\n", c1 >> 3, ((&program[pc + 1 + 4])[c1 >> 3] ), (1 << (c1 & 7))); - if (c1 <= pu[0] && - !bt(cast(uint*)&(program[pc + 1 + 4]), c1)) // assumes BitArray implementation - goto Lnomatch; - pc += 1 + 2 * ushort.sizeof + len; - break; - - case REbit: - pu = (cast(ushort *)&program[pc + 1]); - debug(regexp) printf("\tREbit %d, %d, '%c'\n", - pu[0], pu[1], input[src]); - if (src == input.length) - goto Lnomatch; - len = pu[1]; - c1 = input[src]; - if (c1 > pu[0]) - goto Lnomatch; - if (!bt(cast(uint*)&(program[pc + 1 + 4]), c1)) // assumes BitArray implementation - goto Lnomatch; - src++; - pc += 1 + 2 * ushort.sizeof + len; - break; - - case REnotbit: - pu = (cast(ushort *)&program[pc + 1]); - debug(regexp) printf("\tREnotbit %d, %d, '%c'\n", - pu[0], pu[1], input[src]); - if (src == input.length) - goto Lnomatch; - len = pu[1]; - c1 = input[src]; - if (c1 <= pu[0] && - bt(cast(uint*)&(program[pc + 1 + 4]), c1)) // assumes BitArray implementation - goto Lnomatch; - src++; - pc += 1 + 2 * ushort.sizeof + len; - break; - - case RErange: - len = *cast(uint *)&program[pc + 1]; - debug(regexp) printf("\tRErange %d\n", len); - if (src == input.length) - goto Lnomatch; - // BUG: REA.ignoreCase? - if (memchr(cast(char*)&program[pc + 1 + uint.sizeof], input[src], len) == null) - goto Lnomatch; - src++; - pc += 1 + uint.sizeof + len; - break; - - case REnotrange: - len = *cast(uint *)&program[pc + 1]; - debug(regexp) printf("\tREnotrange %d\n", len); - if (src == input.length) - goto Lnomatch; - // BUG: REA.ignoreCase? - if (memchr(cast(char*)&program[pc + 1 + uint.sizeof], input[src], len) != null) - goto Lnomatch; - src++; - pc += 1 + uint.sizeof + len; - break; - - case REbol: - debug(regexp) printf("\tREbol\n"); - if (src == 0) - { - } - else if (attributes & REA.multiline) - { - if (input[src - 1] != '\n') - goto Lnomatch; - } - else - goto Lnomatch; - pc++; - break; - - case REeol: - debug(regexp) printf("\tREeol\n"); - if (src == input.length) - { - } - else if (attributes & REA.multiline && input[src] == '\n') - src++; - else - goto Lnomatch; - pc++; - break; - - case REor: - len = (cast(uint *)&program[pc + 1])[0]; - debug(regexp) printf("\tREor %d\n", len); - pop = pc + 1 + uint.sizeof; - ss = src; - if (trymatch(pop, pcend)) - { - if (pcend != program.length) - { int s; - - s = src; - if (trymatch(pcend, program.length)) - { debug(regexp) printf("\tfirst operand matched\n"); - src = s; - return 1; - } - else - { - // If second branch doesn't match to end, take first anyway - src = ss; - if (!trymatch(pop + len, program.length)) - { - debug(regexp) printf("\tfirst operand matched\n"); - src = s; - return 1; - } - } - src = ss; - } - else - { debug(regexp) printf("\tfirst operand matched\n"); - return 1; - } - } - pc = pop + len; // proceed with 2nd branch - break; - - case REgoto: - debug(regexp) printf("\tREgoto\n"); - len = (cast(uint *)&program[pc + 1])[0]; - pc += 1 + uint.sizeof + len; - break; - - case REanystar: - debug(regexp) printf("\tREanystar\n"); - pc++; - for (;;) - { int s1; - int s2; - - s1 = src; - if (src == input.length) - break; - if (!(attributes & REA.dotmatchlf) && input[src] == '\n') - break; - src++; - s2 = src; - - // If no match after consumption, but it - // did match before, then no match - if (!trymatch(pc, program.length)) - { - src = s1; - // BUG: should we save/restore pmatch[]? - if (trymatch(pc, program.length)) - { - src = s1; // no match - break; - } - } - src = s2; - } - break; - - case REnm: - case REnmq: - // len, n, m, () - puint = cast(uint *)&program[pc + 1]; - len = puint[0]; - n = puint[1]; - m = puint[2]; - debug(regexp) printf("\tREnm%s len=%d, n=%u, m=%u\n", (program[pc] == REnmq) ? cast(char*)"q" : cast(char*)"", len, n, m); - pop = pc + 1 + uint.sizeof * 3; - for (count = 0; count < n; count++) - { - if (!trymatch(pop, pop + len)) - goto Lnomatch; - } - if (!psave && count < m) - { - //version (Win32) - psave = cast(regmatch_t *)/*alloca*/malloc((re_nsub + 1) * regmatch_t.sizeof); - //else - //psave = new regmatch_t[re_nsub + 1]; - } - if (program[pc] == REnmq) // if minimal munch - { - for (; count < m; count++) - { int s1; - - memcpy(psave, pmatch.ptr, (re_nsub + 1) * regmatch_t.sizeof); - s1 = src; - - if (trymatch(pop + len, program.length)) - { - src = s1; - memcpy(pmatch.ptr, psave, (re_nsub + 1) * regmatch_t.sizeof); - break; - } - - if (!trymatch(pop, pop + len)) - { debug(regexp) printf("\tdoesn't match subexpression\n"); - break; - } - - // If source is not consumed, don't - // infinite loop on the match - if (s1 == src) - { debug(regexp) printf("\tsource is not consumed\n"); - break; - } - } - } - else // maximal munch - { - for (; count < m; count++) - { int s1; - int s2; - - memcpy(psave, pmatch.ptr, (re_nsub + 1) * regmatch_t.sizeof); - s1 = src; - if (!trymatch(pop, pop + len)) - { debug(regexp) printf("\tdoesn't match subexpression\n"); - break; - } - s2 = src; - - // If source is not consumed, don't - // infinite loop on the match - if (s1 == s2) - { debug(regexp) printf("\tsource is not consumed\n"); - break; - } - - // If no match after consumption, but it - // did match before, then no match - if (!trymatch(pop + len, program.length)) - { - src = s1; - if (trymatch(pop + len, program.length)) - { - src = s1; // no match - memcpy(pmatch.ptr, psave, (re_nsub + 1) * regmatch_t.sizeof); - break; - } - } - src = s2; - } - } - debug(regexp) printf("\tREnm len=%d, n=%u, m=%u, DONE count=%d\n", len, n, m, count); - pc = pop + len; - break; - - case REparen: - // len, () - debug(regexp) printf("\tREparen\n"); - puint = cast(uint *)&program[pc + 1]; - len = puint[0]; - n = puint[1]; - pop = pc + 1 + uint.sizeof * 2; - ss = src; - if (!trymatch(pop, pop + len)) - goto Lnomatch; - pmatch[n + 1].rm_so = ss; - pmatch[n + 1].rm_eo = src; - pc = pop + len; - break; - - case REend: - debug(regexp) printf("\tREend\n"); - return 1; // successful match - - case REwordboundary: - debug(regexp) printf("\tREwordboundary\n"); - if (src > 0 && src < input.length) - { - c1 = input[src - 1]; - c2 = input[src]; - if (!( - (isword(cast(rchar)c1) && !isword(cast(rchar)c2)) || - (!isword(cast(rchar)c1) && isword(cast(rchar)c2)) - ) - ) - goto Lnomatch; - } - pc++; - break; - - case REnotwordboundary: - debug(regexp) printf("\tREnotwordboundary\n"); - if (src == 0 || src == input.length) - goto Lnomatch; - c1 = input[src - 1]; - c2 = input[src]; - if ( - (isword(cast(rchar)c1) && !isword(cast(rchar)c2)) || - (!isword(cast(rchar)c1) && isword(cast(rchar)c2)) - ) - goto Lnomatch; - pc++; - break; - - case REdigit: - debug(regexp) printf("\tREdigit\n"); - if (src == input.length) - goto Lnomatch; - if (!isdigit(input[src])) - goto Lnomatch; - src++; - pc++; - break; - - case REnotdigit: - debug(regexp) printf("\tREnotdigit\n"); - if (src == input.length) - goto Lnomatch; - if (isdigit(input[src])) - goto Lnomatch; - src++; - pc++; - break; - - case REspace: - debug(regexp) printf("\tREspace\n"); - if (src == input.length) - goto Lnomatch; - if (!isspace(input[src])) - goto Lnomatch; - src++; - pc++; - break; - - case REnotspace: - debug(regexp) printf("\tREnotspace\n"); - if (src == input.length) - goto Lnomatch; - if (isspace(input[src])) - goto Lnomatch; - src++; - pc++; - break; - - case REword: - debug(regexp) printf("\tREword\n"); - if (src == input.length) - goto Lnomatch; - if (!isword(input[src])) - goto Lnomatch; - src++; - pc++; - break; - - case REnotword: - debug(regexp) printf("\tREnotword\n"); - if (src == input.length) - goto Lnomatch; - if (isword(input[src])) - goto Lnomatch; - src++; - pc++; - break; - - case REbackref: - { - n = program[pc + 1]; - debug(regexp) printf("\tREbackref %d\n", n); - - int so = pmatch[n + 1].rm_so; - int eo = pmatch[n + 1].rm_eo; - len = eo - so; - if (src + len > input.length) - goto Lnomatch; - else if (attributes & REA.ignoreCase) - { - if (icmp(input[src .. src + len], input[so .. eo])) - goto Lnomatch; - } - else if (memcmp(&input[src], &input[so], len * rchar.sizeof)) - goto Lnomatch; - src += len; - pc += 2; - break; - } - - default: - assert(0); - } - } - -Lnomatch: - debug(regexp) printf("\tnomatch pc=%d\n", pc); - src = srcsave; - return 0; -} - -/* =================== Compiler ================== */ - -int parseRegexp() -{ uint offset; - uint gotooffset; - uint len1; - uint len2; - - //printf("parseRegexp() '%.*s'\n", pattern[p .. pattern.length]); - offset = buf.offset; - for (;;) - { - assert(p <= pattern.length); - if (p == pattern.length) - { buf.write(REend); - return 1; - } - switch (pattern[p]) - { - case ')': - return 1; - - case '|': - p++; - gotooffset = buf.offset; - buf.write(REgoto); - buf.write(cast(uint)0); - len1 = buf.offset - offset; - buf.spread(offset, 1 + uint.sizeof); - gotooffset += 1 + uint.sizeof; - parseRegexp(); - len2 = buf.offset - (gotooffset + 1 + uint.sizeof); - buf.data[offset] = REor; - (cast(uint *)&buf.data[offset + 1])[0] = len1; - (cast(uint *)&buf.data[gotooffset + 1])[0] = len2; - break; - - default: - parsePiece(); - break; - } - } - assert(0); -} - -int parsePiece() -{ uint offset; - uint len; - uint n; - uint m; - ubyte op; - int plength = pattern.length; - - //printf("parsePiece() '%.*s'\n", pattern[p .. pattern.length]); - offset = buf.offset; - parseAtom(); - if (p == plength) - return 1; - switch (pattern[p]) - { - case '*': - // Special optimization: replace .* with REanystar - if (buf.offset - offset == 1 && - buf.data[offset] == REanychar && - p + 1 < plength && - pattern[p + 1] != '?') - { - buf.data[offset] = REanystar; - p++; - break; - } - - n = 0; - m = inf; - goto Lnm; - - case '+': - n = 1; - m = inf; - goto Lnm; - - case '?': - n = 0; - m = 1; - goto Lnm; - - case '{': // {n} {n,} {n,m} - p++; - if (p == plength || !isdigit(pattern[p])) - goto Lerr; - n = 0; - do - { - // BUG: handle overflow - n = n * 10 + pattern[p] - '0'; - p++; - if (p == plength) - goto Lerr; - } while (isdigit(pattern[p])); - if (pattern[p] == '}') // {n} - { m = n; - goto Lnm; - } - if (pattern[p] != ',') - goto Lerr; - p++; - if (p == plength) - goto Lerr; - if (pattern[p] == /*{*/ '}') // {n,} - { m = inf; - goto Lnm; - } - if (!isdigit(pattern[p])) - goto Lerr; - m = 0; // {n,m} - do - { - // BUG: handle overflow - m = m * 10 + pattern[p] - '0'; - p++; - if (p == plength) - goto Lerr; - } while (isdigit(pattern[p])); - if (pattern[p] != /*{*/ '}') - goto Lerr; - goto Lnm; - - Lnm: - p++; - op = REnm; - if (p < plength && pattern[p] == '?') - { op = REnmq; // minimal munch version - p++; - } - len = buf.offset - offset; - buf.spread(offset, 1 + uint.sizeof * 3); - buf.data[offset] = op; - uint* puint = cast(uint *)&buf.data[offset + 1]; - puint[0] = len; - puint[1] = n; - puint[2] = m; - break; - - default: - break; - } - return 1; - -Lerr: - error("badly formed {n,m}"); - assert(0); -} - -int parseAtom() -{ ubyte op; - uint offset; - rchar c; - - //printf("parseAtom() '%.*s'\n", pattern[p .. pattern.length]); - if (p < pattern.length) - { - c = pattern[p]; - switch (c) - { - case '*': - case '+': - case '?': - error("*+? not allowed in atom"); - p++; - return 0; - - case '(': - p++; - buf.write(REparen); - offset = buf.offset; - buf.write(cast(uint)0); // reserve space for length - buf.write(re_nsub); - re_nsub++; - parseRegexp(); - *cast(uint *)&buf.data[offset] = - buf.offset - (offset + uint.sizeof * 2); - if (p == pattern.length || pattern[p] != ')') - { - error("')' expected"); - return 0; - } - p++; - break; - - case '[': - if (!parseRange()) - return 0; - break; - - case '.': - p++; - buf.write(REanychar); - break; - - case '^': - p++; - buf.write(REbol); - break; - - case '$': - p++; - buf.write(REeol); - break; - - case '\\': - p++; - if (p == pattern.length) - { error("no character past '\\'"); - return 0; - } - c = pattern[p]; - switch (c) - { - case 'b': op = REwordboundary; goto Lop; - case 'B': op = REnotwordboundary; goto Lop; - case 'd': op = REdigit; goto Lop; - case 'D': op = REnotdigit; goto Lop; - case 's': op = REspace; goto Lop; - case 'S': op = REnotspace; goto Lop; - case 'w': op = REword; goto Lop; - case 'W': op = REnotword; goto Lop; - - Lop: - buf.write(op); - p++; - break; - - case 'f': - case 'n': - case 'r': - case 't': - case 'v': - case 'c': - case 'x': - case 'u': - case '0': - c = cast(char)escape(); - goto Lbyte; - - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': - c -= '1'; - if (c < re_nsub) - { buf.write(REbackref); - buf.write(cast(ubyte)c); - } - else - { error("no matching back reference"); - return 0; - } - p++; - break; - - default: - p++; - goto Lbyte; - } - break; - - default: - p++; - Lbyte: - op = REchar; - if (attributes & REA.ignoreCase) - { - if (isalpha(c)) - { - op = REichar; - c = cast(char)std.ctype.toupper(c); - } - } - if (op == REchar && c <= 0xFF) - { - // Look ahead and see if we can make this into - // an REstring - int q; - int len; - - for (q = p; q < pattern.length; ++q) - { rchar qc = pattern[q]; - - switch (qc) - { - case '{': - case '*': - case '+': - case '?': - if (q == p) - goto Lchar; - q--; - break; - - case '(': case ')': - case '|': - case '[': case ']': - case '.': case '^': - case '$': case '\\': - case '}': - break; - - default: - continue; - } - break; - } - len = q - p; - if (len > 0) - { - debug(regexp) printf("writing string len %d, c = '%c', pattern[p] = '%c'\n", len+1, c, pattern[p]); - buf.reserve(5 + (1 + len) * rchar.sizeof); - buf.write((attributes & REA.ignoreCase) ? REistring : REstring); - buf.write(len + 1); - buf.write(c); - buf.write(pattern[p .. p + len]); - p = q; - break; - } - } - if (c >= 0x80) - { - // Convert to dchar opcode - op = (op == REchar) ? REdchar : REidchar; - buf.write(op); - buf.write(c); - } - else - { - Lchar: - debug(regexp) printf("It's an REchar '%c'\n", c); - buf.write(op); - buf.write(cast(char)c); - } - break; - } - } - return 1; -} - -private: -class Range -{ - uint maxc; - uint maxb; - OutBuffer buf; - ubyte* base; - BitArray bits; - - this(OutBuffer buf) - { - this.buf = buf; - if (buf.data.length) - this.base = &buf.data[buf.offset]; - } - - void setbitmax(uint u) - { uint b; - - //printf("setbitmax(x%x), maxc = x%x\n", u, maxc); - if (u > maxc) - { - maxc = u; - b = u / 8; - if (b >= maxb) - { uint u2; - - u2 = base ? base - &buf.data[0] : 0; - ++b; - version (BigEndian) - { - while (b & (uint.sizeof-1)) - ++b; - } - - buf.fill0(b - maxb); - base = &buf.data[u2]; - maxb = b; - // %% moved array recreate out of this condition - bits.ptr = cast(uint*)this.base; - } - //bits = (cast(bit*)this.base)[0 .. maxc + 1]; - bits.len = maxc + 1; - } - } - - void setbit2(uint u) - { - setbitmax(u + 1); - //printf("setbit2 [x%02x] |= x%02x\n", u >> 3, 1 << (u & 7)); - bits[u] = 1; - } - -}; - -int parseRange() -{ ubyte op; - int c; - int c2; - uint i; - uint cmax; - uint offset; - - cmax = 0x7F; - p++; - op = REbit; - if (p == pattern.length) - goto Lerr; - if (pattern[p] == '^') - { p++; - op = REnotbit; - if (p == pattern.length) - goto Lerr; - } - buf.write(op); - offset = buf.offset; - buf.write(cast(uint)0); // reserve space for length - buf.reserve(128 / 8); - auto r = new Range(buf); - if (op == REnotbit) - r.setbit2(0); - switch (pattern[p]) - { - case ']': - case '-': - c = pattern[p]; - p++; - r.setbit2(c); - break; - - default: - break; - } - - enum RS { start, rliteral, dash }; - RS rs; - - rs = RS.start; - for (;;) - { - if (p == pattern.length) - goto Lerr; - switch (pattern[p]) - { - case ']': - switch (rs) - { case RS.dash: - r.setbit2('-'); - case RS.rliteral: - r.setbit2(c); - break; - case RS.start: - break; - default: - assert(0); - } - p++; - break; - - case '\\': - p++; - r.setbitmax(cmax); - if (p == pattern.length) - goto Lerr; - switch (pattern[p]) - { - case 'd': - for (i = '0'; i <= '9'; i++) - r.bits[i] = 1; - goto Lrs; - - case 'D': - for (i = 1; i < '0'; i++) - r.bits[i] = 1; - for (i = '9' + 1; i <= cmax; i++) - r.bits[i] = 1; - goto Lrs; - - case 's': - for (i = 0; i <= cmax; i++) - if (isspace(i)) - r.bits[i] = 1; - goto Lrs; - - case 'S': - for (i = 1; i <= cmax; i++) - if (!isspace(i)) - r.bits[i] = 1; - goto Lrs; - - case 'w': - for (i = 0; i <= cmax; i++) - if (isword(cast(rchar)i)) - r.bits[i] = 1; - goto Lrs; - - case 'W': - for (i = 1; i <= cmax; i++) - if (!isword(cast(rchar)i)) - r.bits[i] = 1; - goto Lrs; - - Lrs: - switch (rs) - { case RS.dash: - r.setbit2('-'); - case RS.rliteral: - r.setbit2(c); - break; - default: - break; - } - rs = RS.start; - continue; - - default: - break; - } - c2 = escape(); - goto Lrange; - - case '-': - p++; - if (rs == RS.start) - goto Lrange; - else if (rs == RS.rliteral) - rs = RS.dash; - else if (rs == RS.dash) - { - r.setbit2(c); - r.setbit2('-'); - rs = RS.start; - } - continue; - - default: - c2 = pattern[p]; - p++; - Lrange: - switch (rs) - { case RS.rliteral: - r.setbit2(c); - case RS.start: - c = c2; - rs = RS.rliteral; - break; - - case RS.dash: - if (c > c2) - { error("inverted range in character class"); - return 0; - } - r.setbitmax(c2); - //printf("c = %x, c2 = %x\n",c,c2); - for (; c <= c2; c++) - r.bits[c] = 1; - rs = RS.start; - break; - - default: - assert(0); - } - continue; - } - break; - } - if (attributes & REA.ignoreCase) - { - // BUG: what about dchar? - r.setbitmax(0x7F); - for (c = 'a'; c <= 'z'; c++) - { - if (r.bits[c]) - r.bits[c + 'A' - 'a'] = 1; - else if (r.bits[c + 'A' - 'a']) - r.bits[c] = 1; - } - } - //printf("maxc = %d, maxb = %d\n",r.maxc,r.maxb); - (cast(ushort *)&buf.data[offset])[0] = cast(ushort)r.maxc; - (cast(ushort *)&buf.data[offset])[1] = cast(ushort)r.maxb; - return 1; - -Lerr: - error("invalid range"); - return 0; -} - -void error(char[] msg) -{ - errors++; - debug(regexp) printf("error: %.*s\n", cast(int) msg.length, msg.ptr); -//assert(0); -//*(char*)0=0; - throw new RegExpException(msg); -} - -// p is following the \ char -int escape() -in -{ - assert(p < pattern.length); -} -body -{ int c; - int i; - rchar tc; - - c = pattern[p]; // none of the cases are multibyte - switch (c) - { - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - - // BUG: Perl does \a and \e too, should we? - - case 'c': - ++p; - if (p == pattern.length) - goto Lretc; - c = pattern[p]; - // Note: we are deliberately not allowing dchar letters - if (!(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))) - { - Lcerr: - error("letter expected following \\c"); - return 0; - } - c &= 0x1F; - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - c -= '0'; - for (i = 0; i < 2; i++) - { - p++; - if (p == pattern.length) - goto Lretc; - tc = pattern[p]; - if ('0' <= tc && tc <= '7') - { c = c * 8 + (tc - '0'); - // Treat overflow as if last - // digit was not an octal digit - if (c >= 0xFF) - { c >>= 3; - return c; - } - } - else - return c; - } - break; - - case 'x': - c = 0; - for (i = 0; i < 2; i++) - { - p++; - if (p == pattern.length) - goto Lretc; - tc = pattern[p]; - if ('0' <= tc && tc <= '9') - c = c * 16 + (tc - '0'); - else if ('a' <= tc && tc <= 'f') - c = c * 16 + (tc - 'a' + 10); - else if ('A' <= tc && tc <= 'F') - c = c * 16 + (tc - 'A' + 10); - else if (i == 0) // if no hex digits after \x - { - // Not a valid \xXX sequence - return 'x'; - } - else - return c; - } - break; - - case 'u': - c = 0; - for (i = 0; i < 4; i++) - { - p++; - if (p == pattern.length) - goto Lretc; - tc = pattern[p]; - if ('0' <= tc && tc <= '9') - c = c * 16 + (tc - '0'); - else if ('a' <= tc && tc <= 'f') - c = c * 16 + (tc - 'a' + 10); - else if ('A' <= tc && tc <= 'F') - c = c * 16 + (tc - 'A' + 10); - else - { - // Not a valid \uXXXX sequence - p -= i; - return 'u'; - } - } - break; - - default: - break; - } - p++; -Lretc: - return c; -} - -/* ==================== optimizer ======================= */ - -void optimize() -{ ubyte[] prog; - - debug(regexp) printf("RegExp.optimize()\n"); - prog = buf.toBytes(); - for (size_t i = 0; 1;) - { - //printf("\tprog[%d] = %d, %d\n", i, prog[i], REstring); - switch (prog[i]) - { - case REend: - case REanychar: - case REanystar: - case REbackref: - case REeol: - case REchar: - case REichar: - case REdchar: - case REidchar: - case REstring: - case REistring: - case REtestbit: - case REbit: - case REnotbit: - case RErange: - case REnotrange: - case REwordboundary: - case REnotwordboundary: - case REdigit: - case REnotdigit: - case REspace: - case REnotspace: - case REword: - case REnotword: - return; - - case REbol: - i++; - continue; - - case REor: - case REnm: - case REnmq: - case REparen: - case REgoto: - { - auto bitbuf = new OutBuffer; - auto r = new Range(bitbuf); - uint offset; - - offset = i; - if (starrchars(r, prog[i .. prog.length])) - { - debug(regexp) printf("\tfilter built\n"); - buf.spread(offset, 1 + 4 + r.maxb); - buf.data[offset] = REtestbit; - (cast(ushort *)&buf.data[offset + 1])[0] = cast(ushort)r.maxc; - (cast(ushort *)&buf.data[offset + 1])[1] = cast(ushort)r.maxb; - i = offset + 1 + 4; - buf.data[i .. i + r.maxb] = r.base[0 .. r.maxb]; - } - return; - } - default: - assert(0); - } - } -} - -///////////////////////////////////////// -// OR the leading character bits into r. -// Limit the character range from 0..7F, -// trymatch() will allow through anything over maxc. -// Return 1 if success, 0 if we can't build a filter or -// if there is no point to one. - -int starrchars(Range r, ubyte[] prog) -{ rchar c; - uint maxc; - uint maxb; - uint len; - uint b; - uint n; - uint m; - ubyte* pop; - - //printf("RegExp.starrchars(prog = %p, progend = %p)\n", prog, progend); - for (size_t i = 0; i < prog.length;) - { - switch (prog[i]) - { - case REchar: - c = prog[i + 1]; - if (c <= 0x7F) - r.setbit2(c); - return 1; - - case REichar: - c = prog[i + 1]; - if (c <= 0x7F) - { r.setbit2(c); - r.setbit2(std.ctype.tolower(cast(rchar)c)); - } - return 1; - - case REdchar: - case REidchar: - return 1; - - case REanychar: - return 0; // no point - - case REstring: - len = *cast(uint *)&prog[i + 1]; - assert(len); - c = *cast(rchar *)&prog[i + 1 + uint.sizeof]; - debug(regexp) printf("\tREstring %d, '%c'\n", len, c); - if (c <= 0x7F) - r.setbit2(c); - return 1; - - case REistring: - len = *cast(uint *)&prog[i + 1]; - assert(len); - c = *cast(rchar *)&prog[i + 1 + uint.sizeof]; - debug(regexp) printf("\tREistring %d, '%c'\n", len, c); - if (c <= 0x7F) - { r.setbit2(std.ctype.toupper(cast(rchar)c)); - r.setbit2(std.ctype.tolower(cast(rchar)c)); - } - return 1; - - case REtestbit: - case REbit: - maxc = (cast(ushort *)&prog[i + 1])[0]; - maxb = (cast(ushort *)&prog[i + 1])[1]; - if (maxc <= 0x7F) - r.setbitmax(maxc); - else - maxb = r.maxb; - for (b = 0; b < maxb; b++) - r.base[b] |= prog[i + 1 + 4 + b]; - return 1; - - case REnotbit: - maxc = (cast(ushort *)&prog[i + 1])[0]; - maxb = (cast(ushort *)&prog[i + 1])[1]; - if (maxc <= 0x7F) - r.setbitmax(maxc); - else - maxb = r.maxb; - for (b = 0; b < maxb; b++) - r.base[b] |= ~prog[i + 1 + 4 + b]; - return 1; - - case REbol: - case REeol: - return 0; - - case REor: - len = (cast(uint *)&prog[i + 1])[0]; - return starrchars(r, prog[i + 1 + uint.sizeof .. prog.length]) && - starrchars(r, prog[i + 1 + uint.sizeof + len .. prog.length]); - - case REgoto: - len = (cast(uint *)&prog[i + 1])[0]; - i += 1 + uint.sizeof + len; - break; - - case REanystar: - return 0; - - case REnm: - case REnmq: - // len, n, m, () - len = (cast(uint *)&prog[i + 1])[0]; - n = (cast(uint *)&prog[i + 1])[1]; - m = (cast(uint *)&prog[i + 1])[2]; - pop = &prog[i + 1 + uint.sizeof * 3]; - if (!starrchars(r, pop[0 .. len])) - return 0; - if (n) - return 1; - i += 1 + uint.sizeof * 3 + len; - break; - - case REparen: - // len, () - len = (cast(uint *)&prog[i + 1])[0]; - n = (cast(uint *)&prog[i + 1])[1]; - pop = &prog[0] + i + 1 + uint.sizeof * 2; - return starrchars(r, pop[0 .. len]); - - case REend: - return 0; - - case REwordboundary: - case REnotwordboundary: - return 0; - - case REdigit: - r.setbitmax('9'); - for (c = '0'; c <= '9'; c++) - r.bits[c] = 1; - return 1; - - case REnotdigit: - r.setbitmax(0x7F); - for (c = 0; c <= '0'; c++) - r.bits[c] = 1; - for (c = '9' + 1; c <= r.maxc; c++) - r.bits[c] = 1; - return 1; - - case REspace: - r.setbitmax(0x7F); - for (c = 0; c <= r.maxc; c++) - if (isspace(c)) - r.bits[c] = 1; - return 1; - - case REnotspace: - r.setbitmax(0x7F); - for (c = 0; c <= r.maxc; c++) - if (!isspace(c)) - r.bits[c] = 1; - return 1; - - case REword: - r.setbitmax(0x7F); - for (c = 0; c <= r.maxc; c++) - if (isword(cast(rchar)c)) - r.bits[c] = 1; - return 1; - - case REnotword: - r.setbitmax(0x7F); - for (c = 0; c <= r.maxc; c++) - if (!isword(cast(rchar)c)) - r.bits[c] = 1; - return 1; - - case REbackref: - return 0; - - default: - assert(0); - } - } - return 1; -} - -/* ==================== replace ======================= */ - -/*********************** - * After a match is found with test(), this function - * will take the match results and, using the format - * string, generate and return a new string. - */ - -public rchar[] replace(rchar[] format) -{ - return replace3(format, input, pmatch[0 .. re_nsub + 1]); -} - -// Static version that doesn't require a RegExp object to be created - -public static rchar[] replace3(rchar[] format, rchar[] input, regmatch_t[] pmatch) -{ - rchar[] result; - uint c2; - int rm_so; - int rm_eo; - int i; - -// printf("replace3(format = '%.*s', input = '%.*s')\n", format, input); - result.length = format.length; - result.length = 0; - for (size_t f = 0; f < format.length; f++) - { - auto c = format[f]; - L1: - if (c != '$') - { - result ~= c; - continue; - } - ++f; - if (f == format.length) - { - result ~= '$'; - break; - } - c = format[f]; - switch (c) - { - case '&': - rm_so = pmatch[0].rm_so; - rm_eo = pmatch[0].rm_eo; - goto Lstring; - - case '`': - rm_so = 0; - rm_eo = pmatch[0].rm_so; - goto Lstring; - - case '\'': - rm_so = pmatch[0].rm_eo; - rm_eo = input.length; - goto Lstring; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - i = c - '0'; - if (f + 1 == format.length) - { - if (i == 0) - { - result ~= '$'; - result ~= c; - continue; - } - } - else - { - c2 = format[f + 1]; - if (c2 >= '0' && c2 <= '9') - { i = (c - '0') * 10 + (c2 - '0'); - f++; - } - if (i == 0) - { - result ~= '$'; - result ~= c; - c = cast(char)c2; - goto L1; - } - } - - if (i < pmatch.length) - { rm_so = pmatch[i].rm_so; - rm_eo = pmatch[i].rm_eo; - goto Lstring; - } - break; - - Lstring: - if (rm_so != rm_eo) - result ~= input[rm_so .. rm_eo]; - break; - - default: - result ~= '$'; - result ~= c; - break; - } - } - return result; -} - -/************************************ - * Like replace(char[] format), but uses old style formatting: - - - - - - - -
Format - Description -
& - replace with the match -
\n - replace with the nth parenthesized match, n is 1..9 -
\c - replace with char c. -
- */ - -public rchar[] replaceOld(rchar[] format) -{ - rchar[] result; - -//printf("replace: this = %p so = %d, eo = %d\n", this, pmatch[0].rm_so, pmatch[0].rm_eo); -//printf("3input = '%.*s'\n", input); - result.length = format.length; - result.length = 0; - for (size_t i; i < format.length; i++) - { - auto c = format[i]; - switch (c) - { - case '&': -//printf("match = '%.*s'\n", input[pmatch[0].rm_so .. pmatch[0].rm_eo]); - result ~= input[pmatch[0].rm_so .. pmatch[0].rm_eo]; - break; - - case '\\': - if (i + 1 < format.length) - { - c = format[++i]; - if (c >= '1' && c <= '9') - { uint j; - - j = c - '0'; - if (j <= re_nsub && pmatch[j].rm_so != pmatch[j].rm_eo) - result ~= input[pmatch[j].rm_so .. pmatch[j].rm_eo]; - break; - } - } - result ~= c; - break; - - default: - result ~= c; - break; - } - } - return result; -} - -} - -unittest -{ // Created and placed in public domain by Don Clugston - - auto m = search("aBC r s", `bc\x20r[\40]s`, "i"); - assert(m.pre=="a"); - assert(m.match(0)=="BC r s"); - auto m2 = search("7xxyxxx", `^\d([a-z]{2})\D\1`); - assert(m2.match(0)=="7xxyxx"); - // Just check the parsing. - auto m3 = search("dcbxx", `ca|b[\d\]\D\s\S\w-\W]`); - auto m4 = search("xy", `[^\ca-\xFa\r\n\b\f\t\v\0123]{2,485}$`); - auto m5 = search("xxx", `^^\r\n\b{13,}\f{4}\t\v\u02aF3a\w\W`); - auto m6 = search("xxy", `.*y`); - assert(m6.match(0)=="xxy"); - auto m7 = search("QWDEfGH", "(ca|b|defg)+", "i"); - assert(m7.match(0)=="DEfG"); - auto m8 = search("dcbxx", `a?\B\s\S`); - auto m9 = search("dcbxx", `[-w]`); - auto m10 = search("dcbsfd", `aB[c-fW]dB|\d|\D|\u012356|\w|\W|\s|\S`, "i"); - auto m11 = search("dcbsfd", `[]a-]`); - m.replaceOld(`a&b\1c`); - m.replace(`a$&b$'$1c`); -} diff --git a/lphobos/std/socket.d b/lphobos/std/socket.d deleted file mode 100644 index 11d87f0603e..00000000000 --- a/lphobos/std/socket.d +++ /dev/null @@ -1,1666 +0,0 @@ -// Written in the D programming language - -/* - Copyright (C) 2004-2005 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. - - socket.d 1.3 - Jan 2005 - - Thanks to Benjamin Herr for his assistance. -*/ - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, April 2005 -*/ - -/** - * Notes: For Win32 systems, link with ws2_32.lib. - * Example: See /dmd/samples/d/listener.d. - * Authors: Christopher E. Miller - * Macros: - * WIKI=Phobos/StdSocket - */ - -module std.socket; - -private import std.string, std.stdint, std.c.string, std.c.stdlib; - -version(linux) version = Unix; -version(Unix) version = BsdSockets; - -version (skyos) { /* nothging */ } -else -{ - version = have_getservbyport; - version = have_getprotobynumber; -} - - -version(Win32) -{ - private import std.c.windows.windows, std.c.windows.winsock; - private alias std.c.windows.winsock.timeval _ctimeval; - - typedef SOCKET socket_t = INVALID_SOCKET; - private const int _SOCKET_ERROR = SOCKET_ERROR; - - - private int _lasterr() - { - return WSAGetLastError(); - } -} -else version(BsdSockets) -{ - version (Unix) - { - version(linux) { - import std.c.linux.socket, std.c.linux.linux; - const AF_UNSPEC=0, AF_UNIX=1, AF_INET=2, AF_IPX=4, AF_APPLETALK=5; - const MSG_NOSIGNAL=16384; - const FD_SETSIZE=64; - alias std.c.linux.linux.timeval _ctimeval; - } else { - import std.c.unix.unix; - alias std.c.unix.unix.timeval _ctimeval; - } - } - - typedef int32_t socket_t = -1; - private const int _SOCKET_ERROR = -1; - - - private int _lasterr() - { - return getErrno(); - } -} -else -{ - static assert(0); // No socket support yet. -} - - -extern(C) char* strerror_r(int errnum, char* buf, size_t buflen); -/// Base exception thrown from a Socket. -class SocketException: Exception -{ - int errorCode; /// Platform-specific error code. - - this(string msg, int err = 0) - { - errorCode = err; - - version(Unix) - { - if(errorCode > 0) - { - char[80] buf; - auto cs = strerror_r(errorCode, buf.ptr, buf.length); - auto len = strlen(cs); - - if(cs[len - 1] == '\n') - len--; - if(cs[len - 1] == '\r') - len--; - msg = msg ~ ": " ~ cs[0 .. len]; - } - } - - super(msg); - } -} - - -static this() -{ - version(Win32) - { - WSADATA wd; - - // Winsock will still load if an older version is present. - // The version is just a request. - int val; - val = WSAStartup(0x2020, &wd); - if(val) // Request Winsock 2.2 for IPv6. - throw new SocketException("Unable to initialize socket library", val); - } -} - - -static ~this() -{ - version(Win32) - { - WSACleanup(); - } -} - -/** - * The communication domain used to resolve an address. - */ -enum AddressFamily: int -{ - UNSPEC = AF_UNSPEC, /// - UNIX = AF_UNIX, /// local communication - INET = AF_INET, /// internet protocol version 4 - IPX = AF_IPX, /// novell IPX - APPLETALK = AF_APPLETALK, /// appletalk - INET6 = AF_INET6, // internet protocol version 6 -} - - -/** - * Communication semantics - */ -enum SocketType: int -{ - STREAM = SOCK_STREAM, /// sequenced, reliable, two-way communication-based byte streams - DGRAM = SOCK_DGRAM, /// connectionless, unreliable datagrams with a fixed maximum length; data may be lost or arrive out of order - RAW = SOCK_RAW, /// raw protocol access - RDM = SOCK_RDM, /// reliably-delivered message datagrams - SEQPACKET = SOCK_SEQPACKET, /// sequenced, reliable, two-way connection-based datagrams with a fixed maximum length -} - - -/** - * Protocol - */ -enum ProtocolType: int -{ - IP = IPPROTO_IP, /// internet protocol version 4 - ICMP = IPPROTO_ICMP, /// internet control message protocol - IGMP = IPPROTO_IGMP, /// internet group management protocol - GGP = IPPROTO_GGP, /// gateway to gateway protocol - TCP = IPPROTO_TCP, /// transmission control protocol - PUP = IPPROTO_PUP, /// PARC universal packet protocol - UDP = IPPROTO_UDP, /// user datagram protocol - IDP = IPPROTO_IDP, /// Xerox NS protocol - IPV6 = IPPROTO_IPV6, /// internet protocol version 6 -} - - -/** - * Protocol is a class for retrieving protocol information. - */ -class Protocol -{ - ProtocolType type; /// These members are populated when one of the following functions are called without failure: - string name; /// ditto - string[] aliases; /// ditto - - - void populate(protoent* proto) - { - type = cast(ProtocolType)proto.p_proto; - name = std.string.toString(proto.p_name).dup; - - int i; - for(i = 0;; i++) - { - if(!proto.p_aliases[i]) - break; - } - - if(i) - { - aliases = new string[i]; - for(i = 0; i != aliases.length; i++) - { - aliases[i] = std.string.toString(proto.p_aliases[i]).dup; - } - } - else - { - aliases = null; - } - } - - /** Returns false on failure */ - bool getProtocolByName(string name) - { - protoent* proto; - proto = getprotobyname(toStringz(name)); - if(!proto) - return false; - populate(proto); - return true; - } - - - /** Returns false on failure */ - // Same as getprotobynumber(). - bool getProtocolByType(ProtocolType type) - { - version (have_getprotobynumber) - { - protoent* proto; - proto = getprotobynumber(type); - if(!proto) - return false; - populate(proto); - return true; - } - else - return false; - } -} - - -unittest -{ - Protocol proto = new Protocol; - assert(proto.getProtocolByType(ProtocolType.TCP)); - printf("About protocol TCP:\n\tName: %.*s\n", - cast(int) proto.name.length, proto.name.ptr); - foreach(string s; proto.aliases) - { - printf("\tAlias: %.*s\n", cast(int) s.length, s.ptr); - } -} - - -/** - * Service is a class for retrieving service information. - */ -class Service -{ - /** These members are populated when one of the following functions are called without failure: */ - string name; - string[] aliases; /// ditto - ushort port; /// ditto - string protocolName; /// ditto - - - void populate(servent* serv) - { - name = std.string.toString(serv.s_name).dup; - port = ntohs(cast(ushort)serv.s_port); - protocolName = std.string.toString(serv.s_proto).dup; - - int i; - for(i = 0;; i++) - { - if(!serv.s_aliases[i]) - break; - } - - if(i) - { - aliases = new string[i]; - for(i = 0; i != aliases.length; i++) - { - aliases[i] = std.string.toString(serv.s_aliases[i]).dup; - } - } - else - { - aliases = null; - } - } - - /** - * If a protocol name is omitted, any protocol will be matched. - * Returns: false on failure. - */ - bool getServiceByName(string name, string protocolName) - { - servent* serv; - serv = getservbyname(toStringz(name), toStringz(protocolName)); - if(!serv) - return false; - populate(serv); - return true; - } - - - // Any protocol name will be matched. - /// ditto - bool getServiceByName(string name) - { - servent* serv; - serv = getservbyname(toStringz(name), null); - if(!serv) - return false; - populate(serv); - return true; - } - - - /// ditto - bool getServiceByPort(ushort port, string protocolName) - { - version (have_getservbyport) - { - servent* serv; - serv = getservbyport(port, toStringz(protocolName)); - if(!serv) - return false; - populate(serv); - return true; - } - else - return false; - } - - - // Any protocol name will be matched. - /// ditto - bool getServiceByPort(ushort port) - { - version (have_getservbyport) - { - servent* serv; - serv = getservbyport(port, null); - if(!serv) - return false; - populate(serv); - return true; - } - else - return false; - } -} - - -unittest -{ - Service serv = new Service; - if(serv.getServiceByName("epmap", "tcp")) - { - printf("About service epmap:\n\tService: %.*s\n\tPort: %d\n\tProtocol: %.*s\n", - cast(int) serv.name.length, serv.name.ptr, serv.port, - cast(int) serv.protocolName.length, serv.protocolName.ptr); - foreach(char[] s; serv.aliases) - { - printf("\tAlias: %.*s\n", cast(int) s.length, s.ptr); - } - } - else - { - printf("No service for epmap.\n"); - } -} - - -/** - * Base exception thrown from an InternetHost. - */ -class HostException: Exception -{ - int errorCode; /// Platform-specific error code. - - - this(string msg, int err = 0) - { - errorCode = err; - super(msg); - } -} - -/** - * InternetHost is a class for resolving IPv4 addresses. - */ -class InternetHost -{ - /** These members are populated when one of the following functions are called without failure: */ - string name; - string[] aliases; /// ditto - uint32_t[] addrList; /// ditto - - - void validHostent(hostent* he) - { - if(he.h_addrtype != cast(int)AddressFamily.INET || he.h_length != 4) - throw new HostException("Address family mismatch", _lasterr()); - } - - - void populate(hostent* he) - { - int i; - char* p; - - name = std.string.toString(he.h_name).dup; - - for(i = 0;; i++) - { - p = he.h_aliases[i]; - if(!p) - break; - } - - if(i) - { - aliases = new string[i]; - for(i = 0; i != aliases.length; i++) - { - aliases[i] = std.string.toString(he.h_aliases[i]).dup; - } - } - else - { - aliases = null; - } - - for(i = 0;; i++) - { - p = he.h_addr_list[i]; - if(!p) - break; - } - - if(i) - { - addrList = new uint32_t[i]; - for(i = 0; i != addrList.length; i++) - { - addrList[i] = ntohl(*(cast(uint32_t*)he.h_addr_list[i])); - } - } - else - { - addrList = null; - } - } - - /** - * Resolve host name. Returns false if unable to resolve. - */ - bool getHostByName(string name) - { - hostent* he; - synchronized(this.classinfo) he = gethostbyname(toStringz(name)); - if(!he) - return false; - validHostent(he); - populate(he); - return true; - } - - - /** - * Resolve IPv4 address number. Returns false if unable to resolve. - */ - bool getHostByAddr(uint addr) - { - uint x = htonl(addr); - hostent* he; - synchronized(this.classinfo) he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET); - if(!he) - return false; - validHostent(he); - populate(he); - return true; - } - - - /** - * Same as previous, but addr is an IPv4 address string in the - * dotted-decimal form $(I a.b.c.d). - * Returns false if unable to resolve. - */ - bool getHostByAddr(string addr) - { - uint x = inet_addr(std.string.toStringz(addr)); - hostent* he; - synchronized(this.classinfo) he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET); - if(!he) - return false; - validHostent(he); - populate(he); - return true; - } -} - - -unittest -{ - InternetHost ih = new InternetHost; - assert(ih.getHostByName("www.digitalmars.com")); - printf("addrList.length = %d\n", ih.addrList.length); - assert(ih.addrList.length); - InternetAddress ia = new InternetAddress(ih.addrList[0], InternetAddress.PORT_ANY); - char[] sia = ia.toAddrString(); - printf("IPaddress = %.*s\nname = %.*s\n", cast(int) sia.length, sia.ptr, - cast(int) ih.name.length, ih.name.ptr); - foreach(int i, string s; ih.aliases) - { - printf("aliases[%d] = %.*s\n", i, cast(int) s.length, s.ptr); - } - - printf("---\n"); - - assert(ih.getHostByAddr(ih.addrList[0])); - printf("name = %.*s\n", cast(int) ih.name.length, ih.name.ptr); - foreach(int i, string s; ih.aliases) - { - printf("aliases[%d] = %.*s\n", i, cast(int) s.length, s.ptr); - } -} - - -/** - * Base exception thrown from an Address. - */ -class AddressException: Exception -{ - this(string msg) - { - super(msg); - } -} - - -/** - * Address is an abstract class for representing a network addresses. - */ -abstract class Address -{ - protected sockaddr* name(); - protected int nameLen(); - AddressFamily addressFamily(); /// Family of this address. - string toString(); /// Human readable string representing this address. -} - -/** - * - */ -class UnknownAddress: Address -{ - protected: - sockaddr sa; - - - sockaddr* name() - { - return &sa; - } - - - int nameLen() - { - return sa.sizeof; - } - - - public: - AddressFamily addressFamily() - { - return cast(AddressFamily)sa.sa_family; - } - - - string toString() - { - return "Unknown"; - } -} - - -/** - * InternetAddress is a class that represents an IPv4 (internet protocol version - * 4) address and port. - */ -class InternetAddress: Address -{ - protected: - sockaddr_in sin; - - - sockaddr* name() - { - return cast(sockaddr*)&sin; - } - - - int nameLen() - { - return sin.sizeof; - } - - - this() - { - } - - - public: - const uint ADDR_ANY = INADDR_ANY; /// Any IPv4 address number. - const uint ADDR_NONE = INADDR_NONE; /// An invalid IPv4 address number. - const ushort PORT_ANY = 0; /// Any IPv4 port number. - - /// Overridden to return AddressFamily.INET. - AddressFamily addressFamily() - { - return cast(AddressFamily)AddressFamily.INET; - } - - /// Returns the IPv4 port number. - ushort port() - { - return ntohs(sin.sin_port); - } - - /// Returns the IPv4 address number. - uint addr() - { - return ntohl(sin.sin_addr.s_addr); - } - - /** - * Params: - * addr = an IPv4 address string in the dotted-decimal form a.b.c.d, - * or a host name that will be resolved using an InternetHost - * object. - * port = may be PORT_ANY as stated below. - */ - this(string addr, ushort port) - { - uint uiaddr = parse(addr); - if(ADDR_NONE == uiaddr) - { - InternetHost ih = new InternetHost; - if(!ih.getHostByName(addr)) - //throw new AddressException("Invalid internet address"); - throw new AddressException("Unable to resolve host '" ~ addr ~ "'"); - uiaddr = ih.addrList[0]; - } - sin.sin_addr.s_addr = htonl(uiaddr); - sin.sin_port = htons(port); - } - - /** - * Construct a new Address. addr may be ADDR_ANY (default) and port may - * be PORT_ANY, and the actual numbers may not be known until a connection - * is made. - */ - this(uint addr, ushort port) - { - sin.sin_addr.s_addr = htonl(addr); - sin.sin_port = htons(port); - } - - /// ditto - this(ushort port) - { - sin.sin_addr.s_addr = 0; //any, "0.0.0.0" - sin.sin_port = htons(port); - } - - /// Human readable string representing the IPv4 address in dotted-decimal form. - string toAddrString() - { - return std.string.toString(inet_ntoa(sin.sin_addr)).dup; - } - - /// Human readable string representing the IPv4 port. - string toPortString() - { - return std.string.toString(port()); - } - - /// Human readable string representing the IPv4 address and port in the form $(I a.b.c.d:e). - string toString() - { - return toAddrString() ~ ":" ~ toPortString(); - } - - /** - * Parse an IPv4 address string in the dotted-decimal form $(I a.b.c.d) - * and return the number. - * If the string is not a legitimate IPv4 address, - * ADDR_NONE is returned. - */ - static uint parse(string addr) - { - return ntohl(inet_addr(std.string.toStringz(addr))); - } -} - - -unittest -{ - InternetAddress ia = new InternetAddress("63.105.9.61", 80); - assert(ia.toString() == "63.105.9.61:80"); -} - - -/** */ -class SocketAcceptException: SocketException -{ - this(string msg, int err = 0) - { - super(msg, err); - } -} - -/// How a socket is shutdown: -enum SocketShutdown: int -{ - RECEIVE = SD_RECEIVE, /// socket receives are disallowed - SEND = SD_SEND, /// socket sends are disallowed - BOTH = SD_BOTH, /// both RECEIVE and SEND -} - - -/// Flags may be OR'ed together: -enum SocketFlags: int -{ - NONE = 0, /// no flags specified - - OOB = MSG_OOB, /// out-of-band stream data - PEEK = MSG_PEEK, /// peek at incoming data without removing it from the queue, only for receiving - DONTROUTE = MSG_DONTROUTE, /// data should not be subject to routing; this flag may be ignored. Only for sending - NOSIGNAL = MSG_NOSIGNAL, /// don't send SIGPIPE signal on socket write error and instead return EPIPE -} - - -/// Duration timeout value. -extern(C) struct timeval -{ - // D interface - int seconds; /// Number of seconds. - int microseconds; /// Number of additional microseconds. - - // C interface - deprecated - { - alias seconds tv_sec; - alias microseconds tv_usec; - } -} - - -/// A collection of sockets for use with Socket.select. -class SocketSet -{ - private: - uint maxsockets; /// max desired sockets, the fd_set might be capable of holding more - fd_set set; - - - version(Win32) - { - uint count() - { - return set.fd_count; - } - } - else version(BsdSockets) - { - int maxfd; - uint count; - } - - - public: - - /// Set the maximum amount of sockets that may be added. - this(uint max) - { - maxsockets = max; - reset(); - } - - /// Uses the default maximum for the system. - this() - { - this(FD_SETSIZE); - } - - /// Reset the SocketSet so that there are 0 Sockets in the collection. - void reset() - { - FD_ZERO(&set); - - version(BsdSockets) - { - maxfd = -1; - count = 0; - } - } - - - void add(socket_t s) - in - { - // Make sure too many sockets don't get added. - assert(count < maxsockets); - version(BsdSockets) - { - version(GNU) - { - // Tries to account for little and big endian..er needs work - // assert((s/NFDBITS+1)*NFDBITS/8 <= nbytes); - } - else - { - assert(FDELT(s) < (FD_SETSIZE / NFDBITS)); - } - } - } - body - { - FD_SET(s, &set); - - version(BsdSockets) - { - ++count; - if(s > maxfd) - maxfd = s; - } - } - - /// Add a Socket to the collection. Adding more than the maximum has dangerous side affects. - void add(Socket s) - { - add(s.sock); - } - - void remove(socket_t s) - { - FD_CLR(s, &set); - version(BsdSockets) - { - --count; - // note: adjusting maxfd would require scanning the set, not worth it - } - } - - - /// Remove this Socket from the collection. - void remove(Socket s) - { - remove(s.sock); - } - - int isSet(socket_t s) - { - return FD_ISSET(s, &set); - } - - - /// Returns nonzero if this Socket is in the collection. - int isSet(Socket s) - { - return isSet(s.sock); - } - - - /// Return maximum amount of sockets that can be added, like FD_SETSIZE. - uint max() - { - return maxsockets; - } - - - fd_set* toFd_set() - { - return &set; - } - - - int selectn() - { - version(Win32) - { - return count; - } - else version(BsdSockets) - { - return maxfd + 1; - } - } -} - - -/// The level at which a socket option is defined: -enum SocketOptionLevel: int -{ - SOCKET = SOL_SOCKET, /// socket level - IP = ProtocolType.IP, /// internet protocol version 4 level - ICMP = ProtocolType.ICMP, /// - IGMP = ProtocolType.IGMP, /// - GGP = ProtocolType.GGP, /// - TCP = ProtocolType.TCP, /// transmission control protocol level - PUP = ProtocolType.PUP, /// - UDP = ProtocolType.UDP, /// user datagram protocol level - IDP = ProtocolType.IDP, /// - IPV6 = ProtocolType.IPV6, /// internet protocol version 6 level -} - - -/// Linger information for use with SocketOption.LINGER. -extern(C) struct linger -{ - version (BsdSockets) - version (GNU) - { - private alias std.c.unix.unix.linger __unix_linger; - static assert(linger.sizeof == __unix_linger.sizeof); - } - // D interface - version(Win32) - { - uint16_t on; /// Nonzero for on. - uint16_t time; /// Linger time. - } - else version(BsdSockets) - { - version (GNU) - { - - typeof(__unix_linger.l_onoff) on; - typeof(__unix_linger.l_linger) time; - - } - else - { - int32_t on; - int32_t time; - } - } - - // C interface - deprecated - { - alias on l_onoff; - alias time l_linger; - } -} - - -/// Specifies a socket option: -enum SocketOption: int -{ - DEBUG = SO_DEBUG, /// record debugging information - BROADCAST = SO_BROADCAST, /// allow transmission of broadcast messages - REUSEADDR = SO_REUSEADDR, /// allow local reuse of address - LINGER = SO_LINGER, /// linger on close if unsent data is present - OOBINLINE = SO_OOBINLINE, /// receive out-of-band data in band - SNDBUF = SO_SNDBUF, /// send buffer size - RCVBUF = SO_RCVBUF, /// receive buffer size - DONTROUTE = SO_DONTROUTE, /// do not route - - // SocketOptionLevel.TCP: - TCP_NODELAY = .TCP_NODELAY, /// disable the Nagle algorithm for send coalescing - - // SocketOptionLevel.IPV6: - IPV6_UNICAST_HOPS = .IPV6_UNICAST_HOPS, /// - IPV6_MULTICAST_IF = .IPV6_MULTICAST_IF, /// - IPV6_MULTICAST_LOOP = .IPV6_MULTICAST_LOOP, /// - IPV6_JOIN_GROUP = .IPV6_JOIN_GROUP, /// - IPV6_LEAVE_GROUP = .IPV6_LEAVE_GROUP, /// -} - - -/** - * Socket is a class that creates a network communication endpoint using the - * Berkeley sockets interface. - */ -class Socket -{ - private: - socket_t sock; - AddressFamily _family; - - version(Win32) - bool _blocking = false; /// Property to get or set whether the socket is blocking or nonblocking. - - - // For use with accepting(). - protected this() - { - } - - - public: - - /** - * Create a blocking socket. If a single protocol type exists to support - * this socket type within the address family, the ProtocolType may be - * omitted. - */ - this(AddressFamily af, SocketType type, ProtocolType protocol) - { - sock = cast(socket_t)socket(af, type, protocol); - if(sock == socket_t.init) - throw new SocketException("Unable to create socket", _lasterr()); - _family = af; - } - - - // A single protocol exists to support this socket type within the - // protocol family, so the ProtocolType is assumed. - /// ditto - this(AddressFamily af, SocketType type) - { - this(af, type, cast(ProtocolType)0); // Pseudo protocol number. - } - - - /// ditto - this(AddressFamily af, SocketType type, string protocolName) - { - protoent* proto; - proto = getprotobyname(toStringz(protocolName)); - if(!proto) - throw new SocketException("Unable to find the protocol", _lasterr()); - this(af, type, cast(ProtocolType)proto.p_proto); - } - - - ~this() - { - close(); - } - - - /// Get underlying socket handle. - socket_t handle() - { - return sock; - } - - /** - * Get/set socket's blocking flag. - * - * When a socket is blocking, calls to receive(), accept(), and send() - * will block and wait for data/action. - * A non-blocking socket will immediately return instead of blocking. - */ - bool blocking() - { - version(Win32) - { - return _blocking; - } - else version(BsdSockets) - { - return !(fcntl(handle, F_GETFL, 0) & O_NONBLOCK); - } - } - - /// ditto - void blocking(bool byes) - { - version(Win32) - { - uint num = !byes; - if(_SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &num)) - goto err; - _blocking = byes; - } - else version(BsdSockets) - { - int x = fcntl(sock, F_GETFL, 0); - if(-1 == x) - goto err; - if(byes) - x &= ~O_NONBLOCK; - else - x |= O_NONBLOCK; - if(-1 == fcntl(sock, F_SETFL, x)) - goto err; - } - return; // Success. - - err: - throw new SocketException("Unable to set socket blocking", _lasterr()); - } - - - /// Get the socket's address family. - AddressFamily addressFamily() // getter - { - return _family; - } - - /// Property that indicates if this is a valid, alive socket. - bool isAlive() // getter - { - int type, typesize = type.sizeof; - return !getsockopt(sock, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize); - } - - /// Associate a local address with this socket. - void bind(Address addr) - { - if(_SOCKET_ERROR == .bind(sock, addr.name(), addr.nameLen())) - throw new SocketException("Unable to bind socket", _lasterr()); - } - - /** - * Establish a connection. If the socket is blocking, connect waits for - * the connection to be made. If the socket is nonblocking, connect - * returns immediately and the connection attempt is still in progress. - */ - void connect(Address to) - { - if(_SOCKET_ERROR == .connect(sock, to.name(), to.nameLen())) - { - int err; - err = _lasterr(); - - if(!blocking) - { - version(Win32) - { - if(WSAEWOULDBLOCK == err) - return; - } - else version(Unix) - { - if(EINPROGRESS == err) - return; - } - else - { - static assert(0); - } - } - throw new SocketException("Unable to connect socket", err); - } - } - - /** - * Listen for an incoming connection. bind must be called before you can - * listen. The backlog is a request of how many pending incoming - * connections are queued until accept'ed. - */ - void listen(int backlog) - { - if(_SOCKET_ERROR == .listen(sock, backlog)) - throw new SocketException("Unable to listen on socket", _lasterr()); - } - - /** - * Called by accept when a new Socket must be created for a new - * connection. To use a derived class, override this method and return an - * instance of your class. The returned Socket's handle must not be set; - * Socket has a protected constructor this() to use in this situation. - */ - // Override to use a derived class. - // The returned socket's handle must not be set. - protected Socket accepting() - { - return new Socket; - } - - /** - * Accept an incoming connection. If the socket is blocking, accept - * waits for a connection request. Throws SocketAcceptException if unable - * to accept. See accepting for use with derived classes. - */ - Socket accept() - { - socket_t newsock; - //newsock = cast(socket_t).accept(sock, null, null); // DMD 0.101 error: found '(' when expecting ';' following 'statement - alias .accept topaccept; - newsock = cast(socket_t)topaccept(sock, null, null); - if(socket_t.init == newsock) - throw new SocketAcceptException("Unable to accept socket connection", _lasterr()); - - Socket newSocket; - try - { - newSocket = accepting(); - assert(newSocket.sock == socket_t.init); - - newSocket.sock = newsock; - version(Win32) - newSocket._blocking = _blocking; //inherits blocking mode - newSocket._family = _family; //same family - } - catch(Object o) - { - _close(newsock); - throw o; - } - - return newSocket; - } - - /// Disables sends and/or receives. - void shutdown(SocketShutdown how) - { - .shutdown(sock, cast(int)how); - } - - - private static void _close(socket_t sock) - { - version(Win32) - { - .closesocket(sock); - } - else version(BsdSockets) - { - .close(sock); - } - } - - - /** - * Immediately drop any connections and release socket resources. - * Calling shutdown before close is recommended for connection-oriented - * sockets. The Socket object is no longer usable after close. - */ - //calling shutdown() before this is recommended - //for connection-oriented sockets - void close() - { - _close(sock); - sock = socket_t.init; - } - - - private Address newFamilyObject() - { - Address result; - switch(_family) - { - case cast(AddressFamily)AddressFamily.INET: - result = new InternetAddress; - break; - - default: - result = new UnknownAddress; - } - return result; - } - - - /// Returns the local machine's host name. Idea from mango. - static string hostName() // getter - { - char[256] result; // Host names are limited to 255 chars. - if(_SOCKET_ERROR == .gethostname(result.ptr, result.length)) - throw new SocketException("Unable to obtain host name", _lasterr()); - return std.string.toString(cast(char*)result).dup; - } - - /// Remote endpoint Address. - Address remoteAddress() - { - Address addr = newFamilyObject(); - int nameLen = addr.nameLen(); - if(_SOCKET_ERROR == .getpeername(sock, addr.name(), &nameLen)) - throw new SocketException("Unable to obtain remote socket address", _lasterr()); - assert(addr.addressFamily() == _family); - return addr; - } - - /// Local endpoint Address. - Address localAddress() - { - Address addr = newFamilyObject(); - int nameLen = addr.nameLen(); - if(_SOCKET_ERROR == .getsockname(sock, addr.name(), &nameLen)) - throw new SocketException("Unable to obtain local socket address", _lasterr()); - assert(addr.addressFamily() == _family); - return addr; - } - - /// Send or receive error code. - const int ERROR = _SOCKET_ERROR; - - /** - * Send data on the connection. Returns the number of bytes actually - * sent, or ERROR on failure. If the socket is blocking and there is no - * buffer space left, send waits. - */ - //returns number of bytes actually sent, or -1 on error - int send(void[] buf, SocketFlags flags) - { - flags |= SocketFlags.NOSIGNAL; - int sent = .send(sock, buf.ptr, buf.length, cast(int)flags); - return sent; - } - - /// ditto - int send(void[] buf) - { - return send(buf, SocketFlags.NOSIGNAL); - } - - /** - * Send data to a specific destination Address. If the destination address is not specified, a connection must have been made and that address is used. If the socket is blocking and there is no buffer space left, sendTo waits. - */ - int sendTo(void[] buf, SocketFlags flags, Address to) - { - flags |= SocketFlags.NOSIGNAL; - int sent = .sendto(sock, buf.ptr, buf.length, cast(int)flags, to.name(), to.nameLen()); - return sent; - } - - /// ditto - int sendTo(void[] buf, Address to) - { - return sendTo(buf, SocketFlags.NONE, to); - } - - - //assumes you connect()ed - /// ditto - int sendTo(void[] buf, SocketFlags flags) - { - flags |= SocketFlags.NOSIGNAL; - int sent = .sendto(sock, buf.ptr, buf.length, cast(int)flags, null, 0); - return sent; - } - - - //assumes you connect()ed - /// ditto - int sendTo(void[] buf) - { - return sendTo(buf, SocketFlags.NONE); - } - - - /** - * Receive data on the connection. Returns the number of bytes actually - * received, 0 if the remote side has closed the connection, or ERROR on - * failure. If the socket is blocking, receive waits until there is data - * to be received. - */ - //returns number of bytes actually received, 0 on connection closure, or -1 on error - int receive(void[] buf, SocketFlags flags) - { - if(!buf.length) //return 0 and don't think the connection closed - return 0; - int read = .recv(sock, buf.ptr, buf.length, cast(int)flags); - // if(!read) //connection closed - return read; - } - - /// ditto - int receive(void[] buf) - { - return receive(buf, SocketFlags.NONE); - } - - /** - * Receive data and get the remote endpoint Address. - * If the socket is blocking, receiveFrom waits until there is data to - * be received. - * Returns: the number of bytes actually received, - * 0 if the remote side has closed the connection, or ERROR on failure. - */ - int receiveFrom(void[] buf, SocketFlags flags, out Address from) - { - if(!buf.length) //return 0 and don't think the connection closed - return 0; - from = newFamilyObject(); - int nameLen = from.nameLen(); - int read = .recvfrom(sock, buf.ptr, buf.length, cast(int)flags, from.name(), &nameLen); - assert(from.addressFamily() == _family); - // if(!read) //connection closed - return read; - } - - - /// ditto - int receiveFrom(void[] buf, out Address from) - { - return receiveFrom(buf, SocketFlags.NONE, from); - } - - - //assumes you connect()ed - /// ditto - int receiveFrom(void[] buf, SocketFlags flags) - { - if(!buf.length) //return 0 and don't think the connection closed - return 0; - int read = .recvfrom(sock, buf.ptr, buf.length, cast(int)flags, null, null); - // if(!read) //connection closed - return read; - } - - - //assumes you connect()ed - /// ditto - int receiveFrom(void[] buf) - { - return receiveFrom(buf, SocketFlags.NONE); - } - - - /// Get a socket option. Returns the number of bytes written to result. - //returns the length, in bytes, of the actual result - very different from getsockopt() - int getOption(SocketOptionLevel level, SocketOption option, void[] result) - { - int len = result.length; - if(_SOCKET_ERROR == .getsockopt(sock, cast(int)level, cast(int)option, result.ptr, &len)) - throw new SocketException("Unable to get socket option", _lasterr()); - return len; - } - - - /// Common case of getting integer and boolean options. - int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) - { - return getOption(level, option, (&result)[0 .. 1]); - } - - - /// Get the linger option. - int getOption(SocketOptionLevel level, SocketOption option, out linger result) - { - //return getOption(cast(SocketOptionLevel)SocketOptionLevel.SOCKET, SocketOption.LINGER, (&result)[0 .. 1]); - return getOption(level, option, (&result)[0 .. 1]); - } - - // Set a socket option. - void setOption(SocketOptionLevel level, SocketOption option, void[] value) - { - if(_SOCKET_ERROR == .setsockopt(sock, cast(int)level, cast(int)option, value.ptr, value.length)) - throw new SocketException("Unable to set socket option", _lasterr()); - } - - - /// Common case for setting integer and boolean options. - void setOption(SocketOptionLevel level, SocketOption option, int32_t value) - { - setOption(level, option, (&value)[0 .. 1]); - } - - - /// Set the linger option. - void setOption(SocketOptionLevel level, SocketOption option, linger value) - { - //setOption(cast(SocketOptionLevel)SocketOptionLevel.SOCKET, SocketOption.LINGER, (&value)[0 .. 1]); - setOption(level, option, (&value)[0 .. 1]); - } - - - /** - * Wait for a socket to change status. A wait timeout timeval or int microseconds may be specified; if a timeout is not specified or the timeval is null, the maximum timeout is used. The timeval timeout has an unspecified value when select returns. Returns the number of sockets with status changes, 0 on timeout, or -1 on interruption. If the return value is greater than 0, the SocketSets are updated to only contain the sockets having status changes. For a connecting socket, a write status change means the connection is established and it's able to send. For a listening socket, a read status change means there is an incoming connection request and it's able to accept. - */ - //SocketSet's updated to include only those sockets which an event occured - //returns the number of events, 0 on timeout, or -1 on interruption - //for a connect()ing socket, writeability means connected - //for a listen()ing socket, readability means listening - //Winsock: possibly internally limited to 64 sockets per set - static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, timeval* tv) - in - { - //make sure none of the SocketSet's are the same object - if(checkRead) - { - assert(checkRead !is checkWrite); - assert(checkRead !is checkError); - } - if(checkWrite) - { - assert(checkWrite !is checkError); - } - } - body - { - fd_set* fr, fw, fe; - int n = 0; - - version(Win32) - { - // Windows has a problem with empty fd_set`s that aren't null. - fr = (checkRead && checkRead.count()) ? checkRead.toFd_set() : null; - fw = (checkWrite && checkWrite.count()) ? checkWrite.toFd_set() : null; - fe = (checkError && checkError.count()) ? checkError.toFd_set() : null; - } - else - { - if(checkRead) - { - fr = checkRead.toFd_set(); - n = checkRead.selectn(); - } - else - { - fr = null; - } - - if(checkWrite) - { - fw = checkWrite.toFd_set(); - int _n; - _n = checkWrite.selectn(); - if(_n > n) - n = _n; - } - else - { - fw = null; - } - - if(checkError) - { - fe = checkError.toFd_set(); - int _n; - _n = checkError.selectn(); - if(_n > n) - n = _n; - } - else - { - fe = null; - } - } - - int result = .select(n, fr, fw, fe, cast(_ctimeval*)tv); - - version(Win32) - { - if(_SOCKET_ERROR == result && WSAGetLastError() == WSAEINTR) - return -1; - } - else version(Unix) - { - if(_SOCKET_ERROR == result && getErrno() == EINTR) - return -1; - } - else - { - static assert(0); - } - - if(_SOCKET_ERROR == result) - throw new SocketException("Socket select error", _lasterr()); - - return result; - } - - - /// ditto - static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, int microseconds) - { - timeval tv; - tv.seconds = 0; - tv.microseconds = microseconds; - return select(checkRead, checkWrite, checkError, &tv); - } - - - /// ditto - //maximum timeout - static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError) - { - return select(checkRead, checkWrite, checkError, null); - } - - - /+ - bool poll(events) - { - int WSAEventSelect(socket_t s, WSAEVENT hEventObject, int lNetworkEvents); // Winsock 2 ? - int poll(pollfd* fds, int nfds, int timeout); // Unix ? - } - +/ -} - - -/// TcpSocket is a shortcut class for a TCP Socket. -class TcpSocket: Socket -{ - /// Constructs a blocking TCP Socket. - this(AddressFamily family) - { - super(family, SocketType.STREAM, ProtocolType.TCP); - } - - /// Constructs a blocking TCP Socket. - this() - { - this(cast(AddressFamily)AddressFamily.INET); - } - - - //shortcut - /// Constructs a blocking TCP Socket and connects to an InternetAddress. - this(Address connectTo) - { - this(connectTo.addressFamily()); - connect(connectTo); - } -} - - -/// UdpSocket is a shortcut class for a UDP Socket. -class UdpSocket: Socket -{ - /// Constructs a blocking UDP Socket. - this(AddressFamily family) - { - super(family, SocketType.DGRAM, ProtocolType.UDP); - } - - - /// Constructs a blocking UDP Socket. - this() - { - this(cast(AddressFamily)AddressFamily.INET); - } -} - diff --git a/lphobos/std/stdarg.d b/lphobos/std/stdarg.d deleted file mode 100644 index c47747ca9ef..00000000000 --- a/lphobos/std/stdarg.d +++ /dev/null @@ -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; -} diff --git a/lphobos/std/stdint.d b/lphobos/std/stdint.d deleted file mode 100644 index c05a0c13e19..00000000000 --- a/lphobos/std/stdint.d +++ /dev/null @@ -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. - stdint offers a portable way of trading off size - vs efficiency, in a manner compatible with the stdint.h - 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: - - - - - - - - - - -
Exact Alias - Description - At Least Alias - Description - Fast Alias - Description -
int8_t - exactly 8 bits signed - int_least8_t - at least 8 bits signed - int_fast8_t - fast 8 bits signed -
uint8_t - exactly 8 bits unsigned - uint_least8_t - at least 8 bits unsigned - uint_fast8_t - fast 8 bits unsigned - -
int16_t - exactly 16 bits signed - int_least16_t - at least 16 bits signed - int_fast16_t - fast 16 bits signed -
uint16_t - exactly 16 bits unsigned - uint_least16_t - at least 16 bits unsigned - uint_fast16_t - fast 16 bits unsigned - -
int32_t - exactly 32 bits signed - int_least32_t - at least 32 bits signed - int_fast32_t - fast 32 bits signed -
uint32_t - exactly 32 bits unsigned - uint_least32_t - at least 32 bits unsigned - uint_fast32_t - fast 32 bits unsigned - -
int64_t - exactly 64 bits signed - int_least64_t - at least 64 bits signed - int_fast64_t - fast 64 bits signed -
uint64_t - exactly 64 bits unsigned - uint_least64_t - at least 64 bits unsigned - uint_fast64_t - fast 64 bits unsigned -
- - The ptr aliases are integral types guaranteed to be large enough - to hold a pointer without losing bits: - - - - -
Alias - Description -
intptr_t - signed integral type large enough to hold a pointer -
uintptr_t - unsigned integral type large enough to hold a pointer -
- - The max aliases are the largest integral types: - - - - -
Alias - Description -
intmax_t - the largest signed integral type -
uintmax_t - the largest unsigned integral type -
- - * 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; - diff --git a/lphobos/std/stdio.d b/lphobos/std/stdio.d deleted file mode 100644 index 3099869d4ce..00000000000 --- a/lphobos/std/stdio.d +++ /dev/null @@ -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); -} - diff --git a/lphobos/std/stream.d b/lphobos/std/stream.d deleted file mode 100644 index ce635308af7..00000000000 --- a/lphobos/std/stream.d +++ /dev/null @@ -1,2965 +0,0 @@ -/** - * Macros: - * WIKI = Phobos/StdStream - */ - -/* - * Copyright (c) 2001-2005 - * Pavel "EvilOne" Minayev - * with buffering and endian support added by Ben Hinkle - * with buffered readLine performance improvements by Dave Fladebo - * with opApply inspired by (and mostly copied from) Regan Heath - * with bug fixes and MemoryStream/SliceStream enhancements by Derick Eddington - * - * 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. - */ - -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - - Modified by David Friedman, April 2005 -*/ - -module std.stream; - -/* Class structure: - * InputStream interface for reading - * OutputStream interface for writing - * Stream abstract base of stream implementations - * File an OS file stream - * FilterStream a base-class for wrappers around another stream - * BufferedStream a buffered stream wrapping another stream - * BufferedFile a buffered File - * EndianStream a wrapper stream for swapping byte order and BOMs - * SliceStream a portion of another stream - * MemoryStream a stream entirely stored in main memory - * TArrayStream a stream wrapping an array-like buffer - */ - -/// A base class for stream exceptions. -class StreamException: Exception { - /// Construct a StreamException with given error message. - this(char[] msg) { super(msg); } -} - -/// Thrown when unable to read data from Stream. -class ReadException: StreamException { - /// Construct a ReadException with given error message. - this(char[] msg) { super(msg); } -} - -/// Thrown when unable to write data to Stream. -class WriteException: StreamException { - /// Construct a WriteException with given error message. - this(char[] msg) { super(msg); } -} - -/// Thrown when unable to move Stream pointer. -class SeekException: StreamException { - /// Construct a SeekException with given error message. - this(char[] msg) { super(msg); } -} - -// seek whence... -enum SeekPos { - Set, - Current, - End -} - -private { - import std.format; - import std.system; // for Endian enumeration - import std.intrinsic; // for bswap - import std.utf; - import std.stdarg; -} - -version (Windows) { - private import std.file; -} - -/// InputStream is the interface for readable streams. - -interface InputStream { - - /*** - * Read exactly size bytes into the buffer. - * - * Throws a ReadException if it is not correct. - */ - void readExact(void* buffer, size_t size); - - /*** - * Read a block of data big enough to fill the given array buffer. - * - * Returns: the actual number of bytes read. Unfilled bytes are not modified. - */ - size_t read(ubyte[] buffer); - - /*** - * Read a basic type or counted string. - * - * Throw a ReadException if it could not be read. - * Outside of byte, ubyte, and char, the format is - * implementation-specific and should not be used except as opposite actions - * to write. - */ - void read(out byte x); - void read(out ubyte x); /// ditto - void read(out short x); /// ditto - void read(out ushort x); /// ditto - void read(out int x); /// ditto - void read(out uint x); /// ditto - void read(out long x); /// ditto - void read(out ulong x); /// ditto - void read(out float x); /// ditto - void read(out double x); /// ditto - void read(out real x); /// ditto - void read(out ifloat x); /// ditto - void read(out idouble x); /// ditto - void read(out ireal x); /// ditto - void read(out cfloat x); /// ditto - void read(out cdouble x); /// ditto - void read(out creal x); /// ditto - void read(out char x); /// ditto - void read(out wchar x); /// ditto - void read(out dchar x); /// ditto - - // reads a string, written earlier by write() - void read(out char[] s); /// ditto - - // reads a Unicode string, written earlier by write() - void read(out wchar[] s); /// ditto - - /*** - * Read a line that is terminated with some combination of carriage return and - * line feed or end-of-file. - * - * The terminators are not included. The wchar version - * is identical. The optional buffer parameter is filled (reallocating - * it if necessary) and a slice of the result is returned. - */ - char[] readLine(); - char[] readLine(char[] result); /// ditto - wchar[] readLineW(); /// ditto - wchar[] readLineW(wchar[] result); /// ditto - - /*** - * Overload foreach statements to read the stream line by line and call the - * supplied delegate with each line or with each line with line number. - * - * The string passed in line may be reused between calls to the delegate. - * Line numbering starts at 1. - * Breaking out of the foreach will leave the stream - * position at the beginning of the next line to be read. - * For example, to echo a file line-by-line with line numbers run: - * ------------------------------------ - * Stream file = new BufferedFile("sample.txt"); - * foreach(ulong n, char[] line; file) { - * stdout.writefln("line %d: %s",n,line); - * } - * file.close(); - * ------------------------------------ - */ - - // iterate through the stream line-by-line - int opApply(int delegate(inout char[] line) dg); - int opApply(int delegate(inout ulong n, inout char[] line) dg); /// ditto - int opApply(int delegate(inout wchar[] line) dg); /// ditto - int opApply(int delegate(inout ulong n, inout wchar[] line) dg); /// ditto - - /// Read a string of the given length, - /// throwing ReadException if there was a problem. - char[] readString(size_t length); - - /*** - * Read a string of the given length, throwing ReadException if there was a - * problem. - * - * The file format is implementation-specific and should not be used - * except as opposite actions to write. - */ - - wchar[] readStringW(size_t length); - - /*** - * Read and return the next character in the stream. - * - * This is the only method that will handle ungetc properly. - * getcw's format is implementation-specific. - * If EOF is reached then getc returns char.init and getcw returns wchar.init. - */ - - // pushes back character c into the stream; only has - // effect on further calls to getc() and getcw() - char getc(); - wchar getcw(); /// ditto - - /*** - * Push a character back onto the stream. - * - * They will be returned in first-in last-out order from getc/getcw. - * Only has effect on further calls to getc() and getcw(). - */ - char ungetc(char c); - wchar ungetcw(wchar c); /// ditto - - /*** - * Scan a string from the input using a similar form to C's scanf - * and std.format. - * - * An argument of type char[] is interpreted as a format string. - * All other arguments must be pointer types. - * If a format string is not present a default will be supplied computed from - * the base type of the pointer type. An argument of type char[]* is filled - * (possibly with appending characters) and a slice of the result is assigned - * back into the argument. For example the following readf statements - * are equivalent: - * -------------------------- - * int x; - * double y; - * char[] s; - * file.readf(&x, " hello ", &y, &s); - * file.readf("%d hello %f %s", &x, &y, &s); - * file.readf("%d hello %f", &x, &y, "%s", &s); - * -------------------------- - */ - int vreadf(TypeInfo[] arguments, va_list args); - int readf(...); /// ditto - - /// Retrieve the number of bytes available for immediate reading. - size_t available(); - - /*** - * Return whether the current file position is the same as the end of the - * file. - * - * This does not require actually reading past the end, as with stdio. For - * non-seekable streams this might only return true after attempting to read - * past the end. - */ - - bool eof(); - - bool isOpen(); /// Return true if the stream is currently open. -} - -/// Interface for writable streams. -interface OutputStream { - - /*** - * Write exactly size bytes from buffer, or throw a WriteException if that - * could not be done. - */ - void writeExact(void* buffer, size_t size); - - /*** - * Write as much of the buffer as possible, - * returning the number of bytes written. - */ - size_t write(ubyte[] buffer); - - /*** - * Write a basic type. - * - * Outside of byte, ubyte, and char, the format is implementation-specific - * and should only be used in conjunction with read. - * Throw WriteException on error. - */ - void write(byte x); - void write(ubyte x); /// ditto - void write(short x); /// ditto - void write(ushort x); /// ditto - void write(int x); /// ditto - void write(uint x); /// ditto - void write(long x); /// ditto - void write(ulong x); /// ditto - void write(float x); /// ditto - void write(double x); /// ditto - void write(real x); /// ditto - void write(ifloat x); /// ditto - void write(idouble x); /// ditto - void write(ireal x); /// ditto - void write(cfloat x); /// ditto - void write(cdouble x); /// ditto - void write(creal x); /// ditto - void write(char x); /// ditto - void write(wchar x); /// ditto - void write(dchar x); /// ditto - - /*** - * Writes a string, together with its length. - * - * The format is implementation-specific - * and should only be used in conjunction with read. - * Throw WriteException on error. - */ - void write(char[] s); - void write(wchar[] s); /// ditto - - /*** - * Write a line of text, - * appending the line with an operating-system-specific line ending. - * - * Throws WriteException on error. - */ - void writeLine(char[] s); - - /*** - * Write a line of text, - * appending the line with an operating-system-specific line ending. - * - * The format is implementation-specific. - * Throws WriteException on error. - */ - void writeLineW(wchar[] s); - - /*** - * Write a string of text. - * - * Throws WriteException if it could not be fully written. - */ - void writeString(char[] s); - - /*** - * Write a string of text. - * - * The format is implementation-specific. - * Throws WriteException if it could not be fully written. - */ - void writeStringW(wchar[] s); - - /*** - * Print a formatted string into the stream using printf-style syntax, - * returning the number of bytes written. - */ - size_t vprintf(char[] format, va_list args); - size_t printf(char[] format, ...); /// ditto - - /*** - * Print a formatted string into the stream using writef-style syntax. - * References: std.format. - * Returns: self to chain with other stream commands like flush. - */ - OutputStream writef(...); - OutputStream writefln(...); /// ditto - OutputStream writefx(TypeInfo[] arguments, va_list argptr, int newline = false); /// ditto - - void flush(); /// Flush pending output if appropriate. - void close(); /// Close the stream, flushing output if appropriate. - bool isOpen(); /// Return true if the stream is currently open. -} - -/*** - * Stream is the base abstract class from which the other stream classes derive. - * - * Stream's byte order is the format native to the computer. - * - * Reading: - * These methods require that the readable flag be set. - * Problems with reading result in a ReadException being thrown. - * Stream implements the InputStream interface in addition to the - * readBlock method. - * - * Writing: - * These methods require that the writeable flag be set. Problems with writing - * result in a WriteException being thrown. Stream implements the OutputStream - * interface in addition to the following methods: - * writeBlock - * copyFrom - * copyFrom - * - * Seeking: - * These methods require that the seekable flag be set. - * Problems with seeking result in a SeekException being thrown. - * seek, seekSet, seekCur, seekEnd, position, size, toString, toHash - */ - -// not really abstract, but its instances will do nothing useful -class Stream : InputStream, OutputStream { - private import std.string, crc32, std.c.stdlib, std.c.stdio, std.c.stdarg; - - // stream abilities - bool readable = false; /// Indicates whether this stream can be read from. - bool writeable = false; /// Indicates whether this stream can be written to. - bool seekable = false; /// Indicates whether this stream can be seeked within. - protected bool isopen = true; /// Indicates whether this stream is open. - - protected bool readEOF = false; /** Indicates whether this stream is at eof - * after the last read attempt. - */ - - protected bool prevCr = false; /** For a non-seekable stream indicates that - * the last readLine or readLineW ended on a - * '\r' character. - */ - - this() {} - - /*** - * Read up to size bytes into the buffer and return the number of bytes - * actually read. A return value of 0 indicates end-of-file. - */ - abstract size_t readBlock(void* buffer, size_t size); - - // reads block of data of specified size, - // throws ReadException on error - void readExact(void* buffer, size_t size) { - for(;;) { - if (!size) return; - size_t readsize = readBlock(buffer, size); // return 0 on eof - if (readsize == 0) break; - buffer += readsize; - size -= readsize; - } - if (size != 0) - throw new ReadException("not enough data in stream"); - } - - // reads block of data big enough to fill the given - // array, returns actual number of bytes read - size_t read(ubyte[] buffer) { - return readBlock(buffer.ptr, buffer.length); - } - - // read a single value of desired type, - // throw ReadException on error - void read(out byte x) { readExact(&x, x.sizeof); } - void read(out ubyte x) { readExact(&x, x.sizeof); } - void read(out short x) { readExact(&x, x.sizeof); } - void read(out ushort x) { readExact(&x, x.sizeof); } - void read(out int x) { readExact(&x, x.sizeof); } - void read(out uint x) { readExact(&x, x.sizeof); } - void read(out long x) { readExact(&x, x.sizeof); } - void read(out ulong x) { readExact(&x, x.sizeof); } - void read(out float x) { readExact(&x, x.sizeof); } - void read(out double x) { readExact(&x, x.sizeof); } - void read(out real x) { readExact(&x, x.sizeof); } - void read(out ifloat x) { readExact(&x, x.sizeof); } - void read(out idouble x) { readExact(&x, x.sizeof); } - void read(out ireal x) { readExact(&x, x.sizeof); } - void read(out cfloat x) { readExact(&x, x.sizeof); } - void read(out cdouble x) { readExact(&x, x.sizeof); } - void read(out creal x) { readExact(&x, x.sizeof); } - void read(out char x) { readExact(&x, x.sizeof); } - void read(out wchar x) { readExact(&x, x.sizeof); } - void read(out dchar x) { readExact(&x, x.sizeof); } - - // reads a string, written earlier by write() - void read(out char[] s) { - size_t len; - read(len); - s = readString(len); - } - - // reads a Unicode string, written earlier by write() - void read(out wchar[] s) { - size_t len; - read(len); - s = readStringW(len); - } - - // reads a line, terminated by either CR, LF, CR/LF, or EOF - char[] readLine() { - return readLine(null); - } - - // reads a line, terminated by either CR, LF, CR/LF, or EOF - // reusing the memory in buffer if result will fit and otherwise - // allocates a new string - char[] readLine(char[] result) { - size_t strlen = 0; - char ch = getc(); - while (readable) { - switch (ch) { - case '\r': - if (seekable) { - ch = getc(); - if (ch != '\n') - ungetc(ch); - } else { - prevCr = true; - } - case '\n': - case char.init: - result.length = strlen; - return result; - - default: - if (strlen < result.length) { - result[strlen] = ch; - } else { - result ~= ch; - } - strlen++; - } - ch = getc(); - } - result.length = strlen; - return result; - } - - // reads a Unicode line, terminated by either CR, LF, CR/LF, - // or EOF; pretty much the same as the above, working with - // wchars rather than chars - wchar[] readLineW() { - return readLineW(null); - } - - // reads a Unicode line, terminated by either CR, LF, CR/LF, - // or EOF; - // fills supplied buffer if line fits and otherwise allocates a new string. - wchar[] readLineW(wchar[] result) { - size_t strlen = 0; - wchar c = getcw(); - while (readable) { - switch (c) { - case '\r': - if (seekable) { - c = getcw(); - if (c != '\n') - ungetcw(c); - } else { - prevCr = true; - } - case '\n': - case wchar.init: - result.length = strlen; - return result; - - default: - if (strlen < result.length) { - result[strlen] = c; - } else { - result ~= c; - } - strlen++; - } - c = getcw(); - } - result.length = strlen; - return result; - } - - // iterate through the stream line-by-line - due to Regan Heath - int opApply(int delegate(inout char[] line) dg) { - int res = 0; - char[128] buf; - while (!eof()) { - char[] line = readLine(buf); - res = dg(line); - if (res) break; - } - return res; - } - - // iterate through the stream line-by-line with line count and char[] - int opApply(int delegate(inout ulong n, inout char[] line) dg) { - int res = 0; - ulong n = 1; - char[128] buf; - while (!eof()) { - char[] line = readLine(buf); - res = dg(n,line); - if (res) break; - n++; - } - return res; - } - - // iterate through the stream line-by-line with wchar[] - int opApply(int delegate(inout wchar[] line) dg) { - int res = 0; - wchar[128] buf; - while (!eof()) { - wchar[] line = readLineW(buf); - res = dg(line); - if (res) break; - } - return res; - } - - // iterate through the stream line-by-line with line count and wchar[] - int opApply(int delegate(inout ulong n, inout wchar[] line) dg) { - int res = 0; - ulong n = 1; - wchar[128] buf; - while (!eof()) { - wchar[] line = readLineW(buf); - res = dg(n,line); - if (res) break; - n++; - } - return res; - } - - // reads a string of given length, throws - // ReadException on error - char[] readString(size_t length) { - char[] result = new char[length]; - readExact(result.ptr, length); - return result; - } - - // reads a Unicode string of given length, throws - // ReadException on error - wchar[] readStringW(size_t length) { - wchar[] result = new wchar[length]; - readExact(result.ptr, result.length * wchar.sizeof); - return result; - } - - // unget buffer - private wchar[] unget; - final bool ungetAvailable() { return unget.length > 1; } - - // reads and returns next character from the stream, - // handles characters pushed back by ungetc() - // returns char.init on eof. - char getc() { - char c; - if (prevCr) { - prevCr = false; - c = getc(); - if (c != '\n') - return c; - } - if (unget.length > 1) { - c = cast(char)unget[unget.length - 1]; - unget.length = unget.length - 1; - } else { - readBlock(&c,1); - } - return c; - } - - // reads and returns next Unicode character from the - // stream, handles characters pushed back by ungetc() - // returns wchar.init on eof. - wchar getcw() { - wchar c; - if (prevCr) { - prevCr = false; - c = getcw(); - if (c != '\n') - return c; - } - if (unget.length > 1) { - c = unget[unget.length - 1]; - unget.length = unget.length - 1; - } else { - void* buf = &c; - size_t n = readBlock(buf,2); - if (n == 1 && readBlock(buf+1,1) == 0) - throw new ReadException("not enough data in stream"); - } - return c; - } - - // pushes back character c into the stream; only has - // effect on further calls to getc() and getcw() - char ungetc(char c) { - if (c == c.init) return c; - // first byte is a dummy so that we never set length to 0 - if (unget.length == 0) - unget.length = 1; - unget ~= c; - return c; - } - - // pushes back Unicode character c into the stream; only - // has effect on further calls to getc() and getcw() - wchar ungetcw(wchar c) { - if (c == c.init) return c; - // first byte is a dummy so that we never set length to 0 - if (unget.length == 0) - unget.length = 1; - unget ~= c; - return c; - } - - int vreadf(TypeInfo[] arguments, va_list args) { - char[] fmt; - int j = 0; - int count = 0, i = 0; - char c = getc(); - while ((j < arguments.length || i < fmt.length) && !eof()) { - if (fmt.length == 0 || i == fmt.length) { - i = 0; - if (arguments[j] is typeid(char[])) { - fmt = va_arg!(char[])(args); - j++; - continue; - } else if (arguments[j] is typeid(int*) || - arguments[j] is typeid(byte*) || - arguments[j] is typeid(short*) || - arguments[j] is typeid(long*)) { - fmt = "%d"; - } else if (arguments[j] is typeid(uint*) || - arguments[j] is typeid(ubyte*) || - arguments[j] is typeid(ushort*) || - arguments[j] is typeid(ulong*)) { - fmt = "%d"; - } else if (arguments[j] is typeid(float*) || - arguments[j] is typeid(double*) || - arguments[j] is typeid(real*)) { - fmt = "%f"; - } else if (arguments[j] is typeid(char[]*) || - arguments[j] is typeid(wchar[]*) || - arguments[j] is typeid(dchar[]*)) { - fmt = "%s"; - } else if (arguments[j] is typeid(char*)) { - fmt = "%c"; - } - } - if (fmt[i] == '%') { // a field - i++; - bool suppress = false; - if (fmt[i] == '*') { // suppress assignment - suppress = true; - i++; - } - // read field width - int width = 0; - while (isdigit(fmt[i])) { - width = width * 10 + (fmt[i] - '0'); - i++; - } - if (width == 0) - width = -1; - // skip any modifier if present - if (fmt[i] == 'h' || fmt[i] == 'l' || fmt[i] == 'L') - i++; - // check the typechar and act accordingly - switch (fmt[i]) { - case 'd': // decimal/hexadecimal/octal integer - case 'D': - case 'u': - case 'U': - case 'o': - case 'O': - case 'x': - case 'X': - case 'i': - case 'I': - { - while (iswhite(c)) { - c = getc(); - count++; - } - bool neg = false; - if (c == '-') { - neg = true; - c = getc(); - count++; - } else if (c == '+') { - c = getc(); - count++; - } - char ifmt = cast(char)(fmt[i] | 0x20); - if (ifmt == 'i') { // undetermined base - if (c == '0') { // octal or hex - c = getc(); - count++; - if (c == 'x' || c == 'X') { // hex - ifmt = 'x'; - c = getc(); - count++; - } else { // octal - ifmt = 'o'; - } - } - else // decimal - ifmt = 'd'; - } - long n = 0; - switch (ifmt) - { - case 'd': // decimal - case 'u': { - while (isdigit(c) && width) { - n = n * 10 + (c - '0'); - width--; - c = getc(); - count++; - } - } break; - - case 'o': { // octal - while (isoctdigit(c) && width) { - n = n * 010 + (c - '0'); - width--; - c = getc(); - count++; - } - } break; - - case 'x': { // hexadecimal - while (ishexdigit(c) && width) { - n *= 0x10; - if (isdigit(c)) - n += c - '0'; - else - n += 0xA + (c | 0x20) - 'a'; - width--; - c = getc(); - count++; - } - } break; - - default: - assert(0); - } - if (neg) - n = -n; - if (arguments[j] is typeid(int*)) { - int* p = va_arg!(int*)(args); - *p = cast(int)n; - } else if (arguments[j] is typeid(short*)) { - short* p = va_arg!(short*)(args); - *p = cast(short)n; - } else if (arguments[j] is typeid(byte*)) { - byte* p = va_arg!(byte*)(args); - *p = cast(byte)n; - } else if (arguments[j] is typeid(long*)) { - long* p = va_arg!(long*)(args); - *p = n; - } else if (arguments[j] is typeid(uint*)) { - uint* p = va_arg!(uint*)(args); - *p = cast(uint)n; - } else if (arguments[j] is typeid(ushort*)) { - ushort* p = va_arg!(ushort*)(args); - *p = cast(ushort)n; - } else if (arguments[j] is typeid(ubyte*)) { - ubyte* p = va_arg!(ubyte*)(args); - *p = cast(ubyte)n; - } else if (arguments[j] is typeid(ulong*)) { - ulong* p = va_arg!(ulong*)(args); - *p = cast(ulong)n; - } - j++; - i++; - } break; - - case 'f': // float - case 'F': - case 'e': - case 'E': - case 'g': - case 'G': - { - while (iswhite(c)) { - c = getc(); - count++; - } - bool neg = false; - if (c == '-') { - neg = true; - c = getc(); - count++; - } else if (c == '+') { - c = getc(); - count++; - } - real n = 0; - while (isdigit(c) && width) { - n = n * 10 + (c - '0'); - width--; - c = getc(); - count++; - } - if (width && c == '.') { - width--; - c = getc(); - count++; - double frac = 1; - while (isdigit(c) && width) { - n = n * 10 + (c - '0'); - frac *= 10; - width--; - c = getc(); - count++; - } - n /= frac; - } - if (width && (c == 'e' || c == 'E')) { - width--; - c = getc(); - count++; - if (width) { - bool expneg = false; - if (c == '-') { - expneg = true; - width--; - c = getc(); - count++; - } else if (c == '+') { - width--; - c = getc(); - count++; - } - real exp = 0; - while (isdigit(c) && width) { - exp = exp * 10 + (c - '0'); - width--; - c = getc(); - count++; - } - if (expneg) { - while (exp--) - n /= 10; - } else { - while (exp--) - n *= 10; - } - } - } - if (neg) - n = -n; - if (arguments[j] is typeid(float*)) { - float* p = va_arg!(float*)(args); - *p = n; - } else if (arguments[j] is typeid(double*)) { - double* p = va_arg!(double*)(args); - *p = n; - } else if (arguments[j] is typeid(real*)) { - real* p = va_arg!(real*)(args); - *p = n; - } - j++; - i++; - } break; - - case 's': { // string - while (iswhite(c)) { - c = getc(); - count++; - } - char[] s; - char[]* p; - size_t strlen; - if (arguments[j] is typeid(char[]*)) { - p = va_arg!(char[]*)(args); - s = *p; - } - while (!iswhite(c) && c != char.init) { - if (strlen < s.length) { - s[strlen] = c; - } else { - s ~= c; - } - strlen++; - c = getc(); - count++; - } - s = s[0 .. strlen]; - if (arguments[j] is typeid(char[]*)) { - *p = s; - } else if (arguments[j] is typeid(char*)) { - s ~= 0; - char* q = va_arg!(char*)(args); - q[0 .. s.length] = s[]; - } else if (arguments[j] is typeid(wchar[]*)) { - wchar[]* q = va_arg!(wchar[]*)(args); - *q = toUTF16(s); - } else if (arguments[j] is typeid(dchar[]*)) { - dchar[]* q = va_arg!(dchar[]*)(args); - *q = toUTF32(s); - } - j++; - i++; - } break; - - case 'c': { // character(s) - char* s = va_arg!(char*)(args); - if (width < 0) - width = 1; - else - while (iswhite(c)) { - c = getc(); - count++; - } - while (width-- && !eof()) { - *(s++) = c; - c = getc(); - count++; - } - j++; - i++; - } break; - - case 'n': { // number of chars read so far - int* p = va_arg!(int*)(args); - *p = count; - j++; - i++; - } break; - - default: // read character as is - goto nws; - } - } else if (iswhite(fmt[i])) { // skip whitespace - while (iswhite(c)) - c = getc(); - i++; - } else { // read character as is - nws: - if (fmt[i] != c) - break; - c = getc(); - i++; - } - } - ungetc(c); - return count; - } - - int readf(...) { - return vreadf(_arguments, _argptr); - } - - // returns estimated number of bytes available for immediate reading - size_t available() { return 0; } - - /*** - * Write up to size bytes from buffer in the stream, returning the actual - * number of bytes that were written. - */ - abstract size_t writeBlock(void* buffer, size_t size); - - // writes block of data of specified size, - // throws WriteException on error - void writeExact(void* buffer, size_t size) { - for(;;) { - if (!size) return; - size_t writesize = writeBlock(buffer, size); - if (writesize == 0) break; - buffer += writesize; - size -= writesize; - } - if (size != 0) - throw new WriteException("unable to write to stream"); - } - - // writes the given array of bytes, returns - // actual number of bytes written - size_t write(ubyte[] buffer) { - return writeBlock(buffer.ptr, buffer.length); - } - - // write a single value of desired type, - // throw WriteException on error - void write(byte x) { writeExact(&x, x.sizeof); } - void write(ubyte x) { writeExact(&x, x.sizeof); } - void write(short x) { writeExact(&x, x.sizeof); } - void write(ushort x) { writeExact(&x, x.sizeof); } - void write(int x) { writeExact(&x, x.sizeof); } - void write(uint x) { writeExact(&x, x.sizeof); } - void write(long x) { writeExact(&x, x.sizeof); } - void write(ulong x) { writeExact(&x, x.sizeof); } - void write(float x) { writeExact(&x, x.sizeof); } - void write(double x) { writeExact(&x, x.sizeof); } - void write(real x) { writeExact(&x, x.sizeof); } - void write(ifloat x) { writeExact(&x, x.sizeof); } - void write(idouble x) { writeExact(&x, x.sizeof); } - void write(ireal x) { writeExact(&x, x.sizeof); } - void write(cfloat x) { writeExact(&x, x.sizeof); } - void write(cdouble x) { writeExact(&x, x.sizeof); } - void write(creal x) { writeExact(&x, x.sizeof); } - void write(char x) { writeExact(&x, x.sizeof); } - void write(wchar x) { writeExact(&x, x.sizeof); } - void write(dchar x) { writeExact(&x, x.sizeof); } - - // writes a string, together with its length - void write(char[] s) { - write(s.length); - writeString(s); - } - - // writes a Unicode string, together with its length - void write(wchar[] s) { - write(s.length); - writeStringW(s); - } - - // writes a line, throws WriteException on error - void writeLine(char[] s) { - writeString(s); - version (Win32) - writeString("\r\n"); - else version (Mac) - writeString("\r"); - else - writeString("\n"); - } - - // writes a Unicode line, throws WriteException on error - void writeLineW(wchar[] s) { - writeStringW(s); - version (Win32) - writeStringW("\r\n"); - else version (Mac) - writeStringW("\r"); - else - writeStringW("\n"); - } - - // writes a string, throws WriteException on error - void writeString(char[] s) { - writeExact(s.ptr, s.length); - } - - // writes a Unicode string, throws WriteException on error - void writeStringW(wchar[] s) { - writeExact(s.ptr, s.length * wchar.sizeof); - } - - // writes data to stream using vprintf() syntax, - // returns number of bytes written - size_t vprintf(char[] format, va_list args) { - // shamelessly stolen from OutBuffer, - // by Walter's permission - char[1024] buffer; - char* p = buffer.ptr; - char* f = toStringz(format); - size_t psize = buffer.length; - size_t count; - va_list args_copy; - while (true) { - 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); - } else version (Unix) { - 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*/malloc(psize); - } else - throw new Exception("unsupported platform"); - } - writeString(p[0 .. count]); - return count; - } - - // writes data to stream using printf() syntax, - // returns number of bytes written - size_t printf(char[] format, ...) { - version (GNU) - return vprintf(format, _argptr); - else { - va_list ap; - ap = cast(va_list) &format; - ap += format.sizeof; - return vprintf(format, ap); - } - } - - private void doFormatCallback(dchar c) { - char[4] buf; - char[] b; - b = std.utf.toUTF8(buf, c); - writeString(b); - } - - // writes data to stream using writef() syntax, - OutputStream writef(...) { - return writefx(_arguments,_argptr,0); - } - - // writes data with trailing newline - OutputStream writefln(...) { - return writefx(_arguments,_argptr,1); - } - - // writes data with optional trailing newline - OutputStream writefx(TypeInfo[] arguments, va_list argptr, int newline=false) { - doFormat(&doFormatCallback,arguments,argptr); - if (newline) - writeLine(""); - return this; - } - - /*** - * Copies all data from s into this stream. - * This may throw ReadException or WriteException on failure. - * This restores the file position of s so that it is unchanged. - */ - void copyFrom(Stream s) { - if (seekable) { - ulong pos = s.position(); - s.position(0); - copyFrom(s, s.size()); - s.position(pos); - } else { - ubyte[128] buf; - while (!s.eof()) { - size_t m = s.readBlock(buf.ptr, buf.length); - writeExact(buf.ptr, m); - } - } - } - - /*** - * Copy a specified number of bytes from the given stream into this one. - * This may throw ReadException or WriteException on failure. - * Unlike the previous form, this doesn't restore the file position of s. - */ - void copyFrom(Stream s, ulong count) { - ubyte[128] buf; - while (count > 0) { - size_t n = cast(size_t)(count 1) - unget.length = 1; // keep at least 1 so that data ptr stays - } - - // close the stream somehow; the default just flushes the buffer - void close() { - if (isopen) - flush(); - readEOF = prevCr = isopen = readable = writeable = seekable = false; - } - - /*** - * Read the entire stream and return it as a string. - * If the stream is not seekable the contents from the current position to eof - * is read and returned. - */ - override char[] toString() { - if (!readable) - return super.toString(); - size_t pos; - size_t rdlen; - size_t blockSize; - char[] result; - if (seekable) { - ulong orig_pos = position(); - position(0); - blockSize = cast(size_t)size(); - result = new char[blockSize]; - while (blockSize > 0) { - rdlen = readBlock(&result[pos], blockSize); - pos += rdlen; - blockSize -= rdlen; - } - position(orig_pos); - } else { - blockSize = 4096; - result = new char[blockSize]; - while ((rdlen = readBlock(&result[pos], blockSize)) > 0) { - pos += rdlen; - blockSize += rdlen; - result.length = result.length + blockSize; - } - } - return result[0 .. pos]; - } - - /*** - * Get a hash of the stream by reading each byte and using it in a CRC-32 - * checksum. - */ - override size_t toHash() { - if (!readable || !seekable) - return super.toHash(); - ulong pos = position(); - uint crc = init_crc32 (); - position(0); - ulong len = size(); - for (ulong i = 0; i < len; i++) { - ubyte c; - read(c); - crc = update_crc32(c, crc); - } - position(pos); - return crc; - } - - // helper for checking that the stream is readable - final protected void assertReadable() { - if (!readable) - throw new ReadException("Stream is not readable"); - } - // helper for checking that the stream is writeable - final protected void assertWriteable() { - if (!writeable) - throw new WriteException("Stream is not writeable"); - } - // helper for checking that the stream is seekable - final protected void assertSeekable() { - if (!seekable) - throw new SeekException("Stream is not seekable"); - } -} - -/*** - * A base class for streams that wrap a source stream with additional - * functionality. - * - * The method implementations forward read/write/seek calls to the - * source stream. A FilterStream can change the position of the source stream - * arbitrarily and may not keep the source stream state in sync with the - * FilterStream, even upon flushing and closing the FilterStream. It is - * recommended to not make any assumptions about the state of the source position - * and read/write state after a FilterStream has acted upon it. Specifc subclasses - * of FilterStream should document how they modify the source stream and if any - * invariants hold true between the source and filter. - */ -class FilterStream : Stream { - private Stream s; // source stream - - /// Property indicating when this stream closes to close the source stream as - /// well. - /// Defaults to true. - bool nestClose = true; - - /// Construct a FilterStream for the given source. - this(Stream source) { - s = source; - resetSource(); - } - - // source getter/setter - - /*** - * Get the current source stream. - */ - final Stream source(){return s;} - - /*** - * Set the current source stream. - * - * Setting the source stream closes this stream before attaching the new - * source. Attaching an open stream reopens this stream and resets the stream - * state. - */ - void source(Stream s) { - close(); - this.s = s; - resetSource(); - } - - /*** - * Indicates the source stream changed state and that this stream should reset - * any readable, writeable, seekable, isopen and buffering flags. - */ - void resetSource() { - if (s !is null) { - readable = s.readable; - writeable = s.writeable; - seekable = s.seekable; - isopen = s.isOpen(); - } else { - readable = writeable = seekable = false; - isopen = false; - } - readEOF = prevCr = false; - } - - // read from source - size_t readBlock(void* buffer, size_t size) { - size_t res = s.readBlock(buffer,size); - readEOF = res == 0; - return res; - } - - // write to source - size_t writeBlock(void* buffer, size_t size) { - return s.writeBlock(buffer,size); - } - - // close stream - override void close() { - if (isopen) { - super.close(); - if (nestClose) - s.close(); - } - } - - // seek on source - override ulong seek(long offset, SeekPos whence) { - readEOF = false; - return s.seek(offset,whence); - } - - override size_t available () { return s.available(); } - override void flush() { super.flush(); s.flush(); } -} - -/*** - * This subclass is for buffering a source stream. - * - * A buffered stream must be - * closed explicitly to ensure the final buffer content is written to the source - * stream. The source stream position is changed according to the block size so - * reading or writing to the BufferedStream may not change the source stream - * position by the same amount. - */ -class BufferedStream : FilterStream { - ubyte[] buffer; // buffer, if any - uint bufferCurPos; // current position in buffer - uint bufferLen; // amount of data in buffer - bool bufferDirty = false; - uint bufferSourcePos; // position in buffer of source stream position - ulong streamPos; // absolute position in source stream - - /* Example of relationship between fields: - * - * s ...01234567890123456789012EOF - * buffer |-- --| - * bufferCurPos | - * bufferLen |-- --| - * bufferSourcePos | - * - */ - - invariant { - assert(bufferSourcePos <= bufferLen); - assert(bufferCurPos <= bufferLen); - assert(bufferLen <= buffer.length); - } - - const uint DefaultBufferSize = 8192; - - /*** - * Create a buffered stream for the stream source with the buffer size - * bufferSize. - */ - this(Stream source, uint bufferSize = DefaultBufferSize) { - super(source); - if (bufferSize) - buffer = new ubyte[bufferSize]; - } - - protected void resetSource() { - super.resetSource(); - streamPos = 0; - bufferLen = bufferSourcePos = bufferCurPos = 0; - bufferDirty = false; - } - - // reads block of data of specified size using any buffered data - // returns actual number of bytes read - override size_t readBlock(void* result, size_t len) { - if (len == 0) return 0; - - assertReadable(); - - ubyte* outbuf = cast(ubyte*)result; - size_t readsize = 0; - - if (bufferCurPos + len < bufferLen) { - // buffer has all the data so copy it - outbuf[0 .. len] = buffer[bufferCurPos .. bufferCurPos+len]; - bufferCurPos += len; - readsize = len; - goto ExitRead; - } - - readsize = bufferLen - bufferCurPos; - if (readsize > 0) { - // buffer has some data so copy what is left - outbuf[0 .. readsize] = buffer[bufferCurPos .. bufferLen]; - outbuf += readsize; - bufferCurPos += readsize; - len -= readsize; - } - - flush(); - - if (len >= buffer.length) { - // buffer can't hold the data so fill output buffer directly - size_t siz = super.readBlock(outbuf, len); - readsize += siz; - streamPos += siz; - } else { - // read a new block into buffer - bufferLen = super.readBlock(buffer.ptr, buffer.length); - if (bufferLen < len) len = bufferLen; - outbuf[0 .. len] = buffer[0 .. len]; - bufferSourcePos = bufferLen; - streamPos += bufferLen; - bufferCurPos = len; - readsize += len; - } - - ExitRead: - return readsize; - } - - // write block of data of specified size - // returns actual number of bytes written - override size_t writeBlock(void* result, size_t len) { - assertWriteable(); - - ubyte* buf = cast(ubyte*)result; - size_t writesize = 0; - - if (bufferLen == 0) { - // buffer is empty so fill it if possible - if ((len < buffer.length) && (readable)) { - // read in data if the buffer is currently empty - bufferLen = s.readBlock(buffer.ptr, buffer.length); - bufferSourcePos = bufferLen; - streamPos += bufferLen; - - } else if (len >= buffer.length) { - // buffer can't hold the data so write it directly and exit - writesize = s.writeBlock(buf,len); - streamPos += writesize; - goto ExitWrite; - } - } - - if (bufferCurPos + len <= buffer.length) { - // buffer has space for all the data so copy it and exit - buffer[bufferCurPos .. bufferCurPos+len] = buf[0 .. len]; - bufferCurPos += len; - bufferLen = bufferCurPos > bufferLen ? bufferCurPos : bufferLen; - writesize = len; - bufferDirty = true; - goto ExitWrite; - } - - writesize = buffer.length - bufferCurPos; - if (writesize > 0) { - // buffer can take some data - buffer[bufferCurPos .. buffer.length] = buf[0 .. writesize]; - bufferCurPos = bufferLen = buffer.length; - buf += writesize; - len -= writesize; - bufferDirty = true; - } - - assert(bufferCurPos == buffer.length); - assert(bufferLen == buffer.length); - - flush(); - - writesize += writeBlock(buf,len); - - ExitWrite: - return writesize; - } - - override ulong seek(long offset, SeekPos whence) { - assertSeekable(); - - if ((whence != SeekPos.Current) || - (offset + bufferCurPos < 0) || - (offset + bufferCurPos >= bufferLen)) { - flush(); - streamPos = s.seek(offset,whence); - } else { - bufferCurPos += offset; - } - readEOF = false; - return streamPos-bufferSourcePos+bufferCurPos; - } - - // Buffered readLine - Dave Fladebo - // reads a line, terminated by either CR, LF, CR/LF, or EOF - // reusing the memory in buffer if result will fit, otherwise - // will reallocate (using concatenation) - template TreadLine(T) { - T[] readLine(T[] inBuffer) - { - size_t lineSize = 0; - bool haveCR = false; - T c = '\0'; - size_t idx = 0; - ubyte* pc = cast(ubyte*)&c; - - L0: - for(;;) { - uint start = bufferCurPos; - L1: - foreach(ubyte b; buffer[start .. bufferLen]) { - bufferCurPos++; - pc[idx] = b; - if(idx < T.sizeof - 1) { - idx++; - continue L1; - } else { - idx = 0; - } - if(c == '\n' || haveCR) { - if(haveCR && c != '\n') bufferCurPos--; - break L0; - } else { - if(c == '\r') { - haveCR = true; - } else { - if(lineSize < inBuffer.length) { - inBuffer[lineSize] = c; - } else { - inBuffer ~= c; - } - lineSize++; - } - } - } - flush(); - size_t res = super.readBlock(buffer.ptr, buffer.length); - if(!res) break L0; // EOF - bufferSourcePos = bufferLen = res; - streamPos += res; - } - - return inBuffer[0 .. lineSize]; - } - } // template TreadLine(T) - - override char[] readLine(char[] inBuffer) { - if (ungetAvailable()) - return super.readLine(inBuffer); - else - return TreadLine!(char).readLine(inBuffer); - } - alias Stream.readLine readLine; - - override wchar[] readLineW(wchar[] inBuffer) { - if (ungetAvailable()) - return super.readLineW(inBuffer); - else - return TreadLine!(wchar).readLine(inBuffer); - } - alias Stream.readLineW readLineW; - - override void flush() - out { - assert(bufferCurPos == 0); - assert(bufferSourcePos == 0); - assert(bufferLen == 0); - } - body { - if (writeable && bufferDirty) { - if (bufferSourcePos != 0 && seekable) { - // move actual file pointer to front of buffer - streamPos = s.seek(-bufferSourcePos, SeekPos.Current); - } - // write buffer out - bufferSourcePos = s.writeBlock(buffer.ptr, bufferLen); - if (bufferSourcePos != bufferLen) { - throw new WriteException("Unable to write to stream"); - } - } - super.flush(); - long diff = cast(long)bufferCurPos-bufferSourcePos; - if (diff != 0 && seekable) { - // move actual file pointer to current position - streamPos = s.seek(diff, SeekPos.Current); - } - // reset buffer data to be empty - bufferSourcePos = bufferCurPos = bufferLen = 0; - bufferDirty = false; - } - - // returns true if end of stream is reached, false otherwise - override bool eof() { - if ((buffer.length == 0) || !readable) { - return super.eof(); - } - // some simple tests to avoid flushing - if (ungetAvailable() || bufferCurPos != bufferLen) - return false; - if (bufferLen == buffer.length) - flush(); - size_t res = super.readBlock(&buffer[bufferLen],buffer.length-bufferLen); - bufferSourcePos += res; - bufferLen += res; - streamPos += res; - return readEOF; - } - - // returns size of stream - ulong size() { - if (bufferDirty) flush(); - return s.size(); - } - - // returns estimated number of bytes available for immediate reading - size_t available() { - return bufferLen - bufferCurPos; - } -} - -/// An exception for File errors. -class StreamFileException: StreamException { - /// Construct a StreamFileException with given error message. - this(char[] msg) { super(msg); } -} - -/// An exception for errors during File.open. -class OpenException: StreamFileException { - /// Construct an OpenFileException with given error message. - this(char[] msg) { super(msg); } -} - -// access modes; may be or'ed -enum FileMode { - In = 1, - Out = 2, - OutNew = 6, // includes FileMode.Out - Append = 10 // includes FileMode.Out -} - -version(linux) version = Unix; - -version (Win32) { - private import std.c.windows.windows; - extern (Windows) { - void FlushFileBuffers(HANDLE hFile); - DWORD GetFileType(HANDLE hFile); - } -} -version (Unix) { - version(linux) { - private import std.c.linux.linux; - alias std.c.linux.linux sys; - } else { - private import std.c.unix.unix; - alias std.c.unix.unix sys; - } - alias int HANDLE; -} -version (NoSystem) - alias int HANDLE; - -/// This subclass is for unbuffered file system streams. -class File: Stream { - - version (Win32) { - private HANDLE hFile; - } - else version (Unix) { - private HANDLE hFile = -1; - } - else version (NoSystem) - private HANDLE hFile; - - this() { - super(); - version (Win32) { - hFile = null; - } - version (Unix) { - hFile = -1; - } - isopen = false; - } - - // opens existing handle; use with care! - this(HANDLE hFile, FileMode mode) { - super(); - this.hFile = hFile; - readable = cast(bool)(mode & FileMode.In); - writeable = cast(bool)(mode & FileMode.Out); - version(Windows) { - seekable = GetFileType(hFile) == 1; // FILE_TYPE_DISK - } else version (Unix) { - ulong result = lseek(hFile, 0, 0); - seekable = (result != ~0); - } - } - - /*** - * Create the stream with no open file, an open file in read mode, or an open - * file with explicit file mode. - * mode, if given, is a combination of FileMode.In - * (indicating a file that can be read) and FileMode.Out (indicating a file - * that can be written). - * Opening a file for reading that doesn't exist will error. - * Opening a file for writing that doesn't exist will create the file. - * The FileMode.OutNew mode will open the file for writing and reset the - * length to zero. - * The FileMode.Append mode will open the file for writing and move the - * file position to the end of the file. - */ - this(char[] filename, FileMode mode = FileMode.In) { this(); open(filename, mode); } - - - /*** - * Open a file for the stream, in an identical manner to the constructors. - * If an error occurs an OpenException is thrown. - */ - void open(char[] filename, FileMode mode = FileMode.In) { - close(); - int access, share, createMode; - parseMode(mode, access, share, createMode); - seekable = true; - readable = cast(bool)(mode & FileMode.In); - writeable = cast(bool)(mode & FileMode.Out); - version (Win32) { - if (std.file.useWfuncs) { - hFile = CreateFileW(std.utf.toUTF16z(filename), access, share, - null, createMode, 0, null); - } else { - hFile = CreateFileA(std.file.toMBSz(filename), access, share, - null, createMode, 0, null); - } - isopen = hFile != INVALID_HANDLE_VALUE; - } - version (Unix) { - hFile = sys.open(toStringz(filename), access | createMode, share); - isopen = hFile != -1; - } - version (NoSystem) - throw new OpenException("Files not supported on this target"); - if (!isopen) - throw new OpenException("Cannot open or create file '" ~ filename ~ "'"); - else if ((mode & FileMode.Append) == FileMode.Append) - seekEnd(0); - } - - private void parseMode(int mode, - out int access, - out int share, - out int createMode) { - version (Win32) { - if (mode & FileMode.In) { - access |= GENERIC_READ; - share |= FILE_SHARE_READ; - createMode = OPEN_EXISTING; - } - if (mode & FileMode.Out) { - access |= GENERIC_WRITE; - createMode = OPEN_ALWAYS; // will create if not present - } - if ((mode & FileMode.OutNew) == FileMode.OutNew) { - createMode = CREATE_ALWAYS; // resets file - } - } - version (Unix) { - if (mode & FileMode.In) { - access = O_RDONLY; - share = 0660; - } - if (mode & FileMode.Out) { - createMode = O_CREAT; // will create if not present - access = O_WRONLY; - share = 0660; - } - if (access == (O_WRONLY | O_RDONLY)) { - access = O_RDWR; - } - if ((mode & FileMode.OutNew) == FileMode.OutNew) { - access |= O_TRUNC; // resets file - } - } - } - - /// Create a file for writing. - void create(char[] filename) { - create(filename, FileMode.OutNew); - } - - /// ditto - void create(char[] filename, FileMode mode) { - close(); - open(filename, mode | FileMode.OutNew); - } - - /// Close the current file if it is open; otherwise it does nothing. - override void close() { - if (isopen) { - super.close(); - if (hFile) { - version (Win32) { - CloseHandle(hFile); - hFile = null; - } else version (Unix) { - sys.close(hFile); - hFile = -1; - } - } - } - } - - // destructor, closes file if still opened - ~this() { close(); } - - version (Win32) { - // returns size of stream - ulong size() { - assertSeekable(); - uint sizehi; - uint sizelow = GetFileSize(hFile,&sizehi); - return (cast(ulong)sizehi << 32) + sizelow; - } - } - - override size_t readBlock(void* buffer, size_t size) { - assertReadable(); - version (Win32) { - ReadFile(hFile, buffer, size, &size, null); - } else version (Unix) { - size = sys.read(hFile, buffer, size); - if (size == -1) - size = 0; - } - readEOF = (size == 0); - return size; - } - - override size_t writeBlock(void* buffer, size_t size) { - assertWriteable(); - version (Win32) { - WriteFile(hFile, buffer, size, &size, null); - } else version (Unix) { - size = sys.write(hFile, buffer, size); - if (size == -1) - size = 0; - } - return size; - } - - override ulong seek(long offset, SeekPos rel) { - assertSeekable(); - version (Win32) { - int hi = cast(int)(offset>>32); - uint low = SetFilePointer(hFile, cast(int)offset, &hi, rel); - if ((low == INVALID_SET_FILE_POINTER) && (GetLastError() != 0)) - throw new SeekException("unable to move file pointer"); - ulong result = (cast(ulong)hi << 32) + low; - } else version (Unix) { - ulong result = lseek(hFile, cast(off_t)offset, rel); - if (result == 0xFFFFFFFF) - throw new SeekException("unable to move file pointer"); - } else version (NoSystem) { - int result; - throw new SeekException("unable to move file pointer"); - } - readEOF = false; - return result; - } - - /*** - * For a seekable file returns the difference of the size and position and - * otherwise returns 0. - */ - - override size_t available() { - if (seekable) { - ulong lavail = size - position; - if (lavail > size_t.max) lavail = size_t.max; - return cast(size_t)lavail; - } - return 0; - } - - // OS-specific property, just in case somebody wants - // to mess with underlying API - HANDLE handle() { return hFile; } - - // run a few tests - unittest { - File file = new File; - int i = 666; - file.create("stream.$$$"); - // 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 (Unix) - assert(file.position() == 18 + 13 + 4); - // we must be at the end of file - assert(file.eof()); - file.close(); - // no operations are allowed when file is closed - assert(!file.readable && !file.writeable && !file.seekable); - file.open("stream.$$$"); - // should be ok to read - assert(file.readable); - assert(file.available == file.size); - 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 (Unix) - 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 (Unix) - assert(file.position() == 18 + 13 + 4); - // we must be at the end of file - assert(file.eof()); - file.close(); - file.open("stream.$$$",FileMode.OutNew | FileMode.In); - 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 == 4 ); - 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[][4]; - 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.$$$"); - } -} - -/*** - * This subclass is for buffered file system streams. - * - * It is a convenience class for wrapping a File in a BufferedStream. - * A buffered stream must be closed explicitly to ensure the final buffer - * content is written to the file. - */ -class BufferedFile: BufferedStream { - - /// opens file for reading - this() { super(new File()); } - - /// opens file in requested mode and buffer size - this(char[] filename, FileMode mode = FileMode.In, - uint bufferSize = DefaultBufferSize) { - super(new File(filename,mode),bufferSize); - } - - /// opens file for reading with requested buffer size - this(File file, uint bufferSize = DefaultBufferSize) { - super(file,bufferSize); - } - - /// opens existing handle; use with care! - this(HANDLE hFile, FileMode mode, uint buffersize) { - super(new File(hFile,mode),buffersize); - } - - /// opens file in requested mode - void open(char[] filename, FileMode mode = FileMode.In) { - File sf = cast(File)s; - sf.open(filename,mode); - resetSource(); - } - - /// creates file in requested mode - void create(char[] filename, FileMode mode = FileMode.OutNew) { - File sf = cast(File)s; - sf.create(filename,mode); - resetSource(); - } - - // run a few tests same as File - unittest { - BufferedFile file = new BufferedFile; - int i = 666; - file.create("stream.$$$"); - // 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 (Unix) - assert(file.position() == 18 + 13 + 4); - // we must be at the end of file - assert(file.eof()); - long oldsize = cast(long)file.size(); - file.close(); - // no operations are allowed when file is closed - assert(!file.readable && !file.writeable && !file.seekable); - file.open("stream.$$$"); - // should be ok to read - assert(file.readable); - // test getc/ungetc and size() - char c1 = file.getc(); - file.ungetc(c1); - assert( file.size() == oldsize ); - assert(!std.string.cmp(file.readLine(), "Testing stream.d:")); - // jump over "Hello, " - file.seek(7, SeekPos.Current); - version (Win32) - assert(file.position() == 19 + 7); - version (Unix) - 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 (Unix) - assert(file.position() == 18 + 13 + 4); - // we must be at the end of file - assert(file.eof()); - file.close(); - remove("stream.$$$"); - } - -} - -/// UTF byte-order-mark signatures -enum BOM { - UTF8, /// UTF-8 - UTF16LE, /// UTF-16 Little Endian - UTF16BE, /// UTF-16 Big Endian - UTF32LE, /// UTF-32 Little Endian - UTF32BE, /// UTF-32 Big Endian -} - -private const int NBOMS = 5; -Endian[NBOMS] BOMEndian = -[ std.system.endian, - Endian.LittleEndian, Endian.BigEndian, - Endian.LittleEndian, Endian.BigEndian - ]; - -ubyte[][NBOMS] ByteOrderMarks = -[ [0xEF, 0xBB, 0xBF], - [0xFF, 0xFE], - [0xFE, 0xFF], - [0xFF, 0xFE, 0x00, 0x00], - [0x00, 0x00, 0xFE, 0xFF] - ]; - - -/*** - * This subclass wraps a stream with big-endian or little-endian byte order - * swapping. - * - * UTF Byte-Order-Mark (BOM) signatures can be read and deduced or - * written. - * Note that an EndianStream should not be used as the source of another - * FilterStream since a FilterStream call the source with byte-oriented - * read/write requests and the EndianStream will not perform any byte swapping. - * The EndianStream reads and writes binary data (non-getc functions) in a - * one-to-one - * manner with the source stream so the source stream's position and state will be - * kept in sync with the EndianStream if only non-getc functions are called. - */ -/// This causes a crash in -O2 -/+class EndianStream : FilterStream { - - Endian endian; /// Endianness property of the source stream. - - /*** - * Create the endian stream for the source stream source with endianness end. - * The default endianness is the native byte order. - * The Endian type is defined - * in the std.system module. - */ - this(Stream source, Endian end = std.system.endian) { - super(source); - endian = end; - } - - /*** - * Return -1 if no BOM and otherwise read the BOM and return it. - * - * If there is no BOM or if bytes beyond the BOM are read then the bytes read - * are pushed back onto the ungetc buffer or ungetcw buffer. - * Pass ungetCharSize == 2 to use - * ungetcw instead of ungetc when no BOM is present. - */ - int readBOM(int ungetCharSize = 1) { - ubyte[4] BOM_buffer; - int n = 0; // the number of read bytes - int result = -1; // the last match or -1 - for (int i=0; i < NBOMS; ++i) { - int j; - ubyte[] bom = ByteOrderMarks[i]; - for (j=0; j < bom.length; ++j) { - if (n <= j) { // have to read more - if (eof()) - break; - readExact(&BOM_buffer[n++],1); - } - if (BOM_buffer[j] != bom[j]) - break; - } - if (j == bom.length) // found a match - result = i; - } - int m = 0; - if (result != -1) { - endian = BOMEndian[result]; // set stream endianness - m = ByteOrderMarks[result].length; - } - if ((ungetCharSize == 1 && result == -1) || (result == BOM.UTF8)) { - while (n-- > m) - ungetc(BOM_buffer[n]); - } else { // should eventually support unget for dchar as well - if (n & 1) // make sure we have an even number of bytes - readExact(&BOM_buffer[n++],1); - while (n > m) { - n -= 2; - wchar cw = *(cast(wchar*)&BOM_buffer[n]); - fixBO(&cw,2); - ungetcw(cw); - } - } - return result; - } - - /*** - * Correct the byte order of buffer to match native endianness. - * size must be even. - */ - final void fixBO(void* buffer, uint size) { - if (endian != std.system.endian) { - ubyte* startb = cast(ubyte*)buffer; - uint* start = cast(uint*)buffer; - switch (size) { - case 0: break; - case 2: { - ubyte x = *startb; - *startb = *(startb+1); - *(startb+1) = x; - break; - } - case 4: { - *start = bswap(*start); - break; - } - default: { - uint* end = cast(uint*)(buffer + size - uint.sizeof); - while (start < end) { - uint x = bswap(*start); - *start = bswap(*end); - *end = x; - ++start; - --end; - } - startb = cast(ubyte*)start; - ubyte* endb = cast(ubyte*)end; - int len = uint.sizeof - (startb - endb); - if (len > 0) - fixBO(startb,len); - } - } - } - } - - /*** - * Correct the byte order of the given buffer in blocks of the given size and - * repeated the given number of times. - * size must be even. - */ - final void fixBlockBO(void* buffer, uint size, size_t repeat) { - while (repeat--) { - fixBO(buffer,size); - buffer += size; - } - } - - void read(out short x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out ushort x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out int x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out uint x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out long x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out ulong x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out float x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out double x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out real x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out ifloat x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out idouble x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out ireal x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out cfloat x) { readExact(&x, x.sizeof); fixBlockBO(&x,float.sizeof,2); } - void read(out cdouble x) { readExact(&x, x.sizeof); fixBlockBO(&x,double.sizeof,2); } - void read(out creal x) { readExact(&x, x.sizeof); fixBlockBO(&x,real.sizeof,2); } - void read(out wchar x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - void read(out dchar x) { readExact(&x, x.sizeof); fixBO(&x,x.sizeof); } - - wchar getcw() { - wchar c; - if (prevCr) { - prevCr = false; - c = getcw(); - if (c != '\n') - return c; - } - if (unget.length > 1) { - c = unget[unget.length - 1]; - unget.length = unget.length - 1; - } else { - void* buf = &c; - size_t n = readBlock(buf,2); - if (n == 1 && readBlock(buf+1,1) == 0) - throw new ReadException("not enough data in stream"); - fixBO(&c,c.sizeof); - } - return c; - } - - wchar[] readStringW(size_t length) { - wchar[] result = new wchar[length]; - readExact(result.ptr, result.length * wchar.sizeof); - fixBlockBO(&result,2,length); - return result; - } - - /// Write the specified BOM b to the source stream. - void writeBOM(BOM b) { - ubyte[] bom = ByteOrderMarks[b]; - writeBlock(bom.ptr, bom.length); - } - - void write(short x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(ushort x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(int x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(uint x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(long x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(ulong x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(float x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(double x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(real x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(ifloat x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(idouble x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(ireal x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(cfloat x) { fixBlockBO(&x,float.sizeof,2); writeExact(&x, x.sizeof); } - void write(cdouble x) { fixBlockBO(&x,double.sizeof,2); writeExact(&x, x.sizeof); } - void write(creal x) { fixBlockBO(&x,real.sizeof,2); writeExact(&x, x.sizeof); } - void write(wchar x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - void write(dchar x) { fixBO(&x,x.sizeof); writeExact(&x, x.sizeof); } - - void writeStringW(wchar[] str) { - foreach(wchar cw;str) { - fixBO(&cw,2); - s.writeExact(&cw, 2); - } - } - - override bool eof() { return s.eof() && !ungetAvailable(); } - override ulong size() { return s.size(); } - - unittest { - MemoryStream m; - m = new MemoryStream (); - EndianStream em = new EndianStream(m,Endian.BigEndian); - uint x = 0x11223344; - em.write(x); - assert( m.data[0] == 0x11 ); - assert( m.data[1] == 0x22 ); - assert( m.data[2] == 0x33 ); - assert( m.data[3] == 0x44 ); - em.position(0); - ushort x2 = 0x5566; - em.write(x2); - assert( m.data[0] == 0x55 ); - assert( m.data[1] == 0x66 ); - em.position(0); - static ubyte[12] x3 = [1,2,3,4,5,6,7,8,9,10,11,12]; - em.fixBO(x3,12); - if (std.system.endian == Endian.LittleEndian) { - assert( x3[0] == 12 ); - assert( x3[1] == 11 ); - assert( x3[2] == 10 ); - assert( x3[4] == 8 ); - assert( x3[5] == 7 ); - assert( x3[6] == 6 ); - assert( x3[8] == 4 ); - assert( x3[9] == 3 ); - assert( x3[10] == 2 ); - assert( x3[11] == 1 ); - } - em.endian = Endian.LittleEndian; - em.write(x); - assert( m.data[0] == 0x44 ); - assert( m.data[1] == 0x33 ); - assert( m.data[2] == 0x22 ); - assert( m.data[3] == 0x11 ); - em.position(0); - em.write(x2); - assert( m.data[0] == 0x66 ); - assert( m.data[1] == 0x55 ); - em.position(0); - em.fixBO(x3,12); - if (std.system.endian == Endian.BigEndian) { - assert( x3[0] == 12 ); - assert( x3[1] == 11 ); - assert( x3[2] == 10 ); - assert( x3[4] == 8 ); - assert( x3[5] == 7 ); - assert( x3[6] == 6 ); - assert( x3[8] == 4 ); - assert( x3[9] == 3 ); - assert( x3[10] == 2 ); - assert( x3[11] == 1 ); - } - em.writeBOM(BOM.UTF8); - assert( m.position() == 3 ); - assert( m.data[0] == 0xEF ); - assert( m.data[1] == 0xBB ); - assert( m.data[2] == 0xBF ); - em.writeString ("Hello, world"); - em.position(0); - assert( m.position() == 0 ); - assert( em.readBOM == BOM.UTF8 ); - assert( m.position() == 3 ); - assert( em.getc() == 'H' ); - em.position(0); - em.writeBOM(BOM.UTF16BE); - assert( m.data[0] == 0xFE ); - assert( m.data[1] == 0xFF ); - em.position(0); - em.writeBOM(BOM.UTF16LE); - assert( m.data[0] == 0xFF ); - assert( m.data[1] == 0xFE ); - em.position(0); - em.writeString ("Hello, world"); - em.position(0); - assert( em.readBOM == -1 ); - assert( em.getc() == 'H' ); - assert( em.getc() == 'e' ); - assert( em.getc() == 'l' ); - assert( em.getc() == 'l' ); - em.position(0); - } -} -+/ - -/*** - * Parameterized subclass that wraps an array-like buffer with a stream - * interface. - * - * The type Buffer must support the length property, opIndex and opSlice. - * Compile in release mode when directly instantiating a TArrayStream to avoid - * link errors. - */ -class TArrayStream(Buffer): Stream { - Buffer buf; // current data - ulong len; // current data length - ulong cur; // current file position - - /// Create the stream for the the buffer buf. Non-copying. - this(Buffer buf) { - super (); - this.buf = buf; - this.len = buf.length; - readable = writeable = seekable = true; - } - - // ensure subclasses don't violate this - invariant { - assert(len <= buf.length); - assert(cur <= len); - } - - override size_t readBlock(void* buffer, size_t size) { - assertReadable(); - ubyte* cbuf = cast(ubyte*) buffer; - if (len - cur < size) - size = cast(size_t)(len - cur); - ubyte[] ubuf = cast(ubyte[])buf[cast(size_t)cur .. cast(size_t)(cur + size)]; - cbuf[0 .. size] = ubuf[]; - cur += size; - return size; - } - - override size_t writeBlock(void* buffer, size_t size) { - assertWriteable(); - ubyte* cbuf = cast(ubyte*) buffer; - ulong blen = buf.length; - if (cur + size > blen) - size = cast(size_t)(blen - cur); - ubyte[] ubuf = cast(ubyte[])buf[cast(size_t)cur .. cast(size_t)(cur + size)]; - ubuf[] = cbuf[0 .. size]; - cur += size; - if (cur > len) - len = cur; - return size; - } - - override ulong seek(long offset, SeekPos rel) { - assertSeekable(); - long scur; // signed to saturate to 0 properly - - switch (rel) { - case SeekPos.Set: scur = offset; break; - case SeekPos.Current: scur = cast(long)(cur + offset); break; - case SeekPos.End: scur = cast(long)(len + offset); break; - default: - assert(0); - } - - if (scur < 0) - cur = 0; - else if (scur > len) - cur = len; - else - cur = cast(ulong)scur; - - return cur; - } - - override size_t available () { return cast(size_t)(len - cur); } - - /// Get the current memory data in total. - ubyte[] data() { - if (len > size_t.max) - throw new StreamException("Stream too big"); - void[] res = buf[0 .. cast(size_t)len]; - return cast(ubyte[])res; - } - - override char[] toString() { - return cast(char[]) data (); - } -} - -/* Test the TArrayStream */ -unittest { - char[100] buf; - TArrayStream!(char[]) m; - - m = new TArrayStream!(char[]) (buf); - assert (m.isOpen); - m.writeString ("Hello, world"); - assert (m.position () == 12); - assert (m.available == 88); - assert (m.seekSet (0) == 0); - assert (m.available == 100); - assert (m.seekCur (4) == 4); - assert (m.available == 96); - assert (m.seekEnd (-8) == 92); - assert (m.available == 8); - assert (m.size () == 100); - assert (m.seekSet (4) == 4); - assert (m.readString (4) == "o, w"); - m.writeString ("ie"); - assert (buf[0..12] == "Hello, wield"); - assert (m.position == 10); - assert (m.available == 90); - assert (m.size () == 100); -} - -/// This subclass reads and constructs an array of bytes in memory. -class MemoryStream: TArrayStream!(ubyte[]) { - - /// Create the output buffer and setup for reading, writing, and seeking. - // clear to an empty buffer. - this() { this(cast(ubyte[]) null); } - - /*** - * Create the output buffer and setup for reading, writing, and seeking. - * Load it with specific input data. - */ - this(ubyte[] buf) { super (buf); } - this(byte[] buf) { this(cast(ubyte[]) buf); } /// ditto - this(char[] buf) { this(cast(ubyte[]) buf); } /// ditto - - /// Ensure the stream can hold count bytes. - void reserve(size_t count) { - if (cur + count > buf.length) - buf.length = cast(size_t)((cur + count) * 2); - } - - override size_t writeBlock(void* buffer, size_t size) { - reserve(size); - return super.writeBlock(buffer,size); - } - - unittest { - MemoryStream m; - - m = new MemoryStream (); - assert (m.isOpen); - m.writeString ("Hello, world"); - assert (m.position () == 12); - assert (m.seekSet (0) == 0); - assert (m.available == 12); - assert (m.seekCur (4) == 4); - assert (m.available == 8); - assert (m.seekEnd (-8) == 4); - assert (m.available == 8); - assert (m.size () == 12); - assert (m.readString (4) == "o, w"); - m.writeString ("ie"); - assert (cast(char[]) m.data () == "Hello, wield"); - m.seekEnd (0); - m.writeString ("Foo"); - assert (m.position () == 15); - assert (m.available == 0); - m.writeString ("Foo foo foo foo foo foo foo"); - assert (m.position () == 42); - m.position = 0; - assert (m.available == 42); - m.writef("%d %d %s",100,345,"hello"); - char[] str = m.toString; - assert (str[0..13] == "100 345 hello"); - assert (m.available == 29); - assert (m.position == 13); - - MemoryStream m2; - m.position = 3; - m2 = new MemoryStream (); - m2.writeString("before"); - m2.copyFrom(m,10); - str = m2.toString; - assert (str[0..16] == "before 345 hello"); - m2.position = 3; - m2.copyFrom(m); - char[] str2 = m.toString; - str = m2.toString; - assert (str == ("bef" ~ str2)); - } -} - -import std.mmfile; - -/*** - * This subclass wraps a memory-mapped file with the stream API. - * See std.mmfile module. - */ -class MmFileStream : TArrayStream!(MmFile) { - - /// Create stream wrapper for file. - this(MmFile file) { - super (file); - MmFile.Mode mode = file.mode; - writeable = mode > MmFile.Mode.Read; - } - - override void flush() { - if (isopen) { - super.flush(); - buf.flush(); - } - } - - override void close() { - if (isopen) { - super.close(); - delete buf; - buf = null; - } - } -} - -unittest { - MmFile mf = new MmFile("testing.txt",MmFile.Mode.ReadWriteNew,100,null); - MmFileStream m; - m = new MmFileStream (mf); - m.writeString ("Hello, world"); - assert (m.position () == 12); - assert (m.seekSet (0) == 0); - assert (m.seekCur (4) == 4); - assert (m.seekEnd (-8) == 92); - assert (m.size () == 100); - assert (m.seekSet (4)); - assert (m.readString (4) == "o, w"); - m.writeString ("ie"); - ubyte[] dd = m.data(); - assert ((cast(char[]) dd)[0 .. 12] == "Hello, wield"); - m.position = 12; - m.writeString ("Foo"); - assert (m.position () == 15); - m.writeString ("Foo foo foo foo foo foo foo"); - assert (m.position () == 42); - m.close(); - mf = new MmFile("testing.txt"); - m = new MmFileStream (mf); - assert (!m.writeable); - char[] str = m.readString(12); - assert (str == "Hello, wield"); - m.close(); - std.file.remove("testing.txt"); -} - - -/*** - * This subclass slices off a portion of another stream, making seeking relative - * to the boundaries of the slice. - * - * It could be used to section a large file into a - * set of smaller files, such as with tar archives. Reading and writing a - * SliceStream does not modify the position of the source stream if it is - * seekable. - */ -class SliceStream : FilterStream { - private { - ulong pos; // our position relative to low - ulong low; // low stream offset. - ulong high; // high stream offset. - bool bounded; // upper-bounded by high. - } - - /*** - * Indicate both the source stream to use for reading from and the low part of - * the slice. - * - * The high part of the slice is dependent upon the end of the source - * stream, so that if you write beyond the end it resizes the stream normally. - */ - this (Stream s, ulong low) - in { - assert (low <= s.size ()); - } - body { - super(s); - this.low = low; - this.high = 0; - this.bounded = false; - } - - /*** - * Indicate the high index as well. - * - * Attempting to read or write past the high - * index results in the end being clipped off. - */ - this (Stream s, ulong low, ulong high) - in { - assert (low <= high); - assert (high <= s.size ()); - } - body { - super(s); - this.low = low; - this.high = high; - this.bounded = true; - } - - invariant { - if (bounded) - assert (pos <= high - low); - else - assert (pos <= s.size - low); - } - - override size_t readBlock (void *buffer, size_t size) { - assertReadable(); - if (bounded && size > high - low - pos) - size = cast(size_t)(high - low - pos); - ulong bp = s.position; - if (seekable) - s.position = low + pos; - size_t ret = super.readBlock(buffer, size); - if (seekable) { - pos = s.position - low; - s.position = bp; - } - return ret; - } - - override size_t writeBlock (void *buffer, size_t size) { - assertWriteable(); - if (bounded && size > high - low - pos) - size = cast(size_t)(high - low - pos); - ulong bp = s.position; - if (seekable) - s.position = low + pos; - size_t ret = s.writeBlock(buffer, size); - if (seekable) { - pos = s.position - low; - s.position = bp; - } - return ret; - } - - override ulong seek(long offset, SeekPos rel) { - assertSeekable(); - long spos; - - switch (rel) { - case SeekPos.Set: - spos = offset; - break; - case SeekPos.Current: - spos = cast(long)(pos + offset); - break; - case SeekPos.End: - if (bounded) - spos = cast(long)(high - low + offset); - else - spos = cast(long)(s.size - low + offset); - break; - default: - assert(0); - } - - if (spos < 0) - pos = 0; - else if (bounded && spos > high - low) - pos = high - low; - else if (!bounded && spos > s.size - low) - pos = s.size - low; - else - pos = cast(ulong)spos; - - readEOF = false; - return pos; - } - - override size_t available () { - size_t res = s.available; - ulong bp = s.position; - if (bp <= pos+low && pos+low <= bp+res) { - if (!bounded || bp+res <= high) - return cast(size_t)(bp + res - pos - low); - else if (high <= bp+res) - return cast(size_t)(high - pos - low); - } - return 0; - } - - unittest { - MemoryStream m; - SliceStream s; - - m = new MemoryStream ((cast(char[])"Hello, world").dup); - s = new SliceStream (m, 4, 8); - assert (s.size () == 4); - assert (m.position () == 0); - assert (s.position () == 0); - assert (m.available == 12); - assert (s.available == 4); - - assert (s.writeBlock (cast(char *) "Vroom", 5) == 4); - assert (m.position () == 0); - assert (s.position () == 4); - assert (m.available == 12); - assert (s.available == 0); - assert (s.seekEnd (-2) == 2); - assert (s.available == 2); - assert (s.seekEnd (2) == 4); - assert (s.available == 0); - assert (m.position () == 0); - assert (m.available == 12); - - m.seekEnd(0); - m.writeString("\nBlaho"); - assert (m.position == 18); - assert (m.available == 0); - assert (s.position == 4); - assert (s.available == 0); - - s = new SliceStream (m, 4); - assert (s.size () == 14); - assert (s.toString () == "Vrooorld\nBlaho"); - s.seekEnd (0); - assert (s.available == 0); - - s.writeString (", etcetera."); - assert (s.position () == 25); - assert (s.seekSet (0) == 0); - assert (s.size () == 25); - assert (m.position () == 18); - assert (m.size () == 29); - assert (m.toString() == "HellVrooorld\nBlaho, etcetera."); - } -} - -// helper functions -private bool iswhite(char c) { - return c == ' ' || c == '\t' || c == '\r' || c == '\n'; -} - -private bool isdigit(char c) { - return c >= '0' && c <= '9'; -} - -private bool isoctdigit(char c) { - return c >= '0' && c <= '7'; -} - -private bool ishexdigit(char c) { - return isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); -} diff --git a/lphobos/std/string.d b/lphobos/std/string.d deleted file mode 100644 index 383a19b5a7e..00000000000 --- a/lphobos/std/string.d +++ /dev/null @@ -1,4085 +0,0 @@ - -// Written in the D programming language. - -/** - * String handling functions. - * - * To copy or not to copy? - * When a function takes a string as a parameter, and returns a string, - * is that string the same as the input string, modified in place, or - * is it a modified copy of the input string? The D array convention is - * "copy-on-write". This means that if no modifications are done, the - * original string (or slices of it) can be returned. If any modifications - * are done, the returned string is a copy. - * - * Macros: - * WIKI = Phobos/StdString - * Copyright: - * Public Domain - */ - -/* Author: - * Walter Bright, Digital Mars, www.digitalmars.com - */ - -// The code is not optimized for speed, that will have to wait -// until the design is solidified. - -module std.string; - -//debug=string; // uncomment to turn on debugging printf's - -//private import std.stdio; -private import std.c.stdio; -private import std.c.stdlib; -private import std.c.string; -private import std.utf; -private import std.uni; -private import std.array; -private import std.format; -private import std.ctype; -private import std.stdarg; -alias std.c.string.strlen strlen; -alias std.c.string.strcmp strcmp; - -extern (C) -{ - - size_t wcslen(wchar *); - int wcscmp(wchar *, wchar *); -} - -/* ************* Exceptions *************** */ - -/// Thrown on errors in string functions. -class StringException : Exception -{ - this(char[] msg) /// Constructor - { - super(msg); - } -} - -/* ************* Constants *************** */ - -const char[16] hexdigits = "0123456789ABCDEF"; /// 0..9A..F -const char[10] digits = "0123456789"; /// 0..9 -const char[8] octdigits = "01234567"; /// 0..7 -const char[26] lowercase = "abcdefghijklmnopqrstuvwxyz"; /// a..z -const char[26] uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /// A..Z -const char[52] letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; /// A..Za..z -const char[6] whitespace = " \t\v\r\n\f"; /// ASCII whitespace - -const dchar LS = '\u2028'; /// UTF line separator -const dchar PS = '\u2029'; /// UTF paragraph separator - -/// Newline sequence for this system -version (Windows) - const char[2] newline = "\r\n"; -else version (linux) - const char[1] newline = "\n"; - -/********************************** - * Returns true if c is whitespace - */ - -bool iswhite(dchar c) -{ - return (c <= 0x7F) - ? find(whitespace, c) != -1 - : (c == PS || c == LS); -} - -/********************************* - * Convert string to integer. - */ - -long atoi(char[] s) -{ - return std.c.stdlib.atoi(toStringz(s)); -} - -/************************************* - * Convert string to real. - */ - -real atof(char[] s) -{ char* endptr; - - auto result = strtold(toStringz(s), &endptr); - return result; -} - -/********************************** - * Compare two strings. cmp is case sensitive, icmp is case insensitive. - * Returns: - * - * $(TR $(TD < 0) $(TD s1 < s2)) - * $(TR $(TD = 0) $(TD s1 == s2)) - * $(TR $(TD > 0) $(TD s1 > s2)) - *
- */ - -int cmp(char[] s1, char[] s2) -{ - auto len = s1.length; - int result; - - //printf("cmp('%.*s', '%.*s')\n", s1, s2); - if (s2.length < len) - len = s2.length; - result = memcmp(s1.ptr, s2.ptr, len); - if (result == 0) - result = cast(int)s1.length - cast(int)s2.length; - return result; -} - -/********************************* - * ditto - */ - -int icmp(char[] s1, char[] s2) -{ - auto len = s1.length; - int result; - - if (s2.length < len) - len = s2.length; - version (Win32) - { - result = memicmp(s1.ptr, s2.ptr, len); - } - version (linux) - { - for (size_t i = 0; i < len; i++) - { - if (s1[i] != s2[i]) - { - char c1 = s1[i]; - char c2 = s2[i]; - - if (c1 >= 'A' && c1 <= 'Z') - c1 += cast(int)'a' - cast(int)'A'; - if (c2 >= 'A' && c2 <= 'Z') - c2 += cast(int)'a' - cast(int)'A'; - result = cast(int)c1 - cast(int)c2; - if (result) - break; - } - } - } - if (result == 0) - result = cast(int)s1.length - cast(int)s2.length; - return result; -} - -unittest -{ - int result; - - debug(string) printf("string.cmp.unittest\n"); - result = icmp("abc", "abc"); - assert(result == 0); - result = icmp(null, null); - assert(result == 0); - result = icmp("", ""); - assert(result == 0); - result = icmp("abc", "abcd"); - assert(result < 0); - result = icmp("abcd", "abc"); - assert(result > 0); - result = icmp("abc", "abd"); - assert(result < 0); - result = icmp("bbc", "abc"); - assert(result > 0); -} - -/* ******************************** - * Converts a D array of chars to a C-style 0 terminated string. - * Deprecated: replaced with toStringz(). - */ - -deprecated char* toCharz(char[] s) -{ - return toStringz(s); -} - -/********************************* - * Convert array of chars s[] to a C-style 0 terminated string. - */ - -char* toStringz(char[] s) - in - { - } - out (result) - { - if (result) - { assert(strlen(result) == s.length); - assert(memcmp(result, s.ptr, s.length) == 0); - } - } - body - { - char[] copy; - - if (s.length == 0) - return ""; - - /+ Unfortunately, this isn't reliable. - We could make this work if string literals are put - in read-only memory and we test if s[] is pointing into - that. - - /* Peek past end of s[], if it's 0, no conversion necessary. - * Note that the compiler will put a 0 past the end of static - * strings, and the storage allocator will put a 0 past the end - * of newly allocated char[]'s. - */ - char* p = &s[0] + s.length; - if (*p == 0) - return s; - +/ - - // Need to make a copy - copy = new char[s.length + 1]; - copy[0..s.length] = s; - copy[s.length] = 0; - return copy.ptr; - } - -unittest -{ - debug(string) printf("string.toStringz.unittest\n"); - - char* p = toStringz("foo"); - assert(strlen(p) == 3); - char foo[] = "abbzxyzzy"; - p = toStringz(foo[3..5]); - assert(strlen(p) == 2); - - char[] test = ""; - p = toStringz(test); - assert(*p == 0); -} - -/****************************************** - * find, ifind _find first occurrence of c in string s. - * rfind, irfind _find last occurrence of c in string s. - * - * find, rfind are case sensitive; ifind, irfind are case insensitive. - * Returns: - * Index in s where c is found, -1 if not found. - */ - -int find(char[] s, dchar c) -{ - if (c <= 0x7F) - { // Plain old ASCII - auto p = cast(char*)memchr(s.ptr, c, s.length); - if (p) - return p - cast(char *)s; - else - return -1; - } - - // c is a universal character - foreach (int i, dchar c2; s) - { - if (c == c2) - return i; - } - return -1; -} - -unittest -{ - debug(string) printf("string.find.unittest\n"); - - int i; - - i = find(null, cast(dchar)'a'); - assert(i == -1); - i = find("def", cast(dchar)'a'); - assert(i == -1); - i = find("abba", cast(dchar)'a'); - assert(i == 0); - i = find("def", cast(dchar)'f'); - assert(i == 2); -} - - -/****************************************** - * ditto - */ - -int ifind(char[] s, dchar c) -{ - char* p; - - if (c <= 0x7F) - { // Plain old ASCII - char c1 = cast(char) std.ctype.tolower(c); - - foreach (int i, char c2; s) - { - c2 = cast(char)std.ctype.tolower(c2); - if (c1 == c2) - return i; - } - } - else - { // c is a universal character - dchar c1 = std.uni.toUniLower(c); - - foreach (int i, dchar c2; s) - { - c2 = std.uni.toUniLower(c2); - if (c1 == c2) - return i; - } - } - return -1; -} - -unittest -{ - debug(string) printf("string.ifind.unittest\n"); - - int i; - - i = ifind(null, cast(dchar)'a'); - assert(i == -1); - i = ifind("def", cast(dchar)'a'); - assert(i == -1); - i = ifind("Abba", cast(dchar)'a'); - assert(i == 0); - i = ifind("def", cast(dchar)'F'); - assert(i == 2); - - char[] sPlts = "Mars: the fourth Rock (Planet) from the Sun."; - - i = ifind("def", cast(char)'f'); - assert(i == 2); - - i = ifind(sPlts, cast(char)'P'); - assert(i == 23); - i = ifind(sPlts, cast(char)'R'); - assert(i == 2); -} - - -/****************************************** - * ditto - */ - -int rfind(char[] s, dchar c) -{ - size_t i; - - if (c <= 0x7F) - { // Plain old ASCII - for (i = s.length; i-- != 0;) - { - if (s[i] == c) - break; - } - return i; - } - - // c is a universal character - char[4] buf; - char[] t; - t = std.utf.toUTF8(buf, c); - return rfind(s, t); -} - -unittest -{ - debug(string) printf("string.rfind.unittest\n"); - - int i; - - i = rfind(null, cast(dchar)'a'); - assert(i == -1); - i = rfind("def", cast(dchar)'a'); - assert(i == -1); - i = rfind("abba", cast(dchar)'a'); - assert(i == 3); - i = rfind("def", cast(dchar)'f'); - assert(i == 2); -} - -/****************************************** - * ditto - */ - -int irfind(char[] s, dchar c) -{ - size_t i; - - if (c <= 0x7F) - { // Plain old ASCII - char c1 = cast(char) std.ctype.tolower(c); - - for (i = s.length; i-- != 0;) - { char c2 = s[i]; - - c2 = cast(char) std.ctype.tolower(c2); - if (c1 == c2) - break; - } - } - else - { // c is a universal character - dchar c1 = std.uni.toUniLower(c); - - for (i = s.length; i-- != 0;) - { char cx = s[i]; - - if (cx <= 0x7F) - continue; // skip, since c is not ASCII - if ((cx & 0xC0) == 0x80) - continue; // skip non-starting UTF-8 chars - - size_t j = i; - dchar c2 = std.utf.decode(s, j); - c2 = std.uni.toUniLower(c2); - if (c1 == c2) - break; - } - } - return i; -} - -unittest -{ - debug(string) printf("string.irfind.unittest\n"); - - int i; - - i = irfind(null, cast(dchar)'a'); - assert(i == -1); - i = irfind("def", cast(dchar)'a'); - assert(i == -1); - i = irfind("AbbA", cast(dchar)'a'); - assert(i == 3); - i = irfind("def", cast(dchar)'F'); - assert(i == 2); - - char[] sPlts = "Mars: the fourth Rock (Planet) from the Sun."; - - i = irfind("def", cast(char)'f'); - assert(i == 2); - - i = irfind(sPlts, cast(char)'M'); - assert(i == 34); - i = irfind(sPlts, cast(char)'S'); - assert(i == 40); -} - - -/****************************************** - * find, ifind _find first occurrence of sub[] in string s[]. - * rfind, irfind _find last occurrence of sub[] in string s[]. - * - * find, rfind are case sensitive; ifind, irfind are case insensitive. - * Returns: - * Index in s where c is found, -1 if not found. - */ - -int find(char[] s, char[] sub) - out (result) - { - if (result == -1) - { - } - else - { - assert(0 <= result && result < s.length - sub.length + 1); - assert(memcmp(&s[result], sub.ptr, sub.length) == 0); - } - } - body - { - auto sublength = sub.length; - - if (sublength == 0) - return 0; - - if (s.length >= sublength) - { - auto c = sub[0]; - if (sublength == 1) - { - auto p = cast(char*)memchr(s.ptr, c, s.length); - if (p) - return p - &s[0]; - } - else - { - size_t imax = s.length - sublength + 1; - - // Remainder of sub[] - char *q = &sub[1]; - sublength--; - - for (size_t i = 0; i < imax; i++) - { - char *p = cast(char*)memchr(&s[i], c, imax - i); - if (!p) - break; - i = p - &s[0]; - if (memcmp(p + 1, q, sublength) == 0) - return i; - } - } - } - return -1; - } - - -unittest -{ - debug(string) printf("string.find.unittest\n"); - - int i; - - i = find(null, "a"); - assert(i == -1); - i = find("def", "a"); - assert(i == -1); - i = find("abba", "a"); - assert(i == 0); - i = find("def", "f"); - assert(i == 2); - i = find("dfefffg", "fff"); - assert(i == 3); - i = find("dfeffgfff", "fff"); - assert(i == 6); -} - -/****************************************** - * ditto - */ - -int ifind(char[] s, char[] sub) - out (result) - { - if (result == -1) - { - } - else - { - assert(0 <= result && result < s.length - sub.length + 1); - assert(icmp(s[result .. result + sub.length], sub) == 0); - } - } - body - { - auto sublength = sub.length; - int i; - - if (sublength == 0) - return 0; - - if (s.length < sublength) - return -1; - - auto c = sub[0]; - if (sublength == 1) - { - i = ifind(s, c); - } - else if (c <= 0x7F) - { - size_t imax = s.length - sublength + 1; - - // Remainder of sub[] - char[] subn = sub[1 .. sublength]; - - for (i = 0; i < imax; i++) - { - auto j = ifind(s[i .. imax], c); - if (j == -1) - return -1; - i += j; - if (icmp(s[i + 1 .. i + sublength], subn) == 0) - return i; - } - i = -1; - } - else - { - size_t imax = s.length - sublength; - - for (i = 0; i <= imax; i++) - { - if (icmp(s[i .. i + sublength], sub) == 0) - return i; - } - i = -1; - } - return i; - } - - -unittest -{ - debug(string) printf("string.ifind.unittest\n"); - - int i; - - i = ifind(null, "a"); - assert(i == -1); - i = ifind("def", "a"); - assert(i == -1); - i = ifind("abba", "a"); - assert(i == 0); - i = ifind("def", "f"); - assert(i == 2); - i = ifind("dfefffg", "fff"); - assert(i == 3); - i = ifind("dfeffgfff", "fff"); - assert(i == 6); - - char[] sPlts = "Mars: the fourth Rock (Planet) from the Sun."; - char[] sMars = "Who\'s \'My Favorite Maritian?\'"; - - i = ifind(sMars, "MY fAVe"); - assert(i == -1); - i = ifind(sMars, "mY fAVOriTe"); - assert(i == 7); - i = ifind(sPlts, "mArS:"); - assert(i == 0); - i = ifind(sPlts, "rOcK"); - assert(i == 17); - i = ifind(sPlts, "Un."); - assert(i == 41); - i = ifind(sPlts, sPlts); - assert(i == 0); - - i = ifind("\u0100", "\u0100"); - assert(i == 0); - - // Thanks to Carlos Santander B. and zwang - i = ifind("sus mejores cortesanos. Se embarcaron en el puerto de Dubai y", - "page-break-before"); - assert(i == -1); -} - -/****************************************** - * ditto - */ - -int rfind(char[] s, char[] sub) - out (result) - { - if (result == -1) - { - } - else - { - assert(0 <= result && result < s.length - sub.length + 1); - assert(memcmp(&s[0] + result, sub.ptr, sub.length) == 0); - } - } - body - { - char c; - - if (sub.length == 0) - return s.length; - c = sub[0]; - if (sub.length == 1) - return rfind(s, c); - for (int i = s.length - sub.length; i >= 0; i--) - { - if (s[i] == c) - { - if (memcmp(&s[i + 1], &sub[1], sub.length - 1) == 0) - return i; - } - } - return -1; - } - -unittest -{ - int i; - - debug(string) printf("string.rfind.unittest\n"); - i = rfind("abcdefcdef", "c"); - assert(i == 6); - i = rfind("abcdefcdef", "cd"); - assert(i == 6); - i = rfind("abcdefcdef", "x"); - assert(i == -1); - i = rfind("abcdefcdef", "xy"); - assert(i == -1); - i = rfind("abcdefcdef", ""); - assert(i == 10); -} - - -/****************************************** - * ditto - */ - -int irfind(char[] s, char[] sub) - out (result) - { - if (result == -1) - { - } - else - { - assert(0 <= result && result < s.length - sub.length + 1); - assert(icmp(s[result .. result + sub.length], sub) == 0); - } - } - body - { - dchar c; - - if (sub.length == 0) - return s.length; - c = sub[0]; - if (sub.length == 1) - return irfind(s, c); - if (c <= 0x7F) - { - c = std.ctype.tolower(c); - for (int i = s.length - sub.length; i >= 0; i--) - { - if (std.ctype.tolower(s[i]) == c) - { - if (icmp(s[i + 1 .. i + sub.length], sub[1 .. sub.length]) == 0) - return i; - } - } - } - else - { - for (int i = s.length - sub.length; i >= 0; i--) - { - if (icmp(s[i .. i + sub.length], sub) == 0) - return i; - } - } - return -1; - } - -unittest -{ - int i; - - debug(string) printf("string.irfind.unittest\n"); - i = irfind("abcdefCdef", "c"); - assert(i == 6); - i = irfind("abcdefCdef", "cD"); - assert(i == 6); - i = irfind("abcdefcdef", "x"); - assert(i == -1); - i = irfind("abcdefcdef", "xy"); - assert(i == -1); - i = irfind("abcdefcdef", ""); - assert(i == 10); - - char[] sPlts = "Mars: the fourth Rock (Planet) from the Sun."; - char[] sMars = "Who\'s \'My Favorite Maritian?\'"; - - i = irfind("abcdefcdef", "c"); - assert(i == 6); - i = irfind("abcdefcdef", "cd"); - assert(i == 6); - i = irfind( "abcdefcdef", "def" ); - assert(i == 7); - - i = irfind(sMars, "RiTE maR"); - assert(i == 14); - i = irfind(sPlts, "FOuRTh"); - assert(i == 10); - i = irfind(sMars, "whO\'s \'MY"); - assert(i == 0); - i = irfind(sMars, sMars); - assert(i == 0); -} - - -/************************************ - * Convert string s[] to lower case. - */ - -string tolower(string s) -{ - int changed; - char[] r; - - for (size_t i = 0; i < s.length; i++) - { - auto c = s[i]; - if ('A' <= c && c <= 'Z') - { - if (!changed) - { - r = s.dup; - changed = 1; - } - r[i] = cast(char) (c + (cast(char)'a' - 'A')); - } - else if (c > 0x7F) - { - foreach (size_t j, dchar dc; s[i .. length]) - { - if (std.uni.isUniUpper(dc)) - { - dc = std.uni.toUniLower(dc); - if (!changed) - { - r = s[0 .. i + j].dup; - changed = 2; - } - } - if (changed) - { - if (changed == 1) - { r = r[0 .. i + j]; - changed = 2; - } - std.utf.encode(r, dc); - } - } - break; - } - } - return changed ? r : s; -} - -unittest -{ - debug(string) printf("string.tolower.unittest\n"); - - char[] s1 = "FoL"; - char[] s2; - - s2 = tolower(s1); - assert(cmp(s2, "fol") == 0); - assert(s2 != s1); - - s1 = "A\u0100B\u0101d"; - s2 = tolower(s1); - assert(cmp(s2, "a\u0101b\u0101d") == 0); - assert(s2 !is s1); - - s1 = "A\u0460B\u0461d"; - s2 = tolower(s1); - assert(cmp(s2, "a\u0461b\u0461d") == 0); - assert(s2 !is s1); - - s1 = "\u0130"; - s2 = tolower(s1); - assert(s2 == "i"); - assert(s2 !is s1); -} - -/************************************ - * Convert string s[] to upper case. - */ - -string toupper(string s) -{ - int changed; - char[] r; - - for (size_t i = 0; i < s.length; i++) - { - auto c = s[i]; - if ('a' <= c && c <= 'z') - { - if (!changed) - { - r = s.dup; - changed = 1; - } - r[i] = cast(char) (c - (cast(char)'a' - 'A')); - } - else if (c > 0x7F) - { - foreach (size_t j, dchar dc; s[i .. length]) - { - if (std.uni.isUniLower(dc)) - { - dc = std.uni.toUniUpper(dc); - if (!changed) - { - r = s[0 .. i + j].dup; - changed = 2; - } - } - if (changed) - { - if (changed == 1) - { r = r[0 .. i + j]; - changed = 2; - } - std.utf.encode(r, dc); - } - } - break; - } - } - return changed ? r : s; -} - -unittest -{ - debug(string) printf("string.toupper.unittest\n"); - - char[] s1 = "FoL"; - char[] s2; - - s2 = toupper(s1); - assert(cmp(s2, "FOL") == 0); - assert(s2 !is s1); - - s1 = "a\u0100B\u0101d"; - s2 = toupper(s1); - assert(cmp(s2, "A\u0100B\u0100D") == 0); - assert(s2 !is s1); - - s1 = "a\u0460B\u0461d"; - s2 = toupper(s1); - assert(cmp(s2, "A\u0460B\u0460D") == 0); - assert(s2 !is s1); -} - - -/******************************************** - * Capitalize first character of string s[], convert rest of string s[] - * to lower case. - */ - -char[] capitalize(char[] s) -{ - int changed; - int i; - char[] r = s; - - changed = 0; - - foreach (size_t i, dchar c; s) - { dchar c2; - - if (i == 0) - { - c2 = std.uni.toUniUpper(c); - if (c != c2) - { - changed = 1; - r = null; - } - } - else - { - c2 = std.uni.toUniLower(c); - if (c != c2) - { - if (!changed) - { changed = 1; - r = s[0 .. i].dup; - } - } - } - if (changed) - std.utf.encode(r, c2); - } - return r; -} - - -unittest -{ - debug(string) printf("string.toupper.capitalize\n"); - - char[] s1 = "FoL"; - char[] s2; - - s2 = capitalize(s1); - assert(cmp(s2, "Fol") == 0); - assert(s2 !is s1); - - s2 = capitalize(s1[0 .. 2]); - assert(cmp(s2, "Fo") == 0); - assert(s2.ptr == s1.ptr); - - s1 = "fOl"; - s2 = capitalize(s1); - assert(cmp(s2, "Fol") == 0); - assert(s2 !is s1); -} - - -/******************************************** - * Capitalize all words in string s[]. - * Remove leading and trailing whitespace. - * Replace all sequences of whitespace with a single space. - */ - -char[] capwords(char[] s) -{ - char[] r; - bool inword = false; - size_t istart = 0; - size_t i; - - for (i = 0; i < s.length; i++) - { - switch (s[i]) - { - case ' ': - case '\t': - case '\f': - case '\r': - case '\n': - case '\v': - if (inword) - { - r ~= capitalize(s[istart .. i]); - inword = false; - } - break; - - default: - if (!inword) - { - if (r.length) - r ~= ' '; - istart = i; - inword = true; - } - break; - } - } - if (inword) - { - r ~= capitalize(s[istart .. i]); - } - - return r; -} - - -unittest -{ - debug(string) printf("string.capwords.unittest\n"); - - char[] s1 = "\tfoo abc(aD)* \t (q PTT "; - char[] s2; - - s2 = capwords(s1); - //writefln("s2 = '%s'", s2); - assert(cmp(s2, "Foo Abc(ad)* (q Ptt") == 0); -} - -/******************************************** - * Return a string that consists of s[] repeated n times. - */ - -char[] repeat(char[] s, size_t n) -{ - if (n == 0) - return null; - if (n == 1) - return s; - char[] r = new char[n * s.length]; - if (s.length == 1) - r[] = s[0]; - else - { auto len = s.length; - - for (size_t i = 0; i < n * len; i += len) - { - r[i .. i + len] = s[]; - } - } - return r; -} - - -unittest -{ - debug(string) printf("string.repeat.unittest\n"); - - char[] s; - - s = repeat("1234", 0); - assert(s is null); - s = repeat("1234", 1); - assert(cmp(s, "1234") == 0); - s = repeat("1234", 2); - assert(cmp(s, "12341234") == 0); - s = repeat("1", 4); - assert(cmp(s, "1111") == 0); - s = repeat(null, 4); - assert(s is null); -} - - -/******************************************** - * Concatenate all the strings in words[] together into one - * string; use sep[] as the separator. - */ - -char[] join(char[][] words, char[] sep) -{ - char[] result; - - if (words.length) - { - size_t len = 0; - size_t i; - - for (i = 0; i < words.length; i++) - len += words[i].length; - - auto seplen = sep.length; - len += (words.length - 1) * seplen; - - result = new char[len]; - - size_t j; - i = 0; - while (true) - { - uint wlen = words[i].length; - - result[j .. j + wlen] = words[i]; - j += wlen; - i++; - if (i >= words.length) - break; - result[j .. j + seplen] = sep; - j += seplen; - } - assert(j == len); - } - return result; -} - -unittest -{ - debug(string) printf("string.join.unittest\n"); - - char[] word1 = "peter"; - char[] word2 = "paul"; - char[] word3 = "jerry"; - char[][3] words; - char[] r; - int i; - - words[0] = word1; - words[1] = word2; - words[2] = word3; - r = join(words, ","); - i = cmp(r, "peter,paul,jerry"); - assert(i == 0); -} - - -/************************************** - * Split s[] into an array of words, - * using whitespace as the delimiter. - */ - -char[][] split(char[] s) -{ - size_t i; - size_t istart = 0; - bool inword = false; - char[][] words; - - for (i = 0; i < s.length; i++) - { - switch (s[i]) - { - case ' ': - case '\t': - case '\f': - case '\r': - case '\n': - case '\v': - if (inword) - { - words ~= s[istart .. i]; - inword = false; - } - break; - - default: - if (!inword) - { istart = i; - inword = true; - } - break; - } - } - if (inword) - words ~= s[istart .. i]; - return words; -} - -unittest -{ - debug(string) printf("string.split1\n"); - - char[] s = " peter paul\tjerry "; - char[][] words; - int i; - - words = split(s); - assert(words.length == 3); - i = cmp(words[0], "peter"); - assert(i == 0); - i = cmp(words[1], "paul"); - assert(i == 0); - i = cmp(words[2], "jerry"); - assert(i == 0); -} - - -/************************************** - * Split s[] into an array of words, - * using delim[] as the delimiter. - */ - -char[][] split(char[] s, char[] delim) - in - { - assert(delim.length > 0); - } - body - { - size_t i; - size_t j; - char[][] words; - - i = 0; - if (s.length) - { - if (delim.length == 1) - { char c = delim[0]; - size_t nwords = 0; - char* p = &s[0]; - char* pend = p + s.length; - - while (true) - { - nwords++; - p = cast(char*)memchr(p, c, pend - p); - if (!p) - break; - p++; - if (p == pend) - { nwords++; - break; - } - } - words.length = nwords; - - int wordi = 0; - i = 0; - while (true) - { - p = cast(char*)memchr(&s[i], c, s.length - i); - if (!p) - { - words[wordi] = s[i .. s.length]; - break; - } - j = p - &s[0]; - words[wordi] = s[i .. j]; - wordi++; - i = j + 1; - if (i == s.length) - { - words[wordi] = ""; - break; - } - } - assert(wordi + 1 == nwords); - } - else - { size_t nwords = 0; - - while (true) - { - nwords++; - j = find(s[i .. s.length], delim); - if (j == -1) - break; - i += j + delim.length; - if (i == s.length) - { nwords++; - break; - } - assert(i < s.length); - } - words.length = nwords; - - int wordi = 0; - i = 0; - while (true) - { - j = find(s[i .. s.length], delim); - if (j == -1) - { - words[wordi] = s[i .. s.length]; - break; - } - words[wordi] = s[i .. i + j]; - wordi++; - i += j + delim.length; - if (i == s.length) - { - words[wordi] = ""; - break; - } - assert(i < s.length); - } - assert(wordi + 1 == nwords); - } - } - return words; - } - -unittest -{ - debug(string) printf("string.split2\n"); - - char[] s = ",peter,paul,jerry,"; - char[][] words; - int i; - - words = split(s, ","); - assert(words.length == 5); - i = cmp(words[0], ""); - assert(i == 0); - i = cmp(words[1], "peter"); - assert(i == 0); - i = cmp(words[2], "paul"); - assert(i == 0); - i = cmp(words[3], "jerry"); - assert(i == 0); - i = cmp(words[4], ""); - assert(i == 0); - - s = s[0 .. s.length - 1]; // lop off trailing ',' - words = split(s, ","); - assert(words.length == 4); - i = cmp(words[3], "jerry"); - assert(i == 0); - - s = s[1 .. s.length]; // lop off leading ',' - words = split(s, ","); - assert(words.length == 3); - i = cmp(words[0], "peter"); - assert(i == 0); - - char[] s2 = ",,peter,,paul,,jerry,,"; - - words = split(s2, ",,"); - //printf("words.length = %d\n", words.length); - assert(words.length == 5); - i = cmp(words[0], ""); - assert(i == 0); - i = cmp(words[1], "peter"); - assert(i == 0); - i = cmp(words[2], "paul"); - assert(i == 0); - i = cmp(words[3], "jerry"); - assert(i == 0); - i = cmp(words[4], ""); - assert(i == 0); - - s2 = s2[0 .. s2.length - 2]; // lop off trailing ',,' - words = split(s2, ",,"); - assert(words.length == 4); - i = cmp(words[3], "jerry"); - assert(i == 0); - - s2 = s2[2 .. s2.length]; // lop off leading ',,' - words = split(s2, ",,"); - assert(words.length == 3); - i = cmp(words[0], "peter"); - assert(i == 0); -} - - -/************************************** - * Split s[] into an array of lines, - * using CR, LF, or CR-LF as the delimiter. - * The delimiter is not included in the line. - */ - -char[][] splitlines(char[] s) -{ - uint i; - uint istart; - uint nlines; - char[][] lines; - - nlines = 0; - for (i = 0; i < s.length; i++) - { char c; - - c = s[i]; - if (c == '\r' || c == '\n') - { - nlines++; - istart = i + 1; - if (c == '\r' && i + 1 < s.length && s[i + 1] == '\n') - { - i++; - istart++; - } - } - } - if (istart != i) - nlines++; - - lines = new char[][nlines]; - nlines = 0; - istart = 0; - for (i = 0; i < s.length; i++) - { char c; - - c = s[i]; - if (c == '\r' || c == '\n') - { - lines[nlines] = s[istart .. i]; - nlines++; - istart = i + 1; - if (c == '\r' && i + 1 < s.length && s[i + 1] == '\n') - { - i++; - istart++; - } - } - } - if (istart != i) - { lines[nlines] = s[istart .. i]; - nlines++; - } - - assert(nlines == lines.length); - return lines; -} - -unittest -{ - debug(string) printf("string.splitlines\n"); - - char[] s = "\rpeter\n\rpaul\r\njerry\n"; - char[][] lines; - int i; - - lines = splitlines(s); - //printf("lines.length = %d\n", lines.length); - assert(lines.length == 5); - //printf("lines[0] = %llx, '%.*s'\n", lines[0], lines[0]); - assert(lines[0].length == 0); - i = cmp(lines[1], "peter"); - assert(i == 0); - assert(lines[2].length == 0); - i = cmp(lines[3], "paul"); - assert(i == 0); - i = cmp(lines[4], "jerry"); - assert(i == 0); - - s = s[0 .. s.length - 1]; // lop off trailing \n - lines = splitlines(s); - //printf("lines.length = %d\n", lines.length); - assert(lines.length == 5); - i = cmp(lines[4], "jerry"); - assert(i == 0); -} - - -/***************************************** - * Strips leading or trailing whitespace, or both. - */ - -char[] stripl(char[] s) -{ - uint i; - - for (i = 0; i < s.length; i++) - { - if (!std.ctype.isspace(s[i])) - break; - } - return s[i .. s.length]; -} - -char[] stripr(char[] s) /// ditto -{ - uint i; - - for (i = s.length; i > 0; i--) - { - if (!std.ctype.isspace(s[i - 1])) - break; - } - return s[0 .. i]; -} - -char[] strip(char[] s) /// ditto -{ - return stripr(stripl(s)); -} - -unittest -{ - debug(string) printf("string.strip.unittest\n"); - char[] s; - int i; - - s = strip(" foo\t "); - i = cmp(s, "foo"); - assert(i == 0); -} - -/******************************************* - * Returns s[] sans trailing delimiter[], if any. - * If delimiter[] is null, removes trailing CR, LF, or CRLF, if any. - */ - -char[] chomp(char[] s, char[] delimiter = null) -{ - if (delimiter is null) - { auto len = s.length; - - if (len) - { auto c = s[len - 1]; - - if (c == '\r') // if ends in CR - len--; - else if (c == '\n') // if ends in LF - { - len--; - if (len && s[len - 1] == '\r') - len--; // remove CR-LF - } - } - return s[0 .. len]; - } - else if (s.length >= delimiter.length) - { - if (s[length - delimiter.length .. length] == delimiter) - return s[0 .. length - delimiter.length]; - } - return s; -} - -unittest -{ - debug(string) printf("string.chomp.unittest\n"); - char[] s; - - s = chomp(null); - assert(s is null); - s = chomp("hello"); - assert(s == "hello"); - s = chomp("hello\n"); - assert(s == "hello"); - s = chomp("hello\r"); - assert(s == "hello"); - s = chomp("hello\r\n"); - assert(s == "hello"); - s = chomp("hello\n\r"); - assert(s == "hello\n"); - s = chomp("hello\n\n"); - assert(s == "hello\n"); - s = chomp("hello\r\r"); - assert(s == "hello\r"); - s = chomp("hello\nxxx\n"); - assert(s == "hello\nxxx"); - - s = chomp(null, null); - assert(s is null); - s = chomp("hello", "o"); - assert(s == "hell"); - s = chomp("hello", "p"); - assert(s == "hello"); - s = chomp("hello", null); - assert(s == "hello"); - s = chomp("hello", "llo"); - assert(s == "he"); -} - - -/*********************************************** - * Returns s[] sans trailing character, if there is one. - * If last two characters are CR-LF, then both are removed. - */ - -char[] chop(char[] s) -{ auto len = s.length; - - if (len) - { - if (len >= 2 && s[len - 1] == '\n' && s[len - 2] == '\r') - return s[0 .. len - 2]; - - // If we're in a tail of a UTF-8 sequence, back up - while ((s[len - 1] & 0xC0) == 0x80) - { - len--; - if (len == 0) - throw new std.utf.UtfException("invalid UTF sequence", 0); - } - - return s[0 .. len - 1]; - } - return s; -} - - -unittest -{ - debug(string) printf("string.chop.unittest\n"); - char[] s; - - s = chop(null); - assert(s is null); - s = chop("hello"); - assert(s == "hell"); - s = chop("hello\r\n"); - assert(s == "hello"); - s = chop("hello\n\r"); - assert(s == "hello\n"); -} - - -/******************************************* - * Left justify, right justify, or center string s[] - * in field width chars wide. - */ - -char[] ljustify(char[] s, int width) -{ - if (s.length >= width) - return s; - char[] r = new char[width]; - r[0..s.length] = s; - r[s.length .. width] = cast(char)' '; - return r; -} - -/// ditto -char[] rjustify(char[] s, int width) -{ - if (s.length >= width) - return s; - char[] r = new char[width]; - r[0 .. width - s.length] = cast(char)' '; - r[width - s.length .. width] = s; - return r; -} - -/// ditto -char[] center(char[] s, int width) -{ - if (s.length >= width) - return s; - char[] r = new char[width]; - int left = (width - s.length) / 2; - r[0 .. left] = cast(char)' '; - r[left .. left + s.length] = s; - r[left + s.length .. width] = cast(char)' '; - return r; -} - -unittest -{ - debug(string) printf("string.justify.unittest\n"); - - char[] s = "hello"; - char[] r; - int i; - - r = ljustify(s, 8); - i = cmp(r, "hello "); - assert(i == 0); - - r = rjustify(s, 8); - i = cmp(r, " hello"); - assert(i == 0); - - r = center(s, 8); - i = cmp(r, " hello "); - assert(i == 0); - - r = zfill(s, 8); - i = cmp(r, "000hello"); - assert(i == 0); -} - - -/***************************************** - * Same as rjustify(), but fill with '0's. - */ - -char[] zfill(char[] s, int width) -{ - if (s.length >= width) - return s; - char[] r = new char[width]; - r[0 .. width - s.length] = cast(char)'0'; - r[width - s.length .. width] = s; - return r; -} - -/******************************************** - * Replace occurrences of from[] with to[] in s[]. - */ - -char[] replace(char[] s, char[] from, char[] to) -{ - char[] p; - int i; - size_t istart; - - //printf("replace('%.*s','%.*s','%.*s')\n", s, from, to); - if (from.length == 0) - return s; - istart = 0; - while (istart < s.length) - { - i = find(s[istart .. s.length], from); - if (i == -1) - { - p ~= s[istart .. s.length]; - break; - } - p ~= s[istart .. istart + i]; - p ~= to; - istart += i + from.length; - } - return p; -} - -unittest -{ - debug(string) printf("string.replace.unittest\n"); - - char[] s = "This is a foo foo list"; - char[] from = "foo"; - char[] to = "silly"; - char[] r; - int i; - - r = replace(s, from, to); - i = cmp(r, "This is a silly silly list"); - assert(i == 0); - - r = replace(s, "", to); - i = cmp(r, "This is a foo foo list"); - assert(i == 0); -} - -/***************************** - * Return a _string that is string[] with slice[] replaced by replacement[]. - */ - -char[] replaceSlice(char[] string, char[] slice, char[] replacement) -in -{ - // Verify that slice[] really is a slice of string[] - int so = cast(char*)slice - cast(char*)string; - assert(so >= 0); - //printf("string.length = %d, so = %d, slice.length = %d\n", string.length, so, slice.length); - assert(string.length >= so + slice.length); -} -body -{ - char[] result; - int so = cast(char*)slice - cast(char*)string; - - result.length = string.length - slice.length + replacement.length; - - result[0 .. so] = string[0 .. so]; - result[so .. so + replacement.length] = replacement; - result[so + replacement.length .. result.length] = string[so + slice.length .. string.length]; - - return result; -} - -unittest -{ - debug(string) printf("string.replaceSlice.unittest\n"); - - char[] string = "hello"; - char[] slice = string[2 .. 4]; - - char[] r = replaceSlice(string, slice, "bar"); - int i; - i = cmp(r, "hebaro"); - assert(i == 0); -} - -/********************************************** - * Insert sub[] into s[] at location index. - */ - -char[] insert(char[] s, size_t index, char[] sub) -in -{ - assert(0 <= index && index <= s.length); -} -body -{ - if (sub.length == 0) - return s; - - if (s.length == 0) - return sub; - - int newlength = s.length + sub.length; - char[] result = new char[newlength]; - - result[0 .. index] = s[0 .. index]; - result[index .. index + sub.length] = sub; - result[index + sub.length .. newlength] = s[index .. s.length]; - return result; -} - -unittest -{ - debug(string) printf("string.insert.unittest\n"); - - char[] r; - int i; - - r = insert("abcd", 0, "e"); - i = cmp(r, "eabcd"); - assert(i == 0); - - r = insert("abcd", 4, "e"); - i = cmp(r, "abcde"); - assert(i == 0); - - r = insert("abcd", 2, "ef"); - i = cmp(r, "abefcd"); - assert(i == 0); - - r = insert(null, 0, "e"); - i = cmp(r, "e"); - assert(i == 0); - - r = insert("abcd", 0, null); - i = cmp(r, "abcd"); - assert(i == 0); -} - -/*********************************************** - * Count up all instances of sub[] in s[]. - */ - -size_t count(char[] s, char[] sub) -{ - size_t i; - int j; - int count = 0; - - for (i = 0; i < s.length; i += j + sub.length) - { - j = find(s[i .. s.length], sub); - if (j == -1) - break; - count++; - } - return count; -} - -unittest -{ - debug(string) printf("string.count.unittest\n"); - - char[] s = "This is a fofofof list"; - char[] sub = "fof"; - int i; - - i = count(s, sub); - assert(i == 2); -} - - -/************************************************ - * Replace tabs with the appropriate number of spaces. - * tabsize is the distance between tab stops. - */ - -char[] expandtabs(char[] string, int tabsize = 8) -{ - bool changes = false; - char[] result = string; - int column; - int nspaces; - - foreach (size_t i, dchar c; string) - { - switch (c) - { - case '\t': - nspaces = tabsize - (column % tabsize); - if (!changes) - { - changes = true; - result = null; - result.length = string.length + nspaces - 1; - result.length = i + nspaces; - result[0 .. i] = string[0 .. i]; - result[i .. i + nspaces] = ' '; - } - else - { int j = result.length; - result.length = j + nspaces; - result[j .. j + nspaces] = ' '; - } - column += nspaces; - break; - - case '\r': - case '\n': - case PS: - case LS: - column = 0; - goto L1; - - default: - column++; - L1: - if (changes) - { - if (c <= 0x7F) - result ~= cast(char)c; - else - std.utf.encode(result, c); - } - break; - } - } - - return result; -} - -unittest -{ - debug(string) printf("string.expandtabs.unittest\n"); - - char[] s = "This \tis\t a fofof\tof list"; - char[] r; - int i; - - r = expandtabs(s, 8); - i = cmp(r, "This is a fofof of list"); - assert(i == 0); - - r = expandtabs(null); - assert(r == null); - r = expandtabs(""); - assert(r.length == 0); - r = expandtabs("a"); - assert(r == "a"); - r = expandtabs("\t"); - assert(r == " "); - r = expandtabs( " ab\tasdf "); - //writefln("r = '%s'", r); - assert(r == " ab asdf "); - // TODO: need UTF test case -} - - -/******************************************* - * Replace spaces in string with the optimal number of tabs. - * Trailing spaces or tabs in a line are removed. - * Params: - * string = String to convert. - * tabsize = Tab columns are tabsize spaces apart. tabsize defaults to 8. - */ - -char[] entab(char[] string, int tabsize = 8) -{ - bool changes = false; - char[] result = string; - - int nspaces = 0; - int nwhite = 0; - int column = 0; // column number - - foreach (size_t i, dchar c; string) - { - - void change() - { - changes = true; - result = null; - result.length = string.length; - result.length = i; - result[0 .. i] = string[0 .. i]; - } - - switch (c) - { - case '\t': - nwhite++; - if (nspaces) - { - if (!changes) - change(); - - int j = result.length - nspaces; - int ntabs = (((column - nspaces) % tabsize) + nspaces) / tabsize; - result.length = j + ntabs; - result[j .. j + ntabs] = '\t'; - nwhite += ntabs - nspaces; - nspaces = 0; - } - column = (column + tabsize) / tabsize * tabsize; - break; - - case '\r': - case '\n': - case PS: - case LS: - // Truncate any trailing spaces or tabs - if (nwhite) - { - if (!changes) - change(); - result = result[0 .. result.length - nwhite]; - } - break; - - default: - if (nspaces >= 2 && (column % tabsize) == 0) - { - if (!changes) - change(); - - int j = result.length - nspaces; - int ntabs = (nspaces + tabsize - 1) / tabsize; - result.length = j + ntabs; - result[j .. j + ntabs] = '\t'; - nwhite += ntabs - nspaces; - nspaces = 0; - } - if (c == ' ') - { nwhite++; - nspaces++; - } - else - { nwhite = 0; - nspaces = 0; - } - column++; - break; - } - if (changes) - { - if (c <= 0x7F) - result ~= cast(char)c; - else - std.utf.encode(result, c); - } - } - - // Truncate any trailing spaces or tabs - if (nwhite) - result = result[0 .. result.length - nwhite]; - - return result; -} - -unittest -{ - debug(string) printf("string.entab.unittest\n"); - - char[] r; - - r = entab(null); - assert(r == null); - r = entab(""); - assert(r.length == 0); - r = entab("a"); - assert(r == "a"); - r = entab(" "); - assert(r == ""); - r = entab(" x"); - assert(r == "\tx"); - r = entab(" ab asdf "); - assert(r == " ab\tasdf"); - r = entab(" ab asdf "); - assert(r == " ab\t asdf"); - r = entab(" ab \t asdf "); - assert(r == " ab\t asdf"); - r = entab("1234567 \ta"); - assert(r == "1234567\t\ta"); - r = entab("1234567 \ta"); - assert(r == "1234567\t\ta"); - r = entab("1234567 \ta"); - assert(r == "1234567\t\ta"); - r = entab("1234567 \ta"); - assert(r == "1234567\t\ta"); - r = entab("1234567 \ta"); - assert(r == "1234567\t\ta"); - r = entab("1234567 \ta"); - assert(r == "1234567\t\ta"); - r = entab("1234567 \ta"); - assert(r == "1234567\t\ta"); - r = entab("1234567 \ta"); - assert(r == "1234567\t\ta"); - r = entab("1234567 \ta"); - assert(r == "1234567\t\t\ta"); - // TODO: need UTF test case -} - - - -/************************************ - * Construct translation table for translate(). - * BUG: only works with ASCII - */ - -char[] maketrans(char[] from, char[] to) - in - { - assert(from.length == to.length); - assert(from.length <= 128); - foreach (char c; from) - { - assert(c <= 0x7F); - } - foreach (char c; to) - { - assert(c <= 0x7F); - } - } - body - { - char[] t = new char[256]; - int i; - - for (i = 0; i < t.length; i++) - t[i] = cast(char)i; - - for (i = 0; i < from.length; i++) - t[from[i]] = to[i]; - - return t; - } - -/****************************************** - * Translate characters in s[] using table created by maketrans(). - * Delete chars in delchars[]. - * BUG: only works with ASCII - */ - -char[] translate(char[] s, char[] transtab, char[] delchars) - in - { - assert(transtab.length == 256); - } - body - { - char[] r; - int count; - bool[256] deltab; - - deltab[] = false; - foreach (char c; delchars) - { - deltab[c] = true; - } - - count = 0; - foreach (char c; s) - { - if (!deltab[c]) - count++; - //printf("s[%d] = '%c', count = %d\n", i, s[i], count); - } - - r = new char[count]; - count = 0; - foreach (char c; s) - { - if (!deltab[c]) - { - r[count] = transtab[c]; - count++; - } - } - - return r; - } - -unittest -{ - debug(string) printf("string.translate.unittest\n"); - - char[] from = "abcdef"; - char[] to = "ABCDEF"; - char[] s = "The quick dog fox"; - char[] t; - char[] r; - int i; - - t = maketrans(from, to); - r = translate(s, t, "kg"); - //printf("r = '%.*s'\n", r); - i = cmp(r, "ThE quiC Do Fox"); - assert(i == 0); -} - -/*********************************************** - * Convert to char[]. - */ - -char[] toString(bool b) -{ - return b ? "true" : "false"; -} - -/// ditto -char[] toString(char c) -{ - char[] result = new char[2]; - result[0] = c; - result[1] = 0; - return result[0 .. 1]; -} - -unittest -{ - debug(string) printf("string.toString(char).unittest\n"); - - char[] s = "foo"; - char[] s2; - foreach (char c; s) - { - s2 ~= std.string.toString(c); - } - //printf("%.*s", s2); - assert(s2 == "foo"); -} - -char[] toString(ubyte ub) { return toString(cast(uint) ub); } /// ditto -char[] toString(ushort us) { return toString(cast(uint) us); } /// ditto - -/// ditto -char[] toString(uint u) -{ char[uint.sizeof * 3] buffer = void; - int ndigits; - char[] result; - - ndigits = 0; - if (u < 10) - // Avoid storage allocation for simple stuff - result = digits[u .. u + 1]; - else - { - while (u) - { - uint c = (u % 10) + '0'; - u /= 10; - ndigits++; - buffer[buffer.length - ndigits] = cast(char)c; - } - result = new char[ndigits]; - result[] = buffer[buffer.length - ndigits .. buffer.length]; - } - return result; -} - -unittest -{ - debug(string) printf("string.toString(uint).unittest\n"); - - char[] r; - int i; - - r = toString(0u); - i = cmp(r, "0"); - assert(i == 0); - - r = toString(9u); - i = cmp(r, "9"); - assert(i == 0); - - r = toString(123u); - i = cmp(r, "123"); - assert(i == 0); -} - -/// ditto -char[] toString(ulong u) -{ char[ulong.sizeof * 3] buffer; - int ndigits; - char[] result; - - if (u < 0x1_0000_0000) - return toString(cast(uint)u); - ndigits = 0; - while (u) - { - char c = cast(char)((u % 10) + '0'); - u /= 10; - ndigits++; - buffer[buffer.length - ndigits] = c; - } - result = new char[ndigits]; - result[] = buffer[buffer.length - ndigits .. buffer.length]; - return result; -} - -unittest -{ - debug(string) printf("string.toString(ulong).unittest\n"); - - char[] r; - int i; - - r = toString(0uL); - i = cmp(r, "0"); - assert(i == 0); - - r = toString(9uL); - i = cmp(r, "9"); - assert(i == 0); - - r = toString(123uL); - i = cmp(r, "123"); - assert(i == 0); -} - -char[] toString(byte b) { return toString(cast(int) b); } /// ditto -char[] toString(short s) { return toString(cast(int) s); } /// ditto - -/// ditto -char[] toString(int i) -{ char[1 + int.sizeof * 3] buffer; - char[] result; - - if (i >= 0) - return toString(cast(uint)i); - - uint u = -i; - int ndigits = 1; - while (u) - { - char c = cast(char)((u % 10) + '0'); - u /= 10; - buffer[buffer.length - ndigits] = c; - ndigits++; - } - buffer[buffer.length - ndigits] = '-'; - result = new char[ndigits]; - result[] = buffer[buffer.length - ndigits .. buffer.length]; - return result; -} - -unittest -{ - debug(string) printf("string.toString(int).unittest\n"); - - char[] r; - int i; - - r = toString(0); - i = cmp(r, "0"); - assert(i == 0); - - r = toString(9); - i = cmp(r, "9"); - assert(i == 0); - - r = toString(123); - i = cmp(r, "123"); - assert(i == 0); - - r = toString(-0); - i = cmp(r, "0"); - assert(i == 0); - - r = toString(-9); - i = cmp(r, "-9"); - assert(i == 0); - - r = toString(-123); - i = cmp(r, "-123"); - assert(i == 0); -} - -/// ditto -char[] toString(long i) -{ char[1 + long.sizeof * 3] buffer; - char[] result; - - if (i >= 0) - return toString(cast(ulong)i); - if (cast(int)i == i) - return toString(cast(int)i); - - ulong u = cast(ulong)(-i); - int ndigits = 1; - while (u) - { - char c = cast(char)((u % 10) + '0'); - u /= 10; - buffer[buffer.length - ndigits] = c; - ndigits++; - } - buffer[buffer.length - ndigits] = '-'; - result = new char[ndigits]; - result[] = buffer[buffer.length - ndigits .. buffer.length]; - return result; -} - -unittest -{ - debug(string) printf("string.toString(long).unittest\n"); - - char[] r; - int i; - - r = toString(0L); - i = cmp(r, "0"); - assert(i == 0); - - r = toString(9L); - i = cmp(r, "9"); - assert(i == 0); - - r = toString(123L); - i = cmp(r, "123"); - assert(i == 0); - - r = toString(-0L); - i = cmp(r, "0"); - assert(i == 0); - - r = toString(-9L); - i = cmp(r, "-9"); - assert(i == 0); - - r = toString(-123L); - i = cmp(r, "-123"); - assert(i == 0); -} - -/// ditto -char[] toString(float f) { return toString(cast(double) f); } - -/// ditto -char[] toString(double d) -{ - char[20] buffer; - - int len = sprintf(buffer.ptr, "%g", d); - return buffer[0 .. len].dup; -} - -/// ditto -char[] toString(real r) -{ - char[20] buffer; - - int len = sprintf(buffer.ptr, "%Lg", r); - return buffer[0 .. len].dup; -} - -/// ditto -char[] toString(ifloat f) { return toString(cast(idouble) f); } - -/// ditto -char[] toString(idouble d) -{ - char[21] buffer; - - int len = sprintf(buffer.ptr, "%gi", d); - return buffer[0 .. len].dup; -} - -/// ditto -char[] toString(ireal r) -{ - char[21] buffer; - - int len = sprintf(buffer.ptr, "%Lgi", r); - return buffer[0 .. len].dup; -} - -/// ditto -char[] toString(cfloat f) { return toString(cast(cdouble) f); } - -/// ditto -char[] toString(cdouble d) -{ - char[20 + 1 + 20 + 1] buffer; - - int len = sprintf(buffer.ptr, "%g+%gi", d.re, d.im); - return buffer[0 .. len].dup; -} - -/// ditto -char[] toString(creal r) -{ - char[20 + 1 + 20 + 1] buffer; - - int len = sprintf(buffer.ptr, "%Lg+%Lgi", r.re, r.im); - return buffer[0 .. len].dup; -} - - -/****************************************** - * Convert value to string in _radix radix. - * - * radix must be a value from 2 to 36. - * value is treated as a signed value only if radix is 10. - * The characters A through Z are used to represent values 10 through 36. - */ -char[] toString(long value, uint radix) -in -{ - assert(radix >= 2 && radix <= 36); -} -body -{ - if (radix == 10) - return toString(value); // handle signed cases only for radix 10 - return toString(cast(ulong)value, radix); -} - -/// ditto -char[] toString(ulong value, uint radix) -in -{ - assert(radix >= 2 && radix <= 36); -} -body -{ - char[value.sizeof * 8] buffer; - uint i = buffer.length; - - if (value < radix && value < hexdigits.length) - return hexdigits[cast(size_t)value .. cast(size_t)value + 1]; - - do - { ubyte c; - - c = cast(ubyte)(value % radix); - value = value / radix; - i--; - buffer[i] = cast(char)((c < 10) ? c + '0' : c + 'A' - 10); - } while (value); - return buffer[i .. length].dup; -} - -unittest -{ - debug(string) printf("string.toString(ulong, uint).unittest\n"); - - char[] r; - int i; - - r = toString(-10L, 10u); - assert(r == "-10"); - - r = toString(15L, 2u); - //writefln("r = '%s'", r); - assert(r == "1111"); - - r = toString(1L, 2u); - //writefln("r = '%s'", r); - assert(r == "1"); - - r = toString(0x1234AFL, 16u); - //writefln("r = '%s'", r); - assert(r == "1234AF"); -} - -/************************************************* - * Convert C-style 0 terminated string s to char[] string. - */ - -char[] toString(char *s) -{ - return s ? s[0 .. strlen(s)] : cast(char[])null; -} - -unittest -{ - debug(string) printf("string.toString(char*).unittest\n"); - - char[] r; - int i; - - r = toString(null); - i = cmp(r, ""); - assert(i == 0); - - r = toString("foo\0"); - i = cmp(r, "foo"); - assert(i == 0); -} - - -/***************************************************** - * Format arguments into a string. - */ - - -char[] format(...) -{ - char[] s; - - void putc(dchar c) - { - std.utf.encode(s, c); - } - - std.format.doFormat(&putc, _arguments, _argptr); - return s; -} - - -/***************************************************** - * Format arguments into string s which must be large - * enough to hold the result. Throws ArrayBoundsError if it is not. - * Returns: s - */ -char[] sformat(char[] s, ...) -{ size_t i; - - void putc(dchar c) - { - if (c <= 0x7F) - { - if (i >= s.length) - throw new ArrayBoundsError("std.string.sformat", 0); - s[i] = cast(char)c; - ++i; - } - else - { char[4] buf; - char[] b; - - b = std.utf.toUTF8(buf, c); - if (i + b.length > s.length) - throw new ArrayBoundsError("std.string.sformat", 0); - s[i..i+b.length] = b[]; - i += b.length; - } - } - - std.format.doFormat(&putc, _arguments, _argptr); - return s[0 .. i]; -} - - -unittest -{ - debug(string) printf("std.string.format.unittest\n"); - - char[] r; - int i; -/+ - r = format(null); - i = cmp(r, ""); - assert(i == 0); -+/ - r = format("foo"); - i = cmp(r, "foo"); - assert(i == 0); - - r = format("foo%%"); - i = cmp(r, "foo%"); - assert(i == 0); - - r = format("foo%s", 'C'); - i = cmp(r, "fooC"); - assert(i == 0); - - r = format("%s foo", "bar"); - i = cmp(r, "bar foo"); - assert(i == 0); - - r = format("%s foo %s", "bar", "abc"); - i = cmp(r, "bar foo abc"); - assert(i == 0); - - r = format("foo %d", -123); - i = cmp(r, "foo -123"); - assert(i == 0); - - r = format("foo %d", 123); - i = cmp(r, "foo 123"); - assert(i == 0); -} - - -/*********************************************** - * See if character c is in the pattern. - * Patterns: - * - * A pattern is an array of characters much like a character - * class in regular expressions. A sequence of characters - * can be given, such as "abcde". The '-' can represent a range - * of characters, as "a-e" represents the same pattern as "abcde". - * "a-fA-F0-9" represents all the hex characters. - * If the first character of a pattern is '^', then the pattern - * is negated, i.e. "^0-9" means any character except a digit. - * The functions inPattern, countchars, removeschars, - * and squeeze - * use patterns. - * - * Note: In the future, the pattern syntax may be improved - * to be more like regular expression character classes. - */ - -bool inPattern(dchar c, char[] pattern) -{ - bool result = false; - int range = 0; - dchar lastc; - - foreach (size_t i, dchar p; pattern) - { - if (p == '^' && i == 0) - { result = true; - if (i + 1 == pattern.length) - return (c == p); // or should this be an error? - } - else if (range) - { - range = 0; - if (lastc <= c && c <= p || c == p) - return !result; - } - else if (p == '-' && i > result && i + 1 < pattern.length) - { - range = 1; - continue; - } - else if (c == p) - return !result; - lastc = p; - } - return result; -} - - -unittest -{ - debug(string) printf("std.string.inPattern.unittest\n"); - - int i; - - i = inPattern('x', "x"); - assert(i == 1); - i = inPattern('x', "y"); - assert(i == 0); - i = inPattern('x', cast(char[])null); - assert(i == 0); - i = inPattern('x', "^y"); - assert(i == 1); - i = inPattern('x', "yxxy"); - assert(i == 1); - i = inPattern('x', "^yxxy"); - assert(i == 0); - i = inPattern('x', "^abcd"); - assert(i == 1); - i = inPattern('^', "^^"); - assert(i == 0); - i = inPattern('^', "^"); - assert(i == 1); - i = inPattern('^', "a^"); - assert(i == 1); - i = inPattern('x', "a-z"); - assert(i == 1); - i = inPattern('x', "A-Z"); - assert(i == 0); - i = inPattern('x', "^a-z"); - assert(i == 0); - i = inPattern('x', "^A-Z"); - assert(i == 1); - i = inPattern('-', "a-"); - assert(i == 1); - i = inPattern('-', "^A-"); - assert(i == 0); - i = inPattern('a', "z-a"); - assert(i == 1); - i = inPattern('z', "z-a"); - assert(i == 1); - i = inPattern('x', "z-a"); - assert(i == 0); -} - - -/*********************************************** - * See if character c is in the intersection of the patterns. - */ - -int inPattern(dchar c, char[][] patterns) -{ int result; - - foreach (char[] pattern; patterns) - { - if (!inPattern(c, pattern)) - { result = 0; - break; - } - result = 1; - } - return result; -} - - -/******************************************** - * Count characters in s that match pattern. - */ - -size_t countchars(char[] s, char[] pattern) -{ - size_t count; - - foreach (dchar c; s) - { - count += inPattern(c, pattern); - } - return count; -} - - -unittest -{ - debug(string) printf("std.string.count.unittest\n"); - - size_t c; - - c = countchars("abc", "a-c"); - assert(c == 3); - c = countchars("hello world", "or"); - assert(c == 3); -} - - -/******************************************** - * Return string that is s with all characters removed that match pattern. - */ - -char[] removechars(char[] s, char[] pattern) -{ - char[] r = s; - int changed; - size_t j; - - foreach (size_t i, dchar c; s) - { - if (!inPattern(c, pattern)) - { - if (changed) - { - if (r is s) - r = s[0 .. j].dup; - std.utf.encode(r, c); - } - } - else if (!changed) - { changed = 1; - j = i; - } - } - if (changed && r is s) - r = s[0 .. j].dup; - return r; -} - - -unittest -{ - debug(string) printf("std.string.remove.unittest\n"); - - char[] r; - - r = removechars("abc", "a-c"); - assert(r is null); - r = removechars("hello world", "or"); - assert(r == "hell wld"); - r = removechars("hello world", "d"); - assert(r == "hello worl"); -} - - -/*************************************************** - * Return string where sequences of a character in s[] from pattern[] - * are replaced with a single instance of that character. - * If pattern is null, it defaults to all characters. - */ - -char[] squeeze(char[] s, char[] pattern = null) -{ - char[] r = s; - dchar lastc; - size_t lasti; - int run; - bool changed; - - foreach (size_t i, dchar c; s) - { - if (run && lastc == c) - { - changed = true; - } - else if (pattern is null || inPattern(c, pattern)) - { - run = 1; - if (changed) - { if (r is s) - r = s[0 .. lasti].dup; - std.utf.encode(r, c); - } - else - lasti = i + std.utf.stride(s, i); - lastc = c; - } - else - { - run = 0; - if (changed) - { if (r is s) - r = s[0 .. lasti].dup; - std.utf.encode(r, c); - } - } - } - if (changed) - { - if (r is s) - r = s[0 .. lasti]; - } - return r; -} - - -unittest -{ - debug(string) printf("std.string.squeeze.unittest\n"); - char[] s,r; - - r = squeeze("hello"); - //writefln("r = '%s'", r); - assert(r == "helo"); - s = "abcd"; - r = squeeze(s); - assert(r is s); - s = "xyzz"; - r = squeeze(s); - assert(r.ptr == s.ptr); // should just be a slice - r = squeeze("hello goodbyee", "oe"); - assert(r == "hello godbye"); -} - - -/********************************************** - * Return string that is the 'successor' to s[]. - * If the rightmost character is a-zA-Z0-9, it is incremented within - * its case or digits. If it generates a carry, the process is - * repeated with the one to its immediate left. - */ - -char[] succ(char[] s) -{ - if (s.length && isalnum(s[length - 1])) - { - char[] r = s.dup; - size_t i = r.length - 1; - - while (1) - { dchar c = s[i]; - dchar carry; - - switch (c) - { - case '9': - c = '0'; - carry = '1'; - goto Lcarry; - case 'z': - case 'Z': - c -= 'Z' - 'A'; - carry = c; - Lcarry: - r[i] = cast(char)c; - if (i == 0) - { - char[] t = new char[r.length + 1]; - t[0] = cast(char)carry; - t[1 .. length] = r[]; - return t; - } - i--; - break; - - default: - if (std.ctype.isalnum(c)) - r[i]++; - return r; - } - } - } - return s; -} - -unittest -{ - debug(string) printf("std.string.succ.unittest\n"); - - char[] r; - - r = succ(null); - assert(r is null); - r = succ("!@#$%"); - assert(r == "!@#$%"); - r = succ("1"); - assert(r == "2"); - r = succ("9"); - assert(r == "10"); - r = succ("999"); - assert(r == "1000"); - r = succ("zz99"); - assert(r == "aaa00"); -} - - -/*********************************************** - * Replaces characters in str[] that are in from[] - * with corresponding characters in to[] and returns the resulting - * string. - * Params: - * modifiers = a string of modifier characters - * Modifiers: - -
Modifier Description -
c Complement the list of characters in from[] -
d Removes matching characters with no corresponding replacement in to[] -
s Removes adjacent duplicates in the replaced characters -
- - If modifier d is present, then the number of characters - in to[] may be only 0 or 1. - - If modifier d is not present and to[] is null, - then to[] is taken _to be the same as from[]. - - If modifier d is not present and to[] is shorter - than from[], then to[] is extended by replicating the - last character in to[]. - - Both from[] and to[] may contain ranges using the - - character, for example a-d is synonymous with abcd. - Neither accept a leading ^ as meaning the complement of - the string (use the c modifier for that). - */ - -char[] tr(char[] str, char[] from, char[] to, char[] modifiers = null) -{ - int mod_c; - int mod_d; - int mod_s; - - foreach (char c; modifiers) - { - switch (c) - { - case 'c': mod_c = 1; break; // complement - case 'd': mod_d = 1; break; // delete unreplaced chars - case 's': mod_s = 1; break; // squeeze duplicated replaced chars - default: assert(0); - } - } - - if (to is null && !mod_d) - to = from; - - char[] result = new char[str.length]; - result.length = 0; - int m; - dchar lastc; - - foreach (dchar c; str) - { dchar lastf; - dchar lastt; - dchar newc; - int n = 0; - - for (size_t i = 0; i < from.length; ) - { - dchar f = std.utf.decode(from, i); - //writefln("\tf = '%s', c = '%s', lastf = '%x', '%x', i = %d, %d", f, c, lastf, dchar.init, i, from.length); - if (f == '-' && lastf != dchar.init && i < from.length) - { - dchar nextf = std.utf.decode(from, i); - //writefln("\tlastf = '%s', c = '%s', nextf = '%s'", lastf, c, nextf); - if (lastf <= c && c <= nextf) - { - n += c - lastf - 1; - if (mod_c) - goto Lnotfound; - goto Lfound; - } - n += nextf - lastf; - lastf = lastf.init; - continue; - } - - if (c == f) - { if (mod_c) - goto Lnotfound; - goto Lfound; - } - lastf = f; - n++; - } - if (!mod_c) - goto Lnotfound; - n = 0; // consider it 'found' at position 0 - - Lfound: - - // Find the nth character in to[] - //writefln("\tc = '%s', n = %d", c, n); - dchar nextt; - for (size_t i = 0; i < to.length; ) - { dchar t = std.utf.decode(to, i); - if (t == '-' && lastt != dchar.init && i < to.length) - { - nextt = std.utf.decode(to, i); - //writefln("\tlastt = '%s', c = '%s', nextt = '%s', n = %d", lastt, c, nextt, n); - n -= nextt - lastt; - if (n < 0) - { - newc = nextt + n + 1; - goto Lnewc; - } - lastt = dchar.init; - continue; - } - if (n == 0) - { newc = t; - goto Lnewc; - } - lastt = t; - nextt = t; - n--; - } - if (mod_d) - continue; - newc = nextt; - - Lnewc: - if (mod_s && m && newc == lastc) - continue; - std.utf.encode(result, newc); - m = 1; - lastc = newc; - continue; - - Lnotfound: - std.utf.encode(result, c); - lastc = c; - m = 0; - } - return result; -} - -unittest -{ - debug(string) printf("std.string.tr.unittest\n"); - - char[] r; - //writefln("r = '%s'", r); - - r = tr("abcdef", "cd", "CD"); - assert(r == "abCDef"); - - r = tr("abcdef", "b-d", "B-D"); - assert(r == "aBCDef"); - - r = tr("abcdefgh", "b-dh", "B-Dx"); - assert(r == "aBCDefgx"); - - r = tr("abcdefgh", "b-dh", "B-CDx"); - assert(r == "aBCDefgx"); - - r = tr("abcdefgh", "b-dh", "B-BCDx"); - assert(r == "aBCDefgx"); - - r = tr("abcdef", "ef", "*", "c"); - assert(r == "****ef"); - - r = tr("abcdef", "ef", "", "d"); - assert(r == "abcd"); - - r = tr("hello goodbye", "lo", null, "s"); - assert(r == "helo godbye"); - - r = tr("hello goodbye", "lo", "x", "s"); - assert(r == "hex gxdbye"); - - r = tr("14-Jul-87", "a-zA-Z", " ", "cs"); - assert(r == " Jul "); - - r = tr("Abc", "AAA", "XYZ"); - assert(r == "Xbc"); -} - - -/* ************************************************ - * Version : v0.3 - * Author : David L. 'SpottedTiger' Davis - * Date Created : 31.May.05 Compiled and Tested with dmd v0.125 - * Date Modified : 01.Jun.05 Modified the function to handle the - * : imaginary and complex float-point - * : datatypes. - * : - * Licence : Public Domain / Contributed to Digital Mars - */ - -/** - * [in] char[] s can be formatted in the following ways: - * - * Integer Whole Number: - * (for byte, ubyte, short, ushort, int, uint, long, and ulong) - * ['+'|'-']digit(s)[U|L|UL] - * - * examples: 123, 123UL, 123L, +123U, -123L - * - * Floating-Point Number: - * (for float, double, real, ifloat, idouble, and ireal) - * ['+'|'-']digit(s)[.][digit(s)][[e-|e+]digit(s)][i|f|L|Li|fi]] - * or [nan|nani|inf|-inf] - * - * examples: +123., -123.01, 123.3e-10f, 123.3e-10fi, 123.3e-10L - * - * (for cfloat, cdouble, and creal) - * ['+'|'-']digit(s)[.][digit(s)][[e-|e+]digit(s)][+] - * [digit(s)[.][digit(s)][[e-|e+]digit(s)][i|f|L|Li|fi]] - * or [nan|nani|nan+nani|inf|-inf] - * - * examples: nan, -123e-1+456.9e-10Li, +123e+10+456i, 123+456 - * - * [in] bool bAllowSep - * False by default, but when set to true it will accept the - * separator characters "," and "_" within the string, but these - * characters should be stripped from the string before using any - * of the conversion functions like toInt(), toFloat(), and etc - * else an error will occur. - * - * Also please note, that no spaces are allowed within the string - * anywhere whether it's a leading, trailing, or embedded space(s), - * thus they too must be stripped from the string before using this - * function, or any of the conversion functions. - */ - -final bool isNumeric(in char[] s, in bool bAllowSep = false) -{ - int iLen = s.length; - bool bDecimalPoint = false; - bool bExponent = false; - bool bComplex = false; - char[] sx = std.string.tolower(s); - int j = 0; - char c; - - //writefln("isNumeric(char[], bool = false) called!"); - // Empty string, return false - if (iLen == 0) - return false; - - // Check for NaN (Not a Number) - if (sx == "nan" || sx == "nani" || sx == "nan+nani") - return true; - - // Check for Infinity - if (sx == "inf" || sx == "-inf") - return true; - - // A sign is allowed only in the 1st character - if (sx[0] == '-' || sx[0] == '+') - j++; - - for (int i = j; i < iLen; i++) - { - c = sx[i]; - - // Digits are good, continue checking - // with the next character... ;) - if (c >= '0' && c <= '9') - continue; - - // Check for the complex type, and if found - // reset the flags for checking the 2nd number. - else if (c == '+') - if (i > 0) - { - bDecimalPoint = false; - bExponent = false; - bComplex = true; - continue; - } - else - return false; - - // Allow only one exponent per number - else if (c == 'e') - { - // A 2nd exponent found, return not a number - if (bExponent) - return false; - - if (i + 1 < iLen) - { - // Look forward for the sign, and if - // missing then this is not a number. - if (sx[i + 1] != '-' && sx[i + 1] != '+') - return false; - else - { - bExponent = true; - i++; - } - } - else - // Ending in "E", return not a number - return false; - } - // Allow only one decimal point per number to be used - else if (c == '.' ) - { - // A 2nd decimal point found, return not a number - if (bDecimalPoint) - return false; - - bDecimalPoint = true; - continue; - } - // Check for ending literal characters: "f,u,l,i,ul,fi,li", - // and wheater they're being used with the correct datatype. - else if (i == iLen - 2) - { - // Integer Whole Number - if (sx[i..iLen] == "ul" && - (!bDecimalPoint && !bExponent && !bComplex)) - return true; - // Floating-Point Number - else if ((sx[i..iLen] == "fi" || sx[i..iLen] == "li") && - (bDecimalPoint || bExponent || bComplex)) - return true; - else if (sx[i..iLen] == "ul" && - (bDecimalPoint || bExponent || bComplex)) - return false; - // Could be a Integer or a Float, thus - // all these suffixes are valid for both - else if (sx[i..iLen] == "ul" || - sx[i..iLen] == "fi" || - sx[i..iLen] == "li") - return true; - else - return false; - } - else if (i == iLen - 1) - { - // Integer Whole Number - if ((c == 'u' || c == 'l') && - (!bDecimalPoint && !bExponent && !bComplex)) - return true; - // Check to see if the last character in the string - // is the required 'i' character - else if (bComplex) - if (c == 'i') - return true; - else - return false; - // Floating-Point Number - else if ((c == 'l' || c == 'f' || c == 'i') && - (bDecimalPoint || bExponent)) - return true; - // Could be a Integer or a Float, thus - // all these suffixes are valid for both - else if (c == 'l' || c == 'f' || c == 'i') - return true; - else - return false; - } - else - // Check if separators are allow - // to be in the numeric string - if (bAllowSep == true && (c == '_' || c == ',')) - continue; - else - return false; - } - - return true; -} - -/// Allow any object as a parameter -bool isNumeric(...) -{ - return isNumeric(_arguments, _argptr); -} - -/// Check only the first parameter, all others will be ignored. -bool isNumeric(TypeInfo[] _args, va_list _ptr) -{ - char[] s = ""; - wchar[] ws = ""; - dchar[] ds = ""; - - //writefln("isNumeric(...) called!"); - if (_args.length == 0) - return false; - - if (_args[0] == typeid(char[])) - return isNumeric(va_arg!(char[])(_ptr)); - else if (_args[0] == typeid(wchar[])) - return isNumeric(std.utf.toUTF8(va_arg!(wchar[])(_ptr))); - else if (_args[0] == typeid(dchar[])) - return isNumeric(std.utf.toUTF8(va_arg!(dchar[])(_ptr))); - else if (_args[0] == typeid(real)) - return true; - else if (_args[0] == typeid(double)) - return true; - else if (_args[0] == typeid(float)) - return true; - else if (_args[0] == typeid(ulong)) - return true; - else if (_args[0] == typeid(long)) - return true; - else if (_args[0] == typeid(uint)) - return true; - else if (_args[0] == typeid(int)) - return true; - else if (_args[0] == typeid(ushort)) - return true; - else if (_args[0] == typeid(short)) - return true; - else if (_args[0] == typeid(ubyte)) - { - s.length = 1; - s[0]= va_arg!(ubyte)(_ptr); - return isNumeric(cast(char[])s); - } - else if (_args[0] == typeid(byte)) - { - s.length = 1; - s[0] = va_arg!(byte)(_ptr); - return isNumeric(cast(char[])s); - } - else if (_args[0] == typeid(ireal)) - return true; - else if (_args[0] == typeid(idouble)) - return true; - else if (_args[0] == typeid(ifloat)) - return true; - else if (_args[0] == typeid(creal)) - return true; - else if (_args[0] == typeid(cdouble)) - return true; - else if (_args[0] == typeid(cfloat)) - return true; - else if (_args[0] == typeid(char)) - { - s.length = 1; - s[0] = va_arg!(char)(_ptr); - return isNumeric(s); - } - else if (_args[0] == typeid(wchar)) - { - ws.length = 1; - ws[0] = va_arg!(wchar)(_ptr); - return isNumeric(std.utf.toUTF8(ws)); - } - else if (_args[0] == typeid(dchar)) - { - ds.length = 1; - ds[0] = va_arg!(dchar)(_ptr); - return isNumeric(std.utf.toUTF8(ds)); - } - //else if (_args[0] == typeid(cent)) - // return true; - //else if (_args[0] == typeid(ucent)) - // return true; - else - return false; -} - -unittest -{ - debug (string) printf("isNumeric(in char[], bool = false).unittest\n"); - char[] s; - - // Test the isNumeric(in char[]) function - assert(isNumeric("1") == true ); - assert(isNumeric("1.0") == true ); - assert(isNumeric("1e-1") == true ); - assert(isNumeric("12345xxxx890") == false ); - assert(isNumeric("567L") == true ); - assert(isNumeric("23UL") == true ); - assert(isNumeric("-123..56f") == false ); - assert(isNumeric("12.3.5.6") == false ); - assert(isNumeric(" 12.356") == false ); - assert(isNumeric("123 5.6") == false ); - assert(isNumeric("1233E-1+1.0e-1i") == true ); - - assert(isNumeric("123.00E-5+1234.45E-12Li") == true); - assert(isNumeric("123.00e-5+1234.45E-12iL") == false); - assert(isNumeric("123.00e-5+1234.45e-12uL") == false); - assert(isNumeric("123.00E-5+1234.45e-12lu") == false); - - assert(isNumeric("123fi") == true); - assert(isNumeric("123li") == true); - assert(isNumeric("--123L") == false); - assert(isNumeric("+123.5UL") == false); - assert(isNumeric("123f") == true); - assert(isNumeric("123.u") == false); - - assert(isNumeric(std.string.toString(real.nan)) == true); - assert(isNumeric(std.string.toString(-real.infinity)) == true); - assert(isNumeric(std.string.toString(123e+2+1234.78Li)) == true); - - s = "$250.99-"; - assert(isNumeric(s[1..s.length - 2]) == true); - assert(isNumeric(s) == false); - assert(isNumeric(s[0..s.length - 1]) == false); - - // These test calling the isNumeric(...) function - assert(isNumeric(1,123UL) == true); - assert(isNumeric('2') == true); - assert(isNumeric('x') == false); - assert(isNumeric(cast(byte)0x57) == false); // 'W' - assert(isNumeric(cast(byte)0x37) == true); // '7' - assert(isNumeric(cast(wchar[])"145.67") == true); - assert(isNumeric(cast(dchar[])"145.67U") == false); - assert(isNumeric(123_000.23fi) == true); - assert(isNumeric(123.00E-5+1234.45E-12Li) == true); - assert(isNumeric(real.nan) == true); - assert(isNumeric(-real.infinity) == true); -} - - -/***************************** - * Soundex algorithm. - * - * The Soundex algorithm converts a word into 4 characters - * based on how the word sounds phonetically. The idea is that - * two spellings that sound alike will have the same Soundex - * value, which means that Soundex can be used for fuzzy matching - * of names. - * - * Params: - * string = String to convert to Soundex representation. - * buffer = Optional 4 char array to put the resulting Soundex - * characters into. If null, the return value - * buffer will be allocated on the heap. - * Returns: - * The four character array with the Soundex result in it. - * Returns null if there is no Soundex representation for the string. - * - * See_Also: - * $(LINK2 http://en.wikipedia.org/wiki/Soundex, Wikipedia), - * $(LINK2 http://www.archives.gov/publications/general-info-leaflets/55.html, The Soundex Indexing System) - * - * Bugs: - * Only works well with English names. - * There are other arguably better Soundex algorithms, - * but this one is the standard one. - */ - -char[] soundex(char[] string, char[] buffer = null) -in -{ - assert(!buffer || buffer.length >= 4); -} -out (result) -{ - if (result) - { - assert(result.length == 4); - assert(result[0] >= 'A' && result[0] <= 'Z'); - foreach (char c; result[1 .. 4]) - assert(c >= '0' && c <= '6'); - } -} -body -{ - static char[26] dex = - // ABCDEFGHIJKLMNOPQRSTUVWXYZ - "01230120022455012623010202"; - - int b = 0; - char lastc; - foreach (char c; string) - { - if (c >= 'a' && c <= 'z') - c -= 'a' - 'A'; - else if (c >= 'A' && c <= 'Z') - { - ; - } - else - { lastc = lastc.init; - continue; - } - if (b == 0) - { - if (!buffer) - buffer = new char[4]; - buffer[0] = c; - b++; - lastc = dex[c - 'A']; - } - else - { - if (c == 'H' || c == 'W') - continue; - if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') - lastc = lastc.init; - c = dex[c - 'A']; - if (c != '0' && c != lastc) - { - buffer[b] = c; - b++; - lastc = c; - } - } - if (b == 4) - goto Lret; - } - if (b == 0) - buffer = null; - else - buffer[b .. 4] = '0'; -Lret: - return buffer; -} - -unittest -{ char[4] buffer; - - assert(soundex(null) == null); - assert(soundex("") == null); - assert(soundex("0123^&^^**&^") == null); - assert(soundex("Euler") == "E460"); - assert(soundex(" Ellery ") == "E460"); - assert(soundex("Gauss") == "G200"); - assert(soundex("Ghosh") == "G200"); - assert(soundex("Hilbert") == "H416"); - assert(soundex("Heilbronn") == "H416"); - assert(soundex("Knuth") == "K530"); - assert(soundex("Kant", buffer) == "K530"); - assert(soundex("Lloyd") == "L300"); - assert(soundex("Ladd") == "L300"); - assert(soundex("Lukasiewicz", buffer) == "L222"); - assert(soundex("Lissajous") == "L222"); - assert(soundex("Robert") == "R163"); - assert(soundex("Rupert") == "R163"); - assert(soundex("Rubin") == "R150"); - assert(soundex("Washington") == "W252"); - assert(soundex("Lee") == "L000"); - assert(soundex("Gutierrez") == "G362"); - assert(soundex("Pfister") == "P236"); - assert(soundex("Jackson") == "J250"); - assert(soundex("Tymczak") == "T522"); - assert(soundex("Ashcraft") == "A261"); - - assert(soundex("Woo") == "W000"); - assert(soundex("Pilgrim") == "P426"); - assert(soundex("Flingjingwaller") == "F452"); - assert(soundex("PEARSE") == "P620"); - assert(soundex("PIERCE") == "P620"); - assert(soundex("Price") == "P620"); - assert(soundex("CATHY") == "C300"); - assert(soundex("KATHY") == "K300"); - assert(soundex("Jones") == "J520"); - assert(soundex("johnsons") == "J525"); - assert(soundex("Hardin") == "H635"); - assert(soundex("Martinez") == "M635"); -} - - -/*************************************************** - * Construct an associative array consisting of all - * abbreviations that uniquely map to the strings in values. - * - * This is useful in cases where the user is expected to type - * in one of a known set of strings, and the program will helpfully - * autocomplete the string once sufficient characters have been - * entered that uniquely identify it. - * Example: - * --- - * import std.stdio; - * import std.string; - * - * void main() - * { - * static char[][] list = [ "food", "foxy" ]; - * - * auto abbrevs = std.string.abbrev(list); - * - * foreach (key, value; abbrevs) - * { - * writefln("%s => %s", key, value); - * } - * } - * --- - * produces the output: - *

- * fox => foxy
- * food => food
- * foxy => foxy
- * foo => food
- * 
- */ - -char[][char[]] abbrev(char[][] values) -{ - char[][char[]] result; - - // Make a copy when sorting so we follow COW principles. - values = values.dup.sort; - - size_t values_length = values.length; - size_t lasti = values_length; - size_t nexti; - - char[] nv; - char[] lv; - - for (size_t i = 0; i < values_length; i = nexti) - { char[] value = values[i]; - - // Skip dups - for (nexti = i + 1; nexti < values_length; nexti++) - { nv = values[nexti]; - if (value != values[nexti]) - break; - } - - for (size_t j = 0; j < value.length; j += std.utf.stride(value, j)) - { char[] v = value[0 .. j]; - - if ((nexti == values_length || j > nv.length || v != nv[0 .. j]) && - (lasti == values_length || j > lv.length || v != lv[0 .. j])) - result[v] = value; - } - result[value] = value; - lasti = i; - lv = value; - } - - return result; -} - -unittest -{ - debug(string) printf("string.abbrev.unittest\n"); - - char[][] values; - values ~= "hello"; - values ~= "hello"; - values ~= "he"; - - char[][char[]] r; - - r = abbrev(values); - char[][] keys = r.keys.dup; - keys.sort; - - assert(keys.length == 4); - assert(keys[0] == "he"); - assert(keys[1] == "hel"); - assert(keys[2] == "hell"); - assert(keys[3] == "hello"); - - assert(r[keys[0]] == "he"); - assert(r[keys[1]] == "hello"); - assert(r[keys[2]] == "hello"); - assert(r[keys[3]] == "hello"); -} - - -/****************************************** - * Compute column number after string if string starts in the - * leftmost column, which is numbered starting from 0. - */ - -size_t column(char[] string, int tabsize = 8) -{ - size_t column; - - foreach (dchar c; string) - { - switch (c) - { - case '\t': - column = (column + tabsize) / tabsize * tabsize; - break; - - case '\r': - case '\n': - case PS: - case LS: - column = 0; - break; - - default: - column++; - break; - } - } - return column; -} - -unittest -{ - debug(string) printf("string.column.unittest\n"); - - assert(column(null) == 0); - assert(column("") == 0); - assert(column("\t") == 8); - assert(column("abc\t") == 8); - assert(column("12345678\t") == 16); -} - -/****************************************** - * Wrap text into a paragraph. - * - * The input text string s is formed into a paragraph - * by breaking it up into a sequence of lines, delineated - * by \n, such that the number of columns is not exceeded - * on each line. - * The last line is terminated with a \n. - * Params: - * s = text string to be wrapped - * columns = maximum number of _columns in the paragraph - * firstindent = string used to _indent first line of the paragraph - * indent = string to use to _indent following lines of the paragraph - * tabsize = column spacing of tabs - * Returns: - * The resulting paragraph. - */ - -char[] wrap(char[] s, int columns = 80, char[] firstindent = null, - char[] indent = null, int tabsize = 8) -{ - char[] result; - int col; - int spaces; - bool inword; - bool first = true; - size_t wordstart; - - result.length = firstindent.length + s.length; - result.length = firstindent.length; - result[] = firstindent[]; - col = column(result, tabsize); - foreach (size_t i, dchar c; s) - { - if (iswhite(c)) - { - if (inword) - { - if (first) - { - ; - } - else if (col + 1 + (i - wordstart) > columns) - { - result ~= '\n'; - result ~= indent; - col = column(indent, tabsize); - } - else - { result ~= ' '; - col += 1; - } - result ~= s[wordstart .. i]; - col += i - wordstart; - inword = false; - first = false; - } - } - else - { - if (!inword) - { - wordstart = i; - inword = true; - } - } - } - - if (inword) - { - if (col + 1 + (s.length - wordstart) >= columns) - { - result ~= '\n'; - result ~= indent; - } - else if (result.length != firstindent.length) - result ~= ' '; - result ~= s[wordstart .. s.length]; - } - result ~= '\n'; - - return result; -} - -unittest -{ - debug(string) printf("string.wrap.unittest\n"); - - assert(wrap(null) == "\n"); - assert(wrap(" a b df ") == "a b df\n"); - //writefln("'%s'", wrap(" a b df ",3)); - assert(wrap(" a b df ", 3) == "a b\ndf\n"); - assert(wrap(" a bc df ", 3) == "a\nbc\ndf\n"); - //writefln("'%s'", wrap(" abcd df ",3)); - assert(wrap(" abcd df ", 3) == "abcd\ndf\n"); - assert(wrap("x") == "x\n"); - assert(wrap("u u") == "u u\n"); -} - - -/*************************** - * Does string s[] start with an email address? - * Returns: - * null it does not - * char[] it does, and this is the slice of s[] that is that email address - * References: - * RFC2822 - */ -char[] isEmail(char[] s) -{ size_t i; - - if (!isalpha(s[0])) - goto Lno; - - for (i = 1; 1; i++) - { - if (i == s.length) - goto Lno; - auto c = s[i]; - if (isalnum(c)) - continue; - if (c == '-' || c == '_' || c == '.') - continue; - if (c != '@') - goto Lno; - i++; - break; - } - //writefln("test1 '%s'", s[0 .. i]); - - /* Now do the part past the '@' - */ - size_t lastdot; - for (; i < s.length; i++) - { - auto c = s[i]; - if (isalnum(c)) - continue; - if (c == '-' || c == '_') - continue; - if (c == '.') - { - lastdot = i; - continue; - } - break; - } - if (!lastdot || (i - lastdot != 3 && i - lastdot != 4)) - goto Lno; - - return s[0 .. i]; - -Lno: - return null; -} - - -/*************************** - * Does string s[] start with a URL? - * Returns: - * null it does not - * char[] it does, and this is the slice of s[] that is that URL - */ - -char[] isURL(char[] s) -{ - /* Must start with one of: - * http:// - * https:// - * www. - */ - - size_t i; - - if (s.length <= 4) - goto Lno; - - //writefln("isURL(%s)", s); - if (s.length > 7 && std.string.icmp(s[0 .. 7], "http://") == 0) - i = 7; - else if (s.length > 8 && std.string.icmp(s[0 .. 8], "https://") == 0) - i = 8; -// if (icmp(s[0 .. 4], "www.") == 0) -// i = 4; - else - goto Lno; - - size_t lastdot; - for (; i < s.length; i++) - { - auto c = s[i]; - if (isalnum(c)) - continue; - if (c == '-' || c == '_' || c == '?' || - c == '=' || c == '%' || c == '&' || - c == '/' || c == '+' || c == '#' || - c == '~') - continue; - if (c == '.') - { - lastdot = i; - continue; - } - break; - } - //if (!lastdot || (i - lastdot != 3 && i - lastdot != 4)) - if (!lastdot) - goto Lno; - - return s[0 .. i]; - -Lno: - return null; -} - - diff --git a/lphobos/std/system.d b/lphobos/std/system.d deleted file mode 100644 index 12b59386c89..00000000000 --- a/lphobos/std/system.d +++ /dev/null @@ -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; - - diff --git a/lphobos/std/thread.d b/lphobos/std/thread.d deleted file mode 100644 index b9259338253..00000000000 --- a/lphobos/std/thread.d +++ /dev/null @@ -1,1127 +0,0 @@ -// Written in the D programming language - -/* - * Copyright (C) 2002-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. - */ - -/************************** - * The thread module defines the class $(B Thread). - * - * $(B Thread) is the basis - * for writing multithreaded applications. Each thread - * has a unique instance of class $(B Thread) associated with it. - * It is important to use the $(B Thread) class to create and manage - * threads as the garbage collector needs to know about all the threads. - * Macros: - * WIKI=Phobos/StdThread - */ - -module std.thread; - -import std.c.stdio; - -//debug=thread; - -/* ================================ Win32 ================================= */ - -version (Win32) -{ - -private import std.c.windows.windows; - -extern (Windows) alias uint (*stdfp)(void *); - -extern (C) - thread_hdl _beginthreadex(void* security, uint stack_size, - stdfp start_addr, void* arglist, uint initflag, - thread_id* thrdaddr); - -/** - * The type of the thread handle used by the operating system. - * For Windows, it is equivalent to a HANDLE from windows.d. - */ -alias HANDLE thread_hdl; - -alias uint thread_id; - -/** - * Thrown for errors. - */ -class ThreadError : Error -{ - this(char[] s) - { - super("Thread error: " ~ s); - } -} - -/** - * One of these is created for each thread. - */ -class Thread -{ - /** - * Constructor used by classes derived from Thread that override main(). - * The optional stacksize parameter default value of 0 will cause threads - * to be created with the default size for the executable - Dave Fladebo - */ - this(size_t stacksize = 0) - { - this.stacksize = stacksize; - } - - /** - * Constructor used by classes derived from Thread that override run(). - */ - this(int (*fp)(void *), void *arg, size_t stacksize = 0) - { - this.fp = fp; - this.arg = arg; - this.stacksize = stacksize; - } - - /** - * Constructor used by classes derived from Thread that override run(). - */ - this(int delegate() dg, size_t stacksize = 0) - { - this.dg = dg; - this.stacksize = stacksize; - } - - /** - * Destructor - * - * If the thread hasn't been joined yet, detach it. - */ - ~this() - { - if (state != TS.FINISHED) - CloseHandle(hdl); - } - - /** - * The handle to this thread assigned by the operating system. This is set - * to thread_id.init if the thread hasn't been started yet. - */ - thread_hdl hdl; - - void* stackBottom; - - /** - * Create a new thread and start it running. The new thread initializes - * itself and then calls run(). start() can only be called once. - */ - void start() - { - if (state != TS.INITIAL) - error("already started"); - - synchronized (Thread.classinfo) - { - for (int i = 0; 1; i++) - { - if (i == allThreads.length) - error("too many threads"); - if (!allThreads[i]) - { allThreads[i] = this; - idx = i; - if (i >= allThreadsDim) - allThreadsDim = i + 1; - break; - } - } - nthreads++; - } - - state = TS.RUNNING; - hdl = _beginthreadex(null, cast(uint)stacksize, &threadstart, cast(void*)this, 0, &id); - if (hdl == cast(thread_hdl)0) - { state = TS.FINISHED; - synchronized (Thread.classinfo) allThreads[idx] = null; - idx = -1; - error("failed to start"); - } - } - - /** - * Entry point for a thread. If not overridden, it calls the function - * pointer fp and argument arg passed in the constructor, or the delegate - * dg. - * Returns: the thread exit code, which is normally 0. - */ - int run() - { - if (fp) - return fp(arg); - else if (dg) - return dg(); - assert(0); - } - - /***************************** - * Wait for this thread to terminate. - * Simply returns if thread has already terminated. - * Throws: $(B ThreadError) if the thread hasn't begun yet or - * is called on itself. - */ - void wait() - { - if (isSelf) - error("wait on self"); - if (state != TS.FINISHED) - { DWORD dw; - - dw = WaitForSingleObject(hdl, 0xFFFFFFFF); - state = TS.FINISHED; - CloseHandle(hdl); - hdl = null; - } - } - - /****************************** - * Wait for this thread to terminate or until milliseconds time has - * elapsed, whichever occurs first. - * Simply returns if thread has already terminated. - * Throws: $(B ThreadError) if the thread hasn't begun yet or - * is called on itself. - */ - void wait(uint milliseconds) - { - if (isSelf) - error("wait on self"); - if (state != TS.FINISHED) - { DWORD dw; - - dw = WaitForSingleObject(hdl, milliseconds); - state = TS.FINISHED; - CloseHandle(hdl); - hdl = null; - } - } - - /** - * The state of a thread. - */ - enum TS - { - INITIAL, /// The thread hasn't been started yet. - RUNNING, /// The thread is running or paused. - TERMINATED, /// The thread has ended. - FINISHED /// The thread has been cleaned up - } - - /** - * Returns the state of a thread. - */ - TS getState() - { - return state; - } - - /** - * The priority of a thread. - */ - enum PRIORITY - { - INCREASE, /// Increase thread priority - DECREASE, /// Decrease thread priority - IDLE, /// Assign thread low priority - CRITICAL /// Assign thread high priority - } - - /** - * Adjust the priority of this thread. - * Throws: ThreadError if cannot set priority - */ - void setPriority(PRIORITY p) - { - int nPriority; - - switch (p) - { - case PRIORITY.INCREASE: - nPriority = THREAD_PRIORITY_ABOVE_NORMAL; - break; - case PRIORITY.DECREASE: - nPriority = THREAD_PRIORITY_BELOW_NORMAL; - break; - case PRIORITY.IDLE: - nPriority = THREAD_PRIORITY_IDLE; - break; - case PRIORITY.CRITICAL: - nPriority = THREAD_PRIORITY_TIME_CRITICAL; - break; - default: - assert(0); - } - - if (SetThreadPriority(hdl, nPriority) == THREAD_PRIORITY_ERROR_RETURN) - error("set priority"); - } - - /** - * Returns true if this thread is the current thread. - */ - bool isSelf() - { - //printf("id = %d, self = %d\n", id, pthread_self()); - return (id == GetCurrentThreadId()); - } - - /** - * Returns a reference to the Thread for the thread that called the - * function. - */ - static Thread getThis() - { - //printf("getThis(), allThreadsDim = %d\n", allThreadsDim); - thread_id id = GetCurrentThreadId(); - for (int i = 0; i < allThreadsDim; i++) - { - Thread t = allThreads[i]; - if (t && id == t.id) - { - return t; - } - } - printf("didn't find it\n"); - assert(0); - } - - /** - * Returns an array of all the threads currently running. - */ - static Thread[] getAll() - { - synchronized (Thread.classinfo) return allThreads[0 .. allThreadsDim]; - } - - /** - * Suspend execution of this thread. - */ - void pause() - { - if (state != TS.RUNNING || SuspendThread(hdl) == 0xFFFFFFFF) - error("cannot pause"); - } - - /** - * Resume execution of this thread. - */ - void resume() - { - if (state != TS.RUNNING || ResumeThread(hdl) == 0xFFFFFFFF) - error("cannot resume"); - } - - /** - * Suspend execution of all threads but this thread. - */ - static void pauseAll() - { - synchronized (Thread.classinfo) - { - if (nthreads > 1) - { - thread_id thisid = GetCurrentThreadId(); - - for (int i = 0; i < allThreadsDim; i++) - { - Thread t = allThreads[i]; - if (t && t.id != thisid && t.state == TS.RUNNING) - t.pause(); - } - } - } - } - - /** - * Resume execution of all paused threads. - */ - static void resumeAll() - { - synchronized (Thread.classinfo) - { - if (nthreads > 1) - { - thread_id thisid = GetCurrentThreadId(); - - for (int i = 0; i < allThreadsDim; i++) - { - Thread t = allThreads[i]; - if (t && t.id != thisid && t.state == TS.RUNNING) - t.resume(); - } - } - } - } - - /** - * Give up the remainder of this thread's time slice. - */ - static void yield() - { - Sleep(0); - } - - /** - * - */ - static uint nthreads = 1; - - private: - - static uint allThreadsDim; - static Thread[0x400] allThreads; // length matches value in C runtime - - TS state; - int idx = -1; // index into allThreads[] - thread_id id; - size_t stacksize = 0; - - int (*fp)(void *); - void *arg; - - int delegate() dg; - - void error(char[] msg) - { - throw new ThreadError(msg); - } - - - /* *********************************************** - * This is just a wrapper to interface between C rtl and Thread.run(). - */ - - extern (Windows) static uint threadstart(void *p) - { - Thread t = cast(Thread)p; - int result; - - debug (thread) printf("Starting thread %d\n", t.idx); - t.stackBottom = os_query_stackBottom(); - try - { - result = t.run(); - } - catch (Object o) - { - fprintf(stderr, "Error: %.*s\n", o.toString()); - result = 1; - } - - debug (thread) printf("Ending thread %d\n", t.idx); - t.state = TS.TERMINATED; - synchronized (Thread.classinfo) - { - allThreads[t.idx] = null; - t.idx = -1; - nthreads--; - } - return result; - } - - - /************************************** - * Create a Thread for global main(). - */ - - public static void thread_init() - { - Thread t = new Thread(); - - t.state = TS.RUNNING; - t.id = GetCurrentThreadId(); - t.hdl = Thread.getCurrentThreadHandle(); - t.stackBottom = os_query_stackBottom(); - - assert(!allThreads[0]); - allThreads[0] = t; - allThreadsDim = 1; - t.idx = 0; - } - - static ~this() - { - if (allThreadsDim) - { - CloseHandle(allThreads[0].hdl); - allThreads[0].hdl = GetCurrentThread(); - } - } - - /******************************************** - * Returns the handle of the current thread. - * This is needed because GetCurrentThread() always returns -2 which - * is a pseudo-handle representing the current thread. - * The returned thread handle is a windows resource and must be explicitly - * closed. - * Many thanks to Justin (jhenzie@mac.com) for figuring this out - * and providing the fix. - */ - static thread_hdl getCurrentThreadHandle() - { - thread_hdl currentThread = GetCurrentThread(); - thread_hdl actualThreadHandle; - - //thread_hdl currentProcess = cast(thread_hdl)-1; - thread_hdl currentProcess = GetCurrentProcess(); // http://www.digitalmars.com/drn-bin/wwwnews?D/21217 - - - uint access = cast(uint)0x00000002; - - DuplicateHandle(currentProcess, currentThread, currentProcess, - &actualThreadHandle, cast(uint)0, TRUE, access); - - return actualThreadHandle; - } -} - - -/********************************************** - * Determine "bottom" of stack (actually the top on Win32 systems). - */ - -void *os_query_stackBottom() -{ - asm - { - naked ; - mov EAX,FS:4 ; - ret ; - } -} - -} - -/* ================================ linux ================================= */ - -version (linux) -{ - -private import std.c.linux.linux; -private import std.c.linux.linuxextern; -private import llvm.intrinsic; - -alias uint pthread_t; -extern (C) alias void (*__sighandler_t)(int); - -struct sigset_t -{ - uint __val[1024 / (8 * uint.sizeof)]; -} - -struct sigaction_t -{ - __sighandler_t sa_handler; - sigset_t sa_mask; - int sa_flags; - void (*sa_restorer)(); -} - -struct pthread_attr_t -{ - int __detachstate; - int __schedpolicy; - struct __schedparam - { - int __sched_priority; - } - int __inheritsched; - int __scope; - size_t __guardsize; - int __stackaddr_set; - void *__stackaddr; - size_t __stacksize; -} - -unittest -{ - assert(sigset_t.sizeof == 128); - assert(sigaction_t.sizeof == 140); - assert(sem_t.sizeof == 16); -} - -extern (C) -{ - int pthread_create(pthread_t*, void*, void* (*)(void*), void*); - int pthread_join(pthread_t, void**); - int pthread_kill(pthread_t, int); - pthread_t pthread_self(); - int pthread_equal(pthread_t, pthread_t); - int pthread_attr_init(pthread_attr_t*); - int pthread_attr_setstacksize(pthread_attr_t *, size_t); - int pthread_cancel(pthread_t); - int pthread_setcancelstate(int, int*); - int pthread_setcanceltype(int, int*); - int sched_yield(); - int sigfillset(sigset_t*); - int sigdelset(sigset_t*, int); - int sigaction(int, sigaction_t*, sigaction_t*); - int sigsuspend(sigset_t*); - - enum - { - PTHREAD_CANCEL_ENABLE, - PTHREAD_CANCEL_DISABLE - } - - enum - { - PTHREAD_CANCEL_DEFERRED, - PTHREAD_CANCEL_ASYNCHRONOUS - } -} - -class ThreadError : Error -{ - this(char[] s) - { - super("Thread error: " ~ s); - } -} - -class Thread -{ - // The optional stacksize parameter default value of 0 will cause threads - // to be created with the default pthread size - Dave Fladebo - this(size_t stacksize = 0) - { - init(stacksize); - } - - this(int (*fp)(void *), void *arg, size_t stacksize = 0) - { - this.fp = fp; - this.arg = arg; - init(stacksize); - } - - this(int delegate() dg, size_t stacksize = 0) - { - this.dg = dg; - init(stacksize); - } - - ~this() - { - pthread_cond_destroy(&waitCond); - pthread_mutex_destroy(&waitMtx); - if (state != TS.FINISHED) - pthread_detach(id); - } - - pthread_t id; - void* stackBottom; - void* stackTop; - - void start() - { - if (state != TS.INITIAL) - error("already started"); - - synchronized (Thread.classinfo) - { - for (int i = 0; 1; i++) - { - if (i == allThreads.length) - error("too many threads"); - if (!allThreads[i]) - { allThreads[i] = this; - idx = i; - if (i >= allThreadsDim) - allThreadsDim = i + 1; - break; - } - } - nthreads++; - } - - state = TS.RUNNING; - printf("creating thread x%x\n", this); - //result = pthread_create(&id, null, &threadstart, this); - // Create with thread attributes to allow non-default stack size - Dave Fladebo - int result = pthread_create(&id, &threadAttrs, &threadstart, cast(void*)this); - if (result) - { state = TS.FINISHED; - synchronized (Thread.classinfo) allThreads[idx] = null; - idx = -1; - error("failed to start"); // BUG: should report errno - } - printf("t = x%x, id = %d\n", this, id); - } - - int run() - { - if (fp) - return fp(arg); - else if (dg) - return dg(); - assert(0); - } - - void wait() - { - if (isSelf) - error("wait on self"); - - if (state != TS.FINISHED) - { - void *value; - - int result = pthread_join(id, &value); - state = TS.FINISHED; - if (result) - error("failed to wait"); - } - } - - void wait(uint milliseconds) - { - // Implemented for POSIX systems by Dave Fladebo - if (isSelf) - error("wait on self"); - if (state != TS.FINISHED) - { - timespec ts; - timeval tv; - - pthread_mutex_lock(&waitMtx); - gettimeofday(&tv, null); - ts.tv_sec = cast(__time_t)tv.tv_sec + cast(__time_t)(milliseconds / 1_000); - ts.tv_nsec = (tv.tv_usec * 1_000) + ((milliseconds % 1_000) * 1_000_000); - if (ts.tv_nsec > 1_000_000_000) - { - ts.tv_sec += 1; - ts.tv_nsec -= 1_000_000_000; - } - if (pthread_cond_timedwait(&waitCond, &waitMtx, &ts)) - { - int oldstate, oldtype; - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); - - if (pthread_cancel(id)) // thread was not completed in the timeout period, cancel it - { - pthread_mutex_unlock(&waitMtx); - error("cannot terminate thread via timed wait"); - } - - pthread_setcancelstate(oldstate, null); - pthread_setcanceltype(oldtype, null); - - state = TS.TERMINATED; - synchronized (Thread.classinfo) - { - allThreads[idx] = null; - idx = -1; - nthreads--; - } - - pthread_mutex_unlock(&waitMtx); - } - else - { - pthread_mutex_unlock(&waitMtx); - wait(); // condition has been signalled as complete (see threadstart()), terminate normally - } - } - } - - enum TS - { - INITIAL, // created - RUNNING, // running - TERMINATED, // execution finished - FINISHED // pthread_join()'ed - } - - TS getState() - { - return state; - } - - enum PRIORITY - { - INCREASE, - DECREASE, - IDLE, - CRITICAL - } - - void setPriority(PRIORITY p) - { - /+ not implemented - int nPriority; - - switch (p) - { - case PRIORITY.INCREASE: - nPriority = THREAD_PRIORITY_ABOVE_NORMAL; - break; - case PRIORITY.DECREASE: - nPriority = THREAD_PRIORITY_BELOW_NORMAL; - break; - case PRIORITY.IDLE: - nPriority = THREAD_PRIORITY_IDLE; - break; - case PRIORITY.CRITICAL: - nPriority = THREAD_PRIORITY_TIME_CRITICAL; - break; - } - - if (SetThreadPriority(hdl, nPriority) == THREAD_PRIORITY_ERROR_RETURN) - error("set priority"); - +/ - } - - int isSelf() - { - //printf("id = %d, self = %d\n", id, pthread_self()); - return pthread_equal(pthread_self(), id); - } - - static Thread getThis() - { - //printf("getThis(), allThreadsDim = %d\n", allThreadsDim); - pthread_t id = pthread_self(); - //printf("id = %d\n", id); - for (int i = 0; i < allThreadsDim; i++) - { - Thread t = allThreads[i]; - //printf("allThreads[%d] = x%x, id = %d\n", i, t, (t ? t.id : 0)); - if (t && pthread_equal(id, t.id)) - { - return t; - } - } - printf("didn't find it\n"); - assert(null); - } - - static Thread[] getAll() - { - synchronized (Thread.classinfo) return allThreads[0 .. allThreadsDim]; - } - - void pause() - { - if (state == TS.RUNNING) - { - if (pthread_kill(id, SIGUSR1)) - error("cannot pause"); - else - sem_wait(&flagSuspend); // wait for acknowledgement - } - else - error("cannot pause"); - } - - void resume() - { - if (state == TS.RUNNING) - { - if (pthread_kill(id, SIGUSR2)) - error("cannot resume"); - } - else - error("cannot resume"); - } - - static void pauseAll() - { - synchronized (Thread.classinfo) - { - if (nthreads > 1) - { - pthread_t thisid = pthread_self(); - int npause = 0; - - for (int i = 0; i < allThreadsDim; i++) - { - Thread t = allThreads[i]; - if (t && !pthread_equal(thisid, t.id) && t.state == TS.RUNNING) - { - if (pthread_kill(t.id, SIGUSR1)) - t.error("cannot pause"); - else - npause++; // count of paused threads - } - } - - // Wait for each paused thread to acknowledge - while (npause--) - { - sem_wait(&flagSuspend); - } - } - } - } - - static void resumeAll() - { - synchronized (Thread.classinfo) - { - if (nthreads > 1) - { - pthread_t thisid = pthread_self(); - - for (int i = 0; i < allThreadsDim; i++) - { - Thread t = allThreads[i]; - if (t && t.id != thisid && t.state == TS.RUNNING) - t.resume(); - } - } - } - } - - static void yield() - { - sched_yield(); - } - - static uint nthreads = 1; - - private: - - static uint allThreadsDim; - - // Set max to Windows equivalent for compatibility. - // pthread_create will fail gracefully if stack limit - // is reached prior to allThreads max. - static Thread[0x400] allThreads; - - static sem_t flagSuspend; - - TS state; - int idx = -1; // index into allThreads[] - int flags = 0; - - pthread_attr_t threadAttrs; - pthread_mutex_t waitMtx; - pthread_cond_t waitCond; - - int (*fp)(void *); - void *arg; - - int delegate() dg; - - void error(char[] msg) - { - throw new ThreadError(msg); - } - - void init(size_t stackSize) - { - // set to default values regardless - // passing this as the 2nd arg. for pthread_create() - // w/o setting an attribute is equivalent to passing null. - pthread_attr_init(&threadAttrs); - if (stackSize > 0) - { - if (pthread_attr_setstacksize(&threadAttrs,stackSize)) - error("cannot set stack size"); - } - - if (pthread_mutex_init(&waitMtx, null)) - error("cannot initialize wait mutex"); - - if (pthread_cond_init(&waitCond, null)) - error("cannot initialize wait condition"); - } - - /************************************************ - * This is just a wrapper to interface between C rtl and Thread.run(). - */ - - extern (C) static void *threadstart(void *p) - { - Thread t = cast(Thread)p; - int result; - - debug (thread) printf("Starting thread x%x (%d)\n", t, t.idx); - - // Need to set t.id here, because thread is off and running - // before pthread_create() sets it. - t.id = pthread_self(); - - t.stackBottom = getESP(); - try - { - if(t.state == TS.RUNNING) - pthread_cond_signal(&t.waitCond); // signal the wait condition (see the timed wait function) - result = t.run(); - } - catch (Object o) - { - fprintf(stderr, "Error: %.*s\n", o.toString()); - result = 1; - } - - debug (thread) printf("Ending thread %d\n", t.idx); - t.state = TS.TERMINATED; - synchronized (Thread.classinfo) - { - allThreads[t.idx] = null; - t.idx = -1; - nthreads--; - } - return cast(void*)result; - } - - - /************************************** - * Create a Thread for global main(). - */ - - public static void thread_init() - { - Thread t = new Thread(); - - t.state = TS.RUNNING; - t.id = pthread_self(); - - 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); - } - t.stackBottom = *libc_stack_end; - } - else - { - t.stackBottom = cast(void*)__libc_stack_end; - } - - assert(!allThreads[0]); - allThreads[0] = t; - allThreadsDim = 1; - t.idx = 0; - - /* Install signal handlers so we can suspend/resume threads - */ - - int result; - sigaction_t sigact; - result = sigfillset(&sigact.sa_mask); - if (result) - goto Lfail; - sigact.sa_handler = &pauseHandler; - result = sigaction(SIGUSR1, &sigact, null); - if (result) - goto Lfail; - sigact.sa_handler = &resumeHandler; - result = sigaction(SIGUSR2, &sigact, null); - if (result) - goto Lfail; - - result = sem_init(&flagSuspend, 0, 0); - if (result) - goto Lfail; - - return; - - Lfail: - t.error("cannot initialize threads"); - } - - /********************************** - * This gets called when a thread gets SIGUSR1. - */ - - extern (C) static void pauseHandler(int sig) - { int result; - - // Save all registers on the stack so they'll be scanned by the GC - version(none) asm - { - pusha ; - } - - assert(sig == SIGUSR1); - - sigset_t sigmask; - result = sigfillset(&sigmask); - assert(result == 0); - result = sigdelset(&sigmask, SIGUSR2); - assert(result == 0); - - Thread t = getThis(); - t.stackTop = getESP(); - t.flags &= ~1; - // Release the semaphore _after_ stackTop is set - sem_post(&flagSuspend); - while (1) - { - sigsuspend(&sigmask); // suspend until SIGUSR2 - if (t.flags & 1) // ensure it was resumeHandler() - break; - } - - // Restore all registers - version(none) asm - { - popa ; - } - } - - /********************************** - * This gets called when a thread gets SIGUSR2. - */ - - extern (C) static void resumeHandler(int sig) - { - Thread t = getThis(); - - t.flags |= 1; - } - - public static void* getESP() - { - version(D_InlineAsm_X86) - { - asm - { naked ; - mov EAX,ESP ; - ret ; - } - } - else - { - void* p = llvm_frameaddress(0); - assert(p !is null); - return p; - } - } -} - - -} - diff --git a/lphobos/std/traits.d b/lphobos/std/traits.d deleted file mode 100644 index 5f4524d6d2f..00000000000 --- a/lphobos/std/traits.d +++ /dev/null @@ -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; -} diff --git a/lphobos/std/uni.d b/lphobos/std/uni.d deleted file mode 100644 index e4ce1e5df47..00000000000 --- a/lphobos/std/uni.d +++ /dev/null @@ -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)); - } -} diff --git a/lphobos/std/utf.d b/lphobos/std/utf.d deleted file mode 100644 index 6b82b0ea6ee..00000000000 --- a/lphobos/std/utf.d +++ /dev/null @@ -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)
- * $(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)
- * $(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"); -} diff --git a/lphobos/std/zip.d b/lphobos/std/zip.d deleted file mode 100644 index 7aebf5a3166..00000000000 --- a/lphobos/std/zip.d +++ /dev/null @@ -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"); - } -} diff --git a/lphobos/std/zlib.d b/lphobos/std/zlib.d deleted file mode 100644 index 24af3e2ea58..00000000000 --- a/lphobos/std/zlib.d +++ /dev/null @@ -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+ - * 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[] ); -} - diff --git a/lphobos/typeinfo1/ti_byte.d b/lphobos/typeinfo1/ti_byte.d deleted file mode 100644 index 518bbe76104..00000000000 --- a/lphobos/typeinfo1/ti_byte.d +++ /dev/null @@ -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; - } -} - diff --git a/lphobos/typeinfo1/ti_cdouble.d b/lphobos/typeinfo1/ti_cdouble.d deleted file mode 100644 index 84d5d024d6c..00000000000 --- a/lphobos/typeinfo1/ti_cdouble.d +++ /dev/null @@ -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]; - } -} - diff --git a/lphobos/typeinfo1/ti_cfloat.d b/lphobos/typeinfo1/ti_cfloat.d deleted file mode 100644 index b1281eba563..00000000000 --- a/lphobos/typeinfo1/ti_cfloat.d +++ /dev/null @@ -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]; - } -} - diff --git a/lphobos/typeinfo1/ti_char.d b/lphobos/typeinfo1/ti_char.d deleted file mode 100644 index 06fa23bfcbd..00000000000 --- a/lphobos/typeinfo1/ti_char.d +++ /dev/null @@ -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]; - } -} - diff --git a/lphobos/typeinfo1/ti_creal.d b/lphobos/typeinfo1/ti_creal.d deleted file mode 100644 index e877f6021bb..00000000000 --- a/lphobos/typeinfo1/ti_creal.d +++ /dev/null @@ -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]; - } -} - diff --git a/lphobos/typeinfo1/ti_dchar.d b/lphobos/typeinfo1/ti_dchar.d deleted file mode 100644 index b88da81154a..00000000000 --- a/lphobos/typeinfo1/ti_dchar.d +++ /dev/null @@ -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]; - } -} - diff --git a/lphobos/typeinfo1/ti_delegate.d b/lphobos/typeinfo1/ti_delegate.d deleted file mode 100644 index 8ec3d776f6a..00000000000 --- a/lphobos/typeinfo1/ti_delegate.d +++ /dev/null @@ -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; - } -} - diff --git a/lphobos/typeinfo1/ti_double.d b/lphobos/typeinfo1/ti_double.d deleted file mode 100644 index a8bd986a946..00000000000 --- a/lphobos/typeinfo1/ti_double.d +++ /dev/null @@ -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]; - } -} - diff --git a/lphobos/typeinfo1/ti_float.d b/lphobos/typeinfo1/ti_float.d deleted file mode 100644 index dab1a3c4030..00000000000 --- a/lphobos/typeinfo1/ti_float.d +++ /dev/null @@ -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]; - } -} - diff --git a/lphobos/typeinfo1/ti_idouble.d b/lphobos/typeinfo1/ti_idouble.d deleted file mode 100644 index 671e35854ee..00000000000 --- a/lphobos/typeinfo1/ti_idouble.d +++ /dev/null @@ -1,12 +0,0 @@ - -// idouble - -module typeinfo1.ti_idouble; - -private import typeinfo1.ti_double; - -class TypeInfo_p : TypeInfo_d -{ - char[] toString() { return "idouble"; } -} - diff --git a/lphobos/typeinfo1/ti_ifloat.d b/lphobos/typeinfo1/ti_ifloat.d deleted file mode 100644 index ce2d6fa21f2..00000000000 --- a/lphobos/typeinfo1/ti_ifloat.d +++ /dev/null @@ -1,12 +0,0 @@ - -// ifloat - -module typeinfo1.ti_ifloat; - -private import typeinfo1.ti_float; - -class TypeInfo_o : TypeInfo_f -{ - char[] toString() { return "ifloat"; } -} - diff --git a/lphobos/typeinfo1/ti_int.d b/lphobos/typeinfo1/ti_int.d deleted file mode 100644 index 8ae9bbe2d50..00000000000 --- a/lphobos/typeinfo1/ti_int.d +++ /dev/null @@ -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; - } -} - diff --git a/lphobos/typeinfo1/ti_ireal.d b/lphobos/typeinfo1/ti_ireal.d deleted file mode 100644 index f5b16df9555..00000000000 --- a/lphobos/typeinfo1/ti_ireal.d +++ /dev/null @@ -1,12 +0,0 @@ - -// ireal - -module typeinfo1.ti_ireal; - -private import typeinfo1.ti_real; - -class TypeInfo_j : TypeInfo_e -{ - char[] toString() { return "ireal"; } -} - diff --git a/lphobos/typeinfo1/ti_long.d b/lphobos/typeinfo1/ti_long.d deleted file mode 100644 index 7de73a1c5ee..00000000000 --- a/lphobos/typeinfo1/ti_long.d +++ /dev/null @@ -1,43 +0,0 @@ - -// long - -module typeinfo1.ti_long; - -class TypeInfo_l : TypeInfo -{ - char[] toString() { return "long"; } - - hash_t getHash(void *p) - { - return *cast(uint *)p + (cast(uint *)p)[1]; - } - - int equals(void *p1, void *p2) - { - return *cast(long *)p1 == *cast(long *)p2; - } - - int compare(void *p1, void *p2) - { - if (*cast(long *)p1 < *cast(long *)p2) - return -1; - else if (*cast(long *)p1 > *cast(long *)p2) - return 1; - return 0; - } - - size_t tsize() - { - return long.sizeof; - } - - void swap(void *p1, void *p2) - { - long t; - - t = *cast(long *)p1; - *cast(long *)p1 = *cast(long *)p2; - *cast(long *)p2 = t; - } -} - diff --git a/lphobos/typeinfo1/ti_ptr.d b/lphobos/typeinfo1/ti_ptr.d deleted file mode 100644 index 9d7f80211aa..00000000000 --- a/lphobos/typeinfo1/ti_ptr.d +++ /dev/null @@ -1,42 +0,0 @@ - -// pointer - -module typeinfo1.ti_ptr; - -class TypeInfo_P : TypeInfo -{ - hash_t getHash(void *p) - { - return cast(uint)*cast(void* *)p; - } - - int equals(void *p1, void *p2) - { - return *cast(void* *)p1 == *cast(void* *)p2; - } - - int compare(void *p1, void *p2) - { - return *cast(void* *)p1 - *cast(void* *)p2; - } - - size_t tsize() - { - return (void*).sizeof; - } - - void swap(void *p1, void *p2) - { - void* t; - - t = *cast(void* *)p1; - *cast(void* *)p1 = *cast(void* *)p2; - *cast(void* *)p2 = t; - } - - uint flags() - { - return 1; - } -} - diff --git a/lphobos/typeinfo1/ti_real.d b/lphobos/typeinfo1/ti_real.d deleted file mode 100644 index 57ffe20e1b8..00000000000 --- a/lphobos/typeinfo1/ti_real.d +++ /dev/null @@ -1,70 +0,0 @@ - -// real - -module typeinfo1.ti_real; - -class TypeInfo_e : TypeInfo -{ - char[] toString() { return "real"; } - - hash_t getHash(void *p) - { - return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4]; - } - - static bool _isnan(real r) - { - return r !<>= 0; - } - - static int _equals(real f1, real f2) - { - return f1 == f2 || - (_isnan(f1) && _isnan(f2)); - } - - static int _compare(real d1, real 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(real *)p1, *cast(real *)p2); - } - - int compare(void *p1, void *p2) - { - return _compare(*cast(real *)p1, *cast(real *)p2); - } - - size_t tsize() - { - return real.sizeof; - } - - void swap(void *p1, void *p2) - { - real t; - - t = *cast(real *)p1; - *cast(real *)p1 = *cast(real *)p2; - *cast(real *)p2 = t; - } - - void[] init() - { static real r; - - return (&r)[0 .. 1]; - } -} - diff --git a/lphobos/typeinfo1/ti_short.d b/lphobos/typeinfo1/ti_short.d deleted file mode 100644 index 950c3987373..00000000000 --- a/lphobos/typeinfo1/ti_short.d +++ /dev/null @@ -1,39 +0,0 @@ - -// short - -module typeinfo1.ti_short; - -class TypeInfo_s : TypeInfo -{ - char[] toString() { return "short"; } - - hash_t getHash(void *p) - { - return *cast(short *)p; - } - - int equals(void *p1, void *p2) - { - return *cast(short *)p1 == *cast(short *)p2; - } - - int compare(void *p1, void *p2) - { - return *cast(short *)p1 - *cast(short *)p2; - } - - size_t tsize() - { - return short.sizeof; - } - - void swap(void *p1, void *p2) - { - short t; - - t = *cast(short *)p1; - *cast(short *)p1 = *cast(short *)p2; - *cast(short *)p2 = t; - } -} - diff --git a/lphobos/typeinfo1/ti_ubyte.d b/lphobos/typeinfo1/ti_ubyte.d deleted file mode 100644 index aacd1042263..00000000000 --- a/lphobos/typeinfo1/ti_ubyte.d +++ /dev/null @@ -1,43 +0,0 @@ - -// ubyte - -module typeinfo1.ti_ubyte; - -class TypeInfo_h : TypeInfo -{ - char[] toString() { return "ubyte"; } - - hash_t getHash(void *p) - { - return *cast(ubyte *)p; - } - - int equals(void *p1, void *p2) - { - return *cast(ubyte *)p1 == *cast(ubyte *)p2; - } - - int compare(void *p1, void *p2) - { - return *cast(ubyte *)p1 - *cast(ubyte *)p2; - } - - size_t tsize() - { - return ubyte.sizeof; - } - - void swap(void *p1, void *p2) - { - ubyte t; - - t = *cast(ubyte *)p1; - *cast(ubyte *)p1 = *cast(ubyte *)p2; - *cast(ubyte *)p2 = t; - } -} - -class TypeInfo_b : TypeInfo_h -{ - char[] toString() { return "bool"; } -} diff --git a/lphobos/typeinfo1/ti_uint.d b/lphobos/typeinfo1/ti_uint.d deleted file mode 100644 index b76df9d8a17..00000000000 --- a/lphobos/typeinfo1/ti_uint.d +++ /dev/null @@ -1,43 +0,0 @@ - -// uint - -module typeinfo1.ti_uint; - -class TypeInfo_k : TypeInfo -{ - char[] toString() { return "uint"; } - - 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(uint*) p1 < *cast(uint*) p2) - return -1; - else if (*cast(uint*) p1 > *cast(uint*) p2) - return 1; - return 0; - } - - size_t tsize() - { - return uint.sizeof; - } - - void swap(void *p1, void *p2) - { - int t; - - t = *cast(uint *)p1; - *cast(uint *)p1 = *cast(uint *)p2; - *cast(uint *)p2 = t; - } -} - diff --git a/lphobos/typeinfo1/ti_ulong.d b/lphobos/typeinfo1/ti_ulong.d deleted file mode 100644 index 927b0d0bcc3..00000000000 --- a/lphobos/typeinfo1/ti_ulong.d +++ /dev/null @@ -1,43 +0,0 @@ - -// ulong - -module typeinfo1.ti_ulong; - -class TypeInfo_m : TypeInfo -{ - char[] toString() { return "ulong"; } - - hash_t getHash(void *p) - { - return *cast(uint *)p + (cast(uint *)p)[1]; - } - - int equals(void *p1, void *p2) - { - return *cast(ulong *)p1 == *cast(ulong *)p2; - } - - int compare(void *p1, void *p2) - { - if (*cast(ulong *)p1 < *cast(ulong *)p2) - return -1; - else if (*cast(ulong *)p1 > *cast(ulong *)p2) - return 1; - return 0; - } - - size_t tsize() - { - return ulong.sizeof; - } - - void swap(void *p1, void *p2) - { - ulong t; - - t = *cast(ulong *)p1; - *cast(ulong *)p1 = *cast(ulong *)p2; - *cast(ulong *)p2 = t; - } -} - diff --git a/lphobos/typeinfo1/ti_ushort.d b/lphobos/typeinfo1/ti_ushort.d deleted file mode 100644 index bb22181789d..00000000000 --- a/lphobos/typeinfo1/ti_ushort.d +++ /dev/null @@ -1,39 +0,0 @@ - -// ushort - -module typeinfo1.ti_ushort; - -class TypeInfo_t : TypeInfo -{ - char[] toString() { return "ushort"; } - - hash_t getHash(void *p) - { - return *cast(ushort *)p; - } - - int equals(void *p1, void *p2) - { - return *cast(ushort *)p1 == *cast(ushort *)p2; - } - - int compare(void *p1, void *p2) - { - return *cast(ushort *)p1 - *cast(ushort *)p2; - } - - size_t tsize() - { - return ushort.sizeof; - } - - void swap(void *p1, void *p2) - { - ushort t; - - t = *cast(ushort *)p1; - *cast(ushort *)p1 = *cast(ushort *)p2; - *cast(ushort *)p2 = t; - } -} - diff --git a/lphobos/typeinfo1/ti_void.d b/lphobos/typeinfo1/ti_void.d deleted file mode 100644 index a742f2e6c4b..00000000000 --- a/lphobos/typeinfo1/ti_void.d +++ /dev/null @@ -1,44 +0,0 @@ - -// void - -module typeinfo1.ti_void; - -class TypeInfo_v : TypeInfo -{ - char[] toString() { return "void"; } - - hash_t getHash(void *p) - { - assert(0); - } - - 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 void.sizeof; - } - - void swap(void *p1, void *p2) - { - byte t; - - t = *cast(byte *)p1; - *cast(byte *)p1 = *cast(byte *)p2; - *cast(byte *)p2 = t; - } - - uint flags() - { - return 1; - } -} - diff --git a/lphobos/typeinfo1/ti_wchar.d b/lphobos/typeinfo1/ti_wchar.d deleted file mode 100644 index cd7391c9de4..00000000000 --- a/lphobos/typeinfo1/ti_wchar.d +++ /dev/null @@ -1,44 +0,0 @@ - -module typeinfo1.ti_wchar; - - -class TypeInfo_u : TypeInfo -{ - char[] toString() { return "wchar"; } - - hash_t getHash(void *p) - { - return *cast(wchar *)p; - } - - int equals(void *p1, void *p2) - { - return *cast(wchar *)p1 == *cast(wchar *)p2; - } - - int compare(void *p1, void *p2) - { - return *cast(wchar *)p1 - *cast(wchar *)p2; - } - - size_t tsize() - { - return wchar.sizeof; - } - - void swap(void *p1, void *p2) - { - wchar t; - - t = *cast(wchar *)p1; - *cast(wchar *)p1 = *cast(wchar *)p2; - *cast(wchar *)p2 = t; - } - - void[] init() - { static wchar c; - - return (cast(wchar *)&c)[0 .. 1]; - } -} - diff --git a/lphobos/typeinfo2/ti_AC.d b/lphobos/typeinfo2/ti_AC.d deleted file mode 100644 index c36ac3865dd..00000000000 --- a/lphobos/typeinfo2/ti_AC.d +++ /dev/null @@ -1,92 +0,0 @@ -module typeinfo2.ti_AC; - -// Object[] - -class TypeInfo_AC : TypeInfo -{ - hash_t getHash(void *p) - { Object[] s = *cast(Object[]*)p; - hash_t hash = 0; - - foreach (Object o; s) - { - if (o) - hash += o.toHash(); - } - return hash; - } - - int equals(void *p1, void *p2) - { - Object[] s1 = *cast(Object[]*)p1; - Object[] s2 = *cast(Object[]*)p2; - - if (s1.length == s2.length) - { - for (size_t u = 0; u < s1.length; u++) - { Object o1 = s1[u]; - Object o2 = s2[u]; - - // Do not pass null's to Object.opEquals() - if (o1 is o2 || - (!(o1 is null) && !(o2 is null) && o1.opEquals(o2))) - continue; - return 0; - } - return 1; - } - return 0; - } - - int compare(void *p1, void *p2) - { - Object[] s1 = *cast(Object[]*)p1; - Object[] s2 = *cast(Object[]*)p2; - int c; - - c = cast(int)s1.length - cast(int)s2.length; - if (c == 0) - { - for (size_t u = 0; u < s1.length; u++) - { Object o1 = s1[u]; - Object o2 = s2[u]; - - if (o1 is o2) - continue; - - // Regard null references as always being "less than" - if (o1) - { - if (!o2) - { c = 1; - break; - } - c = o1.opCmp(o2); - if (c) - break; - } - else - { c = -1; - break; - } - } - } - return c; - } - - size_t tsize() - { - return (Object[]).sizeof; - } - - uint flags() - { - return 1; - } - - TypeInfo next() - { - return typeid(Object); - } -} - diff --git a/lphobos/typeinfo2/ti_Adouble.d b/lphobos/typeinfo2/ti_Adouble.d deleted file mode 100644 index 634d40dca1a..00000000000 --- a/lphobos/typeinfo2/ti_Adouble.d +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2004-2005 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. - */ - -module typeinfo2.ti_Adouble; - -private import typeinfo1.ti_double; - -// double[] - -class TypeInfo_Ad : TypeInfo -{ - char[] toString() { return "double[]"; } - - hash_t getHash(void *p) - { double[] s = *cast(double[]*)p; - size_t len = s.length; - auto str = s.ptr; - hash_t hash = 0; - - while (len) - { - hash *= 9; - hash += (cast(uint *)str)[0]; - hash += (cast(uint *)str)[1]; - str++; - len--; - } - - return hash; - } - - int equals(void *p1, void *p2) - { - double[] s1 = *cast(double[]*)p1; - double[] s2 = *cast(double[]*)p2; - size_t len = s1.length; - - if (len != s2.length) - return 0; - for (size_t u = 0; u < len; u++) - { - int c = TypeInfo_d._equals(s1[u], s2[u]); - if (c == 0) - return 0; - } - return 1; - } - - int compare(void *p1, void *p2) - { - double[] s1 = *cast(double[]*)p1; - double[] s2 = *cast(double[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int c = TypeInfo_d._compare(s1[u], s2[u]); - if (c) - return c; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (double[]).sizeof; - } - - uint flags() - { - return 1; - } - - TypeInfo next() - { - return typeid(double); - } -} - -// idouble[] - -class TypeInfo_Ap : TypeInfo_Ad -{ - char[] toString() { return "idouble[]"; } - - TypeInfo next() - { - return typeid(idouble); - } -} diff --git a/lphobos/typeinfo2/ti_Afloat.d b/lphobos/typeinfo2/ti_Afloat.d deleted file mode 100644 index 27c2261a563..00000000000 --- a/lphobos/typeinfo2/ti_Afloat.d +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2004-2005 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. - */ - -module typeinfo2.ti_Afloat; - -private import typeinfo1.ti_float; - -// float[] - -class TypeInfo_Af : TypeInfo -{ - char[] toString() { return "float[]"; } - - hash_t getHash(void *p) - { float[] s = *cast(float[]*)p; - size_t len = s.length; - auto str = s.ptr; - hash_t hash = 0; - - while (len) - { - hash *= 9; - hash += *cast(uint *)str; - str++; - len--; - } - - return hash; - } - - int equals(void *p1, void *p2) - { - float[] s1 = *cast(float[]*)p1; - float[] s2 = *cast(float[]*)p2; - size_t len = s1.length; - - if (len != s2.length) - return 0; - for (size_t u = 0; u < len; u++) - { - int c = TypeInfo_f._equals(s1[u], s2[u]); - if (c == 0) - return 0; - } - return 1; - } - - int compare(void *p1, void *p2) - { - float[] s1 = *cast(float[]*)p1; - float[] s2 = *cast(float[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int c = TypeInfo_f._compare(s1[u], s2[u]); - if (c) - return c; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (float[]).sizeof; - } - - uint flags() - { - return 1; - } - - TypeInfo next() - { - return typeid(float); - } -} - -// ifloat[] - -class TypeInfo_Ao : TypeInfo_Af -{ - char[] toString() { return "ifloat[]"; } - - TypeInfo next() - { - return typeid(ifloat); - } -} diff --git a/lphobos/typeinfo2/ti_Ag.d b/lphobos/typeinfo2/ti_Ag.d deleted file mode 100644 index ad68ec732e2..00000000000 --- a/lphobos/typeinfo2/ti_Ag.d +++ /dev/null @@ -1,211 +0,0 @@ -module typeinfo2.ti_Ag; - -private int string_cmp(char[] s1, char[] s2) -{ - auto len = s1.length; - if (s2.length < len) - len = s2.length; - int result = memcmp(s1.ptr, s2.ptr, len); - if (result == 0) - result = cast(int)(cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length); - return result; -} - -extern(C) int memcmp(void*,void*,size_t); - -// byte[] - -class TypeInfo_Ag : TypeInfo -{ - char[] toString() { return "byte[]"; } - - hash_t getHash(void *p) - { byte[] s = *cast(byte[]*)p; - size_t len = s.length; - byte *str = s.ptr; - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 9; - hash += *cast(ubyte *)str; - return hash; - - case 2: - hash *= 9; - hash += *cast(ushort *)str; - return hash; - - case 3: - hash *= 9; - hash += (*cast(ushort *)str << 8) + - (cast(ubyte *)str)[2]; - return hash; - - default: - hash *= 9; - hash += *cast(uint *)str; - str += 4; - len -= 4; - break; - } - } - - return hash; - } - - int equals(void *p1, void *p2) - { - byte[] s1 = *cast(byte[]*)p1; - byte[] s2 = *cast(byte[]*)p2; - - return s1.length == s2.length && - memcmp(cast(byte *)s1, cast(byte *)s2, s1.length) == 0; - } - - int compare(void *p1, void *p2) - { - byte[] s1 = *cast(byte[]*)p1; - byte[] s2 = *cast(byte[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (byte[]).sizeof; - } - - uint flags() - { - return 1; - } - - TypeInfo next() - { - return typeid(byte); - } -} - - -// ubyte[] - -class TypeInfo_Ah : TypeInfo_Ag -{ - char[] toString() { return "ubyte[]"; } - - int compare(void *p1, void *p2) - { - char[] s1 = *cast(char[]*)p1; - char[] s2 = *cast(char[]*)p2; - - return string_cmp(s1, s2); - } - - TypeInfo next() - { - return typeid(ubyte); - } -} - -// void[] - -class TypeInfo_Av : TypeInfo_Ah -{ - char[] toString() { return "void[]"; } - - TypeInfo next() - { - return typeid(void); - } -} - -// bool[] - -class TypeInfo_Ab : TypeInfo_Ah -{ - char[] toString() { return "bool[]"; } - - TypeInfo next() - { - return typeid(bool); - } -} - -// char[] - -class TypeInfo_Aa : TypeInfo_Ag -{ - char[] toString() { return "char[]"; } - - hash_t getHash(void *p) - { char[] s = *cast(char[]*)p; - hash_t hash = 0; - -version (all) -{ - foreach (char c; s) - hash = hash * 11 + c; -} -else -{ - size_t len = s.length; - char *str = s; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 9; - hash += *cast(ubyte *)str; - return hash; - - case 2: - hash *= 9; - hash += *cast(ushort *)str; - return hash; - - case 3: - hash *= 9; - hash += (*cast(ushort *)str << 8) + - (cast(ubyte *)str)[2]; - return hash; - - default: - hash *= 9; - hash += *cast(uint *)str; - str += 4; - len -= 4; - break; - } - } -} - return hash; - } - - TypeInfo next() - { - return typeid(char); - } -} - - diff --git a/lphobos/typeinfo2/ti_Aint.d b/lphobos/typeinfo2/ti_Aint.d deleted file mode 100644 index 1850079e23e..00000000000 --- a/lphobos/typeinfo2/ti_Aint.d +++ /dev/null @@ -1,110 +0,0 @@ -module typeinfo2.ti_Aint; - -extern(C) int memcmp(void*,void*,size_t); - -// int[] - -class TypeInfo_Ai : TypeInfo -{ - char[] toString() { return "int[]"; } - - hash_t getHash(void *p) - { int[] s = *cast(int[]*)p; - auto len = s.length; - auto str = s.ptr; - hash_t hash = 0; - - while (len) - { - hash *= 9; - hash += *cast(uint *)str; - str++; - len--; - } - - return hash; - } - - int equals(void *p1, void *p2) - { - int[] s1 = *cast(int[]*)p1; - int[] s2 = *cast(int[]*)p2; - - return s1.length == s2.length && - memcmp(cast(void *)s1, cast(void *)s2, s1.length * int.sizeof) == 0; - } - - int compare(void *p1, void *p2) - { - int[] s1 = *cast(int[]*)p1; - int[] s2 = *cast(int[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (int[]).sizeof; - } - - uint flags() - { - return 1; - } - - TypeInfo next() - { - return typeid(int); - } -} - -// uint[] - -class TypeInfo_Ak : TypeInfo_Ai -{ - char[] toString() { return "uint[]"; } - - int compare(void *p1, void *p2) - { - uint[] s1 = *cast(uint[]*)p1; - uint[] s2 = *cast(uint[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - return cast(int)s1.length - cast(int)s2.length; - } - - TypeInfo next() - { - return typeid(uint); - } -} - -// dchar[] - -class TypeInfo_Aw : TypeInfo_Ak -{ - char[] toString() { return "dchar[]"; } - - TypeInfo next() - { - return typeid(dchar); - } -} - diff --git a/lphobos/typeinfo2/ti_Along.d b/lphobos/typeinfo2/ti_Along.d deleted file mode 100644 index b0469490493..00000000000 --- a/lphobos/typeinfo2/ti_Along.d +++ /dev/null @@ -1,102 +0,0 @@ -module typeinfo2.ti_Along; - -extern(C) int memcmp(void*,void*,size_t); - -// long[] - -class TypeInfo_Al : TypeInfo -{ - char[] toString() { return "long[]"; } - - hash_t getHash(void *p) - { long[] s = *cast(long[]*)p; - size_t len = s.length; - auto str = s.ptr; - hash_t hash = 0; - - while (len) - { - hash *= 9; - hash += *cast(uint *)str + *(cast(uint *)str + 1); - str++; - len--; - } - - return hash; - } - - int equals(void *p1, void *p2) - { - long[] s1 = *cast(long[]*)p1; - long[] s2 = *cast(long[]*)p2; - - return s1.length == s2.length && - memcmp(cast(void *)s1, cast(void *)s2, s1.length * long.sizeof) == 0; - } - - int compare(void *p1, void *p2) - { - long[] s1 = *cast(long[]*)p1; - long[] s2 = *cast(long[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - if (s1[u] < s2[u]) - return -1; - else if (s1[u] > s2[u]) - return 1; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (long[]).sizeof; - } - - uint flags() - { - return 1; - } - - TypeInfo next() - { - return typeid(long); - } -} - - -// ulong[] - -class TypeInfo_Am : TypeInfo_Al -{ - char[] toString() { return "ulong[]"; } - - int compare(void *p1, void *p2) - { - ulong[] s1 = *cast(ulong[]*)p1; - ulong[] s2 = *cast(ulong[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - if (s1[u] < s2[u]) - return -1; - else if (s1[u] > s2[u]) - return 1; - } - return cast(int)s1.length - cast(int)s2.length; - } - - TypeInfo next() - { - return typeid(ulong); - } -} - - diff --git a/lphobos/typeinfo2/ti_Areal.d b/lphobos/typeinfo2/ti_Areal.d deleted file mode 100644 index 9fee6805730..00000000000 --- a/lphobos/typeinfo2/ti_Areal.d +++ /dev/null @@ -1,113 +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. - */ - -module typeinfo2.ti_Areal; - -private import typeinfo1.ti_real; - -// real[] - -class TypeInfo_Ae : TypeInfo -{ - char[] toString() { return "real[]"; } - - hash_t getHash(void *p) - { real[] s = *cast(real[]*)p; - size_t len = s.length; - auto str = s.ptr; - hash_t hash = 0; - - while (len) - { - hash *= 9; - hash += (cast(uint *)str)[0]; - hash += (cast(uint *)str)[1]; - hash += (cast(ushort *)str)[4]; - str++; - len--; - } - - return hash; - } - - int equals(void *p1, void *p2) - { - real[] s1 = *cast(real[]*)p1; - real[] s2 = *cast(real[]*)p2; - size_t len = s1.length; - - if (len != s2.length) - return 0; - for (size_t u = 0; u < len; u++) - { - int c = TypeInfo_e._equals(s1[u], s2[u]); - if (c == 0) - return 0; - } - return 1; - } - - int compare(void *p1, void *p2) - { - real[] s1 = *cast(real[]*)p1; - real[] s2 = *cast(real[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int c = TypeInfo_e._compare(s1[u], s2[u]); - if (c) - return c; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (real[]).sizeof; - } - - uint flags() - { - return 1; - } - - TypeInfo next() - { - return typeid(real); - } -} - -// ireal[] - -class TypeInfo_Aj : TypeInfo_Ae -{ - char[] toString() { return "ireal[]"; } - - TypeInfo next() - { - return typeid(ireal); - } -} diff --git a/lphobos/typeinfo2/ti_Ashort.d b/lphobos/typeinfo2/ti_Ashort.d deleted file mode 100644 index 0077944dbac..00000000000 --- a/lphobos/typeinfo2/ti_Ashort.d +++ /dev/null @@ -1,125 +0,0 @@ -module typeinfo2.ti_Ashort; - -extern(C) int memcmp(void*,void*,size_t); - -// short[] - -class TypeInfo_As : TypeInfo -{ - char[] toString() { return "short[]"; } - - hash_t getHash(void *p) - { short[] s = *cast(short[]*)p; - size_t len = s.length; - short *str = s.ptr; - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 9; - hash += *cast(ushort *)str; - return hash; - - default: - hash *= 9; - hash += *cast(uint *)str; - str += 2; - len -= 2; - break; - } - } - - return hash; - } - - int equals(void *p1, void *p2) - { - short[] s1 = *cast(short[]*)p1; - short[] s2 = *cast(short[]*)p2; - - return s1.length == s2.length && - memcmp(cast(void *)s1, cast(void *)s2, s1.length * short.sizeof) == 0; - } - - int compare(void *p1, void *p2) - { - short[] s1 = *cast(short[]*)p1; - short[] s2 = *cast(short[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (short[]).sizeof; - } - - uint flags() - { - return 1; - } - - TypeInfo next() - { - return typeid(short); - } -} - - -// ushort[] - -class TypeInfo_At : TypeInfo_As -{ - char[] toString() { return "ushort[]"; } - - int compare(void *p1, void *p2) - { - ushort[] s1 = *cast(ushort[]*)p1; - ushort[] s2 = *cast(ushort[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - return cast(int)s1.length - cast(int)s2.length; - } - - TypeInfo next() - { - return typeid(ushort); - } -} - -// wchar[] - -class TypeInfo_Au : TypeInfo_At -{ - char[] toString() { return "wchar[]"; } - - TypeInfo next() - { - return typeid(wchar); - } -} - - diff --git a/lphobos/typeinfo2/ti_C.d b/lphobos/typeinfo2/ti_C.d deleted file mode 100644 index 2b56392b0f9..00000000000 --- a/lphobos/typeinfo2/ti_C.d +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2004-2005 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. - */ - -module typeinfo2.ti_C; - -// Object - -class TypeInfo_C : TypeInfo -{ - hash_t getHash(void *p) - { - Object o = *cast(Object*)p; - assert(o); - return o.toHash(); - } - - int equals(void *p1, void *p2) - { - Object o1 = *cast(Object*)p1; - Object o2 = *cast(Object*)p2; - - return o1 == o2; - } - - int compare(void *p1, void *p2) - { - Object o1 = *cast(Object*)p1; - Object o2 = *cast(Object*)p2; - int c = 0; - - // Regard null references as always being "less than" - if (!(o1 is o2)) - { - if (o1) - { if (!o2) - c = 1; - else - c = o1.opCmp(o2); - } - else - c = -1; - } - return c; - } - - size_t tsize() - { - return Object.sizeof; - } - - uint flags() - { - return 1; - } -} - diff --git a/lphobos/typeinfos1.d b/lphobos/typeinfos1.d deleted file mode 100644 index 2c746089191..00000000000 --- a/lphobos/typeinfos1.d +++ /dev/null @@ -1,26 +0,0 @@ -module typeinfos1; - -import -typeinfo1.ti_byte, -typeinfo1.ti_cdouble, -typeinfo1.ti_cfloat, -typeinfo1.ti_char, -typeinfo1.ti_creal, -typeinfo1.ti_dchar, -typeinfo1.ti_delegate, -typeinfo1.ti_double, -typeinfo1.ti_float, -typeinfo1.ti_idouble, -typeinfo1.ti_ifloat, -typeinfo1.ti_int, -typeinfo1.ti_ireal, -typeinfo1.ti_long, -typeinfo1.ti_ptr, -typeinfo1.ti_real, -typeinfo1.ti_short, -typeinfo1.ti_ubyte, -typeinfo1.ti_uint, -typeinfo1.ti_ulong, -typeinfo1.ti_ushort, -typeinfo1.ti_void, -typeinfo1.ti_wchar; diff --git a/lphobos/typeinfos2.d b/lphobos/typeinfos2.d deleted file mode 100644 index 6816734654b..00000000000 --- a/lphobos/typeinfos2.d +++ /dev/null @@ -1,12 +0,0 @@ -module typeinfos2; - -import -typeinfo2.ti_AC, -typeinfo2.ti_Adouble, -typeinfo2.ti_Afloat, -typeinfo2.ti_Ag, -typeinfo2.ti_Aint, -typeinfo2.ti_Along, -typeinfo2.ti_Areal, -typeinfo2.ti_Ashort, -typeinfo2.ti_C;