mirror of
https://github.com/dlang/phobos.git
synced 2025-04-28 14:10:30 +03:00
Merge branch 'master' of github.com:D-Programming-Language/phobos
Conflicts: posix.mak
This commit is contained in:
commit
055cea0595
15 changed files with 7451 additions and 4778 deletions
16
changelog.dd
Normal file
16
changelog.dd
Normal 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
2193
etc/c/curl.d
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -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 ]);
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
477
std/container.d
477
std/container.d
|
@ -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 {
|
||||
|
|
8668
std/datetime.d
8668
std/datetime.d
File diff suppressed because it is too large
Load diff
638
std/exception.d
638
std/exception.d
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
19
win32.mak
19
win32.mak
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue