Merge pull request #4845 from MartinNowak/merge_stable

Merge remote-tracking branch 'upstream/stable' into merge_stable
This commit is contained in:
Martin Nowak 2016-10-09 17:38:06 +02:00 committed by GitHub
commit df34e4266c
11 changed files with 108 additions and 554 deletions

View file

@ -1,503 +1,13 @@
Ddoc Ddoc
$(COMMENT Pending changelog for 2.072. This will get copied to dlang.org and $(COMMENT Pending changelog for 2.073. This will get copied to dlang.org and
cleared when master gets merged into stable prior to 2.072. cleared when master gets merged into stable.
) )
$(BUGSTITLE Library Changes, $(BUGSTITLE Library Changes,
$(LI $(RELATIVE_LINK2 std-digest-murmurhash, Implementation of MurmurHash
digest.))
$(LI $(RELATIVE_LINK2 process, Process creation in `std.process` was sped up
on Posix.))
$(LI $(RELATIVE_LINK2 std-algorithm-iteration-cumulativeFold,
`algorithm.iteration.cumulativeFold` was added.))
$(LI $(RELATIVE_LINK2 padLeft-padRight, `std.range.padLeft` and
`std.range.padRight` were added.))
$(LI $(RELATIVE_LINK2 regex-multiple-patterns, `std.regex.regex` now
supports matching multiple patterns in one go.))
$(LI $(RELATIVE_LINK2 regex-with-matches, `std.regex.splitter` now
supports keeping the pattern matches in the resulting range.))
$(LI $(RELATIVE_LINK2 optimization, `findLocalMin` was added to `std.numeric`.))
$(LI $(RELATIVE_LINK2 slice_ptr, `ptr` property and public constructor were
added to `std.experimental.ndslice.slice.Slice`.))
$(LI $(RELATIVE_LINK2 slice_toHash, `toHash` method was
added to `std.experimental.ndslice.slice.Slice`.))
$(LI $(RELATIVE_LINK2 slice_alloc, `slice`, `shape`, `ndarray`, and other
utilities were added to `std.experimental.ndslice.slice`.))
$(LI $(RELATIVE_LINK2 slice_as, `as` lazy tensor was added to
`std.experimental.ndslice.slice`.))
$(LI $(RELATIVE_LINK2 slice_iota, `iotaSlice` lazy tensor was added to
`std.experimental.ndslice.selection`.))
$(LI $(RELATIVE_LINK2 slice_index, `indexSlice` lazy tensor was added to
`std.experimental.ndslice.selection`.))
$(LI $(RELATIVE_LINK2 slice_repeat, `repeatSlice` lazy tensor was added to
`std.experimental.ndslice.selection`.))
$(LI $(RELATIVE_LINK2 slice_map, `mapSlice` lazy tensor was added to
`std.experimental.ndslice.selection`.))
$(LI $(RELATIVE_LINK2 slice_mio, partial support for Math Index Order
was added to `std.experimental.ndslice.slice.Slice`.))
$(LI $(RELATIVE_LINK2 mutation, `std.algorithm.mutation.swapAt` was
exposed))
$(LI $(RELATIVE_LINK2 iota-length-size_t, `std.range.iota's `.length`
property is fixed to `size_t` instead of the type being iterated))
$(LI $(REF isNumber, std,uni) and $(REF isPunctuation, std,uni) now use a separate,
optimized path for ASCII inputs.)
$(LI $(REF isAlphaNum, std,uni), which is analogous to $(REF isAlphaNum, std,ascii)
was added.)
$(LI $(REF regex, std,regex) now supports inline comments with (?#...) syntax.)
$(LI std.regex had numerous optimization applied, compile-time $(REF ctRegex, std,regex)
should now be generally faster then the run-time version.)
$(LI $(REF moveAt, std,range,primitives) accepts only `size_t` for its index
arguments.)
$(LI $(REF isStrictlyMonotonic, std,algorithm,sorting) which doesn't allow
equal values was added.)
$(LI $(REF readLink, std,file) and $(REF symlink, std,file) have been
rangified.)
$(LI All overloads of `std.conv.toImpl` has been made private. Please use
$(REF to, std,conv) instead.)
$(LI $(RELATIVE_LINK2 min-max-element,
`std.algorithm.searching.{min,max}Element` for ranges have been added.))
$(LI $(REF Ternary, std,typecons) was added to represent three valued
logic.)
$(LI $(RELATIVE_LINK2 quantize, Added `std.math.quantize`, for rounding to
the nearest multiple of some number.))
$(LI $(RELATIVE_LINK2 traits, Three new traits were added to `std.traits`.))
$(LI Wrong
$(LINK2 $(ROOT_DIR)spec/function.html#trusted-functions, `@trusted`)
attributes have been
removed from $(MREF etc,c,curl) functions
$(REF_ALTTEXT `curl_easy_escape`, curl_easy_escape, etc,c,curl),
$(REF_ALTTEXT `curl_escape`, curl_escape, etc,c,curl),
$(REF_ALTTEXT `curl_easy_unescape`, curl_easy_unescape, etc,c,curl), and
$(REF_ALTTEXT `curl_unescape`, curl_unescape, etc,c,curl).)
$(LI $(RELATIVE_LINK2 generate, `std.range.generate` fixed to be a proper
range.))
$(LI $(MREF std,numeric) no longer uses `enforce` for verifying
contract preconditions.)
$(LI $(RELATIVE_LINK2 headconst, `Final` was added to
`std.experimental.typecons`))
$(LI $(RELATIVE_LINK2 inner-class, `std.traits.isInnerClass` was added to
identify nested classes with an accessible `outer` pointer))
$(LI $(RELATIVE_LINK2 emplace-inner-class, `std.conv.emplace` no longer allows
to emplace classes directly nested inside other classes without specifying a
suitable `outer` pointer))
) )
$(BUGSTITLE Library Changes, $(BUGSTITLE Library Changes,
$(LI $(LNAME2 std-digest-murmurhash, Implementation of `std.digest.murmurhash`).
$(P $(MREF std,digest,murmurhash) has been added. MurmurHash is a
non-cryptographic hash function suitable for general hash-based lookup. It
is optimized for x86 architectures.
)
------
// Computing the 32-bits hash value of an int array using the convenient digest template.
import std.digest.murmurhash;
ubyte[4] hashed = digest!MurmurHash3_32_opt32([1, 2, 3, 4]);
------
)
$(LI $(LNAME2 process, Process creation in `std.process` was sped up on Posix.)
$(P Previously, Posix systems would attempt to close every file descriptor
from 3 to the maximum file descriptor number if `inheritFDs` was not
specified with `spawnProcess`, `pipeProcess`, etc.
$(MREF std,process) now uses `poll()` to determine which
descriptors need closing.
)
)
$(LI $(LNAME2 std-algorithm-iteration-cumulativeFold,
`algorithm.iteration.cumulativeFold` was added.)
$(P $(REF cumulativeFold, std,algorithm,iteration) returns the successive
reduced values of an input range.)
------
assert([1, 2, 3, 4, 5].cumulativeFold!((a, b) => a + b).array == [1, 3, 6, 10, 15]);
assert([1, 2, 3].cumulativeFold!((a, b) => a + b)(100).array == [101, 103, 106]);
------
)
$(LI $(LNAME2 padLeft-padRight, `std.range.padLeft` and `std.range.padRight`
were added.)
$(P $(REF padLeft, std,range) and $(REF padRight, std,range) are functions for
padding ranges to a specified length using the given element.
)
-------
import std.range;
import std.algorithm.comparison;
assert([1, 2, 3, 4, 5].padLeft(0, 7).equal([0, 0, 1, 2, 3, 4, 5]));
assert("Hello World!".padRight('!', 15).equal("Hello World!!!!"));
-------
)
$(LI $(LNAME2 regex-multiple-patterns, `std.regex.regex` now supports matching multiple patterns in one go.)
-------
import std.regex;
// multi-pattern regex
auto multi = regex([`\d+,\d+`,`(a-z]+):(\d+)`]);
auto m = "abc:43 12,34".matchAll(multi);
assert(m.front.whichPattern == 2);
assert(m.front[1] == "abc");
assert(m.front[2] == "43");
m.popFront();
assert(m.front.whichPattern == 1);
assert(m.front[1] == "12");
-------
)
$(LI $(LNAME2 regex-with-matches, `std.regex.splitter` now supports keeping the
pattern matches in the resulting range.)
-------
import std.regex;
import std.algorithm.comparison : equal;
auto pattern = regex(`([\.,])`);
assert("2003.04.05"
.splitter!(No.keepSeparators)(pattern)
.equal(["2003", "04", "05"]));
assert("2003.04.05"
.splitter!(Yes.keepSeparators)(pattern)
.equal(["2003", ".", "04", ".", "05"]));
-------
)
$(LI $(LNAME2 optimization, `findLocalMin` was added to `std.numeric`.)
$(P $(REF findLocalMin, std,numeric) finds a real minimum of a real function `f(x)` via bracketing.)
-------
import std.numeric, std.math;
auto ret = findLocalMin((double x) => (x-4)^^2, -1e7, 1e7);
assert(ret.x.approxEqual(4.0));
assert(ret.y.approxEqual(0.0));
-------
)
$(LI $(LNAME2 slice_ptr, `ptr` property and public constructor were added to
`std.experimental.ndslice.slice.Slice`.)
$(P `ptr` property allows to access `Slice`'s underlaying pointer or range.
Please refer to $(REF Slice, std,experimental,ndslice,slice)'s
internal binary epresentation before using the property.
`ptr` property is used in $(LINK2 https://github.com/libmir/mir, Mir)
for $(LINK2 http://docs.mir.dlang.io/latest/mir_sparse_package.html, sparse tensors).
`ndslice` developer mirror in Mir will be removed as
soon as LDC (LLVM D compiler) supports D version 2.072..
)
$(P Public constructor for `Slice` was added to support
$(MREF std,experimental,ndslice) integration
with other languages and libraries such as Julia language and NumPy library.
)
)
$(LI $(LNAME2 slice_toHash, $(P $(REF .Slice.toHash, std,experimental,ndslice,slice) method was added.)
---
import std.experimental.ndslice;
// hash is the same for allocated data and generated data
auto a = iotaSlice(3, 7);
auto b = iotaSlice(3, 7).slice;
assert(a.toHash == b.toHash);
---
)
$(LI $(LNAME2 slice_alloc, `slice`, `shape`, `ndarray`, and other utilities
were added to `std.experimental.ndslice.slice`.)
$(P These utility functions have been added to
$(MREF std,experimental,ndslice):)
$(UL
$(LI $(REF makeNdarray, std,experimental,ndslice,slice),)
$(LI $(REF makeSlice, std,experimental,ndslice,slice),)
$(LI $(REF makeUninitializedSlice, std,experimental,ndslice,slice),)
$(LI $(REF ndarray, std,experimental,ndslice,slice),)
$(LI $(REF shape, std,experimental,ndslice,slice),)
$(LI $(REF slice, std,experimental,ndslice,slice),)
$(LI $(REF uninitializedSlice, std,experimental,ndslice,slice).)
)
$(P Example: Transposing common 2D array using `ndslice`)
-----
import std.experimental.ndslice;
auto ar = [[0, 1, 2], [3, 4, 5]];
auto sh = ar.shape; // [2, 3] type of size_t[2]
auto sl = slice!int(sh); // allocates slice with corresponding shape
sl[] = ar; // fills sl with values from ar
ar = sl.transposed.ndarray; // allocates common 2D array
assert(ar == [[0, 3], [1, 4], [2, 5]]);
-----
)
$(LI $(LNAME2 slice_as, $(P $(REF as, std,experimental,ndslice,slice)
lazy tensor was added.)
---
import std.experimental.ndslice;
auto matrix = slice!double([2, 2], 0);
auto stringMatrixView = matrix.as!string;
assert(stringMatrixView ==
[["0", "0"],
["0", "0"]]);
matrix.diagonal[] = 1;
assert(stringMatrixView ==
[["1", "0"],
["0", "1"]]);
---
)
$(LI $(LNAME2 slice_iota, `iotaSlice` lazy tensor was added to `std.experimental.ndslice.selection`.)
$(P $(REF iotaSlice, std,experimental,ndslice,selection) is the fastest possible `Slice`.)
---
import std.experimental.ndslice;
auto sl = iotaSlice([2, 3], 10);
assert(sl.transposed == [[10, 13],
[11, 14],
[12, 15]]);
---
)
$(LI $(LNAME2 slice_index, $(P $(REF indexSlice, std,experimental,ndslice,selection)
lazy tensor was added.)
---
import std.experimental.ndslice;
auto slice = indexSlice(2, 3);
assert(slice == [[[0, 0], [0, 1], [0, 2]],
[[1, 0], [1, 1], [1, 2]]]);
---
)
$(LI $(LNAME2 slice_repeat, $(P $(REF repeatSlice, std,experimental,ndslice,selection)
lazy tensor was added.)
---
import std.experimental.ndslice;
auto sl = iotaSlice(3).repeatSlice(4);
assert(sl == [[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]]);
auto m = 4.repeatSlice(2, 3);
assert(m == [[4, 4, 4],
[4, 4, 4]]);
---
)
$(LI $(LNAME2 slice_map, $(P $(REF mapSlice, std,experimental,ndslice,selection)
lazy tensor was added.)
---
import std.experimental.ndslice;
auto s = iotaSlice(2, 3).mapSlice!(a => a * a);
assert(s == [[ 0, 1, 4],
[ 9, 16, 25]]);
---
)
$(LI $(LNAME2 slice_mio, partial support for Math Index Order was added to `std.experimental.ndslice.slice.Slice`.)
---
import std.experimental.ndslice;
auto sl = iotaSlice(3, 4);
assert(sl[2, 3] == 11); // D & C index order
assert(sl(3, 2) == 11); // Math & Fortran index order
---
)
$(LI $(LNAME2 mutation, `std.algorithm.mutation.swapAt` was exposed)
$(P $(REF swapAt, std,algorithm,mutation) allows to swap elements
of a RandomAccessRange by their indices.
)
)
$(LI $(LNAME2 iota-length-size_t, `std.range.iota's `.length` property is fixed
to `size_t` instead of the type being iterated)
$(P $(REF iota, std,range)'s `.length` property is now always returned as
`size_t`. This means if you are on a 32-bit CPU and you are using
iota to iterate 64-bit types, the length will be truncated to `size_t`.
In non-release mode, you will get an exception if the length exceeds
`size_t.max` in your call to `iota`.
)
)
$(LI $(LNAME2 min-max-element, `std.algorithm.searching.{min,max}Element`
have been added.)
$(P $(REF minElement, algorithm,searching) and $(REF maxElement,
algorithm,searching) are functions to search for the minimum and maximum
element in a range. They support a custom `map` accessor.
)
-------
import std.algorithm.searching;
import std.range;
import std.typecons;
assert([3, 1, 4].minElement == 1);
assert([4, 7, 5].enumerate.maxElement!`a.value` == tuple(1, 7));
-------
)
$(LI $(LNAME2 quantize, Added `std.math.quantize`.)
$(P $(REF quantize, std,math) rounds to the nearest multiple of some number.
Features:)
$(UL
$(LI The rounding method can be specified using the `rfunc` parameter. By
default, the current rounding mode will be used, which is typically
"banker's rounding".)
$(LI Overloads are included for the common case of rounding to the $(I Nth)
digit place in some base.)
$(LI If known at compile time, the base and exponent (digit place) can be
supplied as template parameters for better performance.)
)
---
import std.math;
assert(12345.6789L.quantize(20.0L) == 12340.0L);
assert(12345.6789L.quantize!(10, -2) == 12345.68L);
assert(12345.6789L.quantize!(10, floor)(-2) == 12345.67L);
---
)
$(LI $(LNAME2 traits, Three new traits were added to `std.traits`.)
$(P $(REF isType, std,traits), $(REF isFunction, std,traits), and
$(REF isFinal, std,traits) were added to `std.traits`.
)
-------
import std.traits;
static assert(isType!int);
struct S {}
class C {}
interface I {}
static assert(isType!S);
static assert(isType!C);
static assert(isType!I);
-------
-------
import std.traits;
void func(){}
struct S
{
@property int prop(){ return 0; }
}
static assert(isFunction!func);
static assert(isFunction!(S.prop));
// is a delegate type, not function type
static assert(!isFunction!(typeof(&S.prop)));
-------
-------
import std.traits;
class C
{
void nf() {}
final void ff() {}
}
final class FC {}
static assert(!isFinal!(C));
static assert( isFinal!(FC));
static assert(!isFinal!(C.nf));
static assert( isFinal!(C.ff));
-------
)
$(LI $(LNAME2 generate, `std.range.generate` fixed to be a proper range.)
$(P $(REF generate, std, range) was set up to return a different value on each
call to `front`. In addition, `popFront` did nothing. This means that
manipulation functions like $(REF drop, std, range) did nothing. The new
version uses a one-element cache to meet the expectations of the range
definition. It preserves the ref-ness of the generator as well.
)
)
$(LI $(LNAME2 headconst, `Final` was added to `std.experimental.typecons`.)
$(P $(REF Final, std, experimental, typecons) can't be mutated directly.
However references are typed with their original mutability. This is
equivalent to `final` in Java or `readonly` in C#.
)
-------
auto a = makeFinal([1, 2, 3]);
assert(a[0] == 1);
// a = [2, 3]; // Reassignment is illegal,
a[0] = 42; // Elements or fields are still mutable.
assert(a[0] == 42);
-------
)
$(LI $(LNAME2 inner-class, `std.traits.isInnerClass` was added to identify
nested classes with an accessible `outer` pointer)
$(P Classes, that are nested inside other classes (and not inside functions)
and that don't define any `outer` symbol, have an `outer` field which allows
to get and even set the instance of the outer class they are nested in.
$(REF isInnerClass, std, traits) allows to identify them. The types satisfying
`isInnerClass` are a subset of the ones satisfying `isNested`, as the latter
includes classes and structures nested inside functions or that redefine `outer`.
)
-------
class Outer
{
class Inner1 { }
class Inner2
{
int outer; // redefines outer, so the Outer instance is not accessible
}
static class Inner3 {} // static, thus not nested
}
static assert(isInnerClass!(Outer.Inner1));
static assert(!isInnerClass!(Outer.Inner2));
static assert(!isInnerClass!(Outer.Inner3));
-------
)
$(LI $(LNAME2 emplace-inner-class, `std.conv.emplace` no longer allows to emplace
classes nested directly inside other classes without specifying a suitable `outer`
pointer)
$(P If a class is nested within another class (there's a new trait
$(REF isInnerClass, std, traits) to check for this condition), `emplace` requires
now the outer class instance as additional mandatory parameter. Before this
change, emplacing did not require this parameter and access to variables of the
outer class resulted in segmentation faults.
)
-------
class Outer
{
int x;
class Inner
{
auto getX() { return x; }
}
}
Outer outer = new Outer();
// auto inner = buf.emplace!(Outer.Inner)(); // this is no longer allowed
auto inner = buf.emplace!(Outer.Inner)(outer); // use this instead
auto x = inner.getX(); // this used to cause a segmentation fault;
// now it works as expected
-------
)
) )
Macros: Macros:

View file

@ -216,7 +216,7 @@ EXTRA_MODULES_INTERNAL := $(addprefix \
std/internal/digest/, sha_SSSE3 ) $(addprefix \ std/internal/digest/, sha_SSSE3 ) $(addprefix \
std/internal/math/, biguintcore biguintnoasm biguintx86 \ std/internal/math/, biguintcore biguintnoasm biguintx86 \
gammafunction errorfunction) $(addprefix std/internal/, \ gammafunction errorfunction) $(addprefix std/internal/, \
cstring phobosinit unicode_tables scopebuffer\ cstring encodinginit processinit unicode_tables scopebuffer\
unicode_comp unicode_decomp unicode_grapheme unicode_norm) \ unicode_comp unicode_decomp unicode_grapheme unicode_norm) \
$(addprefix std/internal/test/, dummyrange) \ $(addprefix std/internal/test/, dummyrange) \
$(addprefix std/experimental/ndslice/, internal) \ $(addprefix std/experimental/ndslice/, internal) \

View file

@ -3573,6 +3573,8 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool)
_separatorLength = codeLength!(ElementEncodingType!Range)(separator); _separatorLength = codeLength!(ElementEncodingType!Range)(separator);
} }
if (_input.empty)
_frontLength = _atEnd;
} }
static if (isInfinite!Range) static if (isInfinite!Range)
@ -3704,7 +3706,6 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool)
debug(std_algorithm) scope(success) debug(std_algorithm) scope(success)
writeln("unittest @", __FILE__, ":", __LINE__, " done."); writeln("unittest @", __FILE__, ":", __LINE__, " done.");
assert(equal(splitter("", ' '), [ "" ]));
assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ]));
assert(equal(splitter("žlutoučkýřkůň", 'ř'), [ "žlutoučký", "kůň" ])); assert(equal(splitter("žlutoučkýřkůň", 'ř'), [ "žlutoučký", "kůň" ]));
int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ]; int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ];
@ -3717,7 +3718,7 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool)
// } // }
assert(equal(splitter(a, 0), w)); assert(equal(splitter(a, 0), w));
a = null; a = null;
assert(equal(splitter(a, 0), [ (int[]).init ][])); assert(equal(splitter(a, 0), (int[][]).init));
a = [ 0 ]; a = [ 0 ];
assert(equal(splitter(a, 0), [ (int[]).init, (int[]).init ][])); assert(equal(splitter(a, 0), [ (int[]).init, (int[]).init ][]));
a = [ 0, 1 ]; a = [ 0, 1 ];
@ -3821,17 +3822,17 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
private: private:
Range _input; Range _input;
Separator _separator; Separator _separator;
enum size_t _unComputed = size_t.max - 1, _atEnd = size_t.max; // _frontLength == size_t.max means empty
// _frontLength == _atEnd means empty size_t _frontLength = size_t.max;
size_t _frontLength = _unComputed;
static if (isBidirectionalRange!Range) static if (isBidirectionalRange!Range)
size_t _backLength = _unComputed; size_t _backLength = size_t.max;
@property auto separatorLength() { return _separator.length; } @property auto separatorLength() { return _separator.length; }
void ensureFrontLength() void ensureFrontLength()
{ {
if (_frontLength != _unComputed) return; if (_frontLength != _frontLength.max) return;
assert(!_input.empty);
// compute front length // compute front length
_frontLength = (_separator.empty) ? 1 : _frontLength = (_separator.empty) ? 1 :
_input.length - find!pred(_input, _separator).length; _input.length - find!pred(_input, _separator).length;
@ -3842,7 +3843,8 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
void ensureBackLength() void ensureBackLength()
{ {
static if (isBidirectionalRange!Range) static if (isBidirectionalRange!Range)
if (_backLength != _unComputed) return; if (_backLength != _backLength.max) return;
assert(!_input.empty);
// compute back length // compute back length
static if (isBidirectionalRange!Range && isBidirectionalRange!Separator) static if (isBidirectionalRange!Range && isBidirectionalRange!Separator)
{ {
@ -3874,7 +3876,7 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
{ {
@property bool empty() @property bool empty()
{ {
return _frontLength == _atEnd; return _frontLength == size_t.max && _input.empty;
} }
} }
@ -3886,9 +3888,9 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
{ {
// done, there's no separator in sight // done, there's no separator in sight
_input = _input[_frontLength .. _frontLength]; _input = _input[_frontLength .. _frontLength];
_frontLength = _atEnd; _frontLength = _frontLength.max;
static if (isBidirectionalRange!Range) static if (isBidirectionalRange!Range)
_backLength = _atEnd; _backLength = _backLength.max;
return; return;
} }
if (_frontLength + separatorLength == _input.length) if (_frontLength + separatorLength == _input.length)
@ -3905,7 +3907,7 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
// reading the next item // reading the next item
_input = _input[_frontLength + separatorLength .. _input.length]; _input = _input[_frontLength + separatorLength .. _input.length];
// mark _frontLength as uninitialized // mark _frontLength as uninitialized
_frontLength = _unComputed; _frontLength = _frontLength.max;
} }
static if (isForwardRange!Range) static if (isForwardRange!Range)
@ -3955,8 +3957,6 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
debug(std_algorithm) scope(success) debug(std_algorithm) scope(success)
writeln("unittest @", __FILE__, ":", __LINE__, " done."); writeln("unittest @", __FILE__, ":", __LINE__, " done.");
assert(equal(splitter("", " "), [ "" ]));
auto s = ",abc, de, fg,hi,"; auto s = ",abc, de, fg,hi,";
auto sp0 = splitter(s, ','); auto sp0 = splitter(s, ',');
// //foreach (e; sp0) writeln("[", e, "]"); // //foreach (e; sp0) writeln("[", e, "]");
@ -4131,7 +4131,10 @@ private struct SplitterResult(alias isTerminator, Range)
static if (!fullSlicing) static if (!fullSlicing)
_next = _input.save; _next = _input.save;
findTerminator(); if (!_input.empty)
findTerminator();
else
_end = size_t.max;
} }
static if (isInfinite!Range) static if (isInfinite!Range)
@ -4240,7 +4243,7 @@ private struct SplitterResult(alias isTerminator, Range)
["Mary", "", "has", "a", "little", "lamb.", "", "", ""]); ["Mary", "", "has", "a", "little", "lamb.", "", "", ""]);
compare("Mary has a little lamb.", compare("Mary has a little lamb.",
["Mary", "", "has", "a", "little", "lamb."]); ["Mary", "", "has", "a", "little", "lamb."]);
compare("", [""]); compare("", (string[]).init);
compare(" ", ["", ""]); compare(" ", ["", ""]);
static assert(isForwardRange!(typeof(splitter!"a == ' '"("ABC")))); static assert(isForwardRange!(typeof(splitter!"a == ' '"("ABC"))));
@ -4270,7 +4273,7 @@ private struct SplitterResult(alias isTerminator, Range)
int[][] result; int[][] result;
} }
Entry[] entries = [ Entry[] entries = [
Entry(0, 0, [[]]), Entry(0, 0, []),
Entry(0, 1, [[0]]), Entry(0, 1, [[0]]),
Entry(1, 2, [[], []]), Entry(1, 2, [[], []]),
Entry(2, 7, [[2], [4], [6]]), Entry(2, 7, [[2], [4], [6]]),

View file

@ -55,6 +55,7 @@ module std.encoding;
import std.traits; import std.traits;
import std.typecons; import std.typecons;
import std.range.primitives; import std.range.primitives;
import std.internal.encodinginit;
@system unittest @system unittest
{ {
@ -2360,17 +2361,30 @@ abstract class EncodingScheme
* This function allows user-defined subclasses of EncodingScheme to * This function allows user-defined subclasses of EncodingScheme to
* be declared in other modules. * be declared in other modules.
* *
* Params:
* Klass = The subclass of EncodingScheme to register.
*
* Example: * Example:
* ---------------------------------------------- * ----------------------------------------------
* class Amiga1251 : EncodingScheme * class Amiga1251 : EncodingScheme
* { * {
* shared static this() * shared static this()
* { * {
* EncodingScheme.register("path.to.Amiga1251"); * EncodingScheme.register!Amiga1251;
* } * }
* } * }
* ---------------------------------------------- * ----------------------------------------------
*/ */
static void register(Klass:EncodingScheme)()
{
scope scheme = new Klass();
foreach (encodingName;scheme.names())
{
supported[toLower(encodingName)] = () => new Klass();
}
}
deprecated("Please pass the EncodingScheme subclass as template argument instead.")
static void register(string className) static void register(string className)
{ {
auto scheme = cast(EncodingScheme)ClassInfo.find(className).create(); auto scheme = cast(EncodingScheme)ClassInfo.find(className).create();
@ -2378,7 +2392,7 @@ abstract class EncodingScheme
throw new EncodingException("Unable to create class "~className); throw new EncodingException("Unable to create class "~className);
foreach (encodingName;scheme.names()) foreach (encodingName;scheme.names())
{ {
supported[toLower(encodingName)] = className; supportedFactories[toLower(encodingName)] = className;
} }
} }
@ -2396,7 +2410,12 @@ abstract class EncodingScheme
*/ */
static EncodingScheme create(string encodingName) static EncodingScheme create(string encodingName)
{ {
auto p = toLower(encodingName) in supported; encodingName = toLower(encodingName);
if (auto p = encodingName in supported)
return (*p)();
auto p = encodingName in supportedFactories;
if (p is null) if (p is null)
throw new EncodingException("Unrecognized Encoding: "~encodingName); throw new EncodingException("Unrecognized Encoding: "~encodingName);
string className = *p; string className = *p;
@ -2650,7 +2669,8 @@ abstract class EncodingScheme
return t.length - s.length; return t.length - s.length;
} }
__gshared string[string] supported; __gshared EncodingScheme function()[string] supported;
__gshared string[string] supportedFactories;
} }
/** /**
@ -3297,6 +3317,20 @@ class EncodingSchemeUtf32Native : EncodingScheme
assert(ub.length == 8); assert(ub.length == 8);
} }
// shared static this() called from encodinginit to break ctor cycle
extern(C) void std_encoding_shared_static_this()
{
EncodingScheme.register!EncodingSchemeASCII;
EncodingScheme.register!EncodingSchemeLatin1;
EncodingScheme.register!EncodingSchemeLatin2;
EncodingScheme.register!EncodingSchemeWindows1250;
EncodingScheme.register!EncodingSchemeWindows1252;
EncodingScheme.register!EncodingSchemeUtf8;
EncodingScheme.register!EncodingSchemeUtf16Native;
EncodingScheme.register!EncodingSchemeUtf32Native;
}
//============================================================================= //=============================================================================

View file

@ -0,0 +1,19 @@
// Written in the D programming language.
/++
The purpose of this module is to perform static construction away from the
normal modules to eliminate cyclic construction errors.
Copyright: Copyright 2011 - 2016
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: Martin Nowak, Steven Schveighoffer
Source: $(PHOBOSSRC std/internal/_encodinginit.d)
+/
module std.internal.encodinginit;
extern(C) void std_encoding_shared_static_this();
shared static this()
{
std_encoding_shared_static_this();
}

View file

@ -1,35 +0,0 @@
// Written in the D programming language.
/++
The purpose of this module is to perform static construction away from the
normal modules to eliminate cyclic construction errors.
Copyright: Copyright 2011 - 2016
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: Jonathan M Davis, Kato Shoichi, Steven Schveighoffer
Source: $(PHOBOSSRC std/internal/_phobosinit.d)
+/
module std.internal.phobosinit;
version(OSX)
{
extern(C) void std_process_shared_static_this();
shared static this()
{
std_process_shared_static_this();
}
}
shared static this()
{
import std.encoding : EncodingScheme;
EncodingScheme.register("std.encoding.EncodingSchemeASCII");
EncodingScheme.register("std.encoding.EncodingSchemeLatin1");
EncodingScheme.register("std.encoding.EncodingSchemeLatin2");
EncodingScheme.register("std.encoding.EncodingSchemeWindows1250");
EncodingScheme.register("std.encoding.EncodingSchemeWindows1252");
EncodingScheme.register("std.encoding.EncodingSchemeUtf8");
EncodingScheme.register("std.encoding.EncodingSchemeUtf16Native");
EncodingScheme.register("std.encoding.EncodingSchemeUtf32Native");
}

View file

@ -0,0 +1,22 @@
// Written in the D programming language.
/++
The only purpose of this module is to do the static construction for
std.process in order to eliminate cyclic construction errors.
Copyright: Copyright 2011 -
License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
Authors: Jonathan M Davis and Kato Shoichi
Source: $(PHOBOSSRC std/internal/_processinit.d)
+/
module std.internal.processinit;
version(OSX)
{
extern(C) void std_process_shared_static_this();
shared static this()
{
std_process_shared_static_this();
}
}

View file

@ -976,9 +976,7 @@ private final class ParallelismThread : Thread
// Kill daemon threads. // Kill daemon threads.
shared static ~this() shared static ~this()
{ {
auto allThreads = Thread.getAll(); foreach (ref thread; Thread)
foreach (thread; allThreads)
{ {
auto pthread = cast(ParallelismThread) thread; auto pthread = cast(ParallelismThread) thread;
if (pthread is null) continue; if (pthread is null) continue;

View file

@ -100,6 +100,7 @@ version (Windows)
import std.range.primitives; import std.range.primitives;
import std.stdio; import std.stdio;
import std.internal.processinit;
import std.internal.cstring; import std.internal.cstring;

View file

@ -274,7 +274,8 @@ SRC_STD_C_FREEBSD= \
SRC_STD_INTERNAL= \ SRC_STD_INTERNAL= \
std\internal\cstring.d \ std\internal\cstring.d \
std\internal\phobosinit.d \ std\internal\encodinginit.d \
std\internal\processinit.d \
std\internal\unicode_tables.d \ std\internal\unicode_tables.d \
std\internal\unicode_comp.d \ std\internal\unicode_comp.d \
std\internal\unicode_decomp.d \ std\internal\unicode_decomp.d \

View file

@ -293,7 +293,8 @@ SRC_STD_C_FREEBSD= \
SRC_STD_INTERNAL= \ SRC_STD_INTERNAL= \
std\internal\cstring.d \ std\internal\cstring.d \
std\internal\phobosinit.d \ std\internal\encodinginit.d \
std\internal\processinit.d \
std\internal\unicode_tables.d \ std\internal\unicode_tables.d \
std\internal\unicode_comp.d \ std\internal\unicode_comp.d \
std\internal\unicode_decomp.d \ std\internal\unicode_decomp.d \