mirror of
https://github.com/dlang/phobos.git
synced 2025-04-28 22:21:09 +03:00
Merge pull request #4845 from MartinNowak/merge_stable
Merge remote-tracking branch 'upstream/stable' into merge_stable
This commit is contained in:
commit
df34e4266c
11 changed files with 108 additions and 554 deletions
494
changelog.dd
494
changelog.dd
|
@ -1,503 +1,13 @@
|
|||
Ddoc
|
||||
|
||||
$(COMMENT Pending changelog for 2.072. This will get copied to dlang.org and
|
||||
cleared when master gets merged into stable prior to 2.072.
|
||||
$(COMMENT Pending changelog for 2.073. This will get copied to dlang.org and
|
||||
cleared when master gets merged into stable.
|
||||
)
|
||||
|
||||
$(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,
|
||||
|
||||
$(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:
|
||||
|
|
|
@ -216,7 +216,7 @@ EXTRA_MODULES_INTERNAL := $(addprefix \
|
|||
std/internal/digest/, sha_SSSE3 ) $(addprefix \
|
||||
std/internal/math/, biguintcore biguintnoasm biguintx86 \
|
||||
gammafunction errorfunction) $(addprefix std/internal/, \
|
||||
cstring phobosinit unicode_tables scopebuffer\
|
||||
cstring encodinginit processinit unicode_tables scopebuffer\
|
||||
unicode_comp unicode_decomp unicode_grapheme unicode_norm) \
|
||||
$(addprefix std/internal/test/, dummyrange) \
|
||||
$(addprefix std/experimental/ndslice/, internal) \
|
||||
|
|
|
@ -3573,6 +3573,8 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool)
|
|||
|
||||
_separatorLength = codeLength!(ElementEncodingType!Range)(separator);
|
||||
}
|
||||
if (_input.empty)
|
||||
_frontLength = _atEnd;
|
||||
}
|
||||
|
||||
static if (isInfinite!Range)
|
||||
|
@ -3704,7 +3706,6 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool)
|
|||
|
||||
debug(std_algorithm) scope(success)
|
||||
writeln("unittest @", __FILE__, ":", __LINE__, " done.");
|
||||
assert(equal(splitter("", ' '), [ "" ]));
|
||||
assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ]));
|
||||
assert(equal(splitter("žlutoučkýřkůň", 'ř'), [ "žlutoučký", "kůň" ]));
|
||||
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));
|
||||
a = null;
|
||||
assert(equal(splitter(a, 0), [ (int[]).init ][]));
|
||||
assert(equal(splitter(a, 0), (int[][]).init));
|
||||
a = [ 0 ];
|
||||
assert(equal(splitter(a, 0), [ (int[]).init, (int[]).init ][]));
|
||||
a = [ 0, 1 ];
|
||||
|
@ -3821,17 +3822,17 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
private:
|
||||
Range _input;
|
||||
Separator _separator;
|
||||
enum size_t _unComputed = size_t.max - 1, _atEnd = size_t.max;
|
||||
// _frontLength == _atEnd means empty
|
||||
size_t _frontLength = _unComputed;
|
||||
// _frontLength == size_t.max means empty
|
||||
size_t _frontLength = size_t.max;
|
||||
static if (isBidirectionalRange!Range)
|
||||
size_t _backLength = _unComputed;
|
||||
size_t _backLength = size_t.max;
|
||||
|
||||
@property auto separatorLength() { return _separator.length; }
|
||||
|
||||
void ensureFrontLength()
|
||||
{
|
||||
if (_frontLength != _unComputed) return;
|
||||
if (_frontLength != _frontLength.max) return;
|
||||
assert(!_input.empty);
|
||||
// compute front length
|
||||
_frontLength = (_separator.empty) ? 1 :
|
||||
_input.length - find!pred(_input, _separator).length;
|
||||
|
@ -3842,7 +3843,8 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
void ensureBackLength()
|
||||
{
|
||||
static if (isBidirectionalRange!Range)
|
||||
if (_backLength != _unComputed) return;
|
||||
if (_backLength != _backLength.max) return;
|
||||
assert(!_input.empty);
|
||||
// compute back length
|
||||
static if (isBidirectionalRange!Range && isBidirectionalRange!Separator)
|
||||
{
|
||||
|
@ -3874,7 +3876,7 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
{
|
||||
@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
|
||||
_input = _input[_frontLength .. _frontLength];
|
||||
_frontLength = _atEnd;
|
||||
_frontLength = _frontLength.max;
|
||||
static if (isBidirectionalRange!Range)
|
||||
_backLength = _atEnd;
|
||||
_backLength = _backLength.max;
|
||||
return;
|
||||
}
|
||||
if (_frontLength + separatorLength == _input.length)
|
||||
|
@ -3905,7 +3907,7 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
// reading the next item
|
||||
_input = _input[_frontLength + separatorLength .. _input.length];
|
||||
// mark _frontLength as uninitialized
|
||||
_frontLength = _unComputed;
|
||||
_frontLength = _frontLength.max;
|
||||
}
|
||||
|
||||
static if (isForwardRange!Range)
|
||||
|
@ -3955,8 +3957,6 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
|
|||
|
||||
debug(std_algorithm) scope(success)
|
||||
writeln("unittest @", __FILE__, ":", __LINE__, " done.");
|
||||
assert(equal(splitter("", " "), [ "" ]));
|
||||
|
||||
auto s = ",abc, de, fg,hi,";
|
||||
auto sp0 = splitter(s, ',');
|
||||
// //foreach (e; sp0) writeln("[", e, "]");
|
||||
|
@ -4131,7 +4131,10 @@ private struct SplitterResult(alias isTerminator, Range)
|
|||
static if (!fullSlicing)
|
||||
_next = _input.save;
|
||||
|
||||
findTerminator();
|
||||
if (!_input.empty)
|
||||
findTerminator();
|
||||
else
|
||||
_end = size_t.max;
|
||||
}
|
||||
|
||||
static if (isInfinite!Range)
|
||||
|
@ -4240,7 +4243,7 @@ private struct SplitterResult(alias isTerminator, Range)
|
|||
["Mary", "", "has", "a", "little", "lamb.", "", "", ""]);
|
||||
compare("Mary has a little lamb.",
|
||||
["Mary", "", "has", "a", "little", "lamb."]);
|
||||
compare("", [""]);
|
||||
compare("", (string[]).init);
|
||||
compare(" ", ["", ""]);
|
||||
|
||||
static assert(isForwardRange!(typeof(splitter!"a == ' '"("ABC"))));
|
||||
|
@ -4270,7 +4273,7 @@ private struct SplitterResult(alias isTerminator, Range)
|
|||
int[][] result;
|
||||
}
|
||||
Entry[] entries = [
|
||||
Entry(0, 0, [[]]),
|
||||
Entry(0, 0, []),
|
||||
Entry(0, 1, [[0]]),
|
||||
Entry(1, 2, [[], []]),
|
||||
Entry(2, 7, [[2], [4], [6]]),
|
||||
|
|
|
@ -55,6 +55,7 @@ module std.encoding;
|
|||
import std.traits;
|
||||
import std.typecons;
|
||||
import std.range.primitives;
|
||||
import std.internal.encodinginit;
|
||||
|
||||
@system unittest
|
||||
{
|
||||
|
@ -2360,17 +2361,30 @@ abstract class EncodingScheme
|
|||
* This function allows user-defined subclasses of EncodingScheme to
|
||||
* be declared in other modules.
|
||||
*
|
||||
* Params:
|
||||
* Klass = The subclass of EncodingScheme to register.
|
||||
*
|
||||
* Example:
|
||||
* ----------------------------------------------
|
||||
* class Amiga1251 : EncodingScheme
|
||||
* {
|
||||
* 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)
|
||||
{
|
||||
auto scheme = cast(EncodingScheme)ClassInfo.find(className).create();
|
||||
|
@ -2378,7 +2392,7 @@ abstract class EncodingScheme
|
|||
throw new EncodingException("Unable to create class "~className);
|
||||
foreach (encodingName;scheme.names())
|
||||
{
|
||||
supported[toLower(encodingName)] = className;
|
||||
supportedFactories[toLower(encodingName)] = className;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2396,7 +2410,12 @@ abstract class EncodingScheme
|
|||
*/
|
||||
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)
|
||||
throw new EncodingException("Unrecognized Encoding: "~encodingName);
|
||||
string className = *p;
|
||||
|
@ -2650,7 +2669,8 @@ abstract class EncodingScheme
|
|||
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);
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
|
|
19
std/internal/encodinginit.d
Normal file
19
std/internal/encodinginit.d
Normal 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();
|
||||
}
|
|
@ -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");
|
||||
}
|
22
std/internal/processinit.d
Normal file
22
std/internal/processinit.d
Normal 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();
|
||||
}
|
||||
}
|
|
@ -976,9 +976,7 @@ private final class ParallelismThread : Thread
|
|||
// Kill daemon threads.
|
||||
shared static ~this()
|
||||
{
|
||||
auto allThreads = Thread.getAll();
|
||||
|
||||
foreach (thread; allThreads)
|
||||
foreach (ref thread; Thread)
|
||||
{
|
||||
auto pthread = cast(ParallelismThread) thread;
|
||||
if (pthread is null) continue;
|
||||
|
|
|
@ -100,6 +100,7 @@ version (Windows)
|
|||
|
||||
import std.range.primitives;
|
||||
import std.stdio;
|
||||
import std.internal.processinit;
|
||||
import std.internal.cstring;
|
||||
|
||||
|
||||
|
|
|
@ -274,7 +274,8 @@ SRC_STD_C_FREEBSD= \
|
|||
|
||||
SRC_STD_INTERNAL= \
|
||||
std\internal\cstring.d \
|
||||
std\internal\phobosinit.d \
|
||||
std\internal\encodinginit.d \
|
||||
std\internal\processinit.d \
|
||||
std\internal\unicode_tables.d \
|
||||
std\internal\unicode_comp.d \
|
||||
std\internal\unicode_decomp.d \
|
||||
|
|
|
@ -293,7 +293,8 @@ SRC_STD_C_FREEBSD= \
|
|||
|
||||
SRC_STD_INTERNAL= \
|
||||
std\internal\cstring.d \
|
||||
std\internal\phobosinit.d \
|
||||
std\internal\encodinginit.d \
|
||||
std\internal\processinit.d \
|
||||
std\internal\unicode_tables.d \
|
||||
std\internal\unicode_comp.d \
|
||||
std\internal\unicode_decomp.d \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue