diff -uNr dmd-0.129/dmd/src/dmd/access.c dmd-0.130/dmd/src/dmd/access.c --- dmd-0.129/dmd/src/dmd/access.c 2005-07-19 12:01:30.000000000 +0200 +++ dmd-0.130/dmd/src/dmd/access.c 2005-08-13 12:36:22.000000000 +0200 @@ -53,6 +53,10 @@ { access_ret = smember->prot(); } + else if (smember->isDeclaration()->isStatic()) + { + access_ret = smember->prot(); + } return access_ret; } @@ -73,6 +77,11 @@ enum PROT access; int i; + if (smember->isDeclaration()->isStatic()) + { + access_ret = smember->prot(); + } + for (i = 0; i < baseclasses.dim; i++) { BaseClass *b = (BaseClass *)baseclasses.data[i]; diff -uNr dmd-0.129/dmd/src/dmd/constfold.c dmd-0.130/dmd/src/dmd/constfold.c --- dmd-0.129/dmd/src/dmd/constfold.c 2005-06-15 12:33:54.000000000 +0200 +++ dmd-0.130/dmd/src/dmd/constfold.c 2005-08-26 00:49:06.000000000 +0200 @@ -597,8 +597,8 @@ assert(0); } else - { integer_t n1; - integer_t n2; + { sinteger_t n1; + sinteger_t n2; n1 = e1->toInteger(); n2 = e2->toInteger(); diff -uNr dmd-0.129/dmd/src/dmd/expression.c dmd-0.130/dmd/src/dmd/expression.c --- dmd-0.129/dmd/src/dmd/expression.c 2005-07-23 11:44:12.000000000 +0200 +++ dmd-0.130/dmd/src/dmd/expression.c 2005-09-06 11:13:42.000000000 +0200 @@ -5848,9 +5848,10 @@ error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); e = this; } - else if (t1->ty == Tstruct || t2->ty == Tstruct) + else if (t1->ty == Tstruct || t2->ty == Tstruct || + (t1->ty == Tclass && t2->ty == Tclass)) { - error("need member function opCmp() for struct %s to compare", t1->toChars()); + error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars()); e = this; } #if 1 diff -uNr dmd-0.129/dmd/src/dmd/func.c dmd-0.130/dmd/src/dmd/func.c --- dmd-0.129/dmd/src/dmd/func.c 2005-07-23 10:26:40.000000000 +0200 +++ dmd-0.130/dmd/src/dmd/func.c 2005-08-27 16:14:20.000000000 +0200 @@ -400,6 +400,7 @@ sc2->callSuper = 0; sc2->sbreak = NULL; sc2->scontinue = NULL; + sc2->sw = NULL; sc2->fes = fes; sc2->linkage = LINKd; diff -uNr dmd-0.129/dmd/src/dmd/mars.c dmd-0.130/dmd/src/dmd/mars.c --- dmd-0.129/dmd/src/dmd/mars.c 2005-08-06 22:00:30.000000000 +0200 +++ dmd-0.130/dmd/src/dmd/mars.c 2005-08-09 23:55:34.000000000 +0200 @@ -49,7 +49,7 @@ copyright = "Copyright (c) 1999-2005 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.129"; + version = "v0.130"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); diff -uNr dmd-0.129/dmd/src/dmd/statement.c dmd-0.130/dmd/src/dmd/statement.c --- dmd-0.129/dmd/src/dmd/statement.c 2005-06-30 01:43:14.000000000 +0200 +++ dmd-0.130/dmd/src/dmd/statement.c 2005-08-26 00:54:26.000000000 +0200 @@ -1930,7 +1930,7 @@ cd = exp->type->isClassHandle(); if (!cd) error("can only synchronize on class objects, not '%s'", exp->type->toChars()); - if (cd->isInterfaceDeclaration()) + else if (cd->isInterfaceDeclaration()) { Type *t = new TypeIdentifier(0, Id::Object); t = t->semantic(0, sc); diff -uNr dmd-0.129/dmd/src/phobos/std/c/math.d dmd-0.130/dmd/src/phobos/std/c/math.d --- dmd-0.129/dmd/src/phobos/std/c/math.d 2005-08-06 21:57:06.000000000 +0200 +++ dmd-0.130/dmd/src/phobos/std/c/math.d 2005-09-06 16:06:54.000000000 +0200 @@ -4,6 +4,8 @@ * www.digitalmars.com */ +module std.c.math; + extern (C): alias float float_t; diff -uNr dmd-0.129/dmd/src/phobos/std/c/stddef.d dmd-0.130/dmd/src/phobos/std/c/stddef.d --- dmd-0.129/dmd/src/phobos/std/c/stddef.d 2005-08-06 21:57:06.000000000 +0200 +++ dmd-0.130/dmd/src/phobos/std/c/stddef.d 2005-09-06 16:06:54.000000000 +0200 @@ -5,6 +5,8 @@ * Placed into Public Domain. */ +module std.c.stddef; + version (Win32) { alias wchar wchar_t; diff -uNr dmd-0.129/dmd/src/phobos/std/file.d dmd-0.130/dmd/src/phobos/std/file.d --- dmd-0.129/dmd/src/phobos/std/file.d 2005-08-06 21:57:06.000000000 +0200 +++ dmd-0.130/dmd/src/phobos/std/file.d 2005-09-06 16:06:54.000000000 +0200 @@ -804,7 +804,7 @@ int exists(char[] name) { - return access(toStringz(name),0) != 0; + return access(toStringz(name),0) == 0; /+ struct_stat statbuf; diff -uNr dmd-0.129/dmd/src/phobos/std/math.d dmd-0.130/dmd/src/phobos/std/math.d --- dmd-0.129/dmd/src/phobos/std/math.d 2005-08-06 21:57:06.000000000 +0200 +++ dmd-0.130/dmd/src/phobos/std/math.d 2005-09-06 16:06:54.000000000 +0200 @@ -1,8 +1,25 @@ // math.d -// Written by Walter Bright -// Copyright (c) 2001-2003 Digital Mars -// All Rights Reserved -// www.digitalmars.com +/* + * Copyright (C) 2001-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. + */ module std.math; @@ -821,3 +838,231 @@ return 0; return fabs(x - y) <= precision; } + +/******************************************* + * Submitted by Don Clugston + * http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/27735 + * + * "How equal" are two reals x and y? + * Returns the number of mantissa bits which are equal in x and y; + * this is similar to the concept of "significant figures". + * For example, 0x1.F8p+60 and 0x1.F1p+60 are equal to 5 bits of precision. + * If x==y, then precisionEquality(a,b) == real.mant_dig. + * + * If x and y differ by a factor of two or more, then they have no + * bits in common, so this function returns a value which is <=0. + * Returns 0 if they differ by a factor of >=2 but < 4, + * returns 1 for factors >=4 but <8, etc. + * + * If the numbers have opposite sign, the difference in orders + * of magnitude is based on the IEEE binary encoding. + * For example, -1 and +1 differ by half the number line. + * + * Pretend the numbers were fixed point. In the IEEE extended format, + * there are about 32768 digits in front of the decimal point, and + * the same number behind. But only the first 64 bits after the first '1' + * bit are recorded. + * + * If the exponents are different, then the return value + * is negative, and gives the number of (binary) orders of + * magnitude of difference between a and b. + */ + +private int iabs(int i) +{ + return i >= 0 ? i : -i; +} + +int precisionEquality(real a, real b) +{ + real diff = a-b; + ushort *pa = cast(ushort *)(&a); + ushort *pb = cast(ushort *)(&b); + ushort *pd = cast(ushort *)(&diff); + + // The difference in exponent between 'a' and 'a-b' + // is equal to the number of mantissa bits of a which are + // equal to b. If the difference is negative, then a and b + // have different exponents. If it is positive, then a and b + // are equal to that number of decimal places. + // AND with 0x7FFF to form the absolute value. + // Subtract 1 so that we round downwards. + int bitsdiff = ( ((pa[4]&0x7FFF) + (pb[4]&0x7FFF)-1)>>1) - (pd[4]&0x7FFF); + + if ((pd[4]&0x7FFF) == 0) // Difference is zero or denormal + { + if (a==b) + return real.mant_dig; + // 'diff' is denormal, so the number of equal bits is higher; + // we need to add the number of zeros that lie at the start of + // its mantissa. We do this by multiplying by 2^real.mant_dig + diff*=0x1p+63; + return bitsdiff + real.mant_dig-(pd[4]&0x7FFF); + } + + if (bitsdiff > 0) + return bitsdiff + 1; + + // Check for NAN or Infinity. + if (pd[4]&0x7FFF==0x7FFF) // Result is NAN or INF + { + if (a==b) // both were +INF or both were -INF. + { + return real.mant_dig; + } + if (isnan(diff)) + { + return -65535; // at least one was a NAN. + } + // fall through for comparisons of INF with large reals. + } + // Return the negative of the absolute value of + // the difference in exponents. + + if ((pa[4]^pb[4])&0x8000) // do they have opposite signs? + { // Convert the 'offset' exponent format to twos-complement, + // then do a normal subtraction. + return 1-iabs(pa[4]-(0x8000-pb[4])); + } + return 1-iabs(pa[4]-pb[4]); +} + +unittest +{ + // Exact equality + assert(precisionEquality(real.max,real.max)==real.mant_dig); + assert(precisionEquality(0,0)==real.mant_dig); + assert(precisionEquality(7.1824,7.1824)==real.mant_dig); + assert(precisionEquality(real.infinity,real.infinity)==real.mant_dig); + + // one bit off exact equality + assert(precisionEquality(1+real.epsilon,1)==real.mant_dig-1); + assert(precisionEquality(1,1+real.epsilon)==real.mant_dig-1); + // one bit below. Must round off correctly when exponents are different. + assert(precisionEquality(1,1-real.epsilon)==real.mant_dig-1); + assert(precisionEquality(1-real.epsilon,1)==real.mant_dig-1); + assert(precisionEquality(-1-real.epsilon,-1)==real.mant_dig-1); + assert(precisionEquality(-1+real.epsilon,-1)==real.mant_dig-1); + + // Numbers that are close + assert(precisionEquality(0x1.Bp+5, 0x1.B8p+5)==5); + assert(precisionEquality(0x1.8p+10, 0x1.Cp+10)==2); + assert(precisionEquality(1, 1.1249)==4); + assert(precisionEquality(1.5, 1)==1); + + // Extreme inequality + assert(precisionEquality(real.nan,0)==-65535); + assert(precisionEquality(0,-real.nan)==-65535); + assert(precisionEquality(real.nan,real.infinity)==-65535); + assert(precisionEquality(real.infinity,-real.infinity)==-65533); + assert(precisionEquality(-real.max,real.infinity)==-65532); + assert(precisionEquality(-real.max,real.max)==-65531); + + // Numbers that are half the number line apart + // Note that (real.max_exp-real.min_exp) = 32765 + assert(precisionEquality(-real.max,0)==-32765); + assert(precisionEquality(-1,1)==-32765); + assert(precisionEquality(real.min,1)==-16381); + + // Numbers that differ by one order of magnitude + assert(precisionEquality(real.max,real.infinity)==0); + assert(precisionEquality(1, 2)==0); + assert(precisionEquality(2, 1)==0); + assert(precisionEquality(1.5*(1-real.epsilon), 1)==2); + assert(precisionEquality(4*(1-real.epsilon), 1)==0); + assert(precisionEquality(4, 1)==-1); +} + + +/************************************** + int feqrel(real x, real y) + To what precision is x equal to y? + Public Domain. Author: Don Clugston, 18 Aug 2005. + + 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. + If x == y, then feqrel(x, y) == real.mant_dig. + + If x and y differ by a factor of two or more, or if one or both + is a nan, the return value is 0. +*/ + +int feqrel(real a, real b) +{ + if (a == b) + return real.mant_dig; // ensure diff!=0, cope with INF. + + real diff = fabs(a-b); + + ushort *pa = cast(ushort *)(&a); + ushort *pb = cast(ushort *)(&b); + ushort *pd = cast(ushort *)(&diff); + + // The difference in abs(exponent) between a or b and abs(a-b) + // is equal to the number of mantissa bits of a which are + // equal to b. If negative, a and b have different exponents. + // If positive, a and b 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; i>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 + std.c.linux.linux.lseek(fd, size - 1, SEEK_SET); + char c = 0; + std.c.linux.linux.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 statbuf.st_size) - { - // Need to make the file size bytes big - std.c.linux.linux.lseek(fd, size - 1, SEEK_SET); - char c = 0; - std.c.linux.linux.write(fd, &c, 1); - } - else if (prot & PROT_READ && size == 0) - size = statbuf.st_size; - } - else - { - fd = -1; - flags |= MAP_ANONYMOUS; - } - - p = mmap(address, size, prot, flags, fd, 0); - //printf(" p = %x, size = %d\n", p, size); - - /* Memory mapping stays active even if we close the handle. - * Closing it now avoids worrys about closing it during error - * recovery. - */ - if (fd != -1 && std.c.linux.linux.close(fd) == -1) - errNo(); - - if (p == MAP_FAILED) // in sys/mman.h - errNo(); - data = p[0 .. size]; + debug (MMFILE) printf("MmFile.~this()\n"); + unmap(); + version (Win32) + { + if (hFileMap != null && CloseHandle(hFileMap) != TRUE) + errNo(); + hFileMap = null; + + if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE) + errNo(); + hFile = INVALID_HANDLE_VALUE; + } + else version (linux) + { + if (fd != -1 && std.c.linux.linux.close(fd) == -1) + errNo(); + fd = -1; + } + else + { + static assert(0); + } + data = null; } - else + + /* Flush any pending output. + */ + void flush() { - static assert(0); + debug (MMFILE) printf("MmFile.flush()\n"); + version (Win32) + { + FlushViewOfFile(data, data.length); + } + else version (linux) + { + int i; + + i = msync(cast(void*)data, data.length, MS_SYNC); // sys/mman.h + if (i != 0) + errNo(); + } + else + { + static assert(0); + } } - } - ~this() - { - debug (MMFILE) printf("MmFile.~this()\n"); - version (Win32) + ulong length() { - /* Note that under Windows 95, UnmapViewOfFile() seems to return - * random values, not TRUE or FALSE. - */ - if (data && UnmapViewOfFile(data) == FALSE && - (dwVersion & 0x80000000) == 0) - errNo(); - data = null; - - if (hFileMap != null && CloseHandle(hFileMap) != TRUE) - errNo(); - hFileMap = null; - - if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE) - errNo(); - hFile = INVALID_HANDLE_VALUE; + debug (MMFILE) printf("MmFile.length()\n"); + return size; } - else version (linux) - { - int i; - i = munmap(cast(void*)data, data.length); - if (i != 0) - errNo(); - } - else + Mode mode() { - static assert(0); + debug (MMFILE) printf("MmFile.mode()\n"); + return mMode; } - data = null; - } - /* Flush any pending output. - */ - void flush() - { - debug (MMFILE) printf("MmFile.flush()\n"); - version (Win32) + void[] opSlice() { - FlushViewOfFile(data, data.length); + debug (MMFILE) printf("MmFile.opSlice()\n"); + return opSlice(0,size); } - else version (linux) - { - int i; - i = msync(cast(void*)data, data.length, MS_SYNC); // sys/mman.h - if (i != 0) - errNo(); - } - else + void[] opSlice(ulong i1, ulong i2) { - static assert(0); + debug (MMFILE) printf("MmFile.opSlice(%lld, %lld)\n", i1, i2); + ensureMapped(i1,i2); + size_t off1 = cast(size_t)(i1-start); + size_t off2 = cast(size_t)(i2-start); + return data[off1 .. off2]; } - } - size_t length() - { - debug (MMFILE) printf("MmFile.length()\n"); - return data.length; - } - Mode mode() - { - debug (MMFILE) printf("MmFile.mode()\n"); - return mMode; - } - - void[] opSlice() - { - debug (MMFILE) printf("MmFile.opSlice()\n"); - return data; - } - - void[] opSlice(size_t i1, size_t i2) - { - debug (MMFILE) printf("MmFile.opSlice(%d, %d)\n", i1, i2); - return data[i1 .. i2]; - } - - ubyte opIndex(size_t i) - { - debug (MMFILE) printf("MmFile.opIndex(%d)\n", i); - return (cast(ubyte[])data)[i]; - } + ubyte opIndex(ulong i) + { + debug (MMFILE) printf("MmFile.opIndex(%lld)\n", i); + ensureMapped(i); + size_t off = cast(size_t)(i-start); + return (cast(ubyte[])data)[off]; + } - ubyte opIndex(size_t i, ubyte value) - { - debug (MMFILE) printf("MmFile.opIndex(%d, %d)\n", i, value); - return (cast(ubyte[])data)[i] = value; - } + ubyte opIndexAssign(ubyte value, ulong i) + { + debug (MMFILE) printf("MmFile.opIndex(%lld, %d)\n", i, value); + ensureMapped(i); + size_t off = cast(size_t)(i-start); + return (cast(ubyte[])data)[off] = value; + } - private: - char[] filename; - void[] data; - Mode mMode; + // return true if the given position is currently mapped + private int mapped(ulong i) + { + debug (MMFILE) printf("MmFile.mapped(%lld, %lld, %d)\n", i,start, + data.length); + return i >= start && i < start+data.length; + } - version (Win32) - { - HANDLE hFile = INVALID_HANDLE_VALUE; - HANDLE hFileMap = null; - } - else version (linux) - { - } - else - { - static assert(0); - } + // 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) == FALSE && + (dwVersion & 0x80000000) == 0) + errNo(); + } else { + if (data && munmap(cast(void*)data, data.length) != 0) + errNo(); + } + data = null; + } - // Report error, where errno gives the error number - void errNo() - { - version (Win32) + // map range + private void map(ulong start, size_t len) { - throw new FileException(filename, GetLastError()); + 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 { + p = mmap(address, len, prot, flags, fd, start); + if (p == MAP_FAILED) errNo(); + } + data = p[0 .. len]; + this.start = start; } - else version (linux) + + // ensure a given position is mapped + private void ensureMapped(ulong i) { - throw new FileException(filename, getErrno()); + 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); + } + } } - else + + // ensure a given range is mapped + private void ensureMapped(ulong i, ulong j) { - static assert(0); + 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 (linux) { + int fd; + int prot; + int flags; + int fmode; } else { - static assert(0); + static assert(0); } -*/ + // Report error, where errno gives the error number + void errNo() + { + version (Win32) + { + throw new FileException(filename, GetLastError()); + } + else version (linux) + { + throw new FileException(filename, getErrno()); + } + else + { + static assert(0); + } + } +} +unittest { + 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 (linux) { + // 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 -uNr dmd-0.129/dmd/src/phobos/std/stream.d dmd-0.130/dmd/src/phobos/std/stream.d --- dmd-0.129/dmd/src/phobos/std/stream.d 2005-08-06 21:57:06.000000000 +0200 +++ dmd-0.130/dmd/src/phobos/std/stream.d 2005-09-06 16:06:54.000000000 +0200 @@ -22,11 +22,12 @@ * OutputStream interface for writing * Stream abstract base of stream implementations * File an OS file stream - * BufferedStream a buffered stream wrapping another stream - * BufferedFile a buffered File - * EndianStream a wrapper stream for swapping byte order and BOMs + * 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 - * SliceStream a portion of another stream * TArrayStream a stream wrapping an array-like buffer */ @@ -35,26 +36,21 @@ class StreamException: Exception { this(char[] msg) { super(msg); } } -alias StreamException StreamError; // for backwards compatibility // thrown when unable to read data from Stream class ReadException: StreamException { this(char[] msg) { super(msg); } } -alias ReadException ReadError; // for backwards compatibility // thrown when unable to write data to Stream class WriteException: StreamException { this(char[] msg) { super(msg); } } -alias WriteException WriteError; // for backwards compatibility // thrown when unable to move Stream pointer class SeekException: StreamException { this(char[] msg) { super(msg); } } -alias SeekException SeekError; // for backwards compatibility - // seek whence... enum SeekPos { @@ -1121,7 +1117,7 @@ void close() { if (isopen) flush(); - readEOF = isopen = readable = writeable = seekable = false; + readEOF = prevCr = isopen = readable = writeable = seekable = false; } // creates a string in memory containing copy of stream data @@ -1189,9 +1185,72 @@ } } +// Base class for streams that wrap a backing source stream +class FilterStream : Stream { + private Stream s; // source stream + bit nestClose = true; // close the source when this stream closes + + // Construct a FilterStream around source + this(Stream source) { + s = source; + resetSource(); + } + + // source getter/setter + final Stream source(){return s;} + void source(Stream s) { + close(); + this.s = s; + resetSource(); + } + + // set this streams state for a new or changed source + 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(); } +} + // A stream that wraps a source stream in a buffer -class BufferedStream : Stream { - Stream s; // source stream +class BufferedStream : FilterStream { ubyte[] buffer; // buffer, if any uint bufferCurPos; // current position in buffer uint bufferLen; // amount of data in buffer @@ -1218,38 +1277,18 @@ const uint DefaultBufferSize = 8192; this(Stream source, uint bufferSize = DefaultBufferSize) { - super(); + super(source); if (bufferSize) buffer = new ubyte[bufferSize]; - s = source; - updateAttribs(); } - void updateAttribs() { - if (s !is null) { - readable = s.readable; - writeable = s.writeable; - seekable = s.seekable; - isopen = s.isOpen(); - } else { - readable = writeable = seekable = false; - isopen = false; - } - readEOF = false; + protected void resetSource() { + super.resetSource(); streamPos = 0; bufferLen = bufferSourcePos = bufferCurPos = 0; bufferDirty = false; } - // close source and stream - override void close() { - if (isopen) { - super.close(); - s.close(); - updateAttribs(); - } - } - // 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) { @@ -1281,14 +1320,12 @@ if (len >= buffer.length) { // buffer can't hold the data so fill output buffer directly - size_t siz = s.readBlock(outbuf, len); + size_t siz = super.readBlock(outbuf, len); readsize += siz; streamPos += siz; - readEOF = siz == 0; } else { // read a new block into buffer - bufferLen = s.readBlock(buffer, buffer.length); - readEOF = bufferLen == 0; + bufferLen = super.readBlock(buffer, buffer.length); if (bufferLen < len) len = bufferLen; outbuf[0 .. len] = buffer[0 .. len]; bufferSourcePos = bufferLen; @@ -1413,8 +1450,7 @@ } } flush(); - size_t res = s.readBlock(buffer,buffer.length); - readEOF = res == 0; + size_t res = super.readBlock(buffer,buffer.length); if(!res) break L0; // EOF bufferSourcePos = bufferLen = res; streamPos += res; @@ -1447,7 +1483,6 @@ assert(bufferLen == 0); } body { - super.flush(); if (writeable && bufferDirty) { if (bufferSourcePos != 0 && seekable) { // move actual file pointer to front of buffer @@ -1459,6 +1494,7 @@ 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 @@ -1479,11 +1515,10 @@ return false; if (bufferLen == buffer.length) flush(); - size_t res = s.readBlock(&buffer[bufferLen],buffer.length-bufferLen); + size_t res = super.readBlock(&buffer[bufferLen],buffer.length-bufferLen); bufferSourcePos += res; bufferLen += res; streamPos += res; - readEOF = res == 0; return readEOF; } @@ -1497,7 +1532,6 @@ size_t available() { return bufferLen - bufferCurPos; } - } // generic File error, base class for all @@ -1703,7 +1737,7 @@ override ulong seek(long offset, SeekPos rel) { assertSeekable(); version (Win32) { - int hi = cast(int)((offset>>32) & 0xFFFFFFFF); + int hi = cast(int)(offset>>32); uint low = SetFilePointer(hFile, offset, &hi, rel); if ((low == INVALID_SET_FILE_POINTER) && (GetLastError() != 0)) throw new SeekException("unable to move file pointer"); @@ -1717,6 +1751,15 @@ return result; } + 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; } @@ -1744,6 +1787,7 @@ 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'); @@ -1821,14 +1865,14 @@ void open(char[] filename, FileMode mode = FileMode.In) { File sf = cast(File)s; sf.open(filename,mode); - updateAttribs(); + resetSource(); } // creates file in requested mode void create(char[] filename, FileMode mode = FileMode.Out) { File sf = cast(File)s; sf.create(filename,mode); - updateAttribs(); + resetSource(); } // run a few tests same as File @@ -1900,20 +1944,14 @@ ]; // A stream that wraps a source stream with endian support -class EndianStream : Stream { - Stream s; // source stream +class EndianStream : FilterStream { Endian endian; // endianness of the source stream // Construct an Endian stream with specified endianness, defaulting // to the native endiannes. this(Stream source, Endian end = std.system.endian) { - super(); - s = source; + super(source); endian = end; - readable = s.readable; - writeable = s.writeable; - seekable = s.seekable; - isopen = s.isOpen(); } /* Return -1 if no BOM and otherwise read the BOM and return it. @@ -2007,10 +2045,6 @@ } } - size_t readBlock(void* buffer, size_t size) { - return s.readBlock(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); } @@ -2063,9 +2097,6 @@ writeBlock(bom,bom.length); } - size_t writeBlock(void* buffer, size_t size) { - return s.writeBlock(buffer,size); - } 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); } @@ -2091,23 +2122,6 @@ } } - // close stream - override void close() { - if (isopen) { - super.close(); - s.close(); - } - } - - override ulong seek(long offset, SeekPos whence) { - return s.seek(offset,whence); - } - - override size_t available () { - return s.available(); - } - - override void flush() { super.flush(); s.flush(); } override bool eof() { return s.eof() && !ungetAvailable(); } override ulong size() { return s.size(); } @@ -2200,8 +2214,8 @@ // The Buffer type must support .length, opIndex and opSlice class TArrayStream(Buffer): Stream { Buffer buf; // current data - size_t len; // current data length - size_t cur; // current file position + ulong len; // current data length + ulong cur; // current file position // use this buffer, non-copying. this(Buffer buf) { @@ -2231,8 +2245,9 @@ override size_t writeBlock(void* buffer, size_t size) { assertWriteable(); ubyte* cbuf = cast(ubyte*) buffer; - if (cur + size > buf.length) - size = buf.length - cur; + ulong blen = buf.length; + if (cur + size > blen) + size = blen - cur; ubyte[] ubuf = cast(ubyte[])buf[cur .. cur + size]; ubuf[] = cbuf[0 .. size]; cur += size; @@ -2264,7 +2279,12 @@ override size_t available () { return len - cur; } // returns pointer to stream data - ubyte[] data() { return cast(ubyte[])buf [0 .. len]; } + ubyte[] data() { + if (len > size_t.max) + throw new StreamException("Stream too big"); + void[] res = buf[0 .. len]; + return cast(ubyte[])res; + } override char[] toString() { return cast(char[]) data (); @@ -2323,7 +2343,6 @@ return super.writeBlock(buffer,size); } - /* Test the whole class. */ unittest { MemoryStream m; @@ -2370,45 +2389,28 @@ } } - import std.mmfile; -// TODO: why check isopen and silently proceed? - // stream wrapping memory-mapped files class MmFileStream : TArrayStream!(MmFile) { - // constructor to wrap file this(MmFile file) { super (file); MmFile.Mode mode = file.mode; writeable = mode > MmFile.Mode.Read; } - override size_t readBlock(void* buffer, size_t size) { - if (isopen) - return super.readBlock(buffer,size); - else - return 0; - } - - override size_t writeBlock(void* buffer, size_t size) { - if (isopen) - return super.writeBlock(buffer,size); - else - return 0; - } - - // flush stream override void flush() { - if (isopen) + if (isopen) { + super.flush(); buf.flush(); + } } - // close stream override void close() { if (isopen) { super.close(); delete buf; + buf = null; } } } @@ -2416,7 +2418,6 @@ 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); @@ -2427,7 +2428,8 @@ assert (m.seekSet (4)); assert (m.readString (4) == "o, w"); m.writeString ("ie"); - assert ((cast(char[]) m.data())[0 .. 12] == "Hello, wield"); + ubyte[] dd = m.data(); + assert ((cast(char[]) dd)[0 .. 12] == "Hello, wield"); m.position = 12; m.writeString ("Foo"); assert (m.position () == 15); @@ -2445,112 +2447,72 @@ // slices off a portion of another stream, making seeking // relative to the boundaries of the slice. -class SliceStream : Stream { - Stream base; // stream to base this off of. - ulong pos; // our position relative to low - ulong low; // low stream offset. - ulong high; // high stream offset. - bit bounded; // upper-bounded by high. - bit nestClose; // if set, close base when closing this stream. +class SliceStream : FilterStream { + private { + ulong pos; // our position relative to low + ulong low; // low stream offset. + ulong high; // high stream offset. + bit bounded; // upper-bounded by high. + } - // set the base stream and the low offset but leave the high unbounded. - this (Stream base, ulong low) + // set the s stream and the low offset but leave the high unbounded. + this (Stream s, ulong low) in { - assert (base !is null); - assert (low <= base.size ()); + assert (low <= s.size ()); } body { - super (); - this.base = base; + super(s); this.low = low; this.high = 0; this.bounded = false; - readable = base.readable; - writeable = base.writeable; - seekable = base.seekable; - isopen = base.isOpen(); } - // set the base stream, the low offset, and the high offset. - this (Stream base, ulong low, ulong high) + // set the source stream, the low offset, and the high offset. + this (Stream s, ulong low, ulong high) in { - assert (base !is null); assert (low <= high); - assert (high <= base.size ()); + assert (high <= s.size ()); } body { - super (); - this.base = base; + super(s); this.low = low; this.high = high; this.bounded = true; - readable = base.readable; - writeable = base.writeable; - seekable = base.seekable; - isopen = base.isOpen(); } invariant { if (bounded) assert (pos <= high - low); else - assert (pos <= base.size - low); - } - - override bool isOpen () { - if (isopen) - return base.isOpen(); - else - return false; - } - - override void flush() { - if (isopen) { - super.flush(); - base.flush(); - } - } - - override void close () { - if (isopen) { - super.close(); - if (nestClose) - base.close(); - } + assert (pos <= s.size - low); } override size_t readBlock (void *buffer, size_t size) { assertReadable(); - if (bounded) { - if (size > high - low + pos) - size = high - low + pos; - } - - ulong bp = base.position; + if (bounded && size > high - low - pos) + size = high - low - pos; + ulong bp = s.position; if (seekable) - base.position = low + pos; - size_t ret = base.readBlock(buffer, size); + s.position = low + pos; + size_t ret = super.readBlock(buffer, size); if (seekable) { - pos = base.position - low; - base.position = bp; + pos = s.position - low; + s.position = bp; } return ret; } override size_t writeBlock (void *buffer, size_t size) { assertWriteable(); - if (bounded) { - if (size > high - low + pos) - size = high - low + pos; - } - - ulong bp = base.position; + if (bounded && size > high - low - pos) + size = high - low - pos; + ulong bp = s.position; if (seekable) - base.position = low + pos; - size_t ret = base.writeBlock(buffer, size); + s.position = low + pos; + size_t ret = s.writeBlock(buffer, size); if (seekable) { - pos = base.position - low; - base.position = bp; + pos = s.position - low; + s.position = bp; } return ret; } @@ -2560,40 +2522,45 @@ long spos; switch (rel) { - case SeekPos.Set: { + case SeekPos.Set: spos = offset; break; - } - case SeekPos.Current: { + case SeekPos.Current: spos = pos + offset; break; - } - case SeekPos.End: { + case SeekPos.End: if (bounded) spos = high - low + offset; else - spos = base.size - low + offset; + spos = s.size - low + offset; break; - } } if (spos < 0) pos = 0; else if (bounded && spos > high - low) pos = high - low; - else if (!bounded && spos > base.size - low) - pos = base.size - low; + else if (!bounded && spos > s.size - low) + pos = s.size - low; else pos = spos; + readEOF = false; return pos; } override size_t available () { - return size - pos; + size_t res = s.available; + ulong bp = s.position; + if (bp <= pos+low && pos+low <= bp+res) { + if (!bounded || bp+res <= high) + return bp + res - pos - low; + else if (high <= bp+res) + return high - pos - low; + } + return 0; } - /* Test the whole class. */ unittest { MemoryStream m; SliceStream s; @@ -2627,7 +2594,6 @@ s = new SliceStream (m, 4); assert (s.size () == 14); - assert (s.available == 14); assert (s.toString () == "Vrooorld\nBlaho"); s.seekEnd (0); assert (s.available == 0); @@ -2636,7 +2602,6 @@ assert (s.position () == 25); assert (s.seekSet (0) == 0); assert (s.size () == 25); - assert (s.available == 25); assert (m.position () == 18); assert (m.size () == 29); assert (m.toString() == "HellVrooorld\nBlaho, etcetera."); @@ -2659,28 +2624,3 @@ private bit ishexdigit(char c) { return isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } - -// standard IO devices -deprecated File stdin, stdout, stderr; - -version (Win32) { - // API imports - private extern(Windows) { - HANDLE GetStdHandle(DWORD); - } - - static this() { - // open standard I/O devices - stdin = new File(GetStdHandle(cast(uint)-10), FileMode.In); - stdout = new File(GetStdHandle(cast(uint)-11), FileMode.Out); - stderr = new File(GetStdHandle(cast(uint)-12), FileMode.Out); - } -} else version (linux) { - static this() { - // open standard I/O devices - stdin = new File(0, FileMode.In); - stdout = new File(1, FileMode.Out); - stderr = new File(2, FileMode.Out); - } -} - diff -uNr dmd-0.129/dmd/src/phobos/std/string.d dmd-0.130/dmd/src/phobos/std/string.d --- dmd-0.129/dmd/src/phobos/std/string.d 2005-08-06 21:57:06.000000000 +0200 +++ dmd-0.130/dmd/src/phobos/std/string.d 2005-09-06 16:06:54.000000000 +0200 @@ -31,6 +31,7 @@ private import std.array; private import std.format; private import std.ctype; +private import std.stdarg; extern (C) { @@ -2946,3 +2947,340 @@ 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 + */ + +/+ + ' final bool isNumeric(in char[], in bool = false) + ' --------------------------------------------------------------- + ' [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[] _arguments, va_list _argptr) +{ + char[] s = ""; + wchar[] ws = ""; + dchar[] ds = ""; + + //writefln("isNumeric(...) called!"); + if (_arguments.length == 0) + return false; + + if (_arguments[0] == typeid(char[])) + return isNumeric(va_arg!(char[])(_argptr)); + else if (_arguments[0] == typeid(wchar[])) + return isNumeric(std.utf.toUTF8(va_arg!(wchar[])(_argptr))); + else if (_arguments[0] == typeid(dchar[])) + return isNumeric(std.utf.toUTF8(va_arg!(dchar[])(_argptr))); + else if (_arguments[0] == typeid(real)) + return true; + else if (_arguments[0] == typeid(double)) + return true; + else if (_arguments[0] == typeid(float)) + return true; + else if (_arguments[0] == typeid(ulong)) + return true; + else if (_arguments[0] == typeid(long)) + return true; + else if (_arguments[0] == typeid(uint)) + return true; + else if (_arguments[0] == typeid(int)) + return true; + else if (_arguments[0] == typeid(ushort)) + return true; + else if (_arguments[0] == typeid(short)) + return true; + else if (_arguments[0] == typeid(ubyte)) + { + s.length = 1; + s[0]= va_arg!(ubyte)(_argptr); + return isNumeric(cast(char[])s); + } + else if (_arguments[0] == typeid(byte)) + { + s.length = 1; + s[0] = va_arg!(byte)(_argptr); + return isNumeric(cast(char[])s); + } + else if (_arguments[0] == typeid(ireal)) + return true; + else if (_arguments[0] == typeid(idouble)) + return true; + else if (_arguments[0] == typeid(ifloat)) + return true; + else if (_arguments[0] == typeid(creal)) + return true; + else if (_arguments[0] == typeid(cdouble)) + return true; + else if (_arguments[0] == typeid(cfloat)) + return true; + else if (_arguments[0] == typeid(char)) + { + s.length = 1; + s[0] = va_arg!(char)(_argptr); + return isNumeric(s); + } + else if (_arguments[0] == typeid(wchar)) + { + ws.length = 1; + ws[0] = va_arg!(wchar)(_argptr); + return isNumeric(std.utf.toUTF8(ws)); + } + else if (_arguments[0] == typeid(dchar)) + { + ds.length = 1; + ds[0] = va_arg!(dchar)(_argptr); + return isNumeric(std.utf.toUTF8(ds)); + } + //else if (_arguments[0] == typeid(cent)) + // return true; + //else if (_arguments[0] == typeid(ucent)) + // return true; + else + return false; +} + +unittest +{ + writefln( "isNumeric(in char[], bool = false).unittest" ); + 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); +} + diff -uNr dmd-0.129/dmd/src/phobos/std/uni.d dmd-0.130/dmd/src/phobos/std/uni.d --- dmd-0.129/dmd/src/phobos/std/uni.d 2005-08-06 21:57:06.000000000 +0200 +++ dmd-0.130/dmd/src/phobos/std/uni.d 2005-09-06 16:06:54.000000000 +0200 @@ -1,5 +1,5 @@ -module uni; +module std.uni; int isUniLower(dchar c) {