249 changes: 147 additions & 102 deletions std/algorithm.d

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions std/array.d
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ private template nDimensions(T)
{
static if(isArray!T)
{
enum nDimensions = 1 + nDimensions!(typeof(T.init[0]));
enum nDimensions = 1 + nDimensions!(ArrayTarget!T);
}
else
{
Expand Down Expand Up @@ -266,7 +266,7 @@ if(allSatisfy!(isIntegral, I))
to!string(sizes.length) ~ " dimensions specified for a " ~
to!string(nDimensions!T) ~ " dimensional array.");

alias typeof(T.init[0]) E;
alias ArrayTarget!T E;

auto ptr = cast(E*) GC.malloc(sizes[0] * E.sizeof, blockAttribute!(E));
auto ret = ptr[0..sizes[0]];
Expand Down Expand Up @@ -1533,7 +1533,7 @@ unittest
}
foreach (S; TypeTuple!(string, wstring, dstring, char[], wchar[], dchar[]))
{
alias typeof(S.init[0]) Char;
alias ElementEncodingType!S Char;
S s = to!S("yet another dummy text, yet another ...");
S from = to!S("yet another");
S into = to!S("some");
Expand Down
42 changes: 35 additions & 7 deletions std/bigint.d
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public:
/// It may have a leading + or - sign; followed by "0x" if hexadecimal.
/// Underscores are permitted.
/// BUG: Should throw a IllegalArgumentException/ConvError if invalid character found
this(T:string)(T s)
this(T : const(char)[] )(T s)
{
bool neg = false;
if (s[0] == '-') {
Expand Down Expand Up @@ -112,17 +112,19 @@ public:
}

///
void opAssign(T: long)(T x)
BigInt opAssign(T: long)(T x)
{
data = cast(ulong)((x < 0) ? -x : x);
sign = (x < 0);
return this;
}

///
void opAssign(T:BigInt)(T x)
BigInt opAssign(T:BigInt)(T x)
{
data = x.data;
sign = x.sign;
return this;
}

// BigInt op= integer
Expand Down Expand Up @@ -160,8 +162,14 @@ public:
else static if (op=="%")
{
assert(y!=0, "Division by zero");
static assert(!is(T==long) && !is(T==ulong));
data = cast(ulong)BigUint.modInt(data, cast(uint)u);
static if (is(const(T) == const(long)) || is( const(T) == const(ulong) ))
{
this %= BigInt(y);
}
else
{
data = cast(ulong)BigUint.modInt(data, cast(uint)u);
}
// x%y always has the same sign as x.
// This is not the same as mathematical mod.
}
Expand Down Expand Up @@ -214,8 +222,8 @@ public:
y.checkDivByZero();
if (!isZero())
{
sign ^= y.sign;
data = BigUint.div(data, y.data);
sign = isZero() ? false : sign ^ y.sign;
}
}
else static if (op == "%")
Expand Down Expand Up @@ -342,7 +350,7 @@ public:
}

///
bool opEquals(T: int)(T y) const
bool opEquals(T: long)(T y) const
{
if (sign != (y<0))
return 0;
Expand Down Expand Up @@ -523,6 +531,11 @@ unittest {
assert(BigInt(-0x1234_5678_9ABC_5A5AL).toLong() == -0x1234_5678_9ABC_5A5AL);
assert(BigInt(0xF234_5678_9ABC_5A5AL).toLong() == long.max);
assert(BigInt(-0x123456789ABCL).toInt() == -int.max);
char[] s1 = "123".dup; // bug 8164
assert(BigInt(s1) == 123);
char[] s2 = "0xABC".dup;
assert(BigInt(s2) == 2748);

assert((BigInt(-2) + BigInt(1)) == BigInt(-1));
BigInt a = ulong.max - 5;
auto b = -long.max % a;
Expand All @@ -532,6 +545,7 @@ unittest {
assert(BigInt(1) - 1 == 0);
assert((-4) % BigInt(5) == -4); // bug 5928
assert(BigInt(-4) % BigInt(5) == -4);
assert(BigInt(2)/BigInt(-3) == BigInt(0)); // bug 8022
}

unittest // Recursive division, bug 5568
Expand Down Expand Up @@ -561,6 +575,20 @@ unittest // Recursive division, bug 5568
BigInt z2 = BigInt(1)<<64;
BigInt w2 = BigInt(1)<<128;
assert(z2^^2 == w2);
// Bug 7993
BigInt n7793 = 10;
assert( n7793 / 1 == 10);
// Bug 7973
auto a7973 = 10_000_000_000_000_000;
const c7973 = 10_000_000_000_000_000;
BigInt v7973 = 2551700137;
v7973 %= a7973;
assert(v7973 == 2551700137);
v7973 %= c7973;
assert(v7973 == 2551700137);
// 8165
BigInt[2] a8165;
a8165[0] = a8165[1] = 1;
}

unittest
Expand Down
254 changes: 119 additions & 135 deletions std/complex.d

Large diffs are not rendered by default.

647 changes: 635 additions & 12 deletions std/container.d

Large diffs are not rendered by default.

57 changes: 25 additions & 32 deletions std/conv.d
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ class ConvException : Exception
}
}

deprecated alias ConvException ConvError; /// ditto

private string convError_unexpected(S)(S source) {
return source.empty ? "end of input" : text("'", source.front, "'");
}
Expand Down Expand Up @@ -97,7 +95,7 @@ private
if (isSomeString!T)
{
auto w = appender!T();
FormatSpec!(typeof(T.init[0])) f;
FormatSpec!(ElementEncodingType!T) f;
formatValue(w, src, f);
return w.data;
}
Expand Down Expand Up @@ -136,8 +134,6 @@ class ConvOverflowException : ConvException
}
}

deprecated alias ConvOverflowException ConvOverflowError; /// ditto

/* **************************************************************
The $(D_PARAM to) family of functions converts a value from type
Expand Down Expand Up @@ -784,12 +780,12 @@ $(UL
T toImpl(T, S)(S value)
if (!(isImplicitlyConvertible!(S, T) &&
!isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) &&
isSomeString!T)
isSomeString!T && !isAggregateType!T)
{
static if (isSomeString!S && value[0].sizeof == T.init[0].sizeof)
static if (isSomeString!S && value[0].sizeof == ElementEncodingType!T.sizeof)
{
// string-to-string with incompatible qualifier conversion
static if (is(typeof(T.init[0]) == immutable))
static if (is(ElementEncodingType!T == immutable))
{
// conversion (mutable|const) -> immutable
return value.idup;
Expand All @@ -808,7 +804,7 @@ T toImpl(T, S)(S value)
else static if (is(S == void[]) || is(S == const(void)[]) || is(S == immutable(void)[]))
{
// Converting void array to string
alias Unqual!(typeof(T.init[0])) Char;
alias Unqual!(ElementEncodingType!T) Char;
auto raw = cast(const(ubyte)[]) value;
enforce(raw.length % Char.sizeof == 0,
new ConvException("Alignment mismatch in converting a "
Expand Down Expand Up @@ -1125,7 +1121,7 @@ unittest
}

/**
$(RED Deprecated. It will be removed in December 2012.
$(RED Deprecated. It will be removed in January 2013.
Please use $(XREF format, formattedWrite) instead.)
Conversions to string with optional configures.
Expand All @@ -1134,7 +1130,7 @@ deprecated T toImpl(T, S)(S s, in T leftBracket, in T separator = ", ", in T rig
if (!isSomeChar!(ElementType!S) && (isInputRange!S || isInputRange!(Unqual!S)) &&
isSomeString!T)
{
pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));

static if (!isInputRange!S)
Expand All @@ -1144,7 +1140,7 @@ deprecated T toImpl(T, S)(S s, in T leftBracket, in T separator = ", ", in T rig
}
else
{
alias Unqual!(typeof(T.init[0])) Char;
alias Unqual!(ElementEncodingType!T) Char;
// array-to-string conversion
auto result = appender!(Char[])();
result.put(leftBracket);
Expand All @@ -1171,7 +1167,7 @@ deprecated T toImpl(T, S)(ref S s, in T leftBracket, in T separator = " ", in T
if ((is(S == void[]) || is(S == const(void)[]) || is(S == immutable(void)[])) &&
isSomeString!T)
{
pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));

return toImpl(s);
Expand All @@ -1182,10 +1178,10 @@ deprecated T toImpl(T, S)(S s, in T leftBracket, in T keyval = ":", in T separat
if (isAssociativeArray!S &&
isSomeString!T)
{
pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));

alias Unqual!(typeof(T.init[0])) Char;
alias Unqual!(ElementEncodingType!T) Char;
auto result = appender!(Char[])();
// hash-to-string conversion
result.put(leftBracket);
Expand All @@ -1208,7 +1204,7 @@ deprecated T toImpl(T, S)(S s, in T nullstr)
if (is(S : Object) &&
isSomeString!T)
{
pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));

if (!s)
Expand All @@ -1221,15 +1217,15 @@ deprecated T toImpl(T, S)(S s, in T left, in T separator = ", ", in T right = ")
if (is(S == struct) && !is(typeof(&S.init.toString)) && !isInputRange!S &&
isSomeString!T)
{
pragma(msg, hardDeprec!("2.060", "December 2012", "std.conv.toImpl with extra parameters",
pragma(msg, hardDeprec!("2.060", "January 2013", "std.conv.toImpl with extra parameters",
"std.format.formattedWrite"));

Tuple!(FieldTypeTuple!S) * t = void;
static if ((*t).sizeof == S.sizeof)
{
// ok, attempt to forge the tuple
t = cast(typeof(t)) &s;
alias Unqual!(typeof(T.init[0])) Char;
alias Unqual!(ElementEncodingType!T) Char;
auto app = appender!(Char[])();
app.put(left);
foreach (i, e; t.field)
Expand Down Expand Up @@ -1330,7 +1326,7 @@ T toImpl(T, S)(S value)
!isSomeString!S && isDynamicArray!S &&
!isSomeString!T && isArray!T)
{
alias typeof(T.init[0]) E;
alias ArrayTarget!T E;
auto result = new E[value.length];
foreach (i, e; value)
{
Expand Down Expand Up @@ -1361,6 +1357,14 @@ unittest
uint[][] e = [ a, a ];
auto f = to!(float[][])(e);
assert(f[0] == b && f[1] == b);

// Test for bug 8264
struct Wrap
{
string wrap;
alias wrap this;
}
Wrap[] warr = to!(Wrap[])(["foo", "bar"]); // should work
}

/**
Expand Down Expand Up @@ -2589,7 +2593,7 @@ string up one position.
*/
Target parse(Target, Source)(ref Source s)
if (isSomeString!Source &&
staticIndexOf!(Unqual!Target, dchar, Unqual!(typeof(Source.init[0]))) >= 0)
staticIndexOf!(Unqual!Target, dchar, Unqual!(ElementEncodingType!Source)) >= 0)
{
static if (is(Unqual!Target == dchar))
{
Expand All @@ -2613,7 +2617,7 @@ unittest
foreach (Char; TypeTuple!(char, wchar, dchar))
{
static if (is(Unqual!Char == dchar) ||
Char.sizeof == Str.init[0].sizeof)
Char.sizeof == ElementEncodingType!Str.sizeof)
{
Str s = "aaa";
assert(parse!Char(s) == 'a');
Expand Down Expand Up @@ -2713,17 +2717,6 @@ unittest
assert(parse!(const(NullType))(s) is null);
}

// Parsing typedefs forwards to their host types
deprecated Target parse(Target, Source)(ref Source s)
if (isSomeString!Source &&
is(Target == typedef))
{
static if (is(Target T == typedef))
return cast(Target) parse!T(s);
else
static assert(0);
}

private void skipWS(R)(ref R r)
{
skipAll(r, ' ', '\n', '\t', '\r');
Expand Down
7 changes: 6 additions & 1 deletion std/cpuid.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Written in the D programming language.

/**
* $(RED Scheduled for deprecation. Please use core.cpuid instead.)
* $(RED Deprecated. It will be removed in January 2013. Please use core.cpuid instead.)
*
* Identify the characteristics of the host CPU.
*
Expand Down Expand Up @@ -45,10 +45,15 @@ Source: $(PHOBOSSRC std/_cpuid.d)
*/
module std.cpuid;

pragma(msg, "std.cpuid has been deprecated. It will be removed in January 2013. " ~
"Please use core.cpuid instead.");

import std.string;
import std.conv;
private import core.cpuid;

deprecated:

version(D_InlineAsm_X86)
{
/// Returns everything as a printable string
Expand Down
8 changes: 4 additions & 4 deletions std/datetime.d
Original file line number Diff line number Diff line change
Expand Up @@ -27636,9 +27636,9 @@ auto tz = TimeZone.getTimeZone("America/Los_Angeles");

//Whenever a leap second is added/removed,
//this will have to be adjusted.
enum leapDiff = convert!("seconds", "hnsecs")(24);
_assertPred!"=="(leapSTD.adjTime - leapDiff, std.adjTime);
_assertPred!"=="(leapDST.adjTime - leapDiff, dst.adjTime);
//enum leapDiff = convert!("seconds", "hnsecs")(25);
//_assertPred!"=="(leapSTD.adjTime - leapDiff, std.adjTime);
//_assertPred!"=="(leapDST.adjTime - leapDiff, dst.adjTime);
}
}

Expand Down Expand Up @@ -33891,7 +33891,7 @@ template _isPrintable(T...)
else static if(T.length == 1)
{
enum _isPrintable = (!isArray!(T[0]) && __traits(compiles, to!string(T[0].init))) ||
(isArray!(T[0]) && __traits(compiles, to!string(T[0].init[0])));
__traits(compiles, to!string(ArrayTarget!(T[0]).init));
}
else
{
Expand Down
11 changes: 0 additions & 11 deletions std/encoding.d
Original file line number Diff line number Diff line change
Expand Up @@ -394,11 +394,6 @@ template EncoderFunctions()
void write(E c) { array[0] = c; array = array[1..$]; }
}

deprecated template WriteToBuffer()
{
void write(E c) { buffer ~= c; }
}

template WriteToDelegate()
{
void write(E c) { dg(c); }
Expand Down Expand Up @@ -450,12 +445,6 @@ template EncoderFunctions()
mixin EncodeViaWrite;
}

deprecated template EncodeToBuffer()
{
mixin WriteToBuffer;
mixin EncodeViaWrite;
}

template EncodeToDelegate()
{
mixin WriteToDelegate;
Expand Down
2 changes: 1 addition & 1 deletion std/exception.d
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ class ErrnoException : Exception
uint errno; // operating system error code
this(string msg, string file = null, size_t line = 0)
{
errno = getErrno();
errno = .errno();
version (linux)
{
char[1024] buf = void;
Expand Down
6 changes: 3 additions & 3 deletions std/file.d
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class FileException : Exception

/++
Constructor which takes the error number ($(LUCKY GetLastError)
in Windows, $(D_PARAM getErrno) in Posix).
in Windows, $(D_PARAM errno) in Posix).
Params:
name = Name of file for which the error occurred.
Expand All @@ -229,7 +229,7 @@ class FileException : Exception
this.errno = errno;
}
else version(Posix) this(in char[] name,
uint errno = .getErrno(),
uint errno = .errno,
string file = __FILE__,
size_t line = __LINE__)
{
Expand All @@ -249,7 +249,7 @@ private T cenforce(T)(T condition, lazy const(char)[] name, string file = __FILE
}
else version (Posix)
{
throw new FileException(name, .getErrno(), file, line);
throw new FileException(name, .errno, file, line);
}
}
return condition;
Expand Down
62 changes: 39 additions & 23 deletions std/format.d
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ class FormatException : Exception
}
}

/**
$(RED Scheduled for deprecation. Please use $(D FormatException) instead.)
*/
/*deprecated*/ alias FormatException FormatError;
/++
$(RED Deprecated. It will be removed In January 2013.
Please use $(D FormatException) instead.)
+/
deprecated alias FormatException FormatError;

/**********************************************************************
Interprets variadic argument list $(D args), formats them according
Expand Down Expand Up @@ -1668,12 +1669,24 @@ unittest
/**
Static-size arrays are formatted as dynamic arrays.
*/
void formatValue(Writer, T, Char)(Writer w, ref T obj, ref FormatSpec!Char f)
void formatValue(Writer, T, Char)(Writer w, auto ref T obj, ref FormatSpec!Char f)
if (!hasToString!(T, Char) && isStaticArray!T)
{
formatValue(w, obj[], f);
}

unittest // Test for issue 8310
{
FormatSpec!char f;
auto w = appender!string();

char[2] two = ['a', 'b'];
formatValue(w, two, f);

char[2] getTwo(){ return two; }
formatValue(w, getTwo(), f);
}

/**
Dynamic arrays are formatted as input ranges.
Expand Down Expand Up @@ -4013,7 +4026,7 @@ body
debug (unformatRange) printf("\t) spec = %c, front = %c ", fmt.spec, input.front);
static if (isStaticArray!T)
{
result[i++] = unformatElement!(typeof(T.init[0]))(input, fmt);
result[i++] = unformatElement!(ArrayTarget!T)(input, fmt);
}
else static if (isDynamicArray!T)
{
Expand Down Expand Up @@ -4458,13 +4471,14 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
{
if (valti.classinfo.name.length == 18 &&
valti.classinfo.name[9..18] == "Invariant")
valti = (cast(TypeInfo_Invariant)valti).next;
valti = (cast(TypeInfo_Invariant)valti).next;
else if (valti.classinfo.name.length == 14 &&
valti.classinfo.name[9..14] == "Const")
valti = (cast(TypeInfo_Const)valti).next;
valti = (cast(TypeInfo_Const)valti).next;
else
break;
}

return valti;
}

Expand Down Expand Up @@ -4667,29 +4681,30 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
if (comma) putc(',');
comma = true;
void *pkey = &fakevalue;
version (X86)
pkey -= long.sizeof;
else version(X86_64)
pkey -= 16;
else static assert(false, "unsupported platform");
version (D_LP64)
pkey -= (long.sizeof + 15) & ~(15);
else
pkey -= (long.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1);

// the key comes before the value
auto keysize = keyti.tsize;
version (X86)
auto keysizet = (keysize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
else
version (D_LP64)
auto keysizet = (keysize + 15) & ~(15);
else
auto keysizet = (keysize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);

void* pvalue = pkey + keysizet;

//doFormat(putc, (&keyti)[0..1], pkey);
version (X86)
argptr = pkey;
else
else version (X86_64)
{ __va_list va;
va.stack_args = pkey;
argptr = &va;
}
else static assert(false, "unsupported platform");

ti = keyti;
m = getMan(keyti);
formatArg('s');
Expand All @@ -4698,11 +4713,12 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
//doFormat(putc, (&valti)[0..1], pvalue);
version (X86)
argptr = pvalue;
else
else version (X86_64)
{ __va_list va2;
va2.stack_args = pvalue;
argptr = &va2;
}
else static assert(false, "unsupported platform");

ti = valti;
m = getMan(valti);
Expand Down Expand Up @@ -4849,17 +4865,17 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)

case Mangle.Tsarray:
version (X86)
putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next);
putArray(argptr, (cast(TypeInfo_StaticArray)ti).len, cast()(cast(TypeInfo_StaticArray)ti).next);
else
putArray((cast(__va_list*)argptr).stack_args, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next);
putArray((cast(__va_list*)argptr).stack_args, (cast(TypeInfo_StaticArray)ti).len, cast()(cast(TypeInfo_StaticArray)ti).next);
return;

case Mangle.Tarray:
int mi = 10;
if (ti.classinfo.name.length == 14 &&
ti.classinfo.name[9..14] == "Array")
{ // array of non-primitive types
TypeInfo tn = (cast(TypeInfo_Array)ti).next;
TypeInfo tn = cast()(cast(TypeInfo_Array)ti).next;
tn = skipCI(tn);
switch (cast(Mangle)tn.classinfo.name[9])
{
Expand All @@ -4878,7 +4894,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
{ // associative array
ubyte[long] vaa = va_arg!(ubyte[long])(argptr);
putAArray(vaa,
(cast(TypeInfo_AssociativeArray)ti).next,
cast()(cast(TypeInfo_AssociativeArray)ti).next,
(cast(TypeInfo_AssociativeArray)ti).key);
return;
}
Expand Down Expand Up @@ -5131,7 +5147,7 @@ void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr)
if (ti.classinfo.name.length == 14 &&
ti.classinfo.name[9..14] == "Array")
{
TypeInfo tn = (cast(TypeInfo_Array)ti).next;
TypeInfo tn = cast()(cast(TypeInfo_Array)ti).next;
tn = skipCI(tn);
switch (cast(Mangle)tn.classinfo.name[9])
{
Expand Down
128 changes: 0 additions & 128 deletions std/hash/crc32.d

This file was deleted.

10 changes: 6 additions & 4 deletions std/internal/math/biguintcore.d
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ public:
}

// return false if invalid character found
bool fromHexString(string s)
bool fromHexString(const(char)[] s)
{
//Strip leading zeros
int firstNonZero = 0;
Expand Down Expand Up @@ -369,7 +369,7 @@ public:
}

// return true if OK; false if erroneous characters found
bool fromDecimalString(string s)
bool fromDecimalString(const(char)[] s)
{
//Strip leading zeros
int firstNonZero = 0;
Expand Down Expand Up @@ -547,8 +547,10 @@ public:
}

// return x / y
static BigUint divInt(T)(BigUint x, T y) if ( is(T==uint) )
static BigUint divInt(T)(BigUint x, T y) if ( is(T == uint) )
{
if (y == 1)
return x;
uint [] result = new BigDigit[x.data.length];
if ((y&(-y))==y)
{
Expand Down Expand Up @@ -1413,7 +1415,7 @@ size_t biguintToDecimal(char [] buff, BigDigit [] data)
* Returns:
* the highest index of data which was used.
*/
int biguintFromDecimal(BigDigit [] data, string s)
int biguintFromDecimal(BigDigit [] data, const(char)[] s)
in
{
assert((data.length >= 2) || (data.length == 1 && s.length == 1));
Expand Down
71 changes: 54 additions & 17 deletions std/internal/uni.d
Original file line number Diff line number Diff line change
Expand Up @@ -612,37 +612,74 @@ public:
}


@system unittest//a very sloow test
unittest
{
import std.conv;
uint max_char, max_data;
alias CodepointTrie!8 Trie;
Trie t;
auto wordSet =
CodepointSet.init.add(unicodeAlphabetic).add(unicodeMn).add(unicodeMc)
.add(unicodeMe).add(unicodeNd).add(unicodePc);
t = Trie(wordSet);
auto t = CodepointTrie!8(wordSet);
assert(t['a']);
assert(!t[' ']);
}

unittest
{
CodepointSet set;
set.add(unicodeAlphabetic);
for(size_t i=1;i<set.ivals.length; i++)
assert(set.ivals[i-1] < set.ivals[i],text(set.ivals[i-1], " ",set.ivals[i]));
foreach(up; unicodeProperties)
{
t = Trie(up.set);
foreach(uint ch; up.set[])
assert(t[ch], text("on ch ==", ch));
auto s = up.set.dup.negate().negate();
assert(equal(cast(immutable(Interval)[])s.ivals
, cast(immutable(Interval)[])up.set.ivals));
foreach(ch; up.set.dup.negate()[])
assert(set.ivals[i-1] < set.ivals[i]);
}

@system unittest
{
import std.conv, std.random, std.range;
immutable seed = unpredictableSeed();
auto rnd = Random(seed);

auto testCases = randomSample(unicodeProperties, 10, rnd);

// test trie using ~2000 codepoints
foreach(up; testCases.save)
{
void test(in CodepointSet set, scope void delegate(uint ch) dg)
{
assert(!t[ch], text("negative on ch ==", ch));
foreach (_; 0 .. 10)
{
immutable idx = uniform(0, set.ivals.length / 2, rnd);
immutable lo = set.ivals[2*idx], hi = set.ivals[2*idx+1];
foreach (_2; 0 .. min(10, hi - lo))
dg(uniform(lo, hi, rnd));
}
}

auto neg = up.set.dup.negate();
auto trie = CodepointTrie!8(up.set);
test(up.set, ch => assert(trie[ch], text("on ch == ", ch, " seed was ", seed)));
test(neg, ch => assert(!trie[ch], text("negative on ch == ", ch, " seed was ", seed)));
}

// test that negate is reversible
foreach(up; testCases.save)
{
auto neg = up.set.dup.negate().negate();
assert(equal(up.set.ivals, neg.ivals));
}

// test codepoint forward iterator
auto set = testCases.front.set;
auto rng = set[];
foreach (idx; 0 .. set.ivals.length / 2)
{
immutable lo = set.ivals[2*idx], hi = set.ivals[2*idx+1];
foreach (val; lo .. hi)
{
assert(rng.front == val, text("on val == ", val, " seed was ", seed));
rng.popFront();
}
}
}


//fussy compare for unicode property names as per UTS-18
int comparePropertyName(Char)(const(Char)[] a, const(Char)[] b)
{
Expand Down
35 changes: 31 additions & 4 deletions std/json.d
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum JSON_TYPE : byte {
/// Indicates the type of a $(D JSONValue).
STRING,
INTEGER, /// ditto
UINTEGER,/// integers > 2^63-1
FLOAT, /// ditto
OBJECT, /// ditto
ARRAY, /// ditto
Expand All @@ -52,15 +53,33 @@ struct JSONValue {
string str;
/// Value when $(D type) is $(D JSON_TYPE.INTEGER)
long integer;
/// Value when $(D type) is $(D JSON_TYPE.UINTEGER)
ulong uinteger;
/// Value when $(D type) is $(D JSON_TYPE.FLOAT)
real floating;
/// Value when $(D type) is $(D JSON_TYPE.OBJECT)
JSONValue[string] object;
JSONValue[string] object;
/// Value when $(D type) is $(D JSON_TYPE.ARRAY)
JSONValue[] array;
}
/// Specifies the _type of the value stored in this structure.
JSON_TYPE type;

/// array syntax for json arrays
ref JSONValue opIndex(size_t i)
in { assert(type == JSON_TYPE.ARRAY, "json type is not array"); }
body
{
return array[i];
}

/// hash syntax for json objects
ref JSONValue opIndex(string k)
in { assert(type == JSON_TYPE.OBJECT, "json type is not object"); }
body
{
return object[k];
}
}

/**
Expand Down Expand Up @@ -233,7 +252,7 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T) {
case '0': .. case '9':
case '-':
auto number = appender!string();
bool isFloat;
bool isFloat, isNegative;

void readInteger() {
if(!isDigit(c)) error("Digit expected");
Expand All @@ -249,6 +268,7 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T) {
if(c == '-') {
number.put('-');
c = getChar();
isNegative = true;
}

readInteger();
Expand All @@ -274,8 +294,11 @@ JSONValue parseJSON(T)(T json, int maxDepth = -1) if(isInputRange!T) {
value.floating = parse!real(data);
}
else {
value.type = JSON_TYPE.INTEGER;
value.integer = parse!long(data);
if (isNegative)
value.integer = parse!long(data);
else
value.uinteger = parse!ulong(data);
value.type = !isNegative && value.uinteger & (1UL << 63) ? JSON_TYPE.UINTEGER : JSON_TYPE.INTEGER;
}
break;

Expand Down Expand Up @@ -376,6 +399,10 @@ string toJSON(in JSONValue* root) {
json.put(to!string(value.integer));
break;

case JSON_TYPE.UINTEGER:
json.put(to!string(value.uinteger));
break;

case JSON_TYPE.FLOAT:
json.put(to!string(value.floating));
break;
Expand Down
8 changes: 7 additions & 1 deletion std/math.d
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ creal sqrt(creal z) @safe pure nothrow
* $(TR $(TD $(NAN)) $(TD $(NAN)) )
* )
*/
real exp(real x) @safe pure nothrow
real exp(real x) @trusted pure nothrow
{
version(D_InlineAsm_X86)
{
Expand Down Expand Up @@ -2076,6 +2076,8 @@ private:
DIVBYZERO_MASK = 0x020,
INVALID_MASK = 0xF80 // PowerPC has five types of invalid exceptions.
}
} else version (ARM) {
// TODO: Fill this in for VFP.
} else version(SPARC) { // SPARC FSR is a 32bit register
//(64 bits for Sparc 7 & 8, but high 32 bits are uninteresting).
enum : int {
Expand Down Expand Up @@ -2113,6 +2115,8 @@ private:
return retval;
*/
assert(0, "Not yet supported");
} else version (ARM) {
assert(false, "Not yet supported.");
} else
assert(0, "Not yet supported");
}
Expand All @@ -2133,6 +2137,7 @@ private:
}
}
public:
version (X86_Any) { // TODO: Lift this version condition when we support !x86.
/// The result cannot be represented exactly, so rounding occured.
/// (example: x = sin(0.1); )
@property bool inexact() { return (flags & INEXACT_MASK) != 0; }
Expand All @@ -2144,6 +2149,7 @@ public:
@property bool divByZero() { return (flags & DIVBYZERO_MASK) != 0; }
/// A machine NaN was generated. (example: x = real.infinity * 0.0; )
@property bool invalid() { return (flags & INVALID_MASK) != 0; }
}
}


Expand Down
9 changes: 0 additions & 9 deletions std/metastrings.d
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,3 @@ unittest
assert(parseInteger!("-1234abc").value == "-1234");
assert(parseInteger!("-1234abc").rest == "abc");
}

/**
Deprecated aliases held for backward compatibility.
*/
deprecated alias toStringNow ToString;
/// Ditto
deprecated alias parseUinteger ParseUinteger;
/// Ditto
deprecated alias parseUinteger ParseInteger;
4 changes: 2 additions & 2 deletions std/mmfile.d
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ class MmFile
struct_stat64 statbuf;
if (fstat64(fd, &statbuf))
{
//printf("\tfstat error, errno = %d\n",getErrno());
//printf("\tfstat error, errno = %d\n", errno);
.close(fd);
errnoEnforce(false, "Could not stat file "~filename);
}
Expand Down Expand Up @@ -586,7 +586,7 @@ private:
// }
// else version (linux)
// {
// throw new FileException(filename, getErrno());
// throw new FileException(filename, errno);
// }
// else
// {
Expand Down
4 changes: 2 additions & 2 deletions std/parallelism.d
Original file line number Diff line number Diff line change
Expand Up @@ -1624,7 +1624,7 @@ this() @trusted
static if(
Args.length > 1 &&
randAssignable!(Args[$ - 1]) &&
is(MapType!(Args[0], functions) : typeof(Args[$ - 1].init[0]))
is(MapType!(Args[0], functions) : ElementType!(Args[$ - 1]))
)
{
alias args[$ - 1] buf;
Expand Down Expand Up @@ -3787,7 +3787,7 @@ private struct RoundRobinBuffer(C1, C2)
// No need for constraints because they're already checked for in asyncBuf.

alias ParameterTypeTuple!(C1.init)[0] Array;
alias typeof(Array.init[0]) T;
alias ArrayTarget!Array T;

T[][] bufs;
size_t index;
Expand Down
2 changes: 1 addition & 1 deletion std/path.d
Original file line number Diff line number Diff line change
Expand Up @@ -2708,7 +2708,7 @@ string expandTilde(string inputPath)

// Obtain info from database.
passwd *verify;
setErrno(0);
errno = 0;
if (getpwnam_r(cast(char*) username.ptr, &result, cast(char*) extra_memory, extra_memory_size,
&verify) == 0)
{
Expand Down
3 changes: 2 additions & 1 deletion std/perf.d
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ writefln("Time elapsed: %s msec", elapsedMsec);

module std.perf;

pragma(msg, "std.perf has been scheduled for deprecation. "
pragma(msg, "std.perf has been deprecated. It will be removed in January 2013. " ~
"Please use std.datetime instead.");
deprecated:

version(Windows)
{
Expand Down
235 changes: 208 additions & 27 deletions std/random.d
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
// Written in the D programming language.

/**
Facilities for random number generation. The old-style functions
$(D_PARAM rand_seed) and $(D_PARAM rand) will soon be deprecated as
they rely on global state and as such are subjected to various
thread-related issues.
Facilities for random number generation.
The new-style generator objects hold their own state so they are
immune of threading issues. The generators feature a number of
Expand Down Expand Up @@ -41,10 +38,11 @@ Macros:
WIKI = Phobos/StdRandom
Copyright: Copyright Andrei Alexandrescu 2008 - 2009.
Copyright: Copyright Andrei Alexandrescu 2008 - 2009, Joseph Rushton Wakeling 2012.
License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
Authors: $(WEB erdani.org, Andrei Alexandrescu)
Masahiro Nakagawa (Xorshift randome generator)
$(WEB braingam.es, Joseph Rushton Wakeling) (Algorithm D for random sampling)
Credits: The entire random number library architecture is derived from the
excellent $(WEB open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf, C++0X)
random number facility proposed by Jens Maurer and contributed to by
Expand Down Expand Up @@ -151,8 +149,7 @@ template isUniformRNG(Rng)
/**
* Test if Rng is seedable. The overload
* taking a SeedType also makes sure that the Rng can be seeded with SeedType.
* If SeedType is not an InputRange, additionally checks that the Rng generates
* values of that type.
*
* A seedable random-number generator has the following additional features:
* $(UL
* $(LI it has a 'seed(ElementType)' function)
Expand Down Expand Up @@ -1548,11 +1545,20 @@ foreach (e; randomSample(a, 5))
writeln(e);
}
----
*/
$(D RandomSample) implements Jeffrey Scott Vitter's Algorithm D
(see Vitter $(WEB dx.doi.org/10.1145/358105.893, 1984), $(WEB
dx.doi.org/10.1145/23002.23003, 1987)), which selects a sample
of size $(D n) in O(n) steps and requiring O(n) random variates,
regardless of the size of the data being sampled.
*/
struct RandomSample(R, Random = void)
if(isInputRange!R && (isUniformRNG!Random || is(Random == void)))
{
private size_t _available, _toSelect;
private immutable ushort _alphaInverse = 13; // Vitter's recommended value.
private bool _first, _algorithmA;
private double _Vprime;
private R _input;
private size_t _index;

Expand Down Expand Up @@ -1580,9 +1586,7 @@ Constructor.
_available = total;
_toSelect = howMany;
enforce(_toSelect <= _available);
// we should skip some elements initially so we don't always
// start with the first
prime();
_first = true;
}

/**
Expand All @@ -1596,6 +1600,26 @@ Constructor.
@property auto ref front()
{
assert(!empty);
// The first sample point must be determined here to avoid
// having it always correspond to the first element of the
// input. The rest of the sample points are determined each
// time we call popFront().
if(_first)
{
// We can save ourselves a random variate by checking right
// at the beginning if we should use Algorithm A.
if((_alphaInverse * _toSelect) > _available)
{
_algorithmA = true;
}
else
{
_Vprime = newVprime(_toSelect);
_algorithmA = false;
}
prime();
_first = false;
}
return _input.front;
}

Expand Down Expand Up @@ -1631,33 +1655,190 @@ Returns the index of the visited record.
return _index;
}

private void prime()
/*
Vitter's Algorithm A, used when the ratio of needed sample values
to remaining data values is sufficiently large.
*/
private size_t skipA()
{
if (empty) return;
assert(_available && _available >= _toSelect);
for (;;)
size_t s;
double v, quot, top;

if(_toSelect==1)
{
static if(is(Random == void))
static if(is(Random==void))
{
auto r = uniform(0, _available);
s = uniform(0, _available);
}
else
{
auto r = uniform(0, _available, gen);
s = uniform(0, _available, gen);
}
}
else
{
v = 0;
top = _available - _toSelect;
quot = top / _available;

if (r < _toSelect)
static if(is(Random==void))
{
// chosen!
return;
v = uniform!"()"(0.0, 1.0);
}
else
{
v = uniform!"()"(0.0, 1.0, gen);
}

while (quot > v)
{
++s;
quot *= (top - s) / (_available - s);
}
// not chosen, retry
assert(!_input.empty);
_input.popFront();
++_index;
--_available;
assert(_available > 0);
}

return s;
}

/*
Randomly reset the value of _Vprime.
*/
private double newVprime(size_t remaining)
{
static if(is(Random == void))
{
double r = uniform!"()"(0.0, 1.0);
}
else
{
double r = uniform!"()"(0.0, 1.0, gen);
}

return r ^^ (1.0 / remaining);
}

/*
Vitter's Algorithm D. For an extensive description of the algorithm
and its rationale, see:
* Vitter, J.S. (1984), "Faster methods for random sampling",
Commun. ACM 27(7): 703--718
* Vitter, J.S. (1987) "An efficient algorithm for sequential random
sampling", ACM Trans. Math. Softw. 13(1): 58-67.
Variable names are chosen to match those in Vitter's paper.
*/
private size_t skip()
{
// Step D1: if the number of points still to select is greater
// than a certain proportion of the remaining data points, i.e.
// if n >= alpha * N where alpha = 1/13, we carry out the
// sampling with Algorithm A.
if(_algorithmA)
{
return skipA();
}
else if((_alphaInverse * _toSelect) > _available)
{
_algorithmA = true;
return skipA();
}
// Otherwise, we use the standard Algorithm D mechanism.
else if ( _toSelect > 1 )
{
size_t s;
size_t qu1 = 1 + _available - _toSelect;
double x, y1;

while(true)
{
// Step D2: set values of x and u.
for(x = _available * (1-_Vprime), s = cast(size_t) trunc(x);
s >= qu1;
x = _available * (1-_Vprime), s = cast(size_t) trunc(x))
{
_Vprime = newVprime(_toSelect);
}

static if(is(Random == void))
{
double u = uniform!"()"(0.0, 1.0);
}
else
{
double u = uniform!"()"(0.0, 1.0, gen);
}

y1 = (u * (cast(double) _available) / qu1) ^^ (1.0/(_toSelect - 1));

_Vprime = y1 * ((-x/_available)+1.0) * ( qu1/( (cast(double) qu1) - s ) );

// Step D3: if _Vprime <= 1.0 our work is done and we return S.
// Otherwise ...
if(_Vprime > 1.0)
{
size_t top = _available - 1, limit;
double y2 = 1.0, bottom;

if(_toSelect > (s+1) )
{
bottom = _available - _toSelect;
limit = _available - s;
}
else
{
bottom = _available - (s+1);
limit = qu1;
}

foreach(size_t t; limit.._available)
{
y2 *= top/bottom;
top--;
bottom--;
}

// Step D4: decide whether or not to accept the current value of S.
if( (_available/(_available-x)) < (y1 * (y2 ^^ (1.0/(_toSelect-1)))) )
{
// If it's not acceptable, we generate a new value of _Vprime
// and go back to the start of the for(;;) loop.
_Vprime = newVprime(_toSelect);
}
else
{
// If it's acceptable we generate a new value of _Vprime
// based on the remaining number of sample points needed,
// and return S.
_Vprime = newVprime(_toSelect-1);
return s;
}
}
else
{
// Return if condition D3 satisfied.
return s;
}
}
}
else
{
// If only one sample point remains to be taken ...
return cast(size_t) trunc(_available * _Vprime);
}
}

private void prime()
{
if (empty) return;
assert(_available && _available >= _toSelect);
immutable size_t s = skip();
_input.popFrontN(s);
_index += s;
_available -= s;
assert(_available > 0);
return;
}
}

Expand Down
828 changes: 813 additions & 15 deletions std/range.d

Large diffs are not rendered by default.

221 changes: 203 additions & 18 deletions std/signals.d
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* $(LINK2 http://www.digitalmars.com/d/archives/28456.html, Signal/Slot mechanism?)$(BR)
* $(LINK2 http://www.digitalmars.com/d/archives/19470.html, Modern Features?)$(BR)
* $(LINK2 http://www.digitalmars.com/d/archives/16592.html, Delegates vs interfaces)$(BR)
* $(LINK2 http://www.digitalmars.com/d/archives/16583.html, The importance of component programming (properties, signals and slots, etc))$(BR)
* $(LINK2 http://www.digitalmars.com/d/archives/16583.html, The importance of component programming (properties$(COMMA) signals and slots$(COMMA) etc))$(BR)
* $(LINK2 http://www.digitalmars.com/d/archives/16368.html, signals and slots)$(BR)
*
* Bugs:
Expand Down Expand Up @@ -127,7 +127,7 @@ void main()
a.value = 5; // so should not call o.watch()
a.connect(&o.watch); // connect again
a.value = 6; // should call o.watch()
delete o; // destroying o should automatically disconnect it
destroy(o); // destroying o should automatically disconnect it
a.value = 7; // should not call o.watch()
}
---
Expand All @@ -139,7 +139,7 @@ void main()
*
*/

template Signal(T1...)
mixin template Signal(T1...)
{
static import std.c.stdlib;
static import core.exception;
Expand All @@ -156,7 +156,7 @@ template Signal(T1...)
/***
* Call each of the connected slots, passing the argument(s) i to them.
*/
void emit( T1 i )
final void emit( T1 i )
{
foreach (slot; slots[0 .. slots_idx])
{ if (slot)
Expand All @@ -167,7 +167,7 @@ template Signal(T1...)
/***
* Add a slot to the list of slots to be called when emit() is called.
*/
void connect(slot_t slot)
final void connect(slot_t slot)
{
/* Do this:
* slots ~= slot;
Expand Down Expand Up @@ -204,7 +204,7 @@ template Signal(T1...)
/***
* Remove a slot from the list of slots to be called when emit() is called.
*/
void disconnect( slot_t slot)
final void disconnect(slot_t slot)
{
debug (signal) writefln("Signal.disconnect(slot)");
for (size_t i = 0; i < slots_idx; )
Expand All @@ -227,7 +227,7 @@ template Signal(T1...)
* It causes any slots dependent on o to be removed from the list
* of slots to be called by emit().
*/
void unhook(Object o)
final void unhook(Object o)
{
debug (signal) writefln("Signal.unhook(o = %s)", cast(void*)o);
for (size_t i = 0; i < slots_idx; )
Expand Down Expand Up @@ -286,15 +286,8 @@ unittest
captured_msg = msg;
}

void clear()
{
captured_value = 0;
captured_msg = "";
}

public:
int captured_value;
string captured_msg;
int captured_value;
string captured_msg;
}

class Foo
Expand Down Expand Up @@ -346,8 +339,200 @@ unittest
assert(o.captured_value == 6);
assert(o.captured_msg == "setting new value");

// delete the underlying object and make sure it doesn't cause
// destroy the underlying object and make sure it doesn't cause
// a crash or other problems
delete o;
destroy(o);
a.value = 7;
}

unittest {
class Observer
{
int i;
long l;
string str;

void watchInt(string str, int i)
{
this.str = str;
this.i = i;
}

void watchLong(string str, long l)
{
this.str = str;
this.l = l;
}
}

class Bar
{
@property void value1(int v) { s1.emit("str1", v); }
@property void value2(int v) { s2.emit("str2", v); }
@property void value3(long v) { s3.emit("str3", v); }

mixin Signal!(string, int) s1;
mixin Signal!(string, int) s2;
mixin Signal!(string, long) s3;
}

void test(T)(T a) {
auto o1 = new Observer;
auto o2 = new Observer;
auto o3 = new Observer;

// connect the watcher and trigger it
a.s1.connect(&o1.watchInt);
a.s2.connect(&o2.watchInt);
a.s3.connect(&o3.watchLong);

assert(!o1.i && !o1.l && !o1.str);
assert(!o2.i && !o2.l && !o2.str);
assert(!o3.i && !o3.l && !o3.str);

a.value1 = 11;
assert(o1.i == 11 && !o1.l && o1.str == "str1");
assert(!o2.i && !o2.l && !o2.str);
assert(!o3.i && !o3.l && !o3.str);
o1.i = -11; o1.str = "x1";

a.value2 = 12;
assert(o1.i == -11 && !o1.l && o1.str == "x1");
assert(o2.i == 12 && !o2.l && o2.str == "str2");
assert(!o3.i && !o3.l && !o3.str);
o2.i = -12; o2.str = "x2";

a.value3 = 13;
assert(o1.i == -11 && !o1.l && o1.str == "x1");
assert(o2.i == -12 && !o1.l && o2.str == "x2");
assert(!o3.i && o3.l == 13 && o3.str == "str3");
o3.l = -13; o3.str = "x3";

// disconnect the watchers and make sure it doesn't trigger
a.s1.disconnect(&o1.watchInt);
a.s2.disconnect(&o2.watchInt);
a.s3.disconnect(&o3.watchLong);

a.value1 = 21;
a.value2 = 22;
a.value3 = 23;
assert(o1.i == -11 && !o1.l && o1.str == "x1");
assert(o2.i == -12 && !o1.l && o2.str == "x2");
assert(!o3.i && o3.l == -13 && o3.str == "x3");

// reconnect the watcher and make sure it triggers
a.s1.connect(&o1.watchInt);
a.s2.connect(&o2.watchInt);
a.s3.connect(&o3.watchLong);

a.value1 = 31;
a.value2 = 32;
a.value3 = 33;
assert(o1.i == 31 && !o1.l && o1.str == "str1");
assert(o2.i == 32 && !o1.l && o2.str == "str2");
assert(!o3.i && o3.l == 33 && o3.str == "str3");

// destroy observers
destroy(o1);
destroy(o2);
destroy(o3);
a.value1 = 41;
a.value2 = 42;
a.value3 = 43;
}

test(new Bar);

class BarDerived: Bar
{
@property void value4(int v) { s4.emit("str4", v); }
@property void value5(int v) { s5.emit("str5", v); }
@property void value6(long v) { s6.emit("str6", v); }

mixin Signal!(string, int) s4;
mixin Signal!(string, int) s5;
mixin Signal!(string, long) s6;
}

auto a = new BarDerived;

test!Bar(a);
test!BarDerived(a);

auto o4 = new Observer;
auto o5 = new Observer;
auto o6 = new Observer;

// connect the watcher and trigger it
a.s4.connect(&o4.watchInt);
a.s5.connect(&o5.watchInt);
a.s6.connect(&o6.watchLong);

assert(!o4.i && !o4.l && !o4.str);
assert(!o5.i && !o5.l && !o5.str);
assert(!o6.i && !o6.l && !o6.str);

a.value4 = 44;
assert(o4.i == 44 && !o4.l && o4.str == "str4");
assert(!o5.i && !o5.l && !o5.str);
assert(!o6.i && !o6.l && !o6.str);
o4.i = -44; o4.str = "x4";

a.value5 = 45;
assert(o4.i == -44 && !o4.l && o4.str == "x4");
assert(o5.i == 45 && !o5.l && o5.str == "str5");
assert(!o6.i && !o6.l && !o6.str);
o5.i = -45; o5.str = "x5";

a.value6 = 46;
assert(o4.i == -44 && !o4.l && o4.str == "x4");
assert(o5.i == -45 && !o4.l && o5.str == "x5");
assert(!o6.i && o6.l == 46 && o6.str == "str6");
o6.l = -46; o6.str = "x6";

// disconnect the watchers and make sure it doesn't trigger
a.s4.disconnect(&o4.watchInt);
a.s5.disconnect(&o5.watchInt);
a.s6.disconnect(&o6.watchLong);

a.value4 = 54;
a.value5 = 55;
a.value6 = 56;
assert(o4.i == -44 && !o4.l && o4.str == "x4");
assert(o5.i == -45 && !o4.l && o5.str == "x5");
assert(!o6.i && o6.l == -46 && o6.str == "x6");

// reconnect the watcher and make sure it triggers
a.s4.connect(&o4.watchInt);
a.s5.connect(&o5.watchInt);
a.s6.connect(&o6.watchLong);

a.value4 = 64;
a.value5 = 65;
a.value6 = 66;
assert(o4.i == 64 && !o4.l && o4.str == "str4");
assert(o5.i == 65 && !o4.l && o5.str == "str5");
assert(!o6.i && o6.l == 66 && o6.str == "str6");

// destroy observers
destroy(o4);
destroy(o5);
destroy(o6);
a.value4 = 44;
a.value5 = 45;
a.value6 = 46;
}

version(none) // Disabled because of dmd @@@BUG5028@@@
unittest
{
class A
{
mixin Signal!(string, int) s1;
}

class B : A
{
mixin Signal!(string, int) s2;
}
}
34 changes: 13 additions & 21 deletions std/socket.d
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,12 @@ version(unittest)
class SocketException: Exception
{
/**
* $(RED Scheduled for deprecation. Please use $(D SocketOSException)
* instead.)
* $(RED Deprecated. It will be removed in January 2013.
* Please use $(LREF SocketOSException) instead.)
*
* Provided for compatibility with older code using $(D SocketException).
*/
@property int errorCode() const
deprecated @property int errorCode() const
{
auto osException = cast(SocketOSException)this;
if (osException)
Expand Down Expand Up @@ -1904,18 +1904,14 @@ struct TimeVal
// D interface
mixin FieldProxy!(`ctimeval.tv_sec`, `seconds`);
mixin FieldProxy!(`ctimeval.tv_usec`, `microseconds`);

// C interface
deprecated
{
alias seconds tv_sec;
alias microseconds tv_usec;
}
}
}

/// $(RED Scheduled for deprecation. Please use $(D TimeVal) instead.)
alias TimeVal timeval;
/++
$(RED Deprecated. It will be removed in January 2013.
Please use $(LREF TimeVal) instead.)
+/
deprecated alias TimeVal timeval;


/**
Expand Down Expand Up @@ -2139,18 +2135,14 @@ struct Linger
// D interface
mixin FieldProxy!(`clinger.l_onoff`, `on`);
mixin FieldProxy!(`clinger.l_linger`, `time`);

// C interface
deprecated
{
alias on l_onoff;
alias time l_linger;
}
}
}

/// $(RED Scheduled for deprecation. Please use $(D Linger) instead.)
alias Linger linger;
/++
$(RED Deprecated. It will be removed in January 2013.
Please use $(LREF Linger) instead.)
+/
deprecated alias Linger linger;

/// Specifies a socket option:
enum SocketOption: int
Expand Down
12 changes: 6 additions & 6 deletions std/stdio.d
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Authors: $(WEB digitalmars.com, Walter Bright),
*/
module std.stdio;

public import core.stdc.stdio;
public import core.stdc.stdio, std.string : KeepTerminator;
static import std.c.stdio;
import std.stdiobase;
import core.stdc.errno, core.stdc.stddef, core.stdc.stdlib, core.memory,
Expand Down Expand Up @@ -786,7 +786,7 @@ by $(D buf), whereas $(D buf = stdin.readln()) makes a new memory allocation
with every line. */
S readln(S = string)(dchar terminator = '\n')
{
Unqual!(typeof(S.init[0]))[] buf;
Unqual!(ElementEncodingType!S)[] buf;
readln(buf, terminator);
return assumeUnique(buf);
}
Expand Down Expand Up @@ -942,7 +942,6 @@ Returns the file number corresponding to this object.

/**
Range that reads one line at a time. */
alias std.string.KeepTerminator KeepTerminator;
/// ditto
struct ByLine(Char, Terminator)
{
Expand Down Expand Up @@ -1528,7 +1527,8 @@ unittest
}

/**
* $(RED Scheduled for deprecation. Please use $(D isFileHandle) instead.)
* $(RED Scheduled for deprecation in January 2013.
* Please use $(D isFileHandle) instead.)
*/
alias isFileHandle isStreamingDevice;

Expand Down Expand Up @@ -2262,7 +2262,7 @@ class StdioException : Exception

/**
Initialize with a message and an error code. */
this(string message, uint e = .getErrno())
this(string message, uint e = .errno)
{
errno = e;
version (Posix)
Expand Down Expand Up @@ -2295,7 +2295,7 @@ Initialize with a message and an error code. */
/// ditto
static void opCall()
{
throw new StdioException(null, .getErrno());
throw new StdioException(null, .errno);
}
}

Expand Down
18 changes: 9 additions & 9 deletions std/stream.d
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ interface OutputStream {

// not really abstract, but its instances will do nothing useful
class Stream : InputStream, OutputStream {
private import std.string, std.hash.crc32, std.c.stdlib, std.c.stdio;
private import std.string, crc32, std.c.stdlib, std.c.stdio;

// stream abilities
bool readable = false; /// Indicates whether this stream can be read from.
Expand Down Expand Up @@ -1300,7 +1300,7 @@ class Stream : InputStream, OutputStream {
* If the stream is not seekable the contents from the current position to eof
* is read and returned.
*/
override string toString() {
override string toString() const { with (cast(Stream)this) {
if (!readable)
return super.toString();
try
Expand Down Expand Up @@ -1335,35 +1335,35 @@ class Stream : InputStream, OutputStream {
{
return super.toString();
}
}
} }

/***
* Get a hash of the stream by reading each byte and using it in a CRC-32
* checksum.
*/
override size_t toHash() @trusted {
override size_t toHash() @trusted const { with (cast(Stream)this) {
if (!readable || !seekable)
return super.toHash();
try
{
ulong pos = position;
scope(exit) position(pos);
uint crc = crc32Init;
uint crc = init_crc32();
position(0);
ulong len = size;
for (ulong i = 0; i < len; i++)
{
ubyte c;
read(c);
crc = updateCRC32(crc, c);
crc = update_crc32(c, crc);
}
return crc;
}
catch (Throwable)
{
return super.toHash();
}
}
} }

// helper for checking that the stream is readable
final protected void assertReadable() {
Expand Down Expand Up @@ -2605,10 +2605,10 @@ class TArrayStream(Buffer): Stream {
return cast(ubyte[])res;
}

override string toString() {
override string toString() const { with (cast(TArrayStream!Buffer)this) {
// assume data is UTF8
return to!(string)(cast(char[])data);
}
} }
}

/* Test the TArrayStream */
Expand Down
453 changes: 361 additions & 92 deletions std/string.d

Large diffs are not rendered by default.

229 changes: 220 additions & 9 deletions std/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,167 @@ unittest
}


/*
Get, as a tuple, the identifiers of the parameters to a function symbol.

Example:
---
import std.traits;
int foo(int num, string name);
static assert([ParameterIdentifierTuple!foo] == ["num", "name"]);
---
*/
template ParameterIdentifierTuple(func...)
if (func.length == 1 && isCallable!func)
{
static if (is(typeof(func[0]) PT == __parameters))
{
template Get(size_t i)
{
enum get = (PT[i..i+1] args) => __traits(identifier, args[0]);
enum Get = get(PT[i].init);
}
}
else static if (is(FunctionTypeOf!func PT == __parameters))
{
template Get(size_t i)
{
enum Get = "";
}
}
else
static assert(0, func[0].stringof ~ "is not a function");

template Impl(size_t i = 0)
{
static if (i == PT.length)
alias TypeTuple!() Impl;
else
alias TypeTuple!(Get!(i), Impl!(i+1)) Impl;
}

alias Impl!() ParameterIdentifierTuple;
}

unittest
{
// Test for ddoc example
import std.traits;
int foo(int num, string name);
static assert([ParameterIdentifierTuple!foo] == ["num", "name"]);
}
unittest
{
alias ParameterIdentifierTuple PIT;

void bar(int num, string name, int[] array){}
static assert([PIT!bar] == ["num", "name", "array"]);

// might be changed in the future?
void function(int num, string name) fp;
static assert([PIT!fp] == ["", ""]);

// might be changed in the future?
void delegate(int num, string name, int[long] aa) dg;
static assert([PIT!dg] == ["", "", ""]);
/+
// depends on internal
void baw(int, string, int[]){}
static assert([PIT!baw] == ["_param_0", "_param_1", "_param_2"]);

// depends on internal
void baz(TypeTuple!(int, string, int[]) args){}
static assert([PIT!baz] == ["_param_0", "_param_1", "_param_2"]);
+/
}


/*
Get, as a tuple, the default value of the parameters to a function symbol.
If a parameter doesn't have the default value, $(D void) is returned instead.

Example:
---
import std.traits;
int foo(int num, string name = "hello", int[] arr = [1,2,3]);
static assert(is(ParameterDefaultValueTuple!foo[0] == void));
static assert( ParameterDefaultValueTuple!foo[1] == "hello");
static assert( ParameterDefaultValueTuple!foo[2] == [1,2,3]);
---
*/
template ParameterDefaultValueTuple(func...)
if (func.length == 1 && isCallable!func)
{
static if (is(typeof(func[0]) PT == __parameters))
{
template Get(size_t i)
{
enum get = (PT[i..i+1] args) => args[0];
static if (is(typeof(get())))
enum Get = get();
else
alias void Get;
// If default arg doesn't exist, returns void instead.
}
}
else static if (is(FunctionTypeOf!func PT == __parameters))
{
template Get(size_t i)
{
enum Get = "";
}
}
else
static assert(0, func[0].stringof ~ "is not a function");

template Impl(size_t i = 0)
{
static if (i == PT.length)
alias TypeTuple!() Impl;
else
alias TypeTuple!(Get!(i), Impl!(i+1)) Impl;
}

alias Impl!() ParameterDefaultValueTuple;
}

unittest
{
// Test for ddoc example
int foo(int num, string name = "hello", int[] arr = [1,2,3]);
static assert(is(ParameterDefaultValueTuple!foo[0] == void));
static assert( ParameterDefaultValueTuple!foo[1] == "hello");
static assert( ParameterDefaultValueTuple!foo[2] == [1,2,3]);
}
unittest
{
alias ParameterDefaultValueTuple PDVT;

void bar(int n = 1, string s = "hello"){}
static assert(PDVT!bar.length == 2);
static assert(PDVT!bar[0] == 1);
static assert(PDVT!bar[1] == "hello");
static assert(is(typeof(PDVT!bar) == typeof(TypeTuple!(1, "hello"))));

void baz(int x, int n = 1, string s = "hello"){}
static assert(PDVT!baz.length == 3);
static assert(is(PDVT!baz[0] == void));
static assert( PDVT!baz[1] == 1);
static assert( PDVT!baz[2] == "hello");
static assert(is(typeof(PDVT!baz) == typeof(TypeTuple!(void, 1, "hello"))));

struct Colour
{
ubyte a,r,g,b;

immutable Colour white = Colour(255,255,255,255);
}
void bug8106(Colour c = Colour.white){}
//pragma(msg, PDVT!bug8106);
static assert(PDVT!bug8106[0] == Colour.white);
}


/**
Returns the attributes attached to a function $(D func).

Expand Down Expand Up @@ -1631,7 +1792,7 @@ template hasIndirections(T)
enum Impl = true;
else
enum Impl = Impl!(T[1 .. $]) ||
Impl!(RepresentationTypeTuple!(typeof(T[0].init[0])));
Impl!(RepresentationTypeTuple!(ArrayTarget!(T[0])));
}
else
{
Expand Down Expand Up @@ -1822,9 +1983,8 @@ unittest

struct S4
{
void opAssign(U)(auto ref U u)
if (!__traits(isRef, u))
{}
void opAssign(U)(U u) {}
@disable void opAssign(U)(ref U u);
}
static assert( hasElaborateAssign!S4);
}
Expand Down Expand Up @@ -1873,6 +2033,8 @@ unittest
static assert(!hasElaborateDestructor!S6);
}

template Identity(alias A) { alias A Identity; }

/**
Yields $(D true) if and only if $(D T) is an aggregate that defines
a symbol called $(D name).
Expand All @@ -1882,7 +2044,8 @@ template hasMember(T, string name)
static if (is(T == struct) || is(T == class) || is(T == union) || is(T == interface))
{
enum bool hasMember =
staticIndexOf!(name, __traits(allMembers, T)) != -1;
staticIndexOf!(name, __traits(allMembers, T)) != -1 ||
__traits(compiles, { mixin("alias Identity!(T."~name~") Sym;"); });
}
else
{
Expand All @@ -1908,6 +2071,38 @@ unittest
static assert(isOutputRange!(OutputRange!int, int));
}

// Temporarily disabled until bug4617 is fixed.
version(none) unittest
{
// 8231
struct S {
int x;
void f(){}
void t()(){}
template T(){}
}
struct R1(T) {
T t;
alias t this;
}
struct R2(T) {
T t;
@property ref inout(T) payload() inout { return t; }
alias t this;
}
static assert(hasMember!(S, "x"));
static assert(hasMember!(S, "f"));
static assert(hasMember!(S, "t"));
static assert(hasMember!(S, "T"));
static assert(hasMember!(R1!S, "x"));
static assert(hasMember!(R1!S, "f"));
static assert(hasMember!(R1!S, "t"));
static assert(hasMember!(R1!S, "T"));
static assert(hasMember!(R2!S, "x"));
static assert(hasMember!(R2!S, "f"));
static assert(hasMember!(R2!S, "t"));
static assert(hasMember!(R2!S, "T"));
}

/**
Retrieves the members of an enumerated type $(D enum E).
Expand Down Expand Up @@ -2552,12 +2747,12 @@ template ImplicitConversionTargets(T)
else static if(is(T : Object))
alias TransitiveBaseTypeTuple!(T) ImplicitConversionTargets;
// @@@BUG@@@ this should work
// else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
// alias TypeTuple!(const(typeof(T.init[0]))[]) ImplicitConversionTargets;
// else static if (isDynamicArray!T && !is(ArrayTarget!T == const))
// alias TypeTuple!(const(ArrayTarget!T)[]) ImplicitConversionTargets;
else static if (is(T == char[]))
alias TypeTuple!(const(char)[]) ImplicitConversionTargets;
else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
alias TypeTuple!(const(typeof(T.init[0]))[]) ImplicitConversionTargets;
else static if (isDynamicArray!T && !is(ArrayTarget!T == const))
alias TypeTuple!(const(ArrayTarget!T)[]) ImplicitConversionTargets;
else static if (is(T : void*))
alias TypeTuple!(void*) ImplicitConversionTargets;
else
Expand Down Expand Up @@ -3599,6 +3794,22 @@ unittest
static assert(!isArray!(typeof(null)));
}

/**
Returns the target type of an array.
*/
template ArrayTarget(T : T[])
{
alias T ArrayTarget;
}

unittest
{
static assert( is(ArrayTarget!(int[]) == int));
static assert( is(ArrayTarget!(long[0]) == long));

static assert(!is(ArrayTarget!int));
}

/**
* Detect whether T is an associative array type
*/
Expand Down
153 changes: 3 additions & 150 deletions std/typecons.d
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,9 @@ public:

// This mitigates breakage of old code now that std.range.Zip uses
// Tuple instead of the old Proxy. It's intentionally lacking ddoc
// because it should eventually be deprecated.
auto at(size_t index)() {
// because it was intended for deprecation.
// Now that it has been deprecated, it will be removed in January 2013.
deprecated auto at(size_t index)() {
return field[index];
}

Expand Down Expand Up @@ -452,11 +453,6 @@ public:
}
}

deprecated void assign(R)(R rhs) if (isTuple!R)
{
this = rhs;
}

// @@@BUG4424@@@ workaround
private mixin template _workaround4424()
{
Expand Down Expand Up @@ -724,149 +720,6 @@ unittest
}


/**
Defines truly named enumerated values with parsing and stringizing
primitives.

Example:

----
mixin(defineEnum!("Abc", "A", "B", 5, "C"));
----

is equivalent to the following code:

----
enum Abc { A, B = 5, C }
string enumToString(Abc v) { ... }
Abc enumFromString(string s) { ... }
----

The $(D enumToString) function generates the unqualified names
of the enumerated values, i.e. "A", "B", and "C". The $(D
enumFromString) function expects one of "A", "B", and "C", and throws
an exception in any other case.

A base type can be specified for the enumeration like this:

----
mixin(defineEnum!("Abc", ubyte, "A", "B", "C", 255));
----

In this case the generated $(D enum) will have a $(D ubyte)
representation. */

deprecated template defineEnum(string name, T...)
{
static if (is(typeof(cast(T[0]) T[0].init)))
{
template enumValuesImpl(string name, BaseType, long index, T...)
{
static if (name.length)
{
enum string enumValuesImpl = "enum "~name~" : "~BaseType.stringof
~" { "~enumValuesImpl!("", BaseType, index, T)~"}\n";
}
else
{
static if (!T.length)
{
enum string enumValuesImpl = "";
}
else
{
static if (T.length == 1
|| T.length > 1 && is(typeof(T[1]) : string))
{
enum string enumValuesImpl = T[0]~" = "~ToString!(index)~", "
~enumValuesImpl!("", BaseType, index + 1, T[1 .. $]);
}
else
{
enum string enumValuesImpl = T[0]~" = "~ToString!(T[1])~", "
~enumValuesImpl!("", BaseType, T[1] + 1, T[2 .. $]);
}
}
}
}

template enumParserImpl(string name, bool first, T...)
{
static if (first)
{
enum string enumParserImpl = "bool enumFromString(string s, ref "
~name~" v) {\n"
~enumParserImpl!(name, false, T)
~"return false;\n}\n";
}
else
{
static if (T.length)
enum string enumParserImpl =
"if (s == `"~T[0]~"`) return (v = "~name~"."~T[0]~"), true;\n"
~enumParserImpl!(name, false, T[1 .. $]);
else
enum string enumParserImpl = "";
}
}

template enumPrinterImpl(string name, bool first, T...)
{
static if (first)
{
enum string enumPrinterImpl = "string enumToString("~name~" v) {\n"
~enumPrinterImpl!(name, false, T)~"\n}\n";
}
else
{
static if (T.length)
enum string enumPrinterImpl =
"if (v == "~name~"."~T[0]~") return `"~T[0]~"`;\n"
~enumPrinterImpl!(name, false, T[1 .. $]);
else
enum string enumPrinterImpl = "return null;";
}
}

template StringsOnly(T...)
{
template ValueTuple(T...)
{
alias T ValueTuple;
}

static if (T.length == 1)
static if (is(typeof(T[0]) : string))
alias ValueTuple!(T[0]) StringsOnly;
else
alias ValueTuple!() StringsOnly;
else
static if (is(typeof(T[0]) : string))
alias ValueTuple!(T[0], StringsOnly!(T[1 .. $])) StringsOnly;
else
alias ValueTuple!(StringsOnly!(T[1 .. $])) StringsOnly;
}

enum string defineEnum =
enumValuesImpl!(name, T[0], 0, T[1 .. $])
~ enumParserImpl!(name, true, StringsOnly!(T[1 .. $]))
~ enumPrinterImpl!(name, true, StringsOnly!(T[1 .. $]));
}
else
alias defineEnum!(name, int, T) defineEnum;
}

deprecated unittest
{
mixin(defineEnum!("_24b455e148a38a847d65006bca25f7fe",
"A1", 1, "B1", "C1"));
auto a = _24b455e148a38a847d65006bca25f7fe.A1;
assert(enumToString(a) == "A1");
_24b455e148a38a847d65006bca25f7fe b;
assert(enumFromString("B1", b)
&& b == _24b455e148a38a847d65006bca25f7fe.B1);
}

/**
$(D Rebindable!(T)) is a simple, efficient wrapper that behaves just
like an object of type $(D T), except that you can reassign it to
Expand Down
91 changes: 88 additions & 3 deletions std/utf.d
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ class UTFException : Exception


/++
$(RED Scheduled for deprecation in December 2012.
$(RED Deprecated. It will be removed in January 2013.
Please use $(LREF UTFException) instead.)
+/
alias UTFException UtfException;
deprecated alias UTFException UtfException;


/++
Expand Down Expand Up @@ -1129,6 +1129,7 @@ assert(codeLength!dchar('\U0010FFFF') == 1);
------
+/
ubyte codeLength(C)(dchar c) @safe pure nothrow
if(isSomeChar!C)
{
static if (C.sizeof == 1)
{
Expand Down Expand Up @@ -1163,6 +1164,90 @@ unittest
}


/++
Returns the number of code units that are required to encode $(D str)
in a string whose character type is $(D C). This is particularly useful
when slicing one string with the length of another and the two string
types use different character types.

Examples:
------
assert(codeLength!char("hello world") ==
to!string("hello world").length);
assert(codeLength!wchar("hello world") ==
to!wstring("hello world").length);
assert(codeLength!dchar("hello world") ==
to!dstring("hello world").length);

assert(codeLength!char(`プログラミング`) ==
to!string(`プログラミング`).length);
assert(codeLength!wchar(`プログラミング`) ==
to!wstring(`プログラミング`).length);
assert(codeLength!dchar(`プログラミング`) ==
to!dstring(`プログラミング`).length);

string haystack = `Être sans la verité, ça, ce ne serait pas bien.`;
wstring needle = `Être sans la verité`;
assert(haystack[codeLength!char(needle) .. $] ==
`, ça, ce ne serait pas bien.`);
------
+/
size_t codeLength(C1, C2)(C2[] str) @safe pure
if(isSomeChar!C1 && isSomeChar!C2)
{
static if(is(Unqual!C1 == Unqual!C2))
return str.length;
else
{
size_t total = 0;

foreach(dchar c; str)
total += codeLength!C1(c);

return total;
}
}

//Verify Examples.
unittest
{
assert(codeLength!char("hello world") ==
to!string("hello world").length);
assert(codeLength!wchar("hello world") ==
to!wstring("hello world").length);
assert(codeLength!dchar("hello world") ==
to!dstring("hello world").length);

assert(codeLength!char(`プログラミング`) ==
to!string(`プログラミング`).length);
assert(codeLength!wchar(`プログラミング`) ==
to!wstring(`プログラミング`).length);
assert(codeLength!dchar(`プログラミング`) ==
to!dstring(`プログラミング`).length);

string haystack = `Être sans la verité, ça, ce ne serait pas bien.`;
wstring needle = `Être sans la verité`;
assert(haystack[codeLength!char(needle) .. $] ==
`, ça, ce ne serait pas bien.`);
}

unittest
{
foreach(S; TypeTuple!(char[], const char[], string,
wchar[], const wchar[], wstring,
dchar[], const dchar[], dstring))
{
foreach(C; TypeTuple!(char, wchar, dchar))
{
assert(codeLength!C(to!S("Walter Bright")) == to!(C[])("Walter Bright").length);
assert(codeLength!C(to!S(`言語`)) == to!(C[])(`言語`).length);
assert(codeLength!C(to!S(`ウェブサイト@La_Verité.com`)) ==
to!(C[])(`ウェブサイト@La_Verité.com`).length);
}
}
}


/* =================== Validation ======================= */

/++
Expand Down Expand Up @@ -1604,7 +1689,7 @@ unittest

foreach(S; TypeTuple!(string, wstring, dstring))
{
alias Unqual!(typeof(S.init[0])) C;
alias Unqual!(ElementEncodingType!S) C;

auto s1 = to!S("hello\U00010143\u0100\U00010143");
auto temp = new C[](s1.length + 1);
Expand Down
1,581 changes: 1,581 additions & 0 deletions std/uuid.d

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion std/variant.d
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ private:
{
enforce(0, "Not implemented");
}
static if (isDynamicArray!(A) && allowed!(typeof(A.init[0])))
static if (isDynamicArray!(A) && allowed!(ArrayTarget!A))
{
// array type; input and output are the same VariantN
auto result = cast(VariantN*) parm;
Expand Down
52 changes: 26 additions & 26 deletions std/xml.d
Original file line number Diff line number Diff line change
Expand Up @@ -593,12 +593,12 @@ class Document : Element
* if (d1 == d2) { }
* --------------
*/
override bool opEquals(Object o)
override bool opEquals(const Object o)
{
const doc = toType!(const Document)(o);
return
(prolog != doc.prolog ) ? false : (
(cast()super != cast()cast(const Element)doc) ? false : (
(super != cast(const Element)doc) ? false : (
(epilog != doc.epilog ) ? false : (
true )));
}
Expand All @@ -615,14 +615,14 @@ class Document : Element
* if (d1 < d2) { }
* --------------
*/
override int opCmp(Object o)
override int opCmp(const Object o)
{
const doc = toType!(const Document)(o);
return
((prolog != doc.prolog )
? ( prolog < doc.prolog ? -1 : 1 ) :
((cast()super != cast()cast(const Element)doc)
? ( cast()super < cast()cast(const Element)doc ? -1 : 1 ) :
((super != cast(const Element)doc)
? ( super < cast(const Element)doc ? -1 : 1 ) :
((epilog != doc.epilog )
? ( epilog < doc.epilog ? -1 : 1 ) :
0 )));
Expand All @@ -636,7 +636,7 @@ class Document : Element
*/
override hash_t toHash() @trusted
{
return hash(prolog, hash(epilog, (cast()super).toHash()));
return hash(prolog, hash(epilog, super.toHash()));
}

/**
Expand Down Expand Up @@ -824,14 +824,14 @@ class Element : Item
* if (e1 == e2) { }
* --------------
*/
override bool opEquals(Object o)
override bool opEquals(const Object o)
{
const element = toType!(const Element)(o);
auto len = items.length;
if (len != element.items.length) return false;
foreach (i; 0 .. len)
{
if (!items[i].opEquals(cast()element.items[i])) return false;
if (!items[i].opEquals(element.items[i])) return false;
}
return true;
}
Expand All @@ -848,16 +848,16 @@ class Element : Item
* if (e1 < e2) { }
* --------------
*/
override int opCmp(Object o)
override int opCmp(const Object o)
{
const element = toType!(const Element)(o);
for (uint i=0; ; ++i)
{
if (i == items.length && i == element.items.length) return 0;
if (i == items.length) return -1;
if (i == element.items.length) return 1;
if (items[i] != cast()element.items[i])
return items[i].opCmp(cast()element.items[i]);
if (items[i] != element.items[i])
return items[i].opCmp(element.items[i]);
}
}

Expand Down Expand Up @@ -1091,7 +1091,7 @@ class Tag
* if (tag1 == tag2) { }
* --------------
*/
override bool opEquals(Object o)
override bool opEquals(const Object o)
{
const tag = toType!(const Tag)(o);
return
Expand All @@ -1110,7 +1110,7 @@ class Tag
* if (tag1 < tag2) { }
* --------------
*/
override int opCmp(Object o)
override int opCmp(const Object o)
{
const tag = toType!(const Tag)(o);
return
Expand Down Expand Up @@ -1233,7 +1233,7 @@ class Comment : Item
* if (item1 == item2) { }
* --------------
*/
override bool opEquals(Object o)
override bool opEquals(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(Comment)item;
Expand All @@ -1252,7 +1252,7 @@ class Comment : Item
* if (item1 < item2) { }
* --------------
*/
override int opCmp(Object o)
override int opCmp(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(Comment)item;
Expand Down Expand Up @@ -1312,7 +1312,7 @@ class CData : Item
* if (item1 == item2) { }
* --------------
*/
override bool opEquals(Object o)
override bool opEquals(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(CData)item;
Expand All @@ -1331,7 +1331,7 @@ class CData : Item
* if (item1 < item2) { }
* --------------
*/
override int opCmp(Object o)
override int opCmp(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(CData)item;
Expand Down Expand Up @@ -1389,7 +1389,7 @@ class Text : Item
* if (item1 == item2) { }
* --------------
*/
override bool opEquals(Object o)
override bool opEquals(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(Text)item;
Expand All @@ -1408,7 +1408,7 @@ class Text : Item
* if (item1 < item2) { }
* --------------
*/
override int opCmp(Object o)
override int opCmp(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(Text)item;
Expand Down Expand Up @@ -1471,7 +1471,7 @@ class XMLInstruction : Item
* if (item1 == item2) { }
* --------------
*/
override bool opEquals(Object o)
override bool opEquals(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(XMLInstruction)item;
Expand All @@ -1490,7 +1490,7 @@ class XMLInstruction : Item
* if (item1 < item2) { }
* --------------
*/
override int opCmp(Object o)
override int opCmp(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(XMLInstruction)item;
Expand Down Expand Up @@ -1550,7 +1550,7 @@ class ProcessingInstruction : Item
* if (item1 == item2) { }
* --------------
*/
override bool opEquals(Object o)
override bool opEquals(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(ProcessingInstruction)item;
Expand All @@ -1569,7 +1569,7 @@ class ProcessingInstruction : Item
* if (item1 < item2) { }
* --------------
*/
override int opCmp(Object o)
override int opCmp(const Object o)
{
const item = toType!(const Item)(o);
const t = cast(ProcessingInstruction)item;
Expand Down Expand Up @@ -1599,10 +1599,10 @@ class ProcessingInstruction : Item
abstract class Item
{
/// Compares with another Item of same type for equality
abstract override bool opEquals(Object o);
abstract override bool opEquals(const Object o);

/// Compares with another Item of same type
abstract override int opCmp(Object o);
abstract override int opCmp(const Object o);

/// Returns the hash of this item
abstract override hash_t toHash();
Expand Down Expand Up @@ -2815,7 +2815,7 @@ private alias CheckException Err;

private
{
T toType(T)(Object o)
T toType(T)(const Object o)
{
T t = cast(T)(o);
if (t is null)
Expand Down
3 changes: 2 additions & 1 deletion unittest.d
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public import std.compiler;
public import std.concurrency;
public import std.conv;
public import std.cpuid;
public import std.hash.crc32;
public import std.cstream;
public import std.ctype;
public import std.datetime;
Expand Down Expand Up @@ -53,6 +52,7 @@ public import std.typetuple;
public import std.uni;
public import std.uri;
public import std.utf;
public import std.uuid;
public import std.variant;
public import std.zip;
public import std.zlib;
Expand Down Expand Up @@ -125,6 +125,7 @@ version (all)

bool isEmail = std.net.isemail.isEmail("abc");
auto http = std.net.curl.HTTP("dlang.org");
auto uuid = randomUUID();
}
puts("Success!");
return 0;
Expand Down
46 changes: 24 additions & 22 deletions win32.mak
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ CFLAGS=-mn -6 -r

## Flags for dmd D compiler

DFLAGS=-O -release -nofloat -w -d -property
DFLAGS=-O -release -w -d -property
#DFLAGS=-unittest -g -d
#DFLAGS=-unittest -cov -g -d

## Flags for compiling unittests

UDFLAGS=-O -nofloat -w -d -property
UDFLAGS=-O -w -d -property

## C compiler

Expand Down Expand Up @@ -101,7 +101,7 @@ test.exe : test.obj $(LIB)
# Do not add any more modules to SRCS_1.
SRC_STD_1_HEAVY= std\stdio.d std\stdiobase.d \
std\string.d std\format.d \
std\algorithm.d std\file.d
std\file.d

SRC_STD_2_HEAVY= std\array.d std\functional.d std\range.d \
std\path.d std\outbuffer.d std\utf.d
Expand All @@ -118,6 +118,10 @@ SRC_STD_3= std\csv.d std\math.d std\complex.d std\numeric.d std\bigint.d \
std\compiler.d std\cpuid.d \
std\system.d std\concurrency.d

SRC_STD_4= std\uuid.d

SRC_STD_5_HEAVY= std\algorithm.d

SRC_STD_REST= std\variant.d \
std\syserror.d std\zlib.d \
std\stream.d std\socket.d std\socketstream.d \
Expand All @@ -127,12 +131,13 @@ SRC_STD_REST= std\variant.d \
std\stdint.d \
std\json.d \
std\parallelism.d \
std\mathspecial.d \
std\mathspecial.d \
std\process.d

SRC_STD_ALL= $(SRC_STD_1_HEAVY) $(SRC_STD_2_HEAVY) $(SRC_STD_3) $(SRC_STD_REST)
SRC_STD_ALL= $(SRC_STD_1_HEAVY) $(SRC_STD_2_HEAVY) $(SRC_STD_3) $(SRC_STD_4) \
$(SRC_STD_5_HEAVY) $(SRC_STD_REST)

SRC= unittest.d index.d
SRC= unittest.d crc32.d index.d

SRC_STD= std\zlib.d std\zip.d std\stdint.d std\container.d std\conv.d std\utf.d std\uri.d \
std\math.d std\string.d std\path.d std\datetime.d \
Expand All @@ -142,7 +147,7 @@ SRC_STD= std\zlib.d std\zip.d std\stdint.d std\container.d std\conv.d std\utf.d
std\syserror.d \
std\regexp.d std\random.d std\stream.d std\process.d \
std\socket.d std\socketstream.d std\format.d \
std\stdio.d std\perf.d std\uni.d \
std\stdio.d std\perf.d std\uni.d std\uuid.d \
std\cstream.d std\demangle.d \
std\signals.d std\cpuid.d std\typetuple.d std\traits.d \
std\metastrings.d std\getopt.d \
Expand Down Expand Up @@ -177,25 +182,22 @@ SRC_STD_INTERNAL= std\internal\processinit.d std\internal\uni.d std\internal\uni

SRC_STD_INTERNAL_MATH= std\internal\math\biguintcore.d \
std\internal\math\biguintnoasm.d std\internal\math\biguintx86.d \
std\internal\math\gammafunction.d std\internal\math\errorfunction.d
std\internal\math\gammafunction.d std\internal\math\errorfunction.d

SRC_STD_INTERNAL_WINDOWS= std\internal\windows\advapi32.d

SRC_STD_HASH= std\hash\crc32.d

SRC_ETC=

SRC_ETC_C= etc\c\zlib.d etc\c\curl.d etc\c\sqlite3.d

SRC_TO_COMPILE_NOT_STD= \
SRC_TO_COMPILE_NOT_STD= crc32.d \
$(SRC_STD_NET) \
$(SRC_STD_C) \
$(SRC_STD_WIN) \
$(SRC_STD_C_WIN) \
$(SRC_STD_INTERNAL) \
$(SRC_STD_INTERNAL_MATH) \
$(SRC_STD_INTERNAL_WINDOWS) \
$(SRC_STD_HASH) \
$(SRC_ETC) \
$(SRC_ETC_C)

Expand Down Expand Up @@ -270,7 +272,6 @@ DOCS= $(DOC)\object.html \
$(DOC)\std_container.html \
$(DOC)\std_conv.html \
$(DOC)\std_cpuid.html \
$(DOC)\std_hash_crc32.html \
$(DOC)\std_cstream.html \
$(DOC)\std_ctype.html \
$(DOC)\std_csv.html \
Expand Down Expand Up @@ -314,6 +315,7 @@ DOCS= $(DOC)\object.html \
$(DOC)\std_uni.html \
$(DOC)\std_uri.html \
$(DOC)\std_utf.html \
$(DOC)\std_uuid.html \
$(DOC)\std_variant.html \
$(DOC)\std_xml.html \
$(DOC)\std_zip.html \
Expand Down Expand Up @@ -343,13 +345,16 @@ $(LIB) : $(SRC_TO_COMPILE) \
$(DMD) -lib -of$(LIB) -Xfphobos.json $(DFLAGS) $(SRC_TO_COMPILE) \
etc\c\zlib\zlib.lib $(DRUNTIMELIB)

UNITTEST_OBJS= unittest1.obj unittest2.obj unittest3.obj
UNITTEST_OBJS= unittest1.obj unittest2.obj unittest3.obj unittest4.obj unittest5.obj

unittest : $(LIB)
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest1.obj $(SRC_STD_1_HEAVY)
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest2.obj $(SRC_STD_2_HEAVY)
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest3.obj $(SRC_STD_3)
$(DMD) $(UDFLAGS) -L/co -unittest unittest.d $(SRC_STD_REST) $(SRC_TO_COMPILE_NOT_STD) $(UNITTEST_OBJS) \
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest4.obj $(SRC_STD_4)
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest2.obj $(SRC_STD_5_HEAVY)
$(DMD) $(UDFLAGS) -L/co -c -unittest -ofunittest5.obj $(SRC_STD_REST)
$(DMD) $(UDFLAGS) -L/co -unittest unittest.d $(SRC_TO_COMPILE_NOT_STD) $(UNITTEST_OBJS) \
etc\c\zlib\zlib.lib $(DRUNTIMELIB)
unittest

Expand Down Expand Up @@ -596,6 +601,9 @@ $(DOC)\std_uri.html : $(STDDOC) std\uri.d
$(DOC)\std_utf.html : $(STDDOC) std\utf.d
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_utf.html $(STDDOC) std\utf.d

$(DOC)\std_uuid.html : $(STDDOC) std\uuid.d
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_uuid.html $(STDDOC) std\uuid.d

$(DOC)\std_variant.html : $(STDDOC) std\variant.d
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_variant.html $(STDDOC) std\variant.d

Expand All @@ -614,9 +622,6 @@ $(DOC)\std_zlib.html : $(STDDOC) std\zlib.d
$(DOC)\std_net_isemail.html : $(STDDOC) std\net\isemail.d
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_net_isemail.html $(STDDOC) std\net\isemail.d

$(DOC)\std_hash_crc32.html : $(STDDOC) std\hash\crc32.d
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_hash_crc32.html $(STDDOC) std\hash\crc32.d

$(DOC)\std_net_curl.html : $(STDDOC) std\net\curl.d
$(DMD) -c -o- $(DDOCFLAGS) -Df$(DOC)\std_net_curl.html $(STDDOC) std\net\curl.d

Expand Down Expand Up @@ -674,7 +679,7 @@ $(DOC)\etc_c_zlib.html : $(STDDOC) etc\c\zlib.d
zip : win32.mak posix.mak $(STDDOC) $(SRC) \
$(SRC_STD) $(SRC_STD_C) $(SRC_STD_WIN) \
$(SRC_STD_C_WIN) $(SRC_STD_C_LINUX) $(SRC_STD_C_OSX) $(SRC_STD_C_FREEBSD) \
$(SRC_ETC) $(SRC_ETC_C) $(SRC_ZLIB) $(SRC_STD_NET) $(SRC_STD_HASH) \
$(SRC_ETC) $(SRC_ETC_C) $(SRC_ZLIB) $(SRC_STD_NET) \
$(SRC_STD_INTERNAL) $(SRC_STD_INTERNAL_MATH) $(SRC_STD_INTERNAL_WINDOWS)
del phobos.zip
zip32 -u phobos win32.mak posix.mak $(STDDOC)
Expand All @@ -689,7 +694,6 @@ zip : win32.mak posix.mak $(STDDOC) $(SRC) \
zip32 -u phobos $(SRC_STD_INTERNAL)
zip32 -u phobos $(SRC_STD_INTERNAL_MATH)
zip32 -u phobos $(SRC_STD_INTERNAL_WINDOWS)
zip32 -u phobos $(SRC_STD_HASH)
zip32 -u phobos $(SRC_ETC) $(SRC_ETC_C)
zip32 -u phobos $(SRC_ZLIB)
zip32 -u phobos $(SRC_STD_NET)
Expand Down Expand Up @@ -722,7 +726,6 @@ install:
$(CP) $(SRC_STD_INTERNAL) $(DIR)\src\phobos\std\internal\
$(CP) $(SRC_STD_INTERNAL_MATH) $(DIR)\src\phobos\std\internal\math\
$(CP) $(SRC_STD_INTERNAL_WINDOWS) $(DIR)\src\phobos\std\internal\windows\
$(CP) $(SRC_STD_HASH) $(DIR)\src\phobos\std\hash\
#$(CP) $(SRC_ETC) $(DIR)\src\phobos\etc\
$(CP) $(SRC_ETC_C) $(DIR)\src\phobos\etc\c\
$(CP) $(SRC_ZLIB) $(DIR)\src\phobos\etc\c\zlib\
Expand All @@ -742,7 +745,6 @@ svn:
$(CP) $(SRC_STD_INTERNAL) $(SVN)\std\internal\
$(CP) $(SRC_STD_INTERNAL_MATH) $(SVN)\std\internal\math\
$(CP) $(SRC_STD_INTERNAL_WINDOWS) $(SVN)\std\internal\windows\
$(CP) $(STC_STD_HASH) $(SVN)\std\hash\
#$(CP) $(SRC_ETC) $(SVN)\etc\
$(CP) $(SRC_ETC_C) $(SVN)\etc\c\
$(CP) $(SRC_ZLIB) $(SVN)\etc\c\zlib\
Expand Down