Merge branch 'master' of github.com:D-Programming-Language/phobos

Conflicts:
	posix.mak
This commit is contained in:
Andrei Alexandrescu 2011-04-06 00:32:29 -05:00
commit 055cea0595
15 changed files with 7451 additions and 4778 deletions

16
changelog.dd Normal file
View file

@ -0,0 +1,16 @@
$(VERSION 053, ddd mm, 2011, =================================================,
$(WHATSNEW
$(LI Added bindings for libcurl on Posix: etc.c.curl)
)
$(LIBBUGSFIXED
$(LI $(BUGZILLA 4644): assertExceptionThrown to assert that a particular exception was thrown)
$(LI $(BUGZILLA 4944): Missing tzname even though we have tzset)
$(LI $(BUGZILLA 5451): Three ideas for RedBlackTree)
$(LI $(BUGZILLA 5485): TLS sections handled incorrectly in FreeBSD)
$(LI $(BUGZILLA 5616): std.datetime: not cross-platform)
$(LI $(BUGZILLA 5654): BigInt returns ZERO with strings of single digit number with leading zeros)
$(LI $(BUGZILLA 5731): std.datetime.SysTime prints UTC offsets backwards)
)
)

2193
etc/c/curl.d Normal file

File diff suppressed because it is too large Load diff

View file

@ -165,7 +165,7 @@ STD_MODULES = $(addprefix std/, algorithm array base64 bigint bitmanip \
# Other D modules that aren't under std/
EXTRA_MODULES := $(addprefix std/c/, stdarg stdio) $(addprefix etc/c/, \
zlib) $(addprefix std/internal/math/, biguintcore biguintnoasm \
biguintx86 gammafunction errorfunction)
biguintx86 gammafunction errorfunction) $(addprefix etc/c/, curl)
# OS-specific D modules
EXTRA_MODULES_LINUX := $(addprefix std/c/linux/, linux socket)
@ -245,9 +245,6 @@ DISABLED_TESTS += std/format
DISABLED_TESTS += std/math
# seems to infinite loop, need to reduce
DISABLED_TESTS += std/random
DISABLED_TESTS += std/internal/math/biguintnoasm
$(addprefix $(ROOT)/unittest/,$(DISABLED_TESTS)) :
@echo Testing $@ - disabled
endif

View file

@ -489,7 +489,7 @@ $(D array) at position $(D pos).
Example:
---
int[] a = [ 1, 2, 3, 4 ];
a.insert(2, [ 1, 2 ]);
a.insert(2, [ 1, 2 ]);
assert(a == [ 1, 2, 1, 2, 3, 4 ]);
---
*/

View file

@ -66,7 +66,7 @@ private
{
MsgType type;
Variant data;
this(T...)( MsgType t, T vals )
if( T.length < 1 )
{
@ -95,7 +95,7 @@ private
else
return data.convertsTo!(Tuple!(T));
}
auto get(T...)()
{
static if( T.length == 1 )
@ -501,6 +501,11 @@ bool receiveTimeout(T...)( long ms, T ops )
return mbox.get( ms * TICKS_PER_MILLI, ops );
}
/++ ditto +/
bool receiveTimeout(T...)( Duration duration, T ops )
{
return receiveTimeout(duration.total!"msecs"(), ops);
}
unittest
{
@ -519,6 +524,11 @@ unittest
{
receiveTimeout( 0, (int x) {}, (int x) {} );
} ) );
assert( __traits( compiles,
{
receiveTimeout( dur!"msecs"(10), (int x) {}, (Variant x) {} );
} ) );
}
@ -602,6 +612,115 @@ void setMaxMailboxSize( Tid tid, size_t messages, bool function(Tid) onCrowdingD
}
//////////////////////////////////////////////////////////////////////////////
// Name Registration
//////////////////////////////////////////////////////////////////////////////
private
{
__gshared Tid[string] tidByName;
__gshared string[][Tid] namesByTid;
__gshared Mutex registryLock;
}
shared static this()
{
registryLock = new Mutex;
}
static ~this()
{
auto me = thisTid;
synchronized( registryLock )
{
if( auto allNames = me in namesByTid )
{
foreach( name; *allNames )
tidByName.remove( name );
namesByTid.remove( me );
}
}
}
/**
* Associates name with tid in a process-local map. When the thread
* represented by tid termiantes, any names associated with it will be
* automatically unregistered.
*
* Params:
* name = The name to associate with tid.
* tid = The tid register by name.
*
* Returns:
* true if the name is available and tid is not known to represent a
* defunct thread.
*/
bool register( string name, Tid tid )
{
synchronized( registryLock )
{
if( name in tidByName )
return false;
if( tid.mbox.isClosed )
return false;
namesByTid[tid] ~= name;
tidByName[name] = tid;
return true;
}
}
/**
* Removes the registered name associated with a tid.
*
* Params:
* name = The name to unregister.
*
* Returns:
* true if the name is registered, false if not.
*/
bool unregister( string name )
{
synchronized( registryLock )
{
if( auto tid = name in tidByName )
{
auto allNames = *tid in namesByTid;
auto pos = countUntil( *allNames, name );
remove!(SwapStrategy.unstable)( *allNames, pos );
tidByName.remove( name );
return true;
}
return false;
}
}
/**
* Gets the Tid associated with name.
*
* Params:
* name = The name to locate within the registry.
*
* Returns:
* The associated Tid or Tid.init if name is not registered.
*/
Tid locate( string name )
{
synchronized( registryLock )
{
if( auto tid = name in tidByName )
return *tid;
return Tid.init;
}
}
//////////////////////////////////////////////////////////////////////////////
// MessageBox Implementation
//////////////////////////////////////////////////////////////////////////////
@ -627,6 +746,18 @@ private
}
/*
*
*/
final @property bool isClosed() const
{
synchronized( m_lock )
{
return m_closed;
}
}
/*
* Sets a limit on the maximum number of user messages allowed in the
* mailbox. If this limit is reached, the caller attempting to add
@ -738,7 +869,7 @@ private
{
alias ParameterTypeTuple!(t) Args;
auto op = ops[i];
if( msg.convertsTo!(Args) )
{
static if( is( ReturnType!(t) == bool ) )
@ -765,7 +896,7 @@ private
links.remove( tid );
// Give the owner relationship precedence.
if( *depends && tid != owner )
{
{
auto e = new LinkTerminated( tid );
if( onStandardMsg( Message( MsgType.standard, e ) ) )
return true;
@ -818,7 +949,7 @@ private
continue;
}
list.removeAt( range );
return true;
return true;
}
range.popFront();
continue;
@ -982,8 +1113,8 @@ private
{
return msg.type == MsgType.priority;
}
pure final bool isLinkDeadMsg( ref Message msg )
{
return msg.type == MsgType.linkDead;

View file

@ -4101,13 +4101,10 @@ struct RBNode(V)
* ignored on insertion. If duplicates are allowed, then new elements are
* inserted after all existing duplicate elements.
*/
struct RedBlackTree(T, alias less = "a < b", bool allowDuplicates = false)
if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
class RedBlackTree(T, alias less = "a < b", bool allowDuplicates = false)
if(is(typeof(binaryFun!less(T.init, T.init))))
{
static if(is(typeof(less) == string))
alias binaryFun!(less) _less;
else
alias less _less;
alias binaryFun!less _less;
// BUG: this must come first in the struct due to issue 2810
@ -4118,7 +4115,20 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
{
Node result;
static if(!allowDuplicates)
{
bool added = true;
scope(success)
{
if(added)
++_length;
}
}
else
{
scope(success)
++_length;
}
if(!_end.left)
{
_end.left = result = allocate(n);
@ -4200,11 +4210,6 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
}
return false;
}
private static RedBlackTree create(Elem[] elems...)
{
return RedBlackTree(elems);
}
}
else
{
@ -4219,10 +4224,12 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
// used for convenience
private alias RBNode!Elem.Node Node;
private Node _end;
private Node _end;
private size_t _length;
private void _setup()
{
assert(!_end); //Make sure that _setup isn't run more than once.
_end = allocate();
}
@ -4307,10 +4314,17 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
static if(doUnittest) unittest
{
auto ts = create(1, 2, 3, 4, 5);
auto ts = new RedBlackTree(1, 2, 3, 4, 5);
assert(ts.length == 5);
auto r = ts[];
assert(std.algorithm.equal(r, cast(T[])[1, 2, 3, 4, 5]));
assert(r.front == 1);
static if(less == "a < b")
auto vals = [1, 2, 3, 4, 5];
else
auto vals = [5, 4, 3, 2, 1];
assert(std.algorithm.equal(r, vals));
assert(r.front == vals.front);
assert(r.back != r.front);
auto oldfront = r.front;
auto oldback = r.back;
@ -4319,6 +4333,7 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
assert(r.front != r.back);
assert(r.front != oldfront);
assert(r.back != oldback);
assert(ts.length == 5);
}
// find a node based on an element value
@ -4368,27 +4383,37 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
return _end.left is null;
}
/++
Returns the number of elements in the container.
Complexity: $(BIGOH 1).
+/
@property size_t length()
{
return _length;
}
/**
* Duplicate this container. The resulting container contains a shallow
* copy of the elements.
*
* Complexity: $(BIGOH n)
*/
RedBlackTree dup()
@property RedBlackTree dup()
{
RedBlackTree result;
result._setup();
result._end = _end.dup();
return result;
return new RedBlackTree(_end.dup(), _length);
}
static if(doUnittest) unittest
{
auto ts = create(1, 2, 3, 4, 5);
auto ts2 = ts.dup();
auto ts = new RedBlackTree(1, 2, 3, 4, 5);
assert(ts.length == 5);
auto ts2 = ts.dup;
assert(ts2.length == 5);
assert(std.algorithm.equal(ts[], ts2[]));
ts2.insert(cast(Elem)6);
assert(!std.algorithm.equal(ts[], ts2[]));
assert(ts.length == 5 && ts2.length == 6);
}
/**
@ -4421,11 +4446,12 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
return _end.prev.value;
}
/**
* Check to see if an element exists in the container
*
* Complexity: $(BIGOH log(n))
*/
/++
$(D in) operator. Check to see if the given element exists in the
container.
Complexity: $(BIGOH log(n))
+/
bool opBinaryRight(string op)(Elem e) if (op == "in")
{
return _find(e) !is null;
@ -4433,19 +4459,28 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
static if(doUnittest) unittest
{
auto ts = create(1, 2, 3, 4, 5);
auto ts = new RedBlackTree(1, 2, 3, 4, 5);
assert(cast(Elem)3 in ts);
assert(cast(Elem)6 !in ts);
}
/**
* Clear the container of all elements
* Removes all elements from the container.
*
* Complexity: $(BIGOH 1)
*/
void clear()
{
_end.left = null;
_length = 0;
}
static if(doUnittest) unittest
{
auto ts = new RedBlackTree(1,2,3,4,5);
assert(ts.length == 5);
ts.clear();
assert(ts.empty && ts.length == 0);
}
/**
@ -4500,10 +4535,33 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
static if(doUnittest) unittest
{
auto ts = create(1,2,3,4,5);
assert(ts.stableInsert(cast(Elem[])[6, 7, 8, 9, 10]) == 5);
assert(ts.stableInsert(cast(Elem)11) == 1);
assert(ts.arrayEqual([1,2,3,4,5,6,7,8,9,10,11]));
auto ts = new RedBlackTree(2,1,3,4,5,2,5);
static if(allowDuplicates)
{
assert(ts.length == 7);
assert(ts.stableInsert(cast(Elem[])[7, 8, 6, 9, 10, 8]) == 6);
assert(ts.length == 13);
assert(ts.stableInsert(cast(Elem)11) == 1 && ts.length == 14);
assert(ts.stableInsert(cast(Elem)7) == 1 && ts.length == 15);
static if(less == "a < b")
assert(ts.arrayEqual([1,2,2,3,4,5,5,6,7,7,8,8,9,10,11]));
else
assert(ts.arrayEqual([11,10,9,8,8,7,7,6,5,5,4,3,2,2,1]));
}
else
{
assert(ts.length == 5);
assert(ts.stableInsert(cast(Elem[])[7, 8, 6, 9, 10, 8]) == 5);
assert(ts.length == 10);
assert(ts.stableInsert(cast(Elem)11) == 1 && ts.length == 11);
assert(ts.stableInsert(cast(Elem)7) == 0 && ts.length == 11);
static if(less == "a < b")
assert(ts.arrayEqual([1,2,3,4,5,6,7,8,9,10,11]));
else
assert(ts.arrayEqual([11,10,9,8,7,6,5,4,3,2,1]));
}
}
/**
@ -4513,6 +4571,8 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
*/
Elem removeAny()
{
scope(success)
--_length;
auto n = _end.leftmost;
auto result = n.value;
n.remove(_end);
@ -4523,8 +4583,10 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
static if(doUnittest) unittest
{
auto ts = create(1,2,3,4,5);
auto ts = new RedBlackTree(1,2,3,4,5);
assert(ts.length == 5);
auto x = ts.removeAny();
assert(ts.length == 4);
Elem[] arr;
foreach(Elem i; 1..6)
if(i != x) arr ~= i;
@ -4538,6 +4600,8 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
*/
void removeFront()
{
scope(success)
--_length;
_end.leftmost.remove(_end);
version(RBDoChecks)
check();
@ -4550,6 +4614,8 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
*/
void removeBack()
{
scope(success)
--_length;
_end.prev.remove(_end);
version(RBDoChecks)
check();
@ -4557,19 +4623,29 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
static if(doUnittest) unittest
{
auto ts = create(1,2,3,4,5);
auto ts = new RedBlackTree(1,2,3,4,5);
assert(ts.length == 5);
ts.removeBack();
assert(ts.arrayEqual([1,2,3,4]));
assert(ts.length == 4);
static if(less == "a < b")
assert(ts.arrayEqual([1,2,3,4]));
else
assert(ts.arrayEqual([2,3,4,5]));
ts.removeFront();
assert(ts.arrayEqual([2,3,4]));
assert(ts.arrayEqual([2,3,4]) && ts.length == 3);
}
/**
* Remove the given range from the container. Returns a range containing
* all the elements that were after the given range.
*
* Complexity: $(BIGOH m * log(n))
*/
/++
Removes the given range from the container.
Returns: A range containing all of the elements that were after the
given range.
Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
the range)
+/
Range remove(Range r)
{
auto b = r._begin;
@ -4577,6 +4653,7 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
while(b !is e)
{
b = b.remove(_end);
--_length;
}
version(RBDoChecks)
check();
@ -4585,13 +4662,159 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
static if(doUnittest) unittest
{
auto ts = create(1,2,3,4,5);
auto ts = new RedBlackTree(1,2,3,4,5);
assert(ts.length == 5);
auto r = ts[];
r.popFront();
r.popBack();
assert(ts.length == 5);
auto r2 = ts.remove(r);
assert(ts.length == 2);
assert(ts.arrayEqual([1,5]));
assert(std.algorithm.equal(r2, [5]));
static if(less == "a < b")
assert(std.algorithm.equal(r2, [5]));
else
assert(std.algorithm.equal(r2, [1]));
}
/++
Removes the given $(D Take!Range) from the container
Returns: A range containing all of the elements that were after the
given range.
Complexity: $(BIGOH m * log(n)) (where m is the number of elements in
the range)
+/
Range remove(Take!Range r)
{
auto b = r.original._begin;
while(!r.empty)
r.popFront(); // move take range to its last element
auto e = r.original._begin;
while(b != e)
{
b = b.remove(_end);
--_length;
}
return Range(e, _end);
}
static if(doUnittest) unittest
{
auto ts = new RedBlackTree(1,2,3,4,5);
auto r = ts[];
r.popFront();
assert(ts.length == 5);
auto r2 = ts.remove(take(r, 0));
static if(less == "a < b")
{
assert(std.algorithm.equal(r2, [2,3,4,5]));
auto r3 = ts.remove(take(r, 2));
assert(ts.arrayEqual([1,4,5]) && ts.length == 3);
assert(std.algorithm.equal(r3, [4,5]));
}
else
{
assert(std.algorithm.equal(r2, [4,3,2,1]));
auto r3 = ts.remove(take(r, 2));
assert(ts.arrayEqual([5,2,1]) && ts.length == 3);
assert(std.algorithm.equal(r3, [2,1]));
}
}
/++
Removes elements from the container that are equal to the given values
according to the less comparator. One element is removed for each value
given which is in the container. If $(D allowDuplicates) is true,
duplicates are removed only if duplicate values are given.
Returns: The number of elements removed.
Complexity: $(BIGOH m log(n)) (where m is the number of elements to remove)
Examples:
--------------------
auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
rbt.removeKey(1, 4, 7);
assert(std.algorithm.equal(rbt[], [0, 1, 1, 5]));
rbt.removeKey(1, 1, 0);
assert(std.algorithm.equal(rbt[], [5]));
--------------------
+/
size_t removeKey(U)(U[] elems...)
if(isImplicitlyConvertible!(U, Elem))
{
immutable lenBefore = length;
foreach(e; elems)
{
auto beg = _firstGreaterEqual(e);
if(beg is _end || _less(e, beg.value))
// no values are equal
continue;
beg.remove(_end);
--_length;
}
return lenBefore - length;
}
/++ Ditto +/
size_t removeKey(Stuff)(Stuff stuff)
if(isInputRange!Stuff &&
isImplicitlyConvertible!(ElementType!Stuff, Elem) &&
!is(Stuff == Elem[]))
{
//We use array in case stuff is a Range from this RedBlackTree - either
//directly or indirectly.
return removeKey(array(stuff));
}
static if(doUnittest) unittest
{
auto rbt = new RedBlackTree(5, 4, 3, 7, 2, 1, 7, 6, 2, 19, 45);
static if(allowDuplicates)
{
assert(rbt.length == 11);
assert(rbt.removeKey(cast(Elem)4) == 1 && rbt.length == 10);
assert(rbt.arrayEqual([1,2,2,3,5,6,7,7,19,45]) && rbt.length == 10);
assert(rbt.removeKey(cast(Elem)6, cast(Elem)2, cast(Elem)1) == 3);
assert(rbt.arrayEqual([2,3,5,7,7,19,45]) && rbt.length == 7);
assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 7);
assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 4);
static if(less == "a < b")
assert(std.algorithm.equal(rbt[], [7,7,19,45]));
else
assert(std.algorithm.equal(rbt[], [7,5,3,2]));
}
else
{
assert(rbt.length == 9);
assert(rbt.removeKey(cast(Elem)4) == 1 && rbt.length == 8);
assert(rbt.arrayEqual([1,2,3,5,6,7,19,45]));
assert(rbt.removeKey(cast(Elem)6, cast(Elem)2, cast(Elem)1) == 3);
assert(rbt.arrayEqual([3,5,7,19,45]) && rbt.length == 5);
assert(rbt.removeKey(cast(Elem)(42)) == 0 && rbt.length == 5);
assert(rbt.removeKey(take(rbt[], 3)) == 3 && rbt.length == 2);
static if(less == "a < b")
assert(std.algorithm.equal(rbt[], [19,45]));
else
assert(std.algorithm.equal(rbt[], [5,3]));
}
}
// find the first node where the value is > e
@ -4681,18 +4904,28 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
static if(doUnittest) unittest
{
auto ts = create(1, 2, 3, 4, 5);
auto r1 = ts.lowerBound(3);
assert(std.algorithm.equal(r1, [1,2]));
auto r2 = ts.upperBound(3);
assert(std.algorithm.equal(r2, [4,5]));
auto r3 = ts.equalRange(3);
assert(std.algorithm.equal(r3, [3]));
auto ts = new RedBlackTree(1, 2, 3, 4, 5);
auto rl = ts.lowerBound(3);
auto ru = ts.upperBound(3);
auto re = ts.equalRange(3);
static if(less == "a < b")
{
assert(std.algorithm.equal(rl, [1,2]));
assert(std.algorithm.equal(ru, [4,5]));
}
else
{
assert(std.algorithm.equal(rl, [5,4]));
assert(std.algorithm.equal(ru, [2,1]));
}
assert(std.algorithm.equal(re, [3]));
}
version(RBDoChecks)
{
/**
/*
* Print the tree. This prints a sideways view of the tree in ASCII form,
* with the number of indentations representing the level of the nodes.
* It does not print values, only the tree structure and color of nodes.
@ -4717,7 +4950,7 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
writeln();
}
/**
/*
* Check the tree for validity. This is called after every add or remove.
* This should only be enabled to debug the implementation of the RB Tree.
*/
@ -4773,6 +5006,11 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
}
}
/+
For the moment, using templatized contstructors doesn't seem to work
very well (likely due to bug# 436 and/or bug# 1528). The redBlackTree
helper function seems to do the job well enough though.
/**
* Constructor. Pass in an array of elements, or individual elements to
* initialize the tree with.
@ -4791,17 +5029,136 @@ if (is(typeof(less(T.init, T.init)) == bool) || is(typeof(less) == string))
_setup();
stableInsert(stuff);
}
+/
/++ +/
this()
{
_setup();
}
/++
Constructor. Pass in an array of elements, or individual elements to
initialize the tree with.
+/
this(Elem[] elems...)
{
_setup();
stableInsert(elems);
}
private this(Node end, size_t length)
{
_end = end;
_length = length;
}
}
//Verify Example for removeKey.
unittest
{
auto rbt = redBlackTree!true(0, 1, 1, 1, 4, 5, 7);
rbt.removeKey(1, 4, 7);
assert(std.algorithm.equal(rbt[], [0, 1, 1, 5]));
rbt.removeKey(1, 1, 0);
assert(std.algorithm.equal(rbt[], [5]));
}
unittest
{
RedBlackTree!uint rt1;
RedBlackTree!int rt2;
RedBlackTree!ushort rt3;
RedBlackTree!short rt4;
RedBlackTree!ubyte rt5;
RedBlackTree!byte rt6;
void test(T)()
{
auto rt1 = new RedBlackTree!(T, "a < b", false)();
auto rt2 = new RedBlackTree!(T, "a < b", true)();
auto rt3 = new RedBlackTree!(T, "a > b", false)();
auto rt4 = new RedBlackTree!(T, "a > b", true)();
}
test!long();
test!ulong();
test!int();
test!uint();
test!short();
test!ushort();
test!byte();
test!byte();
}
/++
Convenience function for creating a $(D RedBlackTree!E) from a list of
values.
Examples:
--------------------
auto rbt1 = redBlackTree(0, 1, 5, 7);
auto rbt2 = redBlackTree!string("hello", "world");
auto rbt3 = redBlackTree!true(0, 1, 5, 7, 5);
auto rbt4 = redBlackTree!"a > b"(0, 1, 5, 7);
auto rbt5 = redBlackTree!("a > b", true)(0.1, 1.3, 5.9, 7.2, 5.9);
--------------------
+/
auto redBlackTree(E)(E[] elems...)
{
return new RedBlackTree!E(elems);
}
/++ Ditto +/
auto redBlackTree(bool allowDuplicates, E)(E[] elems...)
{
return new RedBlackTree!(E, "a < b", allowDuplicates)(elems);
}
/++ Ditto +/
auto redBlackTree(alias less, E)(E[] elems...)
{
return new RedBlackTree!(E, less)(elems);
}
/++ Ditto +/
auto redBlackTree(alias less, bool allowDuplicates, E)(E[] elems...)
if(is(typeof(binaryFun!less(E.init, E.init))))
{
//We shouldn't need to instantiate less here, but for some reason,
//dmd can't handle it if we don't (even though the template which
//takes less but not allowDuplicates works just fine).
return new RedBlackTree!(E, binaryFun!less, allowDuplicates)(elems);
}
//Verify Examples.
unittest
{
auto rbt1 = redBlackTree(0, 1, 5, 7);
auto rbt2 = redBlackTree!string("hello", "world");
auto rbt3 = redBlackTree!true(0, 1, 5, 7, 5);
auto rbt4 = redBlackTree!"a > b"(0, 1, 5, 7);
auto rbt5 = redBlackTree!("a > b", true)(0.1, 1.3, 5.9, 7.2, 5.9);
}
//Combinations not in examples.
unittest
{
auto rbt1 = redBlackTree!(true, string)("hello", "hello");
auto rbt2 = redBlackTree!((a, b){return a < b;}, double)(5.1, 2.3);
auto rbt3 = redBlackTree!("a > b", true, string)("hello", "world");
}
unittest
{
auto rt1 = redBlackTree(5, 4, 3, 2, 1);
assert(rt1.length == 5);
assert(array(rt1[]) == [1, 2, 3, 4, 5]);
auto rt2 = redBlackTree!"a > b"(1.1, 2.1);
assert(rt2.length == 2);
assert(array(rt2[]) == [2.1, 1.1]);
auto rt3 = redBlackTree!true(5, 5, 4);
assert(rt3.length == 3);
assert(array(rt3[]) == [4, 5, 5]);
auto rt4 = redBlackTree!string("hello", "hello");
assert(rt4.length == 1);
assert(array(rt4[]) == ["hello"]);
}
version(unittest) struct UnittestMe {

File diff suppressed because it is too large Load diff

View file

@ -1,79 +1,354 @@
// Written in the D programming language.
/**
* This module defines tools related to exceptions and general error
* handling.
*
* Macros:
* WIKI = Phobos/StdException
*
* Synopsis:
*
* ----
* string synopsis()
* {
* FILE* f = enforce(fopen("some/file"));
* // f is not null from here on
* FILE* g = enforceEx!(WriteException)(fopen("some/other/file", "w"));
* // g is not null from here on
* Exception e = collectException(write(g, readln(f)));
* if (e)
* {
* ... an exception occurred...
* }
* char[] line;
* enforce(readln(f, line));
* return assumeUnique(line);
* }
* ----
*
* Copyright: Copyright Andrei Alexandrescu 2008-.
* License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: $(WEB erdani.org, Andrei Alexandrescu)
* Source: $(PHOBOSSRC std/_exception.d)
*/
/++
This module defines functions related to exceptions and general error
handling. It also defines functions intended to aid in unit testing.
Synopsis of some of std.exception's functions:
--------------------
string synopsis()
{
FILE* f = enforce(fopen("some/file"));
// f is not null from here on
FILE* g = enforceEx!(WriteException)(fopen("some/other/file", "w"));
// g is not null from here on
Exception e = collectException(write(g, readln(f)));
if (e)
{
... an exception occurred...
... We have the exception to play around with...
}
string msg = collectExceptionMsg(write(g, readln(f)));
if (msg)
{
... an exception occurred...
... We have the message from the exception but not the exception...
}
char[] line;
enforce(readln(f, line));
return assumeUnique(line);
}
--------------------
Macros:
WIKI = Phobos/StdException
Copyright: Copyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-.
License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0)
Authors: $(WEB erdani.org, Andrei Alexandrescu) and Jonathan M Davis
Source: $(PHOBOSSRC std/_exception.d)
+/
module std.exception;
import std.array, std.c.string, std.conv, std.range, std.string, std.traits;
import core.stdc.errno;
import core.exception, core.stdc.errno;
version(unittest)
{
import std.datetime;
import std.stdio;
}
/*
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
* Written by Andrei Alexandrescu, www.erdani.org
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
/++
Asserts that the given expression does $(I not) throw the given type
of $(D Throwable). If a $(D Throwable) of the given type is thrown,
it is caught and does not escape assertNotThrown. Rather, an
$(D AssertError) is thrown. However, any other $(D Throwable)s will escape.
/**
* If $(D_PARAM value) is nonzero, returns it. Otherwise, throws
* $(D_PARAM new Exception(msg)).
* Example:
* ----
* auto f = enforce(fopen("data.txt"));
* auto line = readln(f);
* enforce(line.length); // expect a non-empty line
* ----
*/
Params:
T = The $(D Throwable) to test for.
expression = The expression to test.
msg = Optional message to output on test failure.
Throws:
$(D AssertError) if the given $(D Throwable) is thrown.
Examples:
--------------------
assertNotThrown!TimeException(std.datetime.TimeOfDay(0, 0, 0));
assertNotThrown(std.datetime.TimeOfDay(23, 59, 59)); //Exception is default.
assert(collectExceptionMsg!AssertError(assertNotThrown!TimeException(
std.datetime.TimeOfDay(12, 0, 60))) ==
`assertNotThrown failed: TimeException was thrown.`);
--------------------
+/
void assertNotThrown(T : Throwable = Exception, E)
(lazy E expression,
string msg = null,
string file = __FILE__,
size_t line = __LINE__)
{
try
expression();
catch(T t)
{
immutable tail = msg.empty ? "." : ": " ~ msg;
throw new AssertError(format("assertNotThrown failed: %s was thrown%s",
T.stringof,
tail),
file,
line,
t);
}
}
//Verify Examples
unittest
{
assertNotThrown!TimeException(std.datetime.TimeOfDay(0, 0, 0));
assertNotThrown(std.datetime.TimeOfDay(23, 59, 59)); //Exception is default.
assert(collectExceptionMsg!AssertError(assertNotThrown!TimeException(
std.datetime.TimeOfDay(12, 0, 60))) ==
`assertNotThrown failed: TimeException was thrown.`);
}
unittest
{
void throwEx(Throwable t) { throw t; }
void nothrowEx() { }
try
assertNotThrown!Exception(nothrowEx());
catch(AssertError)
assert(0);
try
assertNotThrown!Exception(nothrowEx(), "It's a message");
catch(AssertError)
assert(0);
try
assertNotThrown!AssertError(nothrowEx());
catch(AssertError)
assert(0);
try
assertNotThrown!AssertError(nothrowEx(), "It's a message");
catch(AssertError)
assert(0);
{
bool thrown = false;
try
{
assertNotThrown!Exception(
throwEx(new Exception("It's an Exception")));
}
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
{
assertNotThrown!Exception(
throwEx(new Exception("It's an Exception")), "It's a message");
}
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
{
assertNotThrown!AssertError(
throwEx(new AssertError("It's an AssertError",
__FILE__,
__LINE__)));
}
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
{
assertNotThrown!AssertError(
throwEx(new AssertError("It's an AssertError",
__FILE__,
__LINE__)),
"It's a message");
}
catch(AssertError)
thrown = true;
assert(thrown);
}
}
/++
Asserts that the given expression throws the given type of $(D Throwable).
The $(D Throwable) is caught and does not escape assertThrown. However,
any other $(D Throwable)s $(I will) escape, and if no $(D Throwable)
of the given type is thrown, then an $(D AssertError) is thrown.
Params:
T = The $(D Throwable) to test for.
expression = The expression to test.
msg = Optional message to output on test failure.
Throws:
$(D AssertError) if the given $(D Throwable) is not thrown.
Examples:
--------------------
assertThrown!TimeException(std.datetime.TimeOfDay(-1, 15, 30));
assertThrown(std.datetime.TimeOfDay(12, 15, 60)); //Exception is default.
assert(collectExceptionMsg!AssertError(assertThrown!AssertError(
std.datetime.TimeOfDay(12, 0, 0))) ==
`assertThrown failed: No AssertError was thrown.`);
--------------------
+/
void assertThrown(T : Throwable = Exception, E)
(lazy E expression,
string msg = null,
string file = __FILE__,
size_t line = __LINE__)
{
bool thrown = false;
try
expression();
catch(T t)
thrown = true;
if(!thrown)
{
immutable tail = msg.empty ? "." : ": " ~ msg;
throw new AssertError(format("assertThrown failed: No %s was thrown%s",
T.stringof,
tail),
file,
line);
}
}
//Verify Examples
unittest
{
assertThrown!TimeException(std.datetime.TimeOfDay(-1, 15, 30));
assertThrown(std.datetime.TimeOfDay(12, 15, 60)); //Exception is default.
assert(collectExceptionMsg!AssertError(assertThrown!AssertError(
std.datetime.TimeOfDay(12, 0, 0))) ==
`assertThrown failed: No AssertError was thrown.`);
}
unittest
{
void throwEx(Throwable t) { throw t; }
void nothrowEx() { }
try
assertThrown!Exception(throwEx(new Exception("It's an Exception")));
catch(AssertError)
assert(0);
try
{
assertThrown!Exception(throwEx(new Exception("It's an Exception")),
"It's a message");
}
catch(AssertError)
assert(0);
try
{
assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",
__FILE__,
__LINE__)));
}
catch(AssertError)
assert(0);
try
{
assertThrown!AssertError(throwEx(new AssertError("It's an AssertError",
__FILE__,
__LINE__)),
"It's a message");
}
catch(AssertError)
assert(0);
{
bool thrown = false;
try
assertThrown!Exception(nothrowEx());
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
assertThrown!Exception(nothrowEx(), "It's a message");
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
assertThrown!AssertError(nothrowEx());
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
assertThrown!AssertError(nothrowEx(), "It's a message");
catch(AssertError)
thrown = true;
assert(thrown);
}
}
/++
If $(D !value) is true, $(D value) is returned. Otherwise,
$(D new Exception(msg)) is thrown.
Note:
$(D enforce) is used to throw exceptions and is therefore intended to
aid in error handling. It is $(I not) intended for verifying the logic
of your program. That is what $(D assert) is for. Also, do not use
$(D enforce) inside of contracts (i.e. inside of $(D in) and $(D out)
blocks and $(D invariant)s), because they will be compiled out when
compiling with $(I -release). Use $(D assert) in contracts.
Example:
--------------------
auto f = enforce(fopen("data.txt"));
auto line = readln(f);
enforce(line.length, "Expected a non-empty line."));
--------------------
+/
T enforce(T, string file = __FILE__, int line = __LINE__)
(T value, lazy const(char)[] msg = null)
{
@ -81,6 +356,10 @@ T enforce(T, string file = __FILE__, int line = __LINE__)
return value;
}
/++
If $(D !value) is true, $(D value) is returned. Otherwise, the given
delegate is called.
+/
T enforce(T, string file = __FILE__, int line = __LINE__)
(T value, scope void delegate() dg)
{
@ -110,17 +389,16 @@ unittest
}
}
/**
* If $(D_PARAM value) is nonzero, returns it. Otherwise, throws
* $(D_PARAM ex).
* Example:
* ----
* auto f = enforce(fopen("data.txt"));
* auto line = readln(f);
* enforce(line.length, new IOException); // expect a non-empty line
* ----
*/
/++
If $(D !value) is true, $(D value) is returned. Otherwise, $(D ex) is thrown.
Example:
--------------------
auto f = enforce(fopen("data.txt"));
auto line = readln(f);
enforce(line.length, new IOException); // expect a non-empty line
--------------------
+/
T enforce(T)(T value, lazy Throwable ex)
{
if (!value) throw ex();
@ -140,20 +418,18 @@ unittest
}
}
/**
If $(D value) is nonzero, returns it. Otherwise, throws $(D new
ErrnoException(msg)). The $(D ErrnoException) class assumes that the
last operation has set $(D errno) to an error code.
*
* Example:
*
* ----
* auto f = errnoEnforce(fopen("data.txt"));
* auto line = readln(f);
* enforce(line.length); // expect a non-empty line
* ----
*/
/++
If $(D !value) is true, $(D value) is returned. Otherwise,
$(D new ErrnoException(msg)) is thrown. $(D ErrnoException) assumes that the
last operation set $(D errno) to an error code.
Example:
--------------------
auto f = errnoEnforce(fopen("data.txt"));
auto line = readln(f);
enforce(line.length); // expect a non-empty line
--------------------
+/
T errnoEnforce(T, string file = __FILE__, int line = __LINE__)
(T value, lazy string msg = null)
{
@ -161,24 +437,21 @@ T errnoEnforce(T, string file = __FILE__, int line = __LINE__)
return value;
}
/**
* If $(D_PARAM value) is nonzero, returns it. Otherwise, throws
* $(D_PARAM new E(msg)).
* Example:
* ----
* auto f = enforceEx!(FileMissingException)(fopen("data.txt"));
* auto line = readln(f);
* enforceEx!(DataCorruptionException)(line.length);
* ----
*/
/++
If $(D !value) is true, $(D value) is returned. Otherwise, $(D new E(msg))
is thrown.
template enforceEx(E)
Example:
--------------------
auto f = enforceEx!FileMissingException(fopen("data.txt"));
auto line = readln(f);
enforceEx!DataCorruptionException(line.length);
--------------------
+/
T enforceEx(E, T)(T value, lazy string msg = "")
{
T enforceEx(T)(T value, lazy string msg = "")
{
if (!value) throw new E(msg);
return value;
}
if (!value) throw new E(msg);
return value;
}
unittest
@ -196,25 +469,37 @@ unittest
}
}
/**
* Evaluates $(D_PARAM expression). If evaluation throws an exception,
* return that exception. Otherwise, deposit the resulting value in
* $(D_PARAM target) and return $(D_PARAM null).
* Example:
* ----
* int[] a = new int[3];
* int b;
* assert(collectException(a[4], b));
* ----
*/
/++
Catches and returns the exception thrown from the given expression.
If no exception is thrown, then null is returned and $(D result) is
set to the result of the expression.
Exception collectException(T)(lazy T expression, ref T target)
Note that while $(D collectException) $(I can) be used to collect any
$(D Throwable) and not just $(D Exception)s, it is generally ill-advised to
catch anything that is neither an $(D Exception) nor a type derived from
$(D Exception). So, do not use $(D collectException) to collect
non-$(D Exception)s unless you're sure that that's what you really want to
do.
Params:
T = The type of exception to catch.
expression = The expression which may throw an exception.
result = The result of the expression if no exception is thrown.
Example:
--------------------
int[] a = new int[3];
int b;
assert(collectException(a[4], b));
--------------------
+/
T collectException(T = Exception, E)(lazy E expression, ref E result)
{
try
{
target = expression();
result = expression();
}
catch (Exception e)
catch (T e)
{
return e;
}
@ -229,20 +514,31 @@ unittest
assert(collectException(foo(), b));
}
/** Evaluates $(D_PARAM expression). If evaluation throws an
* exception, return that exception. Otherwise, return $(D_PARAM
* null). $(D_PARAM T) can be $(D_PARAM void).
*/
/++
Catches and returns the exception thrown from the given expression.
If no exception is thrown, then null is returned. $(D E) can be
$(D void).
Exception collectException(T)(lazy T expression)
Note that while $(D collectException) $(I can) be used to collect any
$(D Throwable) and not just $(D Exception)s, it is generally ill-advised to
catch anything that is neither an $(D Exception) nor a type derived from
$(D Exception). So, do not use $(D collectException) to collect
non-$(D Exception)s unless you're sure that that's what you really want to
do.
Params:
T = The type of exception to catch.
expression = The expression which may throw an exception.
+/
T collectException(T : Throwable = Exception, E)(lazy E expression)
{
try
{
expression();
}
catch (Exception e)
catch (T t)
{
return e;
return t;
}
return null;
}
@ -253,20 +549,82 @@ unittest
assert(collectException(foo()));
}
/++
Catches the exception thrown from the given expression and returns the
msg property of that exception. If no exception is thrown, then null is
returned. $(D E) can be $(D void).
If an exception is thrown but it has an empty message, then
$(D emptyExceptionMsg) is returned.
Note that while $(D collectExceptionMsg) $(I can) be used to collect any
$(D Throwable) and not just $(D Exception)s, it is generally ill-advised to
catch anything that is neither an $(D Exception) nor a type derived from
$(D Exception). So, do not use $(D collectExceptionMsg) to collect
non-$(D Exception)s unless you're sure that that's what you really want to
do.
Params:
T = The type of exception to catch.
expression = The expression which may throw an exception.
Examples:
--------------------
void throwFunc() {throw new Exception("My Message.");}
assert(collectExceptionMsg(throwFunc()) == "My Message.");
void nothrowFunc() {}
assert(collectExceptionMsg(nothrowFunc()) is null);
void throwEmptyFunc() {throw new Exception("");}
assert(collectExceptionMsg(throwEmptyFunc()) == emptyExceptionMsg);
--------------------
+/
string collectExceptionMsg(T = Exception, E)(lazy E expression)
{
try
{
expression();
return cast(string)null;
}
catch(T e)
return e.msg.empty ? emptyExceptionMsg : e.msg;
}
//Verify Examples.
unittest
{
void throwFunc() {throw new Exception("My Message.");}
assert(collectExceptionMsg(throwFunc()) == "My Message.");
void nothrowFunc() {}
assert(collectExceptionMsg(nothrowFunc()) is null);
void throwEmptyFunc() {throw new Exception("");}
assert(collectExceptionMsg(throwEmptyFunc()) == emptyExceptionMsg);
}
/++
Value that collectExceptionMsg returns when it catches an exception
with an empty exception message.
+/
enum emptyExceptionMsg = "<Empty Exception Message>";
/**
* Casts a mutable array to an immutable array in an idiomatic
* manner. Technically, $(D_PARAM assumeUnique) just inserts a cast,
* manner. Technically, $(D assumeUnique) just inserts a cast,
* but its name documents assumptions on the part of the
* caller. $(D_PARAM assumeUnique(arr)) should only be called when
* there are no more active mutable aliases to elements of $(D_PARAM
* arr). To strenghten this assumption, $(D_PARAM assumeUnique(arr))
* also clears $(D_PARAM arr) before returning. Essentially $(D_PARAM
* caller. $(D assumeUnique(arr)) should only be called when
* there are no more active mutable aliases to elements of $(D
* arr). To strenghten this assumption, $(D assumeUnique(arr))
* also clears $(D arr) before returning. Essentially $(D
* assumeUnique(arr)) indicates commitment from the caller that there
* is no more mutable access to any of $(D_PARAM arr)'s elements
* is no more mutable access to any of $(D arr)'s elements
* (transitively), and that all future accesses will be done through
* the immutable array returned by $(D_PARAM assumeUnique).
* the immutable array returned by $(D assumeUnique).
*
* Typically, $(D_PARAM assumeUnique) is used to return arrays from
* Typically, $(D assumeUnique) is used to return arrays from
* functions that have allocated and built them.
*
* Example:
@ -283,10 +641,10 @@ unittest
* }
* ----
*
* The use in the example above is correct because $(D_PARAM result)
* was private to $(D_PARAM letters) and is unaccessible in writing
* The use in the example above is correct because $(D result)
* was private to $(D letters) and is unaccessible in writing
* after the function returns. The following example shows an
* incorrect use of $(D_PARAM assumeUnique).
* incorrect use of $(D assumeUnique).
*
* Bad:
*
@ -307,7 +665,7 @@ unittest
*
* The example above wreaks havoc on client code because it is
* modifying arrays that callers considered immutable. To obtain an
* immutable array from the writable array $(D_PARAM buffer), replace
* immutable array from the writable array $(D buffer), replace
* the last line with:
* ----
* return to!(string)(sneaky); // not that sneaky anymore
@ -316,12 +674,12 @@ unittest
* The call will duplicate the array appropriately.
*
* Checking for uniqueness during compilation is possible in certain
* cases (see the $(D_PARAM unique) and $(D_PARAM lent) keywords in
* cases (see the $(D unique) and $(D lent) keywords in
* the $(WEB archjava.fluid.cs.cmu.edu/papers/oopsla02.pdf, ArchJava)
* language), but complicates the language considerably. The downside
* of $(D_PARAM assumeUnique)'s convention-based usage is that at this
* of $(D assumeUnique)'s convention-based usage is that at this
* time there is no formal checking of the correctness of the
* assumption; on the upside, the idiomatic use of $(D_PARAM
* assumption; on the upside, the idiomatic use of $(D
* assumeUnique) is simple and rare enough to be tolerable.
*
*/
@ -429,7 +787,7 @@ unittest
}
/*********************
* Thrown if errors that set $(D errno) happen.
* Thrown if errors that set $(D errno) occur.
*/
class ErrnoException : Exception
{

View file

@ -1612,7 +1612,7 @@ version(Windows) void mkdir(in char[] pathname)
version(Posix) void mkdir(in char[] pathname)
{
cenforce(core.sys.posix.sys.stat.mkdir(toStringz(pathname), 0777) == 0,
cenforce(core.sys.posix.sys.stat.mkdir(toStringz(pathname), octal!777) == 0,
pathname);
}

View file

@ -1942,7 +1942,7 @@ here:
stream.clear; formattedWrite(stream, "%#X", 0xABCD);
assert(stream.data == "0XABCD");
stream.clear; formattedWrite(stream, "%#o", 012345);
stream.clear; formattedWrite(stream, "%#o", octal!12345);
assert(stream.data == "012345");
stream.clear; formattedWrite(stream, "%o", 9);
assert(stream.data == "11");
@ -3812,7 +3812,7 @@ unittest
r = std.string.format("%#X", 0xABCD);
assert(r == "0XABCD");
r = std.string.format("%#o", 012345);
r = std.string.format("%#o", octal!12345);
assert(r == "012345");
r = std.string.format("%o", 9);
assert(r == "11");

View file

@ -373,12 +373,12 @@ bool fromDecimalString(string s)
{
//Strip leading zeros
int firstNonZero = 0;
while ((firstNonZero < s.length - 1) &&
while ((firstNonZero < s.length) &&
(s[firstNonZero]=='0' || s[firstNonZero]=='_'))
{
++firstNonZero;
}
if (firstNonZero == s.length - 1 && s.length > 1)
if (firstNonZero == s.length && s.length >= 1)
{
data = ZERO;
return true;
@ -836,6 +836,12 @@ unittest
r.fromHexString("1_E1178E81_00000000");
s = BigUint.pow(r, 15); // Regression test: this used to overflow array bounds
r.fromDecimalString("000_000_00");
assert(r == 0);
r.fromDecimalString("0007");
assert(r == 7);
r.fromDecimalString("0");
assert(r == 0);
}
// Radix conversion tests
@ -1377,17 +1383,28 @@ size_t biguintToDecimal(char [] buff, BigDigit [] data)
* the highest index of data which was used.
*/
int biguintFromDecimal(BigDigit [] data, string s)
in
{
assert((data.length >= 2) || (data.length == 1 && s.length == 1));
}
body
{
// Convert to base 1e19 = 10_000_000_000_000_000_000.
// (this is the largest power of 10 that will fit into a long).
// The length will be less than 1 + s.length/log2(10) = 1 + s.length/3.3219.
// 485 bits will only just fit into 146 decimal digits.
uint lo = 0;
// As we convert the string, we record the number of digits we've seen in base 19:
// hi is the number of digits/19, lo is the extra digits (0 to 18).
// TODO: This is inefficient for very large strings (it is O(n^^2)).
// We should take advantage of fast multiplication once the numbers exceed
// Karatsuba size.
uint lo = 0; // number of powers of digits, 0..18
uint x = 0;
ulong y = 0;
uint hi = 0;
uint hi = 0; // number of base 1e19 digits
data[0] = 0; // initially number is 0.
data[1] = 0;
if (data.length > 1)
data[1] = 0;
for (int i= (s[0]=='-' || s[0]=='+')? 1 : 0; i<s.length; ++i)
{
@ -1447,12 +1464,20 @@ int biguintFromDecimal(BigDigit [] data, string s)
for (int k=0; k<lo; ++k) y*=10;
y+=x;
}
if (lo!=0)
if (lo != 0)
{
if (hi==0)
if (hi == 0)
{
*cast(ulong *)(&data[hi]) = y;
hi=2;
if (data.length == 1)
{
data[0] = cast(uint)(y & 0xFFFF_FFFF);
hi = 1;
}
else
{
*cast(ulong *)(&data[hi]) = y;
hi=2;
}
}
else
{
@ -1467,7 +1492,7 @@ int biguintFromDecimal(BigDigit [] data, string s)
--lo;
}
uint c = multibyteIncrementAssign!('+')(data[0..hi], cast(uint)(y&0xFFFF_FFFF));
if (y>0xFFFF_FFFFL)
if (y > 0xFFFF_FFFFL)
{
c += multibyteIncrementAssign!('+')(data[1..hi], cast(uint)(y>>32));
}
@ -1476,7 +1501,6 @@ int biguintFromDecimal(BigDigit [] data, string s)
data[hi]=c;
++hi;
}
// hi+=2;
}
}
while (hi>1 && data[hi-1]==0)

View file

@ -260,7 +260,7 @@ unittest {
for (int i=0; i<aa.length; ++i) aa[i] = 0x8765_4321 * (i+3);
uint overflow = multibyteMul(aa, aa, 0x8EFD_FCFB, 0x33FF_7461);
uint r = multibyteDivAssign(aa, 0x8EFD_FCFB, overflow);
for (sizediff_t i=aa.length-1; i>=0; --i) { assert(aa[i] == 0x8765_4321 * (i+3)); }
for (int i=0; i<aa.length; ++i) { assert(aa[i] == 0x8765_4321 * (i+3)); }
assert(r==0x33FF_7461);
}

View file

@ -107,14 +107,14 @@ class MmFile
flags = MAP_SHARED;
prot = PROT_READ | PROT_WRITE;
oflag = O_CREAT | O_RDWR | O_TRUNC;
fmode = 0660;
fmode = octal!660;
break;
case Mode.ReadWrite:
flags = MAP_SHARED;
prot = PROT_READ | PROT_WRITE;
oflag = O_CREAT | O_RDWR;
fmode = 0660;
fmode = octal!660;
break;
case Mode.ReadCopyOnWrite:
@ -322,14 +322,14 @@ class MmFile
flags = MAP_SHARED;
prot = PROT_READ | PROT_WRITE;
oflag = O_CREAT | O_RDWR | O_TRUNC;
fmode = 0660;
fmode = octal!660;
break;
case Mode.ReadWrite:
flags = MAP_SHARED;
prot = PROT_READ | PROT_WRITE;
oflag = O_CREAT | O_RDWR;
fmode = 0660;
fmode = octal!660;
break;
case Mode.ReadCopyOnWrite:

View file

@ -793,7 +793,7 @@ class Stream : InputStream, OutputStream {
case 'o': { // octal
while (isoctdigit(c) && width) {
n = n * 010 + (c - '0');
n = n * 8 + (c - '0');
width--;
c = getc();
count++;
@ -1890,7 +1890,7 @@ class File: Stream {
}
}
version (Posix) {
share = 0666;
share = octal!666;
if (mode & FileMode.In) {
access = O_RDONLY;
}

View file

@ -92,7 +92,7 @@ test.obj : test.d
test.exe : test.obj phobos.lib
$(DMD) test.obj -g -L/map
OBJS= Czlib.obj Dzlib.obj \
OBJS= Czlib.obj Dzlib.obj Ccurl.obj \
oldsyserror.obj \
c_stdio.obj
@ -113,8 +113,8 @@ SRCS_1 = std\math.d std\stdio.d std\dateparse.d std\date.d std\datetime.d \
std\intrinsic.d \
std\process.d \
std\system.d \
std\encoding.d
std\encoding.d
SRCS_2 = std\variant.d \
std\stream.d std\socket.d std\socketstream.d \
std\perf.d std\container.d std\conv.d \
@ -287,11 +287,11 @@ SRC_STD_C_FREEBSD= std\c\freebsd\socket.d
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
SRC_ETC=
SRC_ETC_C= etc\c\zlib.d
SRC_ETC_C= etc\c\zlib.d etc\c\curl.d
SRC_ZLIB= \
etc\c\zlib\crc32.h \
@ -547,7 +547,7 @@ biguintnoasm.obj : std\internal\math\biguintnoasm.d
biguintx86.obj : std\internal\math\biguintx86.d
$(DMD) -c $(DFLAGS) std\internal\math\biguintx86.d
gammafunction.obj : std\internal\math\gammafunction.d
$(DMD) -c $(DFLAGS) std\internal\math\gammafunction.d
@ -583,6 +583,9 @@ c_stdio.obj : std\c\stdio.d
Czlib.obj : etc\c\zlib.d
$(DMD) -c $(DFLAGS) etc\c\zlib.d -ofCzlib.obj
Ccurl.obj : etc\c\curl.d
$(DMD) -c $(DFLAGS) etc\c\curl.d -ofCcurl.obj
### std\c\windows
com.obj : std\c\windows\com.d
@ -928,8 +931,8 @@ install:
$(CP) $(DOCS) $(DIR)\html\d\phobos
svn:
$(CP) win32.mak posix.mak $(STDDOC) $(SVN)\
$(CP) $(SRC) $(SVN)\
$(CP) win32.mak posix.mak $(STDDOC) $(SVN)\
$(CP) $(SRC) $(SVN)\
$(CP) $(SRC_STD) $(SVN)\std
$(CP) $(SRC_STD_C) $(SVN)\std\c
$(CP) $(SRC_STD_WIN) $(SVN)\std\windows