phobos 0.122

This commit is contained in:
Brad Roberts 2007-09-10 04:41:44 +00:00
parent 0c3ebe937f
commit d24439d387
11 changed files with 919 additions and 121 deletions

View file

@ -28,25 +28,6 @@ import std.c.stdio;
extern (C):
byte[] _d_arraycat(byte[] x, byte[] y, uint size)
{ byte[] a;
uint length;
if (!x.length)
return y;
if (!y.length)
return x;
length = x.length + y.length;
a = new byte[length * size];
memcpy(a, x, x.length * size);
//a[0 .. x.length * size] = x[];
memcpy(&a[x.length * size], y, y.length * size);
*cast(int *)&a = length; // jam length
//a.length = length;
return a;
}
byte[] _d_arraycatn(uint size, uint n, ...)
{ byte[] a;
uint length;

View file

@ -202,7 +202,7 @@ ulong _d_new(uint length, uint size)
result = 0;
else
{
p = _gc.malloc(length * size);
p = _gc.malloc(length * size + 1);
debug(PRINTF) printf(" p = %p\n", p);
memset(p, 0, length * size);
result = cast(ulong)length + (cast(ulong)cast(uint)p << 32);
@ -215,12 +215,12 @@ ulong _d_newarrayi(uint length, uint size, ...)
void *p;
ulong result;
debug(PRINTF) printf("_d_newarrayi(length = %d, size = %d)\n", length, size);
//debug(PRINTF) printf("_d_newarrayi(length = %d, size = %d)\n", length, size);
if (length == 0 || size == 0)
result = 0;
else
{ void* q = cast(void*)(&size + 1); // pointer to initializer
p = _gc.malloc(length * size);
p = _gc.malloc(length * size + 1);
debug(PRINTF) printf(" p = %p\n", p);
if (size == 1)
memset(p, *cast(ubyte*)q, length);
@ -245,7 +245,7 @@ ulong _d_newbitarray(uint length, bit value)
if (length == 0)
result = 0;
else
{ uint size = (length + 7) >> 3; // number of bytes
{ uint size = (length + 8) >> 3; // number of bytes
ubyte fill = value ? 0xFF : 0;
p = _gc.malloc(size);
@ -361,9 +361,9 @@ byte[] _d_arraysetlength(uint newlength, uint sizeelem, Array *p)
if (newsize > size)
{
uint cap = _gc.capacity(p.data);
if (cap < newsize)
if (cap <= newsize)
{
newdata = cast(byte *)_gc.malloc(newsize);
newdata = cast(byte *)_gc.malloc(newsize + 1);
newdata[0 .. size] = p.data[0 .. size];
}
newdata[size .. newsize] = 0;
@ -371,7 +371,7 @@ byte[] _d_arraysetlength(uint newlength, uint sizeelem, Array *p)
}
else
{
newdata = cast(byte *)_gc.calloc(newsize, 1);
newdata = cast(byte *)_gc.calloc(newsize + 1, 1);
}
}
else
@ -408,9 +408,9 @@ bit[] _d_arraysetlengthb(uint newlength, Array *p)
if (newsize > size)
{
uint cap = _gc.capacity(p.data);
if (cap < newsize)
if (cap <= newsize)
{
newdata = cast(byte *)_gc.malloc(newsize);
newdata = cast(byte *)_gc.malloc(newsize + 1);
newdata[0 .. size] = p.data[0 .. size];
}
newdata[size .. newsize] = 0;
@ -418,7 +418,7 @@ bit[] _d_arraysetlengthb(uint newlength, Array *p)
}
else
{
newdata = cast(byte *)_gc.calloc(newsize, 1);
newdata = cast(byte *)_gc.calloc(newsize + 1, 1);
}
}
else
@ -447,7 +447,7 @@ long _d_arrayappend(Array *px, byte[] y, uint size)
{ byte* newdata;
//newdata = cast(byte *)_gc.malloc(newlength * size);
newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size));
newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size) + 1);
memcpy(newdata, px.data, length * size);
px.data = newdata;
}
@ -468,7 +468,7 @@ long _d_arrayappendb(Array *px, bit[] y)
{ void* newdata;
//newdata = _gc.malloc(newlength * size);
newdata = _gc.malloc(newCapacity(newsize, 1));
newdata = _gc.malloc(newCapacity(newsize, 1) + 1);
memcpy(newdata, px.data, (length + 7) / 8);
px.data = cast(byte*)newdata;
}
@ -492,7 +492,7 @@ uint newCapacity(uint newlength, uint size)
{
version(none)
{
newcap = newlength * size;
uint newcap = newlength * size;
}
else
{
@ -543,6 +543,7 @@ uint newCapacity(uint newlength, uint 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;
}
@ -553,11 +554,18 @@ byte[] _d_arrayappendc(inout byte[] x, in uint size, ...)
size_t cap = _gc.capacity(x);
size_t length = x.length;
size_t newlength = length + 1;
if (newlength * size > cap)
assert(cap == 0 || length * size <= cap);
//printf("_d_arrayappendc(size = %d, ptr = %p, length = %d, cap = %d)\n", size, x.ptr, x.length, cap);
if (newlength * size >= cap)
{ byte* newdata;
//printf("_d_arrayappendc(%d, %d)\n", size, newlength);
newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size));
//printf("_d_arrayappendc(size = %d, newlength = %d, cap = %d)\n", size, newlength, cap);
cap = newCapacity(newlength, size);
assert(cap >= newlength * size);
newdata = cast(byte *)_gc.malloc(cap + 1);
memcpy(newdata, x, length * size);
(cast(void **)(&x))[1] = newdata;
}
@ -565,28 +573,45 @@ byte[] _d_arrayappendc(inout byte[] x, in uint size, ...)
*cast(size_t *)&x = newlength;
(cast(byte *)x)[length * size .. newlength * size] = argp[0 .. size];
assert((cast(uint)x.ptr & 15) == 0);
assert(_gc.capacity(x.ptr) > x.length * size);
return x;
/+
byte[] a;
uint length;
void *argp;
//printf("size = %d\n", size);
length = x.length + 1;
a = new byte[length * size];
memcpy(a, x, x.length * size);
argp = &size + 1;
//printf("*argp = %llx\n", *cast(long *)argp);
memcpy(&a[x.length * size], argp, size);
//printf("a[0] = %llx\n", *cast(long *)&a[0]);
*cast(int *)&a = length; // jam length
//printf("a[0] = %llx\n", *cast(long *)&a[0]);
x = a;
return a;
+/
}
extern (C)
byte[] _d_arraycat(byte[] x, byte[] y, uint size)
out (result)
{
//printf("_d_arraycat(%d,%p ~ %d,%p size = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, size, result.length, result.ptr);
assert(result.length == x.length + y.length);
for (uint i = 0; i < x.length * size; i++)
assert((cast(byte*)result)[i] == (cast(byte*)x)[i]);
for (uint i = 0; i < y.length * size; i++)
assert((cast(byte*)result)[x.length * size + i] == (cast(byte*)y)[i]);
uint cap = _gc.capacity(result.ptr);
assert(!cap || cap > result.length * size);
}
body
{ byte[] a;
uint len;
if (!y.length)
return x;
if (!x.length)
return y;
len = x.length + y.length;
a = new byte[len * size];
memcpy(a, x, x.length * size);
//a[0 .. x.length * size] = x[];
memcpy(&a[x.length * size], y, y.length * size);
*cast(int *)&a = len; // jam length
//a.length = len;
return a;
}
extern (C)
bit[] _d_arrayappendcb(inout bit[] x, bit b)

View file

@ -49,9 +49,12 @@ struct lldiv_t { long quot,rem; }
int getErrno();
int setErrno(int);
const int ERANGE = 34; // on both Windows and linux
double atof(char *);
int atoi(char *);
int atol(char *);
float strtof(char *,char **);
double strtod(char *,char **);
real strtold(char *,char **);
long strtol(char *,char **,int);

View file

@ -3,16 +3,21 @@
// Copyright (c) 2002-2003 Digital Mars
// All Rights Reserved
// www.digitalmars.com
// Some parts contributed by David L. Davis
// Conversion building blocks. These differ from the C equivalents by
// checking for overflow and not allowing whitespace.
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 ****************/
class ConvError : Error
@ -831,4 +836,715 @@ unittest
}
/***************************************************************
* Convert character string to float.
*/
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 || *endptr != 0))
goto Lerr;
return f;
Lerr:
conv_error(s ~ " not representable as a float");
}
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));
}
/***************************************************************
* Convert character string to double.
*/
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 || *endptr != 0))
goto Lerr;
return f;
Lerr:
conv_error(s ~ " not representable as a double");
}
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);
}
/***************************************************************
* Convert character string to real.
* Grammar:
* ['+'|'-'] digit {digit}
*/
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 || *endptr != 0))
goto Lerr;
return f;
Lerr:
conv_error(s ~ " not representable as a real");
}
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?
*/
/***************************************************************
* Convert character string to ifloat.
*/
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));
}
/***************************************************************
* Convert character string to idouble.
*/
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));
}
/***************************************************************
* Convert character string to ireal.
*/
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));
}
/***************************************************************
* Convert character string to cfloat.
* Grammar:
* ['+'|'-'] digit {digit}
*/
cfloat toCfloat(in char[] s)
{
char[] s1;
char[] s2;
real r1;
real r2;
cfloat cf;
bit 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));
}
/***************************************************************
* Convert character string to cdouble.
* Grammar:
* ['+'|'-'] digit {digit}
*/
cdouble toCdouble(in char[] s)
{
char[] s1;
char[] s2;
real r1;
real r2;
cdouble cd;
bit 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));
}
/***************************************************************
* Convert character string to creal.
* Grammar:
* ['+'|'-'] digit {digit}
*/
creal toCreal(in char[] s)
{
char[] s1;
char[] s2;
real r1;
real r2;
creal cr;
bit 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 bit 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 bit feq(in real rx, in real ry, in real precision)
{
if (rx == ry)
return 1;
if (isnan(rx))
return cast(bit)isnan(ry);
if (isnan(ry))
return 0;
return cast(bit)(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 bit feq(in real r1, in real r2)
{
if (r1 == r2)
return 1;
if (isnan(r1))
return cast(bit)isnan(r2);
if (isnan(r2))
return 0;
return cast(bit)(feq(r1, r2, 0.000001L));
}
/****************************************
* compare ireals with given precision
*/
private bit 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(bit)isnan(ry);
if (isnan(ry))
return 0;
return feq(rx, ry, 0.000001L);
}
/****************************************
* compare creals with given precision
*/
private bit 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(bit)isnan(r2b);
if (isnan(r2b))
return 0;
return feq(r1a, r2b, 0.000001L);
}

View file

@ -213,13 +213,13 @@ interface OutputStream {
// writes a line, throws WriteException on error
void writeLine(char[] s);
// writes a UNICODE line, throws WriteException on error
// writes a Unicode line, throws WriteException on error
void writeLineW(wchar[] s);
// writes a string, throws WriteException on error
void writeString(char[] s);
// writes a UNICODE string, throws WriteException on error
// writes a Unicode string, throws WriteException on error
void writeStringW(wchar[] s);
// writes data to stream using vprintf() syntax,
@ -248,17 +248,27 @@ class Stream : InputStream, OutputStream {
bit seekable = false;
protected bit isopen = true;
// flag that last readBlock resulted in eof
protected bit readEOF = false;
this() {}
// reads block of data of specified size,
// returns actual number of bytes read
// returning 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) {
size_t readsize = readBlock(buffer, size);
if (readsize != 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");
}
@ -465,6 +475,7 @@ class Stream : InputStream, OutputStream {
// unget buffer
private wchar[] unget;
final int ungetAvailable() { return unget.length > 1; }
// reads and returns next character from the stream,
// handles characters pushed back by ungetc()
@ -876,7 +887,7 @@ class Stream : InputStream, OutputStream {
writeString("\n");
}
// writes a UNICODE line, throws WriteException on error
// writes a Unicode line, throws WriteException on error
void writeLineW(wchar[] s) {
writeStringW(s);
version (Win32)
@ -892,7 +903,7 @@ class Stream : InputStream, OutputStream {
writeExact(s, s.length);
}
// writes a UNICODE string, throws WriteException on error
// writes a Unicode string, throws WriteException on error
void writeStringW(wchar[] s) {
writeExact(s, s.length * wchar.sizeof);
}
@ -962,10 +973,18 @@ class Stream : InputStream, OutputStream {
// copies all data from given stream into this one,
// may throw ReadException or WriteException on failure
void copyFrom(Stream s) {
ulong pos = s.position();
s.position(0);
copyFrom(s, s.size());
s.position(pos);
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, buf.length);
writeExact(buf, m);
}
}
}
// copies specified number of bytes from given stream into
@ -1001,16 +1020,25 @@ class Stream : InputStream, OutputStream {
// returns size of stream
ulong size() {
assertSeekable();
ulong pos = position(), result = seek(0, SeekPos.End);
position(pos);
return result;
}
// returns true if end of stream is reached, false otherwise
bit eof() { return position() == size(); }
bit eof() {
// for unseekable streams we only know the end when we read it
if (readEOF && !ungetAvailable())
return true;
else if (seekable)
return position() == size();
else
return false;
}
// returns true if the stream is open
bit isOpen() { return isopen; }
bool isOpen() { return isopen; }
// flush the buffer if writeable
void flush() {
@ -1022,7 +1050,7 @@ class Stream : InputStream, OutputStream {
void close() {
if (isopen)
flush();
isopen = readable = writeable = seekable = false;
readEOF = isopen = readable = writeable = seekable = false;
}
// creates a string in memory containing copy of stream data
@ -1049,8 +1077,8 @@ class Stream : InputStream, OutputStream {
result = new char[blockSize];
while ((rdlen = readBlock(&result[pos], blockSize)) > 0) {
pos += rdlen;
result.length = result.length + blockSize;
blockSize += rdlen;
result.length = result.length + blockSize;
}
}
return result[0 .. pos];
@ -1063,7 +1091,8 @@ class Stream : InputStream, OutputStream {
ulong pos = position();
uint crc = init_crc32 ();
position(0);
for (ulong i = 0; i < size(); i++) {
ulong len = size();
for (ulong i = 0; i < len; i++) {
ubyte c;
read(c);
crc = update_crc32(c, crc);
@ -1135,6 +1164,7 @@ class BufferedStream : Stream {
readable = writeable = seekable = false;
isopen = false;
}
readEOF = false;
streamPos = 0;
bufferLen = bufferSourcePos = bufferCurPos = 0;
bufferDirty = false;
@ -1151,45 +1181,49 @@ class BufferedStream : Stream {
// 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 size) {
override size_t readBlock(void* result, size_t len) {
if (len == 0) return 0;
assertReadable();
ubyte* buf = cast(ubyte*)result;
ubyte* outbuf = cast(ubyte*)result;
size_t readsize = 0;
if (bufferCurPos + size <= bufferLen) {
if (bufferCurPos + len < bufferLen) {
// buffer has all the data so copy it
buf[0 .. size] = buffer[bufferCurPos .. bufferCurPos+size];
bufferCurPos += size;
readsize = size;
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
buf[0 .. readsize] = buffer[bufferCurPos .. bufferLen];
buf += readsize;
outbuf[0 .. readsize] = buffer[bufferCurPos .. bufferLen];
outbuf += readsize;
bufferCurPos += readsize;
size -= readsize;
len -= readsize;
}
flush();
if (size >= buffer.length) {
if (len >= buffer.length) {
// buffer can't hold the data so fill output buffer directly
size_t siz = s.readBlock(buf, size);
size_t siz = s.readBlock(outbuf, len);
readsize += siz;
streamPos += siz;
readEOF = siz == 0;
} else {
// read a new block into buffer
bufferLen = s.readBlock(buffer, buffer.length);
if (bufferLen < size) size = bufferLen;
buf[0 .. size] = buffer[0 .. size];
readEOF = bufferLen == 0;
if (bufferLen < len) len = bufferLen;
outbuf[0 .. len] = buffer[0 .. len];
bufferSourcePos = bufferLen;
streamPos += bufferLen;
bufferCurPos = size;
readsize += size;
bufferCurPos = len;
readsize += len;
}
ExitRead:
@ -1198,7 +1232,7 @@ class BufferedStream : Stream {
// write block of data of specified size
// returns actual number of bytes written
override size_t writeBlock(void* result, size_t size) {
override size_t writeBlock(void* result, size_t len) {
assertWriteable();
ubyte* buf = cast(ubyte*)result;
@ -1206,26 +1240,26 @@ class BufferedStream : Stream {
if (bufferLen == 0) {
// buffer is empty so fill it if possible
if ((size < buffer.length) && (readable)) {
if ((len < buffer.length) && (readable)) {
// read in data if the buffer is currently empty
bufferLen = s.readBlock(buffer,buffer.length);
bufferSourcePos = bufferLen;
streamPos += bufferLen;
} else if (size >= buffer.length) {
} else if (len >= buffer.length) {
// buffer can't hold the data so write it directly and exit
writesize = s.writeBlock(buf,size);
writesize = s.writeBlock(buf,len);
streamPos += writesize;
goto ExitWrite;
}
}
if (bufferCurPos + size <= buffer.length) {
if (bufferCurPos + len <= buffer.length) {
// buffer has space for all the data so copy it and exit
buffer[bufferCurPos .. bufferCurPos+size] = buf[0 .. size];
bufferCurPos += size;
buffer[bufferCurPos .. bufferCurPos+len] = buf[0 .. len];
bufferCurPos += len;
bufferLen = bufferCurPos > bufferLen ? bufferCurPos : bufferLen;
writesize = size;
writesize = len;
bufferDirty = true;
goto ExitWrite;
}
@ -1236,7 +1270,7 @@ class BufferedStream : Stream {
buffer[bufferCurPos .. buffer.length] = buf[0 .. writesize];
bufferCurPos = bufferLen = buffer.length;
buf += writesize;
size -= writesize;
len -= writesize;
bufferDirty = true;
}
@ -1245,7 +1279,7 @@ class BufferedStream : Stream {
flush();
writesize += writeBlock(buf,size);
writesize += writeBlock(buf,len);
ExitWrite:
return writesize;
@ -1262,6 +1296,7 @@ class BufferedStream : Stream {
} else {
bufferCurPos += offset;
}
readEOF = false;
return streamPos-bufferSourcePos+bufferCurPos;
}
@ -1318,7 +1353,7 @@ class BufferedStream : Stream {
} // template TreadLine(T)
override char[] readLine(char[] inBuffer) {
if (unget.length > 1)
if (ungetAvailable())
return super.readLine(inBuffer);
else
return TreadLine!(char).readLine(inBuffer);
@ -1326,7 +1361,7 @@ class BufferedStream : Stream {
alias Stream.readLine readLine;
override wchar[] readLineW(wchar[] inBuffer) {
if (unget.length > 1)
if (ungetAvailable())
return super.readLineW(inBuffer);
else
return TreadLine!(wchar).readLine(inBuffer);
@ -1342,7 +1377,7 @@ class BufferedStream : Stream {
body {
super.flush();
if (writeable && bufferDirty) {
if (bufferSourcePos != 0) {
if (bufferSourcePos != 0 && seekable) {
// move actual file pointer to front of buffer
streamPos = s.seek(-bufferSourcePos, SeekPos.Current);
}
@ -1353,7 +1388,7 @@ class BufferedStream : Stream {
}
}
long diff = bufferCurPos-bufferSourcePos;
if (diff != 0) {
if (diff != 0 && seekable) {
// move actual file pointer to current position
streamPos = s.seek(diff, SeekPos.Current);
}
@ -1363,23 +1398,21 @@ class BufferedStream : Stream {
}
// returns true if end of stream is reached, false otherwise
override bit eof() {
override bool eof() {
if ((buffer.length == 0) || !readable) {
return super.eof();
}
if (bufferCurPos == bufferLen) {
if ((bufferLen != buffer.length) &&
(bufferLen != 0)) {
return true;
}
}
else
// some simple tests to avoid flushing
if (ungetAvailable() || bufferCurPos != bufferLen)
return false;
size_t res = s.readBlock(buffer,buffer.length);
bufferSourcePos = bufferLen = res;
if (bufferLen == buffer.length)
flush();
size_t res = s.readBlock(&buffer[bufferLen],buffer.length-bufferLen);
bufferSourcePos += res;
bufferLen += res;
streamPos += res;
bufferCurPos = 0;
return res == 0;
readEOF = res == 0;
return readEOF;
}
// returns size of stream
@ -1572,6 +1605,7 @@ class File: Stream {
version (Win32) {
// returns size of stream
ulong size() {
assertSeekable();
uint sizehi;
uint sizelow = GetFileSize(hFile,&sizehi);
return (cast(ulong)sizehi << 32) + sizelow;
@ -1587,6 +1621,7 @@ class File: Stream {
if (size == -1)
size = 0;
}
readEOF = (size == 0);
return size;
}
@ -1615,6 +1650,7 @@ class File: Stream {
if (result == 0xFFFFFFFF)
throw new SeekException("unable to move file pointer");
}
readEOF = false;
return result;
}
@ -1983,7 +2019,7 @@ class EndianStream : Stream {
}
override void flush() { super.flush(); s.flush(); }
override bit eof() { return s.eof(); }
override bool eof() { return s.eof() && !ungetAvailable(); }
override ulong size() { return s.size(); }
unittest {

View file

@ -49,7 +49,6 @@ extern (C)
void *memmove(void *, void *, uint);
void *memset(void *, uint, uint);
char* strerror(int);
real strtold(char*, char**);
int wcslen(wchar *);
int wcscmp(wchar *, wchar *);

View file

@ -17,8 +17,19 @@ class TypeInfo_r : TypeInfo
}
static int _compare(cdouble f1, cdouble f2)
{
return f1 < f2 ? -1 : f1 > f2 ? 1 : 0;
{ 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)

View file

@ -16,8 +16,19 @@ class TypeInfo_q : TypeInfo
}
static int _compare(cfloat f1, cfloat f2)
{
return f1 < f2 ? -1 : f1 > f2 ? 1 : 0;
{ 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)

View file

@ -18,8 +18,19 @@ class TypeInfo_c : TypeInfo
}
static int _compare(creal f1, creal f2)
{
return f1 < f2 ? -1 : f1 > f2 ? 1 : 0;
{ 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)

View file

@ -43,6 +43,7 @@ import std.uri;
import std.zlib;
import std.md5;
import std.stdio;
import std.conv;
int main(char[][] args)
{
@ -53,7 +54,8 @@ int main(char[][] args)
printf("test1\n");
fncharmatch('a', 'b'); // path
isnan(1.0); // math
feq(1.0, 2.0); // math2
std.math2.feq(1.0, 2.0); // math2
std.conv.toDouble("1.0"); // std.conv
printf("test1\n");
OutBuffer b = new OutBuffer(); // outbuffer
std.ctype.tolower('A'); // ctype

View file

@ -65,6 +65,7 @@ OBJS= asserterror.obj deh.obj switch.obj complex.obj gcstats.obj \
Czlib.obj Dzlib.obj zip.obj process.obj registry.obj recls.obj \
socket.obj socketstream.obj loader.obj stdarg.obj format.obj stdio.obj \
perf.obj openrj.obj uni.obj winsock.obj oldsyserror.obj \
errno.obj \
ti_Aa.obj ti_Ag.obj ti_C.obj ti_int.obj ti_char.obj \
ti_wchar.obj ti_uint.obj ti_short.obj ti_ushort.obj \
ti_byte.obj ti_ubyte.obj ti_long.obj ti_ulong.obj ti_ptr.obj \
@ -363,6 +364,8 @@ etc\c\zlib\zlib.lib:
make -f win32.mak zlib.lib
cd ..\..\..
errno.obj : errno.c
### internal
aaA.obj : internal\aaA.d