mirror of
https://github.com/dlang/phobos.git
synced 2025-04-26 21:22:20 +03:00
phobos 0.122
This commit is contained in:
parent
0c3ebe937f
commit
d24439d387
11 changed files with 919 additions and 121 deletions
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
720
std/conv.d
720
std/conv.d
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
150
std/stream.d
150
std/stream.d
|
@ -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 {
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue