aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2025-01-07 01:05:54 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2025-01-11 02:21:39 +0100
commitdd3026f05111a0858ee87146ba9c37f164afa815 (patch)
tree98325195cedbde6e098d1994ae97975e1461ae21 /libphobos/src/std
parentb0eeb540497c7b9dee01f8724f9a4978b53a12ae (diff)
downloadgcc-dd3026f05111a0858ee87146ba9c37f164afa815.zip
gcc-dd3026f05111a0858ee87146ba9c37f164afa815.tar.gz
gcc-dd3026f05111a0858ee87146ba9c37f164afa815.tar.bz2
d: Merge dmd, druntime 2b89c2909d, phobos bdedad3bf
D front-end changes: - Import latest fixes from dmd v2.110.0-beta.1. D runtime changes: - Import latest fixes from druntime v2.110.0-beta.1. Phobos changes: - Import latest fixes from phobos v2.110.0-beta.1. - Added `popGrapheme' function to `std.uni'. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 2b89c2909d. * Make-lang.in (D_FRONTEND_OBJS): Rename d/basicmangle.o to d/mangle-basic.o, d/cppmangle.o to d/mangle-cpp.o, and d/dmangle.o to d/mangle-package.o. (d/mangle-%.o): New rule. * d-builtins.cc (maybe_set_builtin_1): Update for new front-end interface. * d-diagnostic.cc (verrorReport): Likewise. (verrorReportSupplemental): Likewise. * d-frontend.cc (getTypeInfoType): Likewise. * d-lang.cc (d_init_options): Likewise. (d_handle_option): Likewise. (d_post_options): Likewise. * d-target.cc (TargetC::contributesToAggregateAlignment): New. * d-tree.h (create_typeinfo): Adjust prototype. * decl.cc (layout_struct_initializer): Update for new front-end interface. * typeinfo.cc (create_typeinfo): Remove generate parameter. * types.cc (layout_aggregate_members): Update for new front-end interface. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 2b89c2909d. * src/MERGE: Merge upstream phobos bdedad3bf.
Diffstat (limited to 'libphobos/src/std')
-rw-r--r--libphobos/src/std/algorithm/comparison.d2
-rw-r--r--libphobos/src/std/algorithm/iteration.d9
-rw-r--r--libphobos/src/std/algorithm/mutation.d14
-rw-r--r--libphobos/src/std/algorithm/sorting.d73
-rw-r--r--libphobos/src/std/array.d9
-rw-r--r--libphobos/src/std/base64.d69
-rw-r--r--libphobos/src/std/bigint.d64
-rw-r--r--libphobos/src/std/bitmanip.d276
-rw-r--r--libphobos/src/std/checkedint.d12
-rw-r--r--libphobos/src/std/complex.d32
-rw-r--r--libphobos/src/std/concurrency.d3
-rw-r--r--libphobos/src/std/container/dlist.d3
-rw-r--r--libphobos/src/std/container/package.d12
-rw-r--r--libphobos/src/std/container/rbtree.d23
-rw-r--r--libphobos/src/std/container/slist.d3
-rw-r--r--libphobos/src/std/container/util.d4
-rw-r--r--libphobos/src/std/conv.d25
-rw-r--r--libphobos/src/std/datetime/date.d60
-rw-r--r--libphobos/src/std/datetime/interval.d26
-rw-r--r--libphobos/src/std/datetime/systime.d30
-rw-r--r--libphobos/src/std/datetime/timezone.d10
-rw-r--r--libphobos/src/std/exception.d4
-rw-r--r--libphobos/src/std/experimental/allocator/common.d33
-rw-r--r--libphobos/src/std/experimental/allocator/mallocator.d30
-rw-r--r--libphobos/src/std/file.d2
-rw-r--r--libphobos/src/std/format/internal/write.d15
-rw-r--r--libphobos/src/std/functional.d2
-rw-r--r--libphobos/src/std/int128.d68
-rw-r--r--libphobos/src/std/internal/math/biguintcore.d37
-rw-r--r--libphobos/src/std/internal/test/dummyrange.d23
-rw-r--r--libphobos/src/std/json.d423
-rw-r--r--libphobos/src/std/logger/core.d20
-rw-r--r--libphobos/src/std/numeric.d39
-rw-r--r--libphobos/src/std/parallelism.d3
-rw-r--r--libphobos/src/std/path.d17
-rw-r--r--libphobos/src/std/process.d111
-rw-r--r--libphobos/src/std/random.d15
-rw-r--r--libphobos/src/std/range/package.d76
-rw-r--r--libphobos/src/std/range/primitives.d3
-rw-r--r--libphobos/src/std/regex/internal/backtracking.d4
-rw-r--r--libphobos/src/std/regex/internal/parser.d2
-rw-r--r--libphobos/src/std/regex/internal/thompson.d18
-rw-r--r--libphobos/src/std/regex/package.d2
-rw-r--r--libphobos/src/std/socket.d2
-rw-r--r--libphobos/src/std/stdio.d35
-rw-r--r--libphobos/src/std/string.d228
-rw-r--r--libphobos/src/std/traits.d6
-rw-r--r--libphobos/src/std/typecons.d56
-rw-r--r--libphobos/src/std/uni/package.d250
-rw-r--r--libphobos/src/std/utf.d4
-rw-r--r--libphobos/src/std/uuid.d5
-rw-r--r--libphobos/src/std/variant.d13
52 files changed, 1482 insertions, 823 deletions
diff --git a/libphobos/src/std/algorithm/comparison.d b/libphobos/src/std/algorithm/comparison.d
index 5c70960..60fd114 100644
--- a/libphobos/src/std/algorithm/comparison.d
+++ b/libphobos/src/std/algorithm/comparison.d
@@ -102,7 +102,7 @@ template among(values...)
if (isExpressionTuple!values)
{
uint among(Value)(Value value)
- if (!is(CommonType!(Value, values) == void))
+ if (!is(CommonType!(Value, values) == void))
{
switch (value)
{
diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d
index 1453d2b..8a3add3 100644
--- a/libphobos/src/std/algorithm/iteration.d
+++ b/libphobos/src/std/algorithm/iteration.d
@@ -443,7 +443,8 @@ if (fun.length >= 1)
A range with each fun applied to all the elements. If there is more than one
fun, the element type will be `Tuple` containing one element for each fun.
*/
- auto map(Range)(Range r) if (isInputRange!(Unqual!Range))
+ auto map(Range)(Range r)
+ if (isInputRange!(Unqual!Range))
{
import std.meta : AliasSeq, staticMap;
@@ -1308,7 +1309,8 @@ if (is(typeof(unaryFun!predicate)))
A range containing only elements `x` in `range` for
which `predicate(x)` returns `true`.
*/
- auto filter(Range)(Range range) if (isInputRange!(Unqual!Range))
+ auto filter(Range)(Range range)
+ if (isInputRange!(Unqual!Range))
{
return FilterResult!(unaryFun!predicate, Range)(range);
}
@@ -1545,7 +1547,8 @@ template filterBidirectional(alias pred)
Returns:
A range containing only the elements in `r` for which `pred` returns `true`.
*/
- auto filterBidirectional(Range)(Range r) if (isBidirectionalRange!(Unqual!Range))
+ auto filterBidirectional(Range)(Range r)
+ if (isBidirectionalRange!(Unqual!Range))
{
return FilterBidiResult!(unaryFun!pred, Range)(r);
}
diff --git a/libphobos/src/std/algorithm/mutation.d b/libphobos/src/std/algorithm/mutation.d
index e434d24..ea1a1b2 100644
--- a/libphobos/src/std/algorithm/mutation.d
+++ b/libphobos/src/std/algorithm/mutation.d
@@ -2860,6 +2860,13 @@ Params:
lhs = Data to be swapped with `rhs`.
rhs = Data to be swapped with `lhs`.
*/
+void swap(T)(ref T lhs, ref T rhs)
+if (is(typeof(lhs.proxySwap(rhs))))
+{
+ lhs.proxySwap(rhs);
+}
+
+/// ditto
void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow @nogc
if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))))
{
@@ -3121,13 +3128,6 @@ if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))))
swap(a3, a4);
}
-/// ditto
-void swap(T)(ref T lhs, ref T rhs)
-if (is(typeof(lhs.proxySwap(rhs))))
-{
- lhs.proxySwap(rhs);
-}
-
/**
Swaps two elements in-place of a range `r`,
specified by their indices `i1` and `i2`.
diff --git a/libphobos/src/std/algorithm/sorting.d b/libphobos/src/std/algorithm/sorting.d
index cb47153..29839d1 100644
--- a/libphobos/src/std/algorithm/sorting.d
+++ b/libphobos/src/std/algorithm/sorting.d
@@ -2625,11 +2625,21 @@ private template TimSortImpl(alias pred, R)
// can't use `temp.length` if there's no default constructor
static if (__traits(compiles, { T defaultConstructed; cast(void) defaultConstructed; }))
{
- if (__ctfe) temp.length = newSize;
- else temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
+
+ static if (hasElaborateAssign!T)
+ temp.length = newSize;
+ else
+ {
+ if (__ctfe) temp.length = newSize;
+ else temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
+ }
}
else
{
+ static assert(!hasElaborateAssign!T,
+ "Structs which have opAssign but cannot be default-initialized " ~
+ "do not currently work with stable sort: " ~
+ "https://issues.dlang.org/show_bug.cgi?id=24810");
temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
}
}
@@ -3093,6 +3103,65 @@ private template TimSortImpl(alias pred, R)
array.sort!((a, b) => false, SwapStrategy.stable);
}
+// https://issues.dlang.org/show_bug.cgi?id=24809
+@safe unittest
+{
+ static struct E
+ {
+ int value;
+ int valid = 42;
+
+ ~this()
+ {
+ assert(valid == 42);
+ }
+ }
+
+ import std.array : array;
+ import std.range : chain, only, repeat;
+ auto arr = chain(repeat(E(41), 18),
+ only(E(39)),
+ repeat(E(41), 16),
+ only(E(1)),
+ repeat(E(42), 33),
+ only(E(33)),
+ repeat(E(42), 16),
+ repeat(E(43), 27),
+ only(E(33)),
+ repeat(E(43), 34),
+ only(E(34)),
+ only(E(43)),
+ only(E(63)),
+ repeat(E(44), 42),
+ only(E(27)),
+ repeat(E(44), 11),
+ repeat(E(45), 64),
+ repeat(E(46), 3),
+ only(E(11)),
+ repeat(E(46), 7),
+ only(E(4)),
+ repeat(E(46), 34),
+ only(E(36)),
+ repeat(E(46), 17),
+ repeat(E(47), 36),
+ only(E(39)),
+ repeat(E(47), 26),
+ repeat(E(48), 17),
+ only(E(21)),
+ repeat(E(48), 5),
+ only(E(39)),
+ repeat(E(48), 14),
+ only(E(58)),
+ repeat(E(48), 24),
+ repeat(E(49), 13),
+ only(E(40)),
+ repeat(E(49), 38),
+ only(E(18)),
+ repeat(E(49), 11),
+ repeat(E(50), 6)).array();
+
+ arr.sort!((a, b) => a.value < b.value, SwapStrategy.stable)();
+}
// schwartzSort
/**
diff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d
index 27d2167..acd5311 100644
--- a/libphobos/src/std/array.d
+++ b/libphobos/src/std/array.d
@@ -3701,7 +3701,8 @@ if (isDynamicArray!A)
* Params:
* item = the single item to append
*/
- void put(U)(U item) if (canPutItem!U)
+ void put(U)(U item)
+ if (canPutItem!U)
{
static if (isSomeChar!T && isSomeChar!U && T.sizeof < U.sizeof)
{
@@ -3730,7 +3731,8 @@ if (isDynamicArray!A)
}
// Const fixing hack.
- void put(Range)(Range items) if (canPutConstRange!Range)
+ void put(Range)(Range items)
+ if (canPutConstRange!Range)
{
alias p = put!(Unqual!Range);
p(items);
@@ -3743,7 +3745,8 @@ if (isDynamicArray!A)
* Params:
* items = the range of items to append
*/
- void put(Range)(Range items) if (canPutRange!Range)
+ void put(Range)(Range items)
+ if (canPutRange!Range)
{
// note, we disable this branch for appending one type of char to
// another because we can't trust the length portion.
diff --git a/libphobos/src/std/base64.d b/libphobos/src/std/base64.d
index 0fc92ac..0ce81b5 100644
--- a/libphobos/src/std/base64.d
+++ b/libphobos/src/std/base64.d
@@ -299,9 +299,10 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
* ditto
*/
- char[] encode(R1, R2)(R1 source, R2 buffer) if (!isArray!R1 && isInputRange!R1 &&
- is(ElementType!R1 : ubyte) && hasLength!R1 &&
- is(R2 == char[]))
+ char[] encode(R1, R2)(R1 source, R2 buffer)
+ if (!isArray!R1 && isInputRange!R1 &&
+ is(ElementType!R1 : ubyte) && hasLength!R1 &&
+ is(R2 == char[]))
in
{
assert(buffer.length >= encodeLength(source.length), "Insufficient buffer for encoding");
@@ -474,8 +475,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* ditto
*/
size_t encode(R1, R2)(R1 source, auto ref R2 range)
- if (!isArray!R1 && isInputRange!R1 && is(ElementType!R1 : ubyte) &&
- hasLength!R1 && !is(R2 == char[]) && isOutputRange!(R2, char))
+ if (!isArray!R1 && isInputRange!R1 && is(ElementType!R1 : ubyte) &&
+ hasLength!R1 && !is(R2 == char[]) && isOutputRange!(R2, char))
{
immutable srcLen = source.length;
if (srcLen == 0)
@@ -559,7 +560,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* A newly-allocated `char[]` buffer containing the encoded string.
*/
@safe
- pure char[] encode(Range)(Range source) if (isArray!Range && is(ElementType!Range : ubyte))
+ pure char[] encode(Range)(Range source)
+ if (isArray!Range && is(ElementType!Range : ubyte))
{
return encode(source, new char[encodeLength(source.length)]);
}
@@ -575,8 +577,9 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
* ditto
*/
- char[] encode(Range)(Range source) if (!isArray!Range && isInputRange!Range &&
- is(ElementType!Range : ubyte) && hasLength!Range)
+ char[] encode(Range)(Range source)
+ if (!isArray!Range && isInputRange!Range &&
+ is(ElementType!Range : ubyte) && hasLength!Range)
{
return encode(source, new char[encodeLength(source.length)]);
}
@@ -592,8 +595,9 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Note: This struct is not intended to be created in user code directly;
* use the $(LREF encoder) function instead.
*/
- struct Encoder(Range) if (isInputRange!Range && (is(ElementType!Range : const(ubyte)[]) ||
- is(ElementType!Range : const(char)[])))
+ struct Encoder(Range)
+ if (isInputRange!Range && (is(ElementType!Range : const(ubyte)[]) ||
+ is(ElementType!Range : const(char)[])))
{
private:
Range range_;
@@ -702,7 +706,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Note: This struct is not intended to be created in user code directly;
* use the $(LREF encoder) function instead.
*/
- struct Encoder(Range) if (isInputRange!Range && is(ElementType!Range : ubyte))
+ struct Encoder(Range)
+ if (isInputRange!Range && is(ElementType!Range : ubyte))
{
private:
Range range_;
@@ -884,7 +889,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* }
* -----
*/
- Encoder!(Range) encoder(Range)(Range range) if (isInputRange!Range)
+ Encoder!(Range) encoder(Range)(Range range)
+ if (isInputRange!Range)
{
return typeof(return)(range);
}
@@ -981,8 +987,9 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* base alphabet of the current Base64 encoding scheme.
*/
@trusted
- pure ubyte[] decode(R1, R2)(in R1 source, return scope R2 buffer) if (isArray!R1 && is(ElementType!R1 : dchar) &&
- is(R2 == ubyte[]) && isOutputRange!(R2, ubyte))
+ pure ubyte[] decode(R1, R2)(in R1 source, return scope R2 buffer)
+ if (isArray!R1 && is(ElementType!R1 : dchar) &&
+ is(R2 == ubyte[]) && isOutputRange!(R2, ubyte))
in
{
assert(buffer.length >= realDecodeLength(source), "Insufficient buffer for decoding");
@@ -1065,9 +1072,10 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
* ditto
*/
- ubyte[] decode(R1, R2)(R1 source, R2 buffer) if (!isArray!R1 && isInputRange!R1 &&
- is(ElementType!R1 : dchar) && hasLength!R1 &&
- is(R2 == ubyte[]) && isOutputRange!(R2, ubyte))
+ ubyte[] decode(R1, R2)(R1 source, R2 buffer)
+ if (!isArray!R1 && isInputRange!R1 &&
+ is(ElementType!R1 : dchar) && hasLength!R1 &&
+ is(R2 == ubyte[]) && isOutputRange!(R2, ubyte))
in
{
assert(buffer.length >= decodeLength(source.length), "Insufficient buffer for decoding");
@@ -1156,8 +1164,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* base alphabet of the current Base64 encoding scheme.
*/
size_t decode(R1, R2)(in R1 source, auto ref R2 range)
- if (isArray!R1 && is(ElementType!R1 : dchar) &&
- !is(R2 == ubyte[]) && isOutputRange!(R2, ubyte))
+ if (isArray!R1 && is(ElementType!R1 : dchar) &&
+ !is(R2 == ubyte[]) && isOutputRange!(R2, ubyte))
out(result)
{
immutable expect = realDecodeLength(source);
@@ -1244,8 +1252,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* ditto
*/
size_t decode(R1, R2)(R1 source, auto ref R2 range)
- if (!isArray!R1 && isInputRange!R1 && is(ElementType!R1 : dchar) &&
- hasLength!R1 && !is(R2 == ubyte[]) && isOutputRange!(R2, ubyte))
+ if (!isArray!R1 && isInputRange!R1 && is(ElementType!R1 : dchar) &&
+ hasLength!R1 && !is(R2 == ubyte[]) && isOutputRange!(R2, ubyte))
out(result)
{
// @@@BUG@@@ Workaround for DbC problem.
@@ -1334,7 +1342,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* A newly-allocated `ubyte[]` buffer containing the decoded string.
*/
@safe
- pure ubyte[] decode(Range)(Range source) if (isArray!Range && is(ElementType!Range : dchar))
+ pure ubyte[] decode(Range)(Range source)
+ if (isArray!Range && is(ElementType!Range : dchar))
{
return decode(source, new ubyte[decodeLength(source.length)]);
}
@@ -1350,8 +1359,9 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
/**
* ditto
*/
- ubyte[] decode(Range)(Range source) if (!isArray!Range && isInputRange!Range &&
- is(ElementType!Range : dchar) && hasLength!Range)
+ ubyte[] decode(Range)(Range source)
+ if (!isArray!Range && isInputRange!Range &&
+ is(ElementType!Range : dchar) && hasLength!Range)
{
return decode(source, new ubyte[decodeLength(source.length)]);
}
@@ -1367,8 +1377,9 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Note: This struct is not intended to be created in user code directly;
* use the $(LREF decoder) function instead.
*/
- struct Decoder(Range) if (isInputRange!Range && (is(ElementType!Range : const(char)[]) ||
- is(ElementType!Range : const(ubyte)[])))
+ struct Decoder(Range)
+ if (isInputRange!Range && (is(ElementType!Range : const(char)[]) ||
+ is(ElementType!Range : const(ubyte)[])))
{
private:
Range range_;
@@ -1492,7 +1503,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Note: This struct is not intended to be created in user code directly;
* use the $(LREF decoder) function instead.
*/
- struct Decoder(Range) if (isInputRange!Range && is(ElementType!Range : char))
+ struct Decoder(Range)
+ if (isInputRange!Range && is(ElementType!Range : char))
{
private:
Range range_;
@@ -1683,7 +1695,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* }
* -----
*/
- Decoder!(Range) decoder(Range)(Range range) if (isInputRange!Range)
+ Decoder!(Range) decoder(Range)(Range range)
+ if (isInputRange!Range)
{
return typeof(return)(range);
}
diff --git a/libphobos/src/std/bigint.d b/libphobos/src/std/bigint.d
index 0240ea1..a8b3897 100644
--- a/libphobos/src/std/bigint.d
+++ b/libphobos/src/std/bigint.d
@@ -63,8 +63,8 @@ public:
* Throws:
* $(REF ConvException, std,conv) if the string doesn't represent a valid number
*/
- this(Range)(Range s) if (
- isBidirectionalRange!Range &&
+ this(Range)(Range s)
+ if (isBidirectionalRange!Range &&
isSomeChar!(ElementType!Range) &&
!isInfinite!Range &&
!isNarrowString!Range)
@@ -160,8 +160,8 @@ public:
* (ignored when magnitude is zero)
* magnitude = a finite range of unsigned integers
*/
- this(Range)(bool isNegative, Range magnitude) if (
- isInputRange!Range &&
+ this(Range)(bool isNegative, Range magnitude)
+ if (isInputRange!Range &&
isUnsigned!(ElementType!Range) &&
(hasLength!Range || isForwardRange!Range) &&
!isInfinite!Range)
@@ -181,7 +181,8 @@ public:
}
/// Construct a `BigInt` from a built-in integral type.
- this(T)(T x) pure nothrow @safe if (isIntegral!T)
+ this(T)(T x) pure nothrow @safe
+ if (isIntegral!T)
{
data = data.init; // @@@: Workaround for compiler bug
opAssign(x);
@@ -196,7 +197,8 @@ public:
}
/// Construct a `BigInt` from another `BigInt`.
- this(T)(T x) pure nothrow @safe if (is(immutable T == immutable BigInt))
+ this(T)(T x) pure nothrow @safe
+ if (is(immutable T == immutable BigInt))
{
opAssign(x);
}
@@ -210,7 +212,8 @@ public:
}
/// Assignment from built-in integer types.
- BigInt opAssign(T)(T x) pure nothrow @safe if (isIntegral!T)
+ BigInt opAssign(T)(T x) pure nothrow @safe
+ if (isIntegral!T)
{
data = cast(ulong) absUnsign(x);
sign = (x < 0);
@@ -247,8 +250,8 @@ public:
* `BigInt op= integer`.
*/
BigInt opOpAssign(string op, T)(T y) pure nothrow @safe return scope
- if ((op=="+" || op=="-" || op=="*" || op=="/" || op=="%"
- || op==">>" || op=="<<" || op=="^^" || op=="|" || op=="&" || op=="^") && isIntegral!T)
+ if ((op=="+" || op=="-" || op=="*" || op=="/" || op=="%"
+ || op==">>" || op=="<<" || op=="^^" || op=="|" || op=="&" || op=="^") && isIntegral!T)
{
ulong u = absUnsign(y);
@@ -436,8 +439,7 @@ public:
* Implements assignment operators of the form `BigInt op= BigInt`.
*/
BigInt opOpAssign(string op, T)(T y) pure nothrow @safe return scope
- if ((op=="+" || op== "-" || op=="*" || op=="|" || op=="&" || op=="^" || op=="/" || op=="%")
- && is (T: BigInt))
+ if ((op=="+" || op== "-" || op=="*" || op=="|" || op=="&" || op=="^" || op=="/" || op=="%") && is (T: BigInt))
{
static if (op == "+")
{
@@ -494,9 +496,8 @@ public:
* Implements binary operators between `BigInt`s.
*/
BigInt opBinary(string op, T)(T y) pure nothrow @safe const return scope
- if ((op=="+" || op == "*" || op=="-" || op=="|" || op=="&" || op=="^" ||
- op=="/" || op=="%")
- && is (T: BigInt))
+ if ((op=="+" || op == "*" || op=="-" || op=="|" || op=="&" || op=="^" ||
+ op=="/" || op=="%") && is (T: BigInt))
{
BigInt r = this;
return r.opOpAssign!(op)(y);
@@ -515,9 +516,9 @@ public:
* Implements binary operators between `BigInt`'s and built-in integers.
*/
BigInt opBinary(string op, T)(T y) pure nothrow @safe const return scope
- if ((op=="+" || op == "*" || op=="-" || op=="/" || op=="|" || op=="&" ||
- op=="^"|| op==">>" || op=="<<" || op=="^^")
- && isIntegral!T)
+ if ((op=="+" || op == "*" || op=="-" || op=="/" || op=="|" || op=="&" ||
+ op=="^"|| op==">>" || op=="<<" || op=="^^")
+ && isIntegral!T)
{
BigInt r = this;
r.opOpAssign!(op)(y);
@@ -546,7 +547,7 @@ public:
)
*/
auto opBinary(string op, T)(T y) pure nothrow @safe const
- if (op == "%" && isIntegral!T)
+ if (op == "%" && isIntegral!T)
{
assert(y != 0, "% 0 not allowed");
@@ -602,7 +603,7 @@ public:
`BigInt` on the right-hand side.
*/
BigInt opBinaryRight(string op, T)(T y) pure nothrow @safe const
- if ((op=="+" || op=="*" || op=="|" || op=="&" || op=="^") && isIntegral!T)
+ if ((op=="+" || op=="*" || op=="|" || op=="&" || op=="^") && isIntegral!T)
{
return opBinary!(op)(y);
}
@@ -627,7 +628,7 @@ public:
// BigInt = integer op BigInt
/// ditto
BigInt opBinaryRight(string op, T)(T y) pure nothrow @safe const
- if (op == "-" && isIntegral!T)
+ if (op == "-" && isIntegral!T)
{
ulong u = absUnsign(y);
BigInt r;
@@ -643,7 +644,7 @@ public:
// integer = integer op BigInt
/// ditto
T opBinaryRight(string op, T)(T x) pure nothrow @safe const
- if ((op=="%" || op=="/") && isIntegral!T)
+ if ((op=="%" || op=="/") && isIntegral!T)
{
checkDivByZero();
@@ -669,7 +670,8 @@ public:
/**
Implements `BigInt` unary operators.
*/
- BigInt opUnary(string op)() pure nothrow @safe const if (op=="+" || op=="-" || op=="~")
+ BigInt opUnary(string op)() pure nothrow @safe const
+ if (op=="+" || op=="-" || op=="~")
{
static if (op=="-")
{
@@ -687,7 +689,8 @@ public:
// non-const unary operations
/// ditto
- BigInt opUnary(string op)() pure nothrow @safe if (op=="++" || op=="--")
+ BigInt opUnary(string op)() pure nothrow @safe
+ if (op=="++" || op=="--")
{
static if (op=="++")
{
@@ -721,7 +724,8 @@ public:
}
/// ditto
- bool opEquals(T)(const T y) const pure nothrow @nogc @safe if (isIntegral!T)
+ bool opEquals(T)(const T y) const pure nothrow @nogc @safe
+ if (isIntegral!T)
{
if (sign != (y<0))
return 0;
@@ -729,7 +733,8 @@ public:
}
/// ditto
- bool opEquals(T)(const T y) const pure nothrow @nogc if (isFloatingPoint!T)
+ bool opEquals(T)(const T y) const pure nothrow @nogc
+ if (isFloatingPoint!T)
{
return 0 == opCmp(y);
}
@@ -896,7 +901,8 @@ public:
/**
Implements casting to floating point types.
*/
- T opCast(T)() @safe nothrow @nogc const if (isFloatingPoint!T)
+ T opCast(T)() @safe nothrow @nogc const
+ if (isFloatingPoint!T)
{
return toFloat!(T, "nearest");
}
@@ -1090,7 +1096,8 @@ public:
}
/// ditto
- int opCmp(T)(const T y) pure nothrow @nogc @safe const if (isIntegral!T)
+ int opCmp(T)(const T y) pure nothrow @nogc @safe const
+ if (isIntegral!T)
{
if (sign != (y<0) )
return sign ? -1 : 1;
@@ -1098,7 +1105,8 @@ public:
return sign? -cmp: cmp;
}
/// ditto
- int opCmp(T)(const T y) nothrow @nogc @safe const if (isFloatingPoint!T)
+ int opCmp(T)(const T y) nothrow @nogc @safe const
+ if (isFloatingPoint!T)
{
import core.bitop : bsr;
import std.math.operations : cmp;
diff --git a/libphobos/src/std/bitmanip.d b/libphobos/src/std/bitmanip.d
index 0993d34..15211a3 100644
--- a/libphobos/src/std/bitmanip.d
+++ b/libphobos/src/std/bitmanip.d
@@ -1925,7 +1925,7 @@ public:
* Support for unary operator ~ for `BitArray`.
*/
BitArray opUnary(string op)() const pure nothrow
- if (op == "~")
+ if (op == "~")
{
auto dim = this.dim;
@@ -1962,7 +1962,7 @@ public:
* Support for binary bitwise operators for `BitArray`.
*/
BitArray opBinary(string op)(const BitArray e2) const pure nothrow
- if (op == "-" || op == "&" || op == "|" || op == "^")
+ if (op == "-" || op == "&" || op == "|" || op == "^")
in
{
assert(e2.length == _len, "e2 must have the same length as this");
@@ -2064,7 +2064,7 @@ public:
* Support for operator op= for `BitArray`.
*/
BitArray opOpAssign(string op)(const BitArray e2) @nogc pure nothrow return scope
- if (op == "-" || op == "&" || op == "|" || op == "^")
+ if (op == "-" || op == "&" || op == "|" || op == "^")
in
{
assert(e2.length == _len, "e2 must have the same length as this");
@@ -2185,7 +2185,7 @@ public:
* concatenation semantics are not followed)
*/
BitArray opOpAssign(string op)(bool b) pure nothrow return scope
- if (op == "~")
+ if (op == "~")
{
length = _len + 1;
this[_len - 1] = b;
@@ -2215,7 +2215,7 @@ public:
* ditto
*/
BitArray opOpAssign(string op)(BitArray b) pure nothrow return scope
- if (op == "~")
+ if (op == "~")
{
auto istart = _len;
length = _len + b.length;
@@ -2249,7 +2249,7 @@ public:
* Support for binary operator ~ for `BitArray`.
*/
BitArray opBinary(string op)(bool b) const pure nothrow
- if (op == "~")
+ if (op == "~")
{
BitArray r;
@@ -2261,7 +2261,7 @@ public:
/** ditto */
BitArray opBinaryRight(string op)(bool b) const pure nothrow
- if (op == "~")
+ if (op == "~")
{
BitArray r;
@@ -2274,7 +2274,7 @@ public:
/** ditto */
BitArray opBinary(string op)(BitArray b) const pure nothrow
- if (op == "~")
+ if (op == "~")
{
BitArray r;
@@ -2398,7 +2398,7 @@ public:
* preserve bits past the end of the array.)
*/
void opOpAssign(string op)(size_t nbits) @nogc pure nothrow
- if (op == "<<")
+ if (op == "<<")
{
size_t wordsToShift = nbits / bitsPerSizeT;
size_t bitsToShift = nbits % bitsPerSizeT;
@@ -2432,7 +2432,7 @@ public:
* preserve bits past the end of the array.)
*/
void opOpAssign(string op)(size_t nbits) @nogc pure nothrow
- if (op == ">>")
+ if (op == ">>")
{
size_t wordsToShift = nbits / bitsPerSizeT;
size_t bitsToShift = nbits % bitsPerSizeT;
@@ -2945,58 +2945,6 @@ if (isIntegral!T || isSomeChar!T || isBoolean!T)
}
-private union EndianSwapper(T)
-if (canSwapEndianness!T)
-{
- T value;
- ubyte[T.sizeof] array;
-
- static if (is(immutable FloatingPointTypeOf!(T) == immutable float))
- uint intValue;
- else static if (is(immutable FloatingPointTypeOf!(T) == immutable double))
- ulong intValue;
-
-}
-
-// Can't use EndianSwapper union during CTFE.
-private auto ctfeRead(T)(const ubyte[T.sizeof] array)
-if (__traits(isIntegral, T))
-{
- Unqual!T result;
- version (LittleEndian)
- foreach_reverse (b; array)
- result = cast() cast(T) ((result << 8) | b);
- else
- foreach (b; array)
- result = cast() cast(T) ((result << 8) | b);
- return cast(T) result;
-}
-
-// Can't use EndianSwapper union during CTFE.
-private auto ctfeBytes(T)(const T value)
-if (__traits(isIntegral, T))
-{
- ubyte[T.sizeof] result;
- Unqual!T tmp = value;
- version (LittleEndian)
- {
- foreach (i; 0 .. T.sizeof)
- {
- result[i] = cast(ubyte) tmp;
- tmp = cast() cast(T) (tmp >>> 8);
- }
- }
- else
- {
- foreach_reverse (i; 0 .. T.sizeof)
- {
- result[i] = cast(ubyte) tmp;
- tmp = cast()(T) (tmp >>> 8);
- }
- }
- return result;
-}
-
/++
Converts the given value from the native endianness to big endian and
returns it as a `ubyte[n]` where `n` is the size of the given type.
@@ -3010,13 +2958,21 @@ if (__traits(isIntegral, T))
and therefore could vary from machine to machine (which could make it
unusable if you tried to transfer it to another machine).
+/
-auto nativeToBigEndian(T)(const T val) @safe pure nothrow @nogc
+auto nativeToBigEndian(T)(const T val) @trusted pure nothrow @nogc
if (canSwapEndianness!T)
{
- version (LittleEndian)
- return nativeToEndianImpl!true(val);
+ static if (isFloatOrDouble!T)
+ return nativeToBigEndian(*cast(const UnsignedOfSize!(T.sizeof)*) &val);
else
- return nativeToEndianImpl!false(val);
+ {
+ enum len = T.sizeof;
+ ubyte[len] retval;
+
+ static foreach (i; 0 .. len)
+ retval[i] = cast(ubyte)(val >> (len - i - 1) * 8);
+
+ return retval;
+ }
}
///
@@ -3043,26 +2999,6 @@ if (canSwapEndianness!T)
assert(cd == bigEndianToNative!double(swappedCD));
}
-private auto nativeToEndianImpl(bool swap, T)(const T val) @safe pure nothrow @nogc
-if (__traits(isIntegral, T))
-{
- if (!__ctfe)
- {
- static if (swap)
- return EndianSwapper!T(swapEndian(val)).array;
- else
- return EndianSwapper!T(val).array;
- }
- else
- {
- // Can't use EndianSwapper in CTFE.
- static if (swap)
- return ctfeBytes(swapEndian(val));
- else
- return ctfeBytes(val);
- }
-}
-
@safe unittest
{
import std.meta;
@@ -3149,13 +3085,25 @@ if (__traits(isIntegral, T))
because the FPU will mess up any swapped floating point values. So, you
can't actually have swapped floating point values as floating point values).
+/
-T bigEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
+T bigEndianToNative(T, size_t n)(ubyte[n] val) @trusted pure nothrow @nogc
if (canSwapEndianness!T && n == T.sizeof)
{
- version (LittleEndian)
- return endianToNativeImpl!(true, T, n)(val);
+ static if (isFloatOrDouble!T)
+ {
+ auto retval = bigEndianToNative!(UnsignedOfSize!(T.sizeof))(val);
+ return *cast(const T*) &retval;
+ }
else
- return endianToNativeImpl!(false, T, n)(val);
+ {
+ enum len = T.sizeof;
+ alias U = UnsignedOfSize!len;
+ U retval;
+
+ static foreach (i; 0 .. len)
+ retval |= (cast(U) val[i]) << (len - i - 1) * 8;
+
+ return cast(T) retval;
+ }
}
///
@@ -3179,13 +3127,21 @@ if (canSwapEndianness!T && n == T.sizeof)
because the FPU will mess up any swapped floating point values. So, you
can't actually have swapped floating point values as floating point values).
+/
-auto nativeToLittleEndian(T)(const T val) @safe pure nothrow @nogc
+auto nativeToLittleEndian(T)(const T val) @trusted pure nothrow @nogc
if (canSwapEndianness!T)
{
- version (BigEndian)
- return nativeToEndianImpl!true(val);
+ static if (isFloatOrDouble!T)
+ return nativeToLittleEndian(*cast(const UnsignedOfSize!(T.sizeof)*) &val);
else
- return nativeToEndianImpl!false(val);
+ {
+ enum len = T.sizeof;
+ ubyte[len] retval;
+
+ static foreach (i; 0 .. len)
+ retval[i] = cast(ubyte)(val >> i * 8);
+
+ return retval;
+ }
}
///
@@ -3195,9 +3151,21 @@ if (canSwapEndianness!T)
ubyte[4] swappedI = nativeToLittleEndian(i);
assert(i == littleEndianToNative!int(swappedI));
+ float f = 123.45f;
+ ubyte[4] swappedF = nativeToLittleEndian(f);
+ assert(f == littleEndianToNative!float(swappedF));
+
+ const float cf = 123.45f;
+ ubyte[4] swappedCF = nativeToLittleEndian(cf);
+ assert(cf == littleEndianToNative!float(swappedCF));
+
double d = 123.45;
ubyte[8] swappedD = nativeToLittleEndian(d);
assert(d == littleEndianToNative!double(swappedD));
+
+ const double cd = 123.45;
+ ubyte[8] swappedCD = nativeToLittleEndian(cd);
+ assert(cd == littleEndianToNative!double(swappedCD));
}
@safe unittest
@@ -3259,13 +3227,25 @@ if (canSwapEndianness!T)
and therefore could vary from machine to machine (which could make it
unusable if you tried to transfer it to another machine).
+/
-T littleEndianToNative(T, size_t n)(ubyte[n] val) @safe pure nothrow @nogc
+T littleEndianToNative(T, size_t n)(ubyte[n] val) @trusted pure nothrow @nogc
if (canSwapEndianness!T && n == T.sizeof)
{
- version (BigEndian)
- return endianToNativeImpl!(true, T, n)(val);
+ static if (isFloatOrDouble!T)
+ {
+ auto retval = littleEndianToNative!(UnsignedOfSize!(T.sizeof))(val);
+ return *cast(const T*) &retval;
+ }
else
- return endianToNativeImpl!(false, T, n)(val);
+ {
+ enum len = T.sizeof;
+ alias U = UnsignedOfSize!len;
+ U retval;
+
+ static foreach (i; 0 .. len)
+ retval |= (cast(U) val[i]) << i * 8;
+
+ return cast(T) retval;
+ }
}
///
@@ -3280,70 +3260,6 @@ if (canSwapEndianness!T && n == T.sizeof)
assert(c == littleEndianToNative!dchar(swappedC));
}
-private T endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @nogc nothrow pure @trusted
-if (__traits(isIntegral, T) && n == T.sizeof)
-{
- if (!__ctfe)
- {
- EndianSwapper!T es = { array: val };
- static if (swap)
- return swapEndian(es.value);
- else
- return es.value;
- }
- else
- {
- static if (swap)
- return swapEndian(ctfeRead!T(val));
- else
- return ctfeRead!T(val);
- }
-}
-
-private auto nativeToEndianImpl(bool swap, T)(const T val) @trusted pure nothrow @nogc
-if (isFloatOrDouble!T)
-{
- if (!__ctfe)
- {
- EndianSwapper!T es = EndianSwapper!T(val);
- static if (swap)
- es.intValue = swapEndian(es.intValue);
- return es.array;
- }
- else
- {
- static if (T.sizeof == 4)
- uint intValue = *cast(const uint*) &val;
- else static if (T.sizeof == 8)
- ulong intValue = *cast(const ulong*) & val;
- static if (swap)
- intValue = swapEndian(intValue);
- return ctfeBytes(intValue);
- }
-}
-
-private auto endianToNativeImpl(bool swap, T, size_t n)(ubyte[n] val) @trusted pure nothrow @nogc
-if (isFloatOrDouble!T && n == T.sizeof)
-{
- if (!__ctfe)
- {
- EndianSwapper!T es = { array: val };
- static if (swap)
- es.intValue = swapEndian(es.intValue);
- return es.value;
- }
- else
- {
- static if (n == 4)
- uint x = ctfeRead!uint(val);
- else static if (n == 8)
- ulong x = ctfeRead!ulong(val);
- static if (swap)
- x = swapEndian(x);
- return *cast(T*) &x;
- }
-}
-
private template isFloatOrDouble(T)
{
enum isFloatOrDouble = isFloatingPoint!T &&
@@ -3405,6 +3321,42 @@ private template canSwapEndianness(T)
}
}
+private template UnsignedOfSize(size_t n)
+{
+ static if (n == 8)
+ alias UnsignedOfSize = ulong;
+ else static if (n == 4)
+ alias UnsignedOfSize = uint;
+ else static if (n == 2)
+ alias UnsignedOfSize = ushort;
+ else static if (n == 1)
+ alias UnsignedOfSize = ubyte;
+ else
+ alias UnsignedOfSize = void;
+}
+
+@safe unittest
+{
+ static assert(is(UnsignedOfSize!(byte.sizeof) == ubyte));
+ static assert(is(UnsignedOfSize!(ubyte.sizeof) == ubyte));
+ static assert(is(UnsignedOfSize!(short.sizeof) == ushort));
+ static assert(is(UnsignedOfSize!(ushort.sizeof) == ushort));
+ static assert(is(UnsignedOfSize!(int.sizeof) == uint));
+ static assert(is(UnsignedOfSize!(uint.sizeof) == uint));
+ static assert(is(UnsignedOfSize!(long.sizeof) == ulong));
+ static assert(is(UnsignedOfSize!(ulong.sizeof) == ulong));
+
+ static assert(is(UnsignedOfSize!(bool.sizeof) == ubyte));
+ static assert(is(UnsignedOfSize!(char.sizeof) == ubyte));
+ static assert(is(UnsignedOfSize!(wchar.sizeof) == ushort));
+ static assert(is(UnsignedOfSize!(dchar.sizeof) == uint));
+
+ static assert(is(UnsignedOfSize!(float.sizeof) == uint));
+ static assert(is(UnsignedOfSize!(double.sizeof) == ulong));
+
+ static assert(is(UnsignedOfSize!10 == void));
+}
+
/++
Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
`T`. The value returned is converted from the given endianness to the
diff --git a/libphobos/src/std/checkedint.d b/libphobos/src/std/checkedint.d
index cec1dc1..630ae41 100644
--- a/libphobos/src/std/checkedint.d
+++ b/libphobos/src/std/checkedint.d
@@ -3362,12 +3362,14 @@ version (StdUnittest) private struct CountOverflows
static struct Hook1
{
uint calls;
- auto hookOpUnary(string op, T)(T value) if (op == "-")
+ auto hookOpUnary(string op, T)(T value)
+ if (op == "-")
{
++calls;
return T(42);
}
- auto hookOpUnary(string op, T)(T value) if (op == "~")
+ auto hookOpUnary(string op, T)(T value)
+ if (op == "~")
{
++calls;
return T(43);
@@ -3383,12 +3385,14 @@ version (StdUnittest) private struct CountOverflows
static struct Hook2
{
uint calls;
- void hookOpUnary(string op, T)(ref T value) if (op == "++")
+ void hookOpUnary(string op, T)(ref T value)
+ if (op == "++")
{
++calls;
--value;
}
- void hookOpUnary(string op, T)(ref T value) if (op == "--")
+ void hookOpUnary(string op, T)(ref T value)
+ if (op == "--")
{
++calls;
++value;
diff --git a/libphobos/src/std/complex.d b/libphobos/src/std/complex.d
index 60746f9..01e8dd2 100644
--- a/libphobos/src/std/complex.d
+++ b/libphobos/src/std/complex.d
@@ -156,7 +156,7 @@ if (isFloatingPoint!T)
/// ditto
void toString(Writer, Char)(scope Writer w, scope const ref FormatSpec!Char formatSpec) const
- if (isOutputRange!(Writer, const(Char)[]))
+ if (isOutputRange!(Writer, const(Char)[]))
{
import std.format.write : formatValue;
import std.math.traits : signbit;
@@ -231,14 +231,14 @@ if (isFloatingPoint!T)
// +complex
Complex opUnary(string op)() const
- if (op == "+")
+ if (op == "+")
{
return this;
}
// -complex
Complex opUnary(string op)() const
- if (op == "-")
+ if (op == "-")
{
return Complex(-re, -im);
}
@@ -255,7 +255,7 @@ if (isFloatingPoint!T)
// complex op numeric
Complex!(CommonType!(T,R)) opBinary(string op, R)(const R r) const
- if (isNumeric!R)
+ if (isNumeric!R)
{
alias C = typeof(return);
auto w = C(this.re, this.im);
@@ -264,21 +264,21 @@ if (isFloatingPoint!T)
// numeric + complex, numeric * complex
Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(const R r) const
- if ((op == "+" || op == "*") && (isNumeric!R))
+ if ((op == "+" || op == "*") && (isNumeric!R))
{
return opBinary!(op)(r);
}
// numeric - complex
Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(const R r) const
- if (op == "-" && isNumeric!R)
+ if (op == "-" && isNumeric!R)
{
return Complex(r - re, -im);
}
// numeric / complex
Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(const R r) const
- if (op == "/" && isNumeric!R)
+ if (op == "/" && isNumeric!R)
{
version (FastMath)
{
@@ -320,7 +320,7 @@ if (isFloatingPoint!T)
// numeric ^^ complex
Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(const R lhs) const
- if (op == "^^" && isNumeric!R)
+ if (op == "^^" && isNumeric!R)
{
import core.math : cos, sin;
import std.math.exponential : exp, log;
@@ -349,7 +349,7 @@ if (isFloatingPoint!T)
// complex += complex, complex -= complex
ref Complex opOpAssign(string op, C)(const C z)
- if ((op == "+" || op == "-") && is(C R == Complex!R))
+ if ((op == "+" || op == "-") && is(C R == Complex!R))
{
mixin ("re "~op~"= z.re;");
mixin ("im "~op~"= z.im;");
@@ -358,7 +358,7 @@ if (isFloatingPoint!T)
// complex *= complex
ref Complex opOpAssign(string op, C)(const C z)
- if (op == "*" && is(C R == Complex!R))
+ if (op == "*" && is(C R == Complex!R))
{
auto temp = re*z.re - im*z.im;
im = im*z.re + re*z.im;
@@ -368,7 +368,7 @@ if (isFloatingPoint!T)
// complex /= complex
ref Complex opOpAssign(string op, C)(const C z)
- if (op == "/" && is(C R == Complex!R))
+ if (op == "/" && is(C R == Complex!R))
{
version (FastMath)
{
@@ -409,7 +409,7 @@ if (isFloatingPoint!T)
// complex ^^= complex
ref Complex opOpAssign(string op, C)(const C z)
- if (op == "^^" && is(C R == Complex!R))
+ if (op == "^^" && is(C R == Complex!R))
{
import core.math : cos, sin;
import std.math.exponential : exp, log;
@@ -425,7 +425,7 @@ if (isFloatingPoint!T)
// complex += numeric, complex -= numeric
ref Complex opOpAssign(string op, U : T)(const U a)
- if (op == "+" || op == "-")
+ if (op == "+" || op == "-")
{
mixin ("re "~op~"= a;");
return this;
@@ -433,7 +433,7 @@ if (isFloatingPoint!T)
// complex *= numeric, complex /= numeric
ref Complex opOpAssign(string op, U : T)(const U a)
- if (op == "*" || op == "/")
+ if (op == "*" || op == "/")
{
mixin ("re "~op~"= a;");
mixin ("im "~op~"= a;");
@@ -442,7 +442,7 @@ if (isFloatingPoint!T)
// complex ^^= real
ref Complex opOpAssign(string op, R)(const R r)
- if (op == "^^" && isFloatingPoint!R)
+ if (op == "^^" && isFloatingPoint!R)
{
import core.math : cos, sin;
immutable ab = abs(this)^^r;
@@ -454,7 +454,7 @@ if (isFloatingPoint!T)
// complex ^^= int
ref Complex opOpAssign(string op, U)(const U i)
- if (op == "^^" && isIntegral!U)
+ if (op == "^^" && isIntegral!U)
{
switch (i)
{
diff --git a/libphobos/src/std/concurrency.d b/libphobos/src/std/concurrency.d
index 267f682..94265a2 100644
--- a/libphobos/src/std/concurrency.d
+++ b/libphobos/src/std/concurrency.d
@@ -163,7 +163,8 @@ private
MsgType type;
Variant data;
- this(T...)(MsgType t, T vals) if (T.length > 0)
+ this(T...)(MsgType t, T vals)
+ if (T.length > 0)
{
static if (T.length == 1)
{
diff --git a/libphobos/src/std/container/dlist.d b/libphobos/src/std/container/dlist.d
index 4fdf13d..728aacd 100644
--- a/libphobos/src/std/container/dlist.d
+++ b/libphobos/src/std/container/dlist.d
@@ -245,7 +245,8 @@ struct DList(T)
/**
Constructor taking a number of nodes
*/
- this(U)(U[] values...) if (isImplicitlyConvertible!(U, T))
+ this(U)(U[] values...)
+ if (isImplicitlyConvertible!(U, T))
{
insertBack(values);
}
diff --git a/libphobos/src/std/container/package.d b/libphobos/src/std/container/package.d
index 763da8b..fc04950 100644
--- a/libphobos/src/std/container/package.d
+++ b/libphobos/src/std/container/package.d
@@ -801,7 +801,8 @@ Indexing operators yield or modify the value at a specified index.
/**
$(D k in container) returns true if the given key is in the container.
*/
- bool opBinaryRight(string op)(KeyType k) if (op == "in")
+ bool opBinaryRight(string op)(KeyType k)
+ if (op == "in")
{
assert(0, "Not implemented");
}
@@ -843,13 +844,15 @@ define `opBinary`.
Complexity: $(BIGOH n + m), where m is the number of elements in $(D
stuff)
*/
- TotalContainer opBinary(string op)(Stuff rhs) if (op == "~")
+ TotalContainer opBinary(string op)(Stuff rhs)
+ if (op == "~")
{
assert(0, "Not implemented");
}
/// ditto
- TotalContainer opBinaryRight(string op)(Stuff lhs) if (op == "~")
+ TotalContainer opBinaryRight(string op)(Stuff lhs)
+ if (op == "~")
{
assert(0, "Not implemented");
}
@@ -857,7 +860,8 @@ stuff)
/**
Forwards to $(D insertAfter(this[], stuff)).
*/
- void opOpAssign(string op)(Stuff stuff) if (op == "~")
+ void opOpAssign(string op)(Stuff stuff)
+ if (op == "~")
{
assert(0, "Not implemented");
}
diff --git a/libphobos/src/std/container/rbtree.d b/libphobos/src/std/container/rbtree.d
index 9bd8d27..5369702 100644
--- a/libphobos/src/std/container/rbtree.d
+++ b/libphobos/src/std/container/rbtree.d
@@ -1057,7 +1057,8 @@ if (is(typeof(binaryFun!less(T.init, T.init))))
Complexity: $(BIGOH log(n))
+/
- bool opBinaryRight(string op)(Elem e) const if (op == "in")
+ bool opBinaryRight(string op)(Elem e) const
+ if (op == "in")
{
return _find(e) !is null;
}
@@ -1261,7 +1262,8 @@ if (is(typeof(binaryFun!less(T.init, T.init))))
*
* Complexity: $(BIGOH log(n))
*/
- size_t stableInsert(Stuff)(Stuff stuff) if (isImplicitlyConvertible!(Stuff, Elem))
+ size_t stableInsert(Stuff)(Stuff stuff)
+ if (isImplicitlyConvertible!(Stuff, Elem))
{
static if (allowDuplicates)
{
@@ -1283,8 +1285,8 @@ if (is(typeof(binaryFun!less(T.init, T.init))))
* Complexity: $(BIGOH m * log(n))
*/
size_t stableInsert(Stuff)(scope Stuff stuff)
- if (isInputRange!Stuff &&
- isImplicitlyConvertible!(ElementType!Stuff, Elem))
+ if (isInputRange!Stuff &&
+ isImplicitlyConvertible!(ElementType!Stuff, Elem))
{
size_t result = 0;
static if (allowDuplicates)
@@ -1534,7 +1536,7 @@ assert(equal(rbt[], [5]));
--------------------
+/
size_t removeKey(U...)(U elems)
- if (allSatisfy!(isImplicitlyConvertibleToElem, U))
+ if (allSatisfy!(isImplicitlyConvertibleToElem, U))
{
Elem[U.length] toRemove = [elems];
return removeKey(toRemove[]);
@@ -1542,7 +1544,7 @@ assert(equal(rbt[], [5]));
/++ Ditto +/
size_t removeKey(U)(scope U[] elems)
- if (isImplicitlyConvertible!(U, Elem))
+ if (isImplicitlyConvertible!(U, Elem))
{
immutable lenBefore = length;
@@ -1564,9 +1566,9 @@ assert(equal(rbt[], [5]));
/++ Ditto +/
size_t removeKey(Stuff)(Stuff stuff)
- if (isInputRange!Stuff &&
- isImplicitlyConvertible!(ElementType!Stuff, Elem) &&
- !isDynamicArray!Stuff)
+ if (isInputRange!Stuff &&
+ isImplicitlyConvertible!(ElementType!Stuff, Elem) &&
+ !isDynamicArray!Stuff)
{
import std.array : array;
//We use array in case stuff is a Range from this RedBlackTree - either
@@ -1873,7 +1875,8 @@ assert(equal(rbt[], [5]));
/**
* Constructor. Pass in a range of elements to initialize the tree with.
*/
- this(Stuff)(Stuff stuff) if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, Elem))
+ this(Stuff)(Stuff stuff)
+ if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, Elem))
{
_setup();
stableInsert(stuff);
diff --git a/libphobos/src/std/container/slist.d b/libphobos/src/std/container/slist.d
index 0b504b4..ef6fbf0 100644
--- a/libphobos/src/std/container/slist.d
+++ b/libphobos/src/std/container/slist.d
@@ -182,7 +182,8 @@ if (!is(T == shared))
/**
Constructor taking a number of nodes
*/
- this(U)(U[] values...) if (isImplicitlyConvertible!(U, T))
+ this(U)(U[] values...)
+ if (isImplicitlyConvertible!(U, T))
{
insertFront(values);
}
diff --git a/libphobos/src/std/container/util.d b/libphobos/src/std/container/util.d
index cc273a2..0b883d0 100644
--- a/libphobos/src/std/container/util.d
+++ b/libphobos/src/std/container/util.d
@@ -109,14 +109,14 @@ if (!is(Container))
import std.traits : isDynamicArray;
auto make(Range)(Range range)
- if (!isDynamicArray!Range && isInputRange!Range && !isInfinite!Range)
+ if (!isDynamicArray!Range && isInputRange!Range && !isInfinite!Range)
{
import std.range : ElementType;
return .make!(Container!(ElementType!Range, Args))(range);
}
auto make(T)(T[] items...)
- if (!isInfinite!T)
+ if (!isInfinite!T)
{
return .make!(Container!(T, Args))(items);
}
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index 3aa73c6..9c9d8db 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -205,21 +205,21 @@ $(PRE $(I UnsignedInteger):
template to(T)
{
T to(A...)(A args)
- if (A.length > 0)
+ if (A.length > 0)
{
return toImpl!T(args);
}
// Fix https://issues.dlang.org/show_bug.cgi?id=6175
T to(S)(ref S arg)
- if (isStaticArray!S)
+ if (isStaticArray!S)
{
return toImpl!T(arg);
}
// Fix https://issues.dlang.org/show_bug.cgi?id=16108
T to(S)(ref S arg)
- if (isAggregateType!S && !isCopyable!S)
+ if (isAggregateType!S && !isCopyable!S)
{
return toImpl!T(arg);
}
@@ -917,9 +917,22 @@ if (!is(S : T) &&
auto result = ()@trusted{ return cast(T) value; }();
if (!result && value)
{
- throw new ConvException("Cannot convert object of static type "
- ~S.classinfo.name~" and dynamic type "~value.classinfo.name
- ~" to type "~T.classinfo.name);
+ string name(TypeInfo ti) @trusted
+ {
+ while (auto tc = (cast(TypeInfo_Const) ti))
+ {
+ ti = tc.base;
+ }
+ if (auto tinf = cast(TypeInfo_Interface) ti)
+ {
+ ti = tinf.info;
+ }
+ TypeInfo_Class tc = cast(TypeInfo_Class) ti;
+ assert(tc);
+ return tc.name;
+ }
+ throw new ConvException("Cannot convert object of static type " ~
+ name(typeid(S)) ~ " and dynamic type " ~ name(typeid(value)) ~ " to type " ~ name(typeid(T)));
}
return result;
}
diff --git a/libphobos/src/std/datetime/date.d b/libphobos/src/std/datetime/date.d
index c757b1e..0f417b1 100644
--- a/libphobos/src/std/datetime/date.d
+++ b/libphobos/src/std/datetime/date.d
@@ -1075,7 +1075,7 @@ public:
+/
ref DateTime add(string units)
(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe pure nothrow @nogc
- if (units == "years" || units == "months")
+ if (units == "years" || units == "months")
{
_date.add!units(value, allowOverflow);
return this;
@@ -1140,7 +1140,7 @@ public:
+/
ref DateTime roll(string units)
(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe pure nothrow @nogc
- if (units == "years" || units == "months")
+ if (units == "years" || units == "months")
{
_date.roll!units(value, allowOverflow);
return this;
@@ -1209,7 +1209,7 @@ public:
A reference to the `DateTime` (`this`).
+/
ref DateTime roll(string units)(long value) @safe pure nothrow @nogc
- if (units == "days")
+ if (units == "days")
{
_date.roll!"days"(value);
return this;
@@ -1250,9 +1250,9 @@ public:
/// ditto
ref DateTime roll(string units)(long value) @safe pure nothrow @nogc
- if (units == "hours" ||
- units == "minutes" ||
- units == "seconds")
+ if (units == "hours" ||
+ units == "minutes" ||
+ units == "seconds")
{
_tod.roll!units(value);
return this;
@@ -2138,7 +2138,7 @@ public:
this $(LREF DateTime).
+/
DateTime opBinary(string op)(Duration duration) const @safe pure nothrow @nogc
- if (op == "+" || op == "-")
+ if (op == "+" || op == "-")
{
DateTime retval = this;
immutable seconds = duration.total!"seconds";
@@ -2233,7 +2233,7 @@ public:
$(LREF DateTime).
+/
ref DateTime opOpAssign(string op)(Duration duration) @safe pure nothrow @nogc
- if (op == "+" || op == "-")
+ if (op == "+" || op == "-")
{
import core.time : convert;
import std.format : format;
@@ -2339,7 +2339,7 @@ public:
)
+/
Duration opBinary(string op)(DateTime rhs) const @safe pure nothrow @nogc
- if (op == "-")
+ if (op == "-")
{
immutable dateResult = _date - rhs.date;
immutable todResult = _tod - rhs._tod;
@@ -3151,7 +3151,7 @@ public:
be valid.
+/
static DateTime fromISOString(S)(scope const S isoString) @safe pure
- if (isSomeString!S)
+ if (isSomeString!S)
{
import std.algorithm.searching : countUntil;
import std.exception : enforce;
@@ -3252,7 +3252,7 @@ public:
would not be valid.
+/
static DateTime fromISOExtString(S)(scope const S isoExtString) @safe pure
- if (isSomeString!(S))
+ if (isSomeString!(S))
{
import std.algorithm.searching : countUntil;
import std.exception : enforce;
@@ -3353,7 +3353,7 @@ public:
would not be valid.
+/
static DateTime fromSimpleString(S)(scope const S simpleString) @safe pure
- if (isSomeString!(S))
+ if (isSomeString!(S))
{
import std.algorithm.searching : countUntil;
import std.exception : enforce;
@@ -4483,7 +4483,7 @@ public:
+/
@safe pure nothrow @nogc
ref Date add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
- if (units == "years")
+ if (units == "years")
{
_year += value;
@@ -4724,7 +4724,7 @@ public:
// Shares documentation with "years" version.
@safe pure nothrow @nogc
ref Date add(string units)(long months, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
- if (units == "months")
+ if (units == "months")
{
auto years = months / 12;
months %= 12;
@@ -5268,7 +5268,7 @@ public:
+/
@safe pure nothrow @nogc
ref Date roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
- if (units == "years")
+ if (units == "years")
{
return add!"years"(value, allowOverflow);
}
@@ -5313,7 +5313,7 @@ public:
// Shares documentation with "years" version.
@safe pure nothrow @nogc
ref Date roll(string units)(long months, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
- if (units == "months")
+ if (units == "months")
{
months %= 12;
auto newMonth = _month + months;
@@ -5910,7 +5910,7 @@ public:
A reference to the `Date` (`this`).
+/
ref Date roll(string units)(long days) @safe pure nothrow @nogc
- if (units == "days")
+ if (units == "days")
{
immutable limit = maxDay(_year, _month);
days %= limit;
@@ -6148,7 +6148,7 @@ public:
this $(LREF Date).
+/
Date opBinary(string op)(Duration duration) const @safe pure nothrow @nogc
- if (op == "+" || op == "-")
+ if (op == "+" || op == "-")
{
Date retval = this;
immutable days = duration.total!"days";
@@ -6238,7 +6238,7 @@ public:
this $(LREF Date).
+/
ref Date opOpAssign(string op)(Duration duration) @safe pure nothrow @nogc
- if (op == "+" || op == "-")
+ if (op == "+" || op == "-")
{
immutable days = duration.total!"days";
mixin("return _addDays(" ~ op ~ "days);");
@@ -6313,7 +6313,7 @@ public:
)
+/
Duration opBinary(string op)(Date rhs) const @safe pure nothrow @nogc
- if (op == "-")
+ if (op == "-")
{
import core.time : dur;
return dur!"days"(this.dayOfGregorianCal - rhs.dayOfGregorianCal);
@@ -7621,7 +7621,7 @@ public:
valid.
+/
static Date fromISOString(S)(scope const S isoString) @safe pure
- if (isSomeString!S)
+ if (isSomeString!S)
{
import std.algorithm.searching : startsWith;
import std.conv : to, text, ConvException;
@@ -7764,7 +7764,7 @@ public:
would not be valid.
+/
static Date fromISOExtString(S)(scope const S isoExtString) @safe pure
- if (isSomeString!(S))
+ if (isSomeString!(S))
{
import std.algorithm.searching : startsWith;
import std.conv : to, ConvException;
@@ -7902,7 +7902,7 @@ public:
be valid.
+/
static Date fromSimpleString(S)(scope const S simpleString) @safe pure
- if (isSomeString!(S))
+ if (isSomeString!(S))
{
import std.algorithm.searching : startsWith;
import std.conv : to, ConvException;
@@ -8606,7 +8606,7 @@ public:
A reference to the `TimeOfDay` (`this`).
+/
ref TimeOfDay roll(string units)(long value) @safe pure nothrow @nogc
- if (units == "hours")
+ if (units == "hours")
{
import core.time : dur;
return this += dur!"hours"(value);
@@ -8655,7 +8655,7 @@ public:
/// ditto
ref TimeOfDay roll(string units)(long value) @safe pure nothrow @nogc
- if (units == "minutes" || units == "seconds")
+ if (units == "minutes" || units == "seconds")
{
import std.format : format;
@@ -8851,7 +8851,7 @@ public:
this $(LREF TimeOfDay).
+/
TimeOfDay opBinary(string op)(Duration duration) const @safe pure nothrow @nogc
- if (op == "+" || op == "-")
+ if (op == "+" || op == "-")
{
TimeOfDay retval = this;
immutable seconds = duration.total!"seconds";
@@ -8938,7 +8938,7 @@ public:
this $(LREF TimeOfDay).
+/
ref TimeOfDay opOpAssign(string op)(Duration duration) @safe pure nothrow @nogc
- if (op == "+" || op == "-")
+ if (op == "+" || op == "-")
{
immutable seconds = duration.total!"seconds";
mixin("return _addSeconds(" ~ op ~ "seconds);");
@@ -9004,7 +9004,7 @@ public:
rhs = The $(LREF TimeOfDay) to subtract from this one.
+/
Duration opBinary(string op)(TimeOfDay rhs) const @safe pure nothrow @nogc
- if (op == "-")
+ if (op == "-")
{
immutable lhsSec = _hour * 3600 + _minute * 60 + _second;
immutable rhsSec = rhs._hour * 3600 + rhs._minute * 60 + rhs._second;
@@ -9201,7 +9201,7 @@ public:
not be valid.
+/
static TimeOfDay fromISOString(S)(scope const S isoString) @safe pure
- if (isSomeString!S)
+ if (isSomeString!S)
{
import std.conv : to, text, ConvException;
import std.exception : enforce;
@@ -9326,7 +9326,7 @@ public:
would not be valid.
+/
static TimeOfDay fromISOExtString(S)(scope const S isoExtString) @safe pure
- if (isSomeString!S)
+ if (isSomeString!S)
{
import std.conv : ConvException, text, to;
import std.string : strip;
diff --git a/libphobos/src/std/datetime/interval.d b/libphobos/src/std/datetime/interval.d
index d787e3a..832a2cb 100644
--- a/libphobos/src/std/datetime/interval.d
+++ b/libphobos/src/std/datetime/interval.d
@@ -137,7 +137,7 @@ public:
--------------------
+/
this(U)(scope const TP begin, scope const U end) pure
- if (is(immutable TP == immutable U))
+ if (is(immutable TP == immutable U))
{
if (!_valid(begin, end))
throw new DateTimeException("Arguments would result in an invalid Interval.");
@@ -162,7 +162,7 @@ public:
--------------------
+/
this(D)(scope const TP begin, scope const D duration) pure
- if (__traits(compiles, begin + duration))
+ if (__traits(compiles, begin + duration))
{
_begin = cast(TP) begin;
_end = begin + duration;
@@ -1118,7 +1118,7 @@ public:
--------------------
+/
void shift(D)(D duration) pure
- if (__traits(compiles, begin + duration))
+ if (__traits(compiles, begin + duration))
{
_enforceNotEmpty();
@@ -1168,7 +1168,7 @@ public:
--------------------
+/
void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
- if (isIntegral!T)
+ if (isIntegral!T)
{
_enforceNotEmpty();
@@ -1215,7 +1215,7 @@ public:
--------------------
+/
void expand(D)(D duration, Direction dir = Direction.both) pure
- if (__traits(compiles, begin + duration))
+ if (__traits(compiles, begin + duration))
{
_enforceNotEmpty();
@@ -3919,7 +3919,7 @@ assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
--------------------
+/
void shift(D)(D duration) pure nothrow
- if (__traits(compiles, begin + duration))
+ if (__traits(compiles, begin + duration))
{
_begin += duration;
}
@@ -3960,7 +3960,7 @@ assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
--------------------
+/
void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
- if (isIntegral!T)
+ if (isIntegral!T)
{
auto begin = _begin;
@@ -3992,7 +3992,7 @@ assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
--------------------
+/
void expand(D)(D duration) pure nothrow
- if (__traits(compiles, begin + duration))
+ if (__traits(compiles, begin + duration))
{
_begin -= duration;
}
@@ -4028,7 +4028,7 @@ assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
--------------------
+/
void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
- if (isIntegral!T)
+ if (isIntegral!T)
{
auto begin = _begin;
@@ -6145,7 +6145,7 @@ assert(interval2 == NegInfInterval!Date( Date(2012, 2, 15)));
--------------------
+/
void shift(D)(D duration) pure nothrow
- if (__traits(compiles, end + duration))
+ if (__traits(compiles, end + duration))
{
_end += duration;
}
@@ -6185,7 +6185,7 @@ assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
--------------------
+/
void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
- if (isIntegral!T)
+ if (isIntegral!T)
{
auto end = _end;
@@ -6217,7 +6217,7 @@ assert(interval2 == NegInfInterval!Date(Date(2012, 2, 28)));
--------------------
+/
void expand(D)(D duration) pure nothrow
- if (__traits(compiles, end + duration))
+ if (__traits(compiles, end + duration))
{
_end += duration;
}
@@ -6253,7 +6253,7 @@ assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
--------------------
+/
void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
- if (isIntegral!T)
+ if (isIntegral!T)
{
auto end = _end;
diff --git a/libphobos/src/std/datetime/systime.d b/libphobos/src/std/datetime/systime.d
index a2e52ae..fd2a9e1 100644
--- a/libphobos/src/std/datetime/systime.d
+++ b/libphobos/src/std/datetime/systime.d
@@ -2444,7 +2444,7 @@ public:
this SysTime.
+/
T toUnixTime(T = time_t)() @safe const pure nothrow scope
- if (is(T == int) || is(T == long))
+ if (is(T == int) || is(T == long))
{
return stdTimeToUnixTime!T(_stdTime);
}
@@ -2792,7 +2792,7 @@ public:
causing the month to increment.
+/
ref SysTime add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow scope
- if (units == "years" || units == "months")
+ if (units == "years" || units == "months")
{
auto hnsecs = adjTime;
auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
@@ -4830,7 +4830,7 @@ public:
$(LREF SysTime).
+/
ref SysTime roll(string units)(long value) @safe nothrow scope
- if (units == "days")
+ if (units == "days")
{
auto hnsecs = adjTime;
auto gdays = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
@@ -5195,7 +5195,7 @@ public:
// Shares documentation with "days" version.
ref SysTime roll(string units)(long value) @safe nothrow scope
- if (units == "hours" || units == "minutes" || units == "seconds")
+ if (units == "hours" || units == "minutes" || units == "seconds")
{
try
{
@@ -5871,7 +5871,7 @@ public:
// Shares documentation with "days" version.
ref SysTime roll(string units)(long value) @safe nothrow scope
- if (units == "msecs" || units == "usecs" || units == "hnsecs")
+ if (units == "msecs" || units == "usecs" || units == "hnsecs")
{
auto hnsecs = adjTime;
immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
@@ -6308,7 +6308,7 @@ public:
this $(LREF SysTime).
+/
SysTime opBinary(string op)(Duration duration) @safe const pure nothrow return scope
- if (op == "+" || op == "-")
+ if (op == "+" || op == "-")
{
SysTime retval = SysTime(this._stdTime, this._timezone);
immutable hnsecs = duration.total!"hnsecs";
@@ -6528,7 +6528,7 @@ public:
this $(LREF SysTime).
+/
ref SysTime opOpAssign(string op)(Duration duration) @safe pure nothrow scope
- if (op == "+" || op == "-")
+ if (op == "+" || op == "-")
{
immutable hnsecs = duration.total!"hnsecs";
mixin("_stdTime " ~ op ~ "= hnsecs;");
@@ -6732,7 +6732,7 @@ public:
)
+/
Duration opBinary(string op)(SysTime rhs) @safe const pure nothrow scope
- if (op == "-")
+ if (op == "-")
{
return dur!"hnsecs"(_stdTime - rhs._stdTime);
}
@@ -7992,7 +7992,7 @@ public:
Returns a $(REF Date,std,datetime,date) equivalent to this $(LREF SysTime).
+/
Date opCast(T)() @safe const nothrow scope
- if (is(immutable T == immutable Date))
+ if (is(immutable T == immutable Date))
{
return Date(dayOfGregorianCal);
}
@@ -8033,7 +8033,7 @@ public:
$(LREF SysTime).
+/
DateTime opCast(T)() @safe const nothrow scope
- if (is(immutable T == immutable DateTime))
+ if (is(immutable T == immutable DateTime))
{
try
{
@@ -8099,7 +8099,7 @@ public:
$(LREF SysTime).
+/
TimeOfDay opCast(T)() @safe const nothrow scope
- if (is(immutable T == immutable TimeOfDay))
+ if (is(immutable T == immutable TimeOfDay))
{
try
{
@@ -8156,7 +8156,7 @@ public:
// should be allowed, and it doesn't work without this opCast() since opCast()
// has already been defined for other types.
SysTime opCast(T)() @safe const pure nothrow scope
- if (is(immutable T == immutable SysTime))
+ if (is(immutable T == immutable SysTime))
{
return SysTime(_stdTime, _timezone);
}
@@ -8799,7 +8799,7 @@ public:
be valid.
+/
static SysTime fromISOString(S)(scope const S isoString, immutable TimeZone tz = null) @safe
- if (isSomeString!S)
+ if (isSomeString!S)
{
import std.algorithm.searching : startsWith, find;
import std.conv : to;
@@ -9100,7 +9100,7 @@ public:
be valid.
+/
static SysTime fromISOExtString(S)(scope const S isoExtString, immutable TimeZone tz = null) @safe
- if (isSomeString!(S))
+ if (isSomeString!(S))
{
import std.algorithm.searching : countUntil, find;
import std.conv : to;
@@ -9351,7 +9351,7 @@ public:
be valid.
+/
static SysTime fromSimpleString(S)(scope const S simpleString, immutable TimeZone tz = null) @safe
- if (isSomeString!(S))
+ if (isSomeString!(S))
{
import std.algorithm.searching : find;
import std.conv : to;
diff --git a/libphobos/src/std/datetime/timezone.d b/libphobos/src/std/datetime/timezone.d
index 4b6f27d..6a1898b 100644
--- a/libphobos/src/std/datetime/timezone.d
+++ b/libphobos/src/std/datetime/timezone.d
@@ -1550,7 +1550,7 @@ package:
isoString = A string which represents a time zone in the ISO format.
+/
static immutable(SimpleTimeZone) fromISOString(S)(S isoString) @safe pure
- if (isSomeString!S)
+ if (isSomeString!S)
{
import std.algorithm.searching : startsWith;
import std.conv : text, to, ConvException;
@@ -1704,7 +1704,7 @@ package:
isoExtString = A string which represents a time zone in the ISO format.
+/
static immutable(SimpleTimeZone) fromISOExtString(S)(scope S isoExtString) @safe pure
- if (isSomeString!S)
+ if (isSomeString!S)
{
import std.algorithm.searching : startsWith;
import std.conv : ConvException, to;
@@ -2642,7 +2642,7 @@ private:
Reads an int from a TZ file.
+/
static T readVal(T)(ref File tzFile) @trusted
- if ((isIntegral!T || isSomeChar!T) || is(immutable T == immutable bool))
+ if ((isIntegral!T || isSomeChar!T) || is(immutable T == immutable bool))
{
import std.bitmanip : bigEndianToNative;
T[1] buff;
@@ -2657,7 +2657,7 @@ private:
Reads an array of values from a TZ file.
+/
static T readVal(T)(ref File tzFile, size_t length) @trusted
- if (isArray!T)
+ if (isArray!T)
{
auto buff = new T(length);
@@ -2672,7 +2672,7 @@ private:
Reads a `TempTTInfo` from a TZ file.
+/
static T readVal(T)(ref File tzFile) @safe
- if (is(T == TempTTInfo))
+ if (is(T == TempTTInfo))
{
return TempTTInfo(readVal!int(tzFile),
readVal!bool(tzFile),
diff --git a/libphobos/src/std/exception.d b/libphobos/src/std/exception.d
index c3024d7..9b1a7c8 100644
--- a/libphobos/src/std/exception.d
+++ b/libphobos/src/std/exception.d
@@ -1801,7 +1801,7 @@ expression.
@system unittest
{
import std.format : format;
- assert("%s".format.ifThrown!Exception(e => e.classinfo.name) == "std.format.FormatException");
+ assert("%s".format.ifThrown!Exception(e => typeid(e).name) == "std.format.FormatException");
}
//Verify Examples
@@ -1834,7 +1834,7 @@ expression.
static assert(!__traits(compiles, (new Object()).ifThrown(1)));
//Use a lambda to get the thrown object.
- assert("%s".format().ifThrown(e => e.classinfo.name) == "std.format.FormatException");
+ assert("%s".format().ifThrown(e => typeid(e).name) == "std.format.FormatException");
}
@system unittest
diff --git a/libphobos/src/std/experimental/allocator/common.d b/libphobos/src/std/experimental/allocator/common.d
index d2efe33..b06fb62 100644
--- a/libphobos/src/std/experimental/allocator/common.d
+++ b/libphobos/src/std/experimental/allocator/common.d
@@ -67,6 +67,39 @@ unittest
}
/**
+State of an allocator `A`.
+
+`AllocatorState!(A).sizeof` is zero for `A` being `NullAllocator`, `Mallocator`,
+`GCAllocator`, and `MMapAllocator` and typically non-zero for the other.
+ */
+mixin template AllocatorState(A)
+if (isAllocator!A)
+{
+ static if (stateSize!A == 0)
+ alias allocator = A.instance;
+ else
+ A allocator;
+}
+
+///
+@safe @nogc nothrow pure
+unittest
+{
+ import std.experimental.allocator.building_blocks.null_allocator : NullAllocator;
+ import std.experimental.allocator.mallocator : Mallocator;
+ import std.experimental.allocator.gc_allocator : GCAllocator;
+ import std.experimental.allocator.mmap_allocator : MmapAllocator;
+ struct S
+ {
+ mixin AllocatorState!NullAllocator n;
+ mixin AllocatorState!GCAllocator g;
+ mixin AllocatorState!Mallocator m;
+ mixin AllocatorState!MmapAllocator p;
+ }
+ static assert(S.sizeof == 1);
+}
+
+/**
Returns `true` if the `Allocator` has the alignment known at compile time;
otherwise it returns `false`.
*/
diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d
index 087dbec..fbe9366 100644
--- a/libphobos/src/std/experimental/allocator/mallocator.d
+++ b/libphobos/src/std/experimental/allocator/mallocator.d
@@ -118,9 +118,9 @@ struct Mallocator
version (CRuntime_Microsoft)
{
- @nogc nothrow private extern(C) void* _aligned_malloc(size_t, size_t);
- @nogc nothrow private extern(C) void _aligned_free(void *memblock);
- @nogc nothrow private extern(C) void* _aligned_realloc(void *, size_t, size_t);
+ @nogc nothrow pure private extern(C) void* _aligned_malloc(size_t, size_t);
+ @nogc nothrow pure private extern(C) void _aligned_free(void *memblock);
+ @nogc nothrow pure private extern(C) void* _aligned_realloc(void *, size_t, size_t);
}
/**
@@ -138,7 +138,7 @@ struct AlignedMallocator
/**
Forwards to $(D alignedAllocate(bytes, platformAlignment)).
*/
- @trusted @nogc nothrow
+ @trusted @nogc nothrow pure
void[] allocate(size_t bytes) shared
{
if (!bytes) return null;
@@ -152,7 +152,7 @@ struct AlignedMallocator
`__aligned_malloc`) on Windows.
*/
version (Posix)
- @trusted @nogc nothrow
+ @trusted @nogc nothrow pure
void[] alignedAllocate(size_t bytes, uint a) shared
{
import core.stdc.errno : ENOMEM, EINVAL;
@@ -184,7 +184,7 @@ version (LDC_AddressSanitizer)
return result[0 .. bytes];
}
else version (Windows)
- @trusted @nogc nothrow
+ @trusted @nogc nothrow pure
void[] alignedAllocate(size_t bytes, uint a) shared
{
auto result = _aligned_malloc(bytes, a);
@@ -198,15 +198,15 @@ version (LDC_AddressSanitizer)
`__aligned_free(b.ptr)`) on Windows.
*/
version (Posix)
- @system @nogc nothrow
+ @system @nogc nothrow pure
bool deallocate(void[] b) shared
{
- import core.stdc.stdlib : free;
- free(b.ptr);
+ import core.memory : pureFree;
+ pureFree(b.ptr);
return true;
}
else version (Windows)
- @system @nogc nothrow
+ @system @nogc nothrow pure
bool deallocate(void[] b) shared
{
_aligned_free(b.ptr);
@@ -219,7 +219,7 @@ version (LDC_AddressSanitizer)
Should be used with blocks obtained with `allocate` otherwise the custom
alignment passed with `alignedAllocate` can be lost.
*/
- @system @nogc nothrow
+ @system @nogc nothrow pure
bool reallocate(ref void[] b, size_t newSize) shared
{
return alignedReallocate(b, newSize, alignment);
@@ -233,7 +233,7 @@ version (LDC_AddressSanitizer)
$(D __aligned_realloc(b.ptr, newSize, a))).
*/
version (Windows)
- @system @nogc nothrow
+ @system @nogc nothrow pure
bool alignedReallocate(ref void[] b, size_t s, uint a) shared
{
if (!s)
@@ -250,7 +250,7 @@ version (LDC_AddressSanitizer)
/// ditto
version (Posix)
- @system @nogc nothrow
+ @system @nogc nothrow pure
bool alignedReallocate(ref void[] b, size_t s, uint a) shared
{
if (!s)
@@ -281,7 +281,7 @@ version (LDC_AddressSanitizer)
}
///
-@nogc @system nothrow unittest
+pure @nogc @system nothrow unittest
{
auto buffer = AlignedMallocator.instance.alignedAllocate(1024 * 1024 * 4,
128);
@@ -290,7 +290,7 @@ version (LDC_AddressSanitizer)
}
version (Posix)
-@nogc @system nothrow unittest
+pure @nogc @system nothrow unittest
{
// https://issues.dlang.org/show_bug.cgi?id=16398
// test the "pseudo" alignedReallocate for Posix
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index 2a0d139..c3466ac 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -4794,7 +4794,7 @@ private struct DirIteratorImpl
}
this(R)(R pathname, SpanMode mode, bool followSymlink)
- if (isSomeFiniteCharInputRange!R)
+ if (isSomeFiniteCharInputRange!R)
{
_mode = mode;
_followSymlink = followSymlink;
diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d
index 16c7a51..8b60565 100644
--- a/libphobos/src/std/format/internal/write.d
+++ b/libphobos/src/std/format/internal/write.d
@@ -1935,7 +1935,8 @@ template hasToString(T, Char)
static struct G
{
string toString() {return "";}
- void toString(Writer)(ref Writer w) if (isOutputRange!(Writer, string)) {}
+ void toString(Writer)(ref Writer w)
+ if (isOutputRange!(Writer, string)) {}
}
static struct H
{
@@ -1946,7 +1947,8 @@ template hasToString(T, Char)
}
static struct I
{
- void toString(Writer)(ref Writer w) if (isOutputRange!(Writer, string)) {}
+ void toString(Writer)(ref Writer w)
+ if (isOutputRange!(Writer, string)) {}
void toString(Writer)(ref Writer w, scope const ref FormatSpec!char fmt)
if (isOutputRange!(Writer, string))
{}
@@ -2042,7 +2044,8 @@ template hasToString(T, Char)
static struct G
{
string toString() const {return "";}
- void toString(Writer)(ref Writer w) const if (isOutputRange!(Writer, string)) {}
+ void toString(Writer)(ref Writer w) const
+ if (isOutputRange!(Writer, string)) {}
}
static struct H
{
@@ -2053,7 +2056,8 @@ template hasToString(T, Char)
}
static struct I
{
- void toString(Writer)(ref Writer w) const if (isOutputRange!(Writer, string)) {}
+ void toString(Writer)(ref Writer w) const
+ if (isOutputRange!(Writer, string)) {}
void toString(Writer)(ref Writer w, scope const ref FormatSpec!char fmt) const
if (isOutputRange!(Writer, string))
{}
@@ -2603,7 +2607,8 @@ if ((is(T == struct) || is(T == union)) && (hasToString!(T, Char) || !is(Builtin
{
int n = 0;
alias n this;
- T opCast(T) () if (is(T == Frop))
+ T opCast(T) ()
+ if (is(T == Frop))
{
return Frop();
}
diff --git a/libphobos/src/std/functional.d b/libphobos/src/std/functional.d
index 588a9c8..5022702 100644
--- a/libphobos/src/std/functional.d
+++ b/libphobos/src/std/functional.d
@@ -445,7 +445,7 @@ if (S=="<"||S==">"||S=="<="||S==">="||S=="=="||S=="!=")
{
import std.traits : isIntegral;
private bool unsafeOp(ElementType1, ElementType2)(ElementType1 a, ElementType2 b) pure
- if (isIntegral!ElementType1 && isIntegral!ElementType2)
+ if (isIntegral!ElementType1 && isIntegral!ElementType2)
{
import std.traits : CommonType;
alias T = CommonType!(ElementType1, ElementType2);
diff --git a/libphobos/src/std/int128.d b/libphobos/src/std/int128.d
index 9289544..c556915 100644
--- a/libphobos/src/std/int128.d
+++ b/libphobos/src/std/int128.d
@@ -111,7 +111,7 @@ public struct Int128
* Returns: lvalue of result
*/
Int128 opUnary(string op)() const
- if (op == "+")
+ if (op == "+")
{
return this;
}
@@ -121,7 +121,7 @@ public struct Int128
* Returns: lvalue of result
*/
Int128 opUnary(string op)() const
- if (op == "-" || op == "~")
+ if (op == "-" || op == "~")
{
static if (op == "-")
return Int128(neg(this.data));
@@ -134,7 +134,7 @@ public struct Int128
* Returns: lvalue of result
*/
Int128 opUnary(string op)()
- if (op == "++" || op == "--")
+ if (op == "++" || op == "--")
{
static if (op == "++")
this.data = inc(this.data);
@@ -206,9 +206,9 @@ public struct Int128
* Returns: value after the operation is applied
*/
Int128 opBinary(string op)(Int128 op2) const
- if (op == "+" || op == "-" ||
- op == "*" || op == "/" || op == "%" ||
- op == "&" || op == "|" || op == "^")
+ if (op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^")
{
static if (op == "+")
return Int128(add(this.data, op2.data));
@@ -236,10 +236,10 @@ public struct Int128
/// ditto
Int128 opBinary(string op, Int)(const Int op2) const
- if ((op == "+" || op == "-" ||
- op == "*" || op == "/" || op == "%" ||
- op == "&" || op == "|" || op == "^") &&
- is(Int : long) && __traits(isIntegral, Int))
+ if ((op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^") &&
+ is(Int : long) && __traits(isIntegral, Int))
{
static if (__traits(isUnsigned, Int))
return mixin("this " ~ op ~ " Int128(0, op2)");
@@ -249,20 +249,20 @@ public struct Int128
/// ditto
Int128 opBinary(string op, IntLike)(auto ref IntLike op2) const
- if ((op == "+" || op == "-" ||
- op == "*" || op == "/" || op == "%" ||
- op == "&" || op == "|" || op == "^") &&
- is(IntLike : long) && !__traits(isIntegral, IntLike))
+ if ((op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^") &&
+ is(IntLike : long) && !__traits(isIntegral, IntLike))
{
return opBinary!(op)(__traits(getMember, op2, __traits(getAliasThis, IntLike)[0]));
}
/// ditto
Int128 opBinaryRight(string op, Int)(const Int op2) const
- if ((op == "+" || op == "-" ||
- op == "*" || op == "/" || op == "%" ||
- op == "&" || op == "|" || op == "^") &&
- is(Int : long) && __traits(isIntegral, Int))
+ if ((op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^") &&
+ is(Int : long) && __traits(isIntegral, Int))
{
static if (__traits(isUnsigned, Int))
mixin("return Int128(0, op2) " ~ op ~ " this;");
@@ -272,31 +272,31 @@ public struct Int128
/// ditto
Int128 opBinaryRight(string op, IntLike)(auto ref IntLike op2) const
- if ((op == "+" || op == "-" ||
- op == "*" || op == "/" || op == "%" ||
- op == "&" || op == "|" || op == "^") &&
- is(IntLike : long) && !__traits(isIntegral, IntLike))
+ if ((op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^") &&
+ is(IntLike : long) && !__traits(isIntegral, IntLike))
{
return opBinaryRight!(op)(__traits(getMember, op2, __traits(getAliasThis, IntLike)[0]));
}
/// ditto
Int128 opBinary(string op)(long op2) const
- if (op == "<<")
+ if (op == "<<")
{
return Int128(shl(this.data, cast(uint) op2));
}
/// ditto
Int128 opBinary(string op)(long op2) const
- if (op == ">>")
+ if (op == ">>")
{
return Int128(sar(this.data, cast(uint) op2));
}
/// ditto
Int128 opBinary(string op)(long op2) const
- if (op == ">>>")
+ if (op == ">>>")
{
return Int128(shr(this.data, cast(uint) op2));
}
@@ -307,10 +307,10 @@ public struct Int128
* Returns: lvalue of updated left operand
*/
ref Int128 opOpAssign(string op)(Int128 op2)
- if (op == "+" || op == "-" ||
- op == "*" || op == "/" || op == "%" ||
- op == "&" || op == "|" || op == "^" ||
- op == "<<" || op == ">>" || op == ">>>")
+ if (op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^" ||
+ op == "<<" || op == ">>" || op == ">>>")
{
mixin("this = this " ~ op ~ " op2;");
return this;
@@ -318,11 +318,11 @@ public struct Int128
/// ditto
ref Int128 opOpAssign(string op, Int)(auto ref Int op2)
- if ((op == "+" || op == "-" ||
- op == "*" || op == "/" || op == "%" ||
- op == "&" || op == "|" || op == "^" ||
- op == "<<" || op == ">>" || op == ">>>")
- && is(Int : long))
+ if ((op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^" ||
+ op == "<<" || op == ">>" || op == ">>>")
+ && is(Int : long))
{
mixin("this = this " ~ op ~ " op2;");
return this;
diff --git a/libphobos/src/std/internal/math/biguintcore.d b/libphobos/src/std/internal/math/biguintcore.d
index 9df6bb2..9c794b6 100644
--- a/libphobos/src/std/internal/math/biguintcore.d
+++ b/libphobos/src/std/internal/math/biguintcore.d
@@ -250,7 +250,8 @@ private:
data = x;
}
package(std) // used from: std.bigint
- this(T)(T x) pure nothrow @safe scope if (isIntegral!T)
+ this(T)(T x) pure nothrow @safe scope
+ if (isIntegral!T)
{
opAssign(x);
}
@@ -312,7 +313,8 @@ public:
}
///
- void opAssign(Tulong)(Tulong u) pure nothrow @safe scope if (is (Tulong == ulong))
+ void opAssign(Tulong)(Tulong u) pure nothrow @safe scope
+ if (is (Tulong == ulong))
{
if (u == 0) data = ZERO;
else if (u == 1) data = ONE;
@@ -356,7 +358,8 @@ public:
}
///
- int opCmp(Tulong)(Tulong y) pure nothrow @nogc const @safe scope if (is (Tulong == ulong))
+ int opCmp(Tulong)(Tulong y) pure nothrow @nogc const @safe scope
+ if (is (Tulong == ulong))
{
if (data.length > maxBigDigits!Tulong)
return 1;
@@ -501,8 +504,8 @@ public:
}
// return false if invalid character found
- bool fromHexString(Range)(Range s) scope if (
- isBidirectionalRange!Range && isSomeChar!(ElementType!Range))
+ bool fromHexString(Range)(Range s) scope
+ if (isBidirectionalRange!Range && isSomeChar!(ElementType!Range))
{
import std.range : walkLength;
@@ -570,8 +573,8 @@ public:
}
// return true if OK; false if erroneous characters found
- bool fromDecimalString(Range)(Range s) scope if (
- isForwardRange!Range && isSomeChar!(ElementType!Range))
+ bool fromDecimalString(Range)(Range s) scope
+ if (isForwardRange!Range && isSomeChar!(ElementType!Range))
{
import std.range : walkLength;
@@ -596,9 +599,9 @@ public:
}
void fromMagnitude(Range)(Range magnitude) scope
- if (isInputRange!Range
- && (isForwardRange!Range || hasLength!Range)
- && isUnsigned!(ElementType!Range))
+ if (isInputRange!Range
+ && (isForwardRange!Range || hasLength!Range)
+ && isUnsigned!(ElementType!Range))
{
while (!magnitude.empty && magnitude.front == 0)
magnitude.popFront;
@@ -711,7 +714,7 @@ public:
// return x >> y
BigUint opBinary(string op, Tulong)(Tulong y) pure nothrow @safe const return scope
- if (op == ">>" && is (Tulong == ulong))
+ if (op == ">>" && is (Tulong == ulong))
{
assert(y > 0, "Can not right shift BigUint by 0");
uint bits = cast(uint) y & BIGDIGITSHIFTMASK;
@@ -735,7 +738,7 @@ public:
// return x << y
BigUint opBinary(string op, Tulong)(Tulong y) pure nothrow @safe const scope
- if (op == "<<" && is (Tulong == ulong))
+ if (op == "<<" && is (Tulong == ulong))
{
assert(y > 0, "Can not left shift BigUint by 0");
if (isZero()) return this;
@@ -761,8 +764,8 @@ public:
// If wantSub is false, return x + y, leaving sign unchanged
// If wantSub is true, return abs(x - y), negating sign if x < y
- static BigUint addOrSubInt(Tulong)(const scope BigUint x, Tulong y,
- bool wantSub, ref bool sign) pure nothrow @safe if (is(Tulong == ulong))
+ static BigUint addOrSubInt(Tulong)(const scope BigUint x, Tulong y, bool wantSub, ref bool sign) pure nothrow @safe
+ if (is(Tulong == ulong))
{
BigUint r;
if (wantSub)
@@ -921,7 +924,8 @@ public:
}
// return x % y
- static uint modInt(T)(scope BigUint x, T y_) pure if ( is(immutable T == immutable uint) )
+ static uint modInt(T)(scope BigUint x, T y_) pure
+ if ( is(immutable T == immutable uint) )
{
import core.memory : GC;
uint y = y_;
@@ -994,7 +998,8 @@ public:
// return x op y
static BigUint bitwiseOp(string op)(scope BigUint x, scope BigUint y, bool xSign, bool ySign, ref bool resultSign)
- pure nothrow @safe if (op == "|" || op == "^" || op == "&")
+ pure nothrow @safe
+ if (op == "|" || op == "^" || op == "&")
{
auto d1 = includeSign(x.data, y.uintLength, xSign);
auto d2 = includeSign(y.data, x.uintLength, ySign);
diff --git a/libphobos/src/std/internal/test/dummyrange.d b/libphobos/src/std/internal/test/dummyrange.d
index e07e275..42dc264 100644
--- a/libphobos/src/std/internal/test/dummyrange.d
+++ b/libphobos/src/std/internal/test/dummyrange.d
@@ -255,10 +255,11 @@ class ReferenceInputRange(T)
{
import std.array : array;
- this(Range)(Range r) if (isInputRange!Range) {_payload = array(r);}
- final @property ref T front(){return _payload.front;}
- final void popFront(){_payload.popFront();}
- final @property bool empty(){return _payload.empty;}
+ this(Range)(Range r)
+ if (isInputRange!Range) {_payload = array(r);}
+ final @property ref T front() {return _payload.front;}
+ final void popFront() {_payload.popFront();}
+ final @property bool empty() {return _payload.empty;}
protected T[] _payload;
}
@@ -268,8 +269,8 @@ Infinite input range
class ReferenceInfiniteInputRange(T)
{
this(T first = T.init) {_val = first;}
- final @property T front(){return _val;}
- final void popFront(){++_val;}
+ final @property T front() {return _val;}
+ final void popFront() {++_val;}
enum bool empty = false;
protected T _val;
}
@@ -279,7 +280,8 @@ Reference forward range
*/
class ReferenceForwardRange(T) : ReferenceInputRange!T
{
- this(Range)(Range r) if (isInputRange!Range) {super(r);}
+ this(Range)(Range r)
+ if (isInputRange!Range) {super(r);}
final @property auto save(this This)() {return new This( _payload);}
}
@@ -298,9 +300,10 @@ Reference bidirectional range
*/
class ReferenceBidirectionalRange(T) : ReferenceForwardRange!T
{
- this(Range)(Range r) if (isInputRange!Range) {super(r);}
- final @property ref T back(){return _payload.back;}
- final void popBack(){_payload.popBack();}
+ this(Range)(Range r)
+ if (isInputRange!Range) {super(r);}
+ final @property ref T back() {return _payload.back;}
+ final void popBack() {_payload.popBack();}
}
@safe unittest
diff --git a/libphobos/src/std/json.d b/libphobos/src/std/json.d
index 9dcec89..7182f6e 100644
--- a/libphobos/src/std/json.d
+++ b/libphobos/src/std/json.d
@@ -85,6 +85,7 @@ enum JSONOptions
escapeNonAsciiChars = 0x2, /// Encode non-ASCII characters with a Unicode escape sequence
doNotEscapeSlashes = 0x4, /// Do not escape slashes ('/')
strictParsing = 0x8, /// Strictly follow RFC-8259 grammar when parsing
+ preserveObjectOrder = 0x16, /// Preserve order of object keys when parsing
}
/**
@@ -126,13 +127,30 @@ struct JSONValue
{
import std.exception : enforce;
+ import std.typecons : Tuple;
+
+ alias OrderedObjectMember = Tuple!(
+ string, "key",
+ JSONValue, "value",
+ );
+
union Store
{
+ struct Object
+ {
+ bool isOrdered;
+ union
+ {
+ JSONValue[string] unordered;
+ OrderedObjectMember[] ordered;
+ }
+ }
+
string str;
long integer;
ulong uinteger;
double floating;
- JSONValue[string] object;
+ Object object;
JSONValue[] array;
}
private Store store;
@@ -272,9 +290,9 @@ struct JSONValue
}
/***
- * Value getter/setter for `JSONType.object`.
+ * Value getter/setter for unordered `JSONType.object`.
* Throws: `JSONException` for read access if `type` is not
- * `JSONType.object`.
+ * `JSONType.object` or the object is ordered.
* Note: This is @system because of the following pattern:
---
auto a = &(json.object());
@@ -286,7 +304,9 @@ struct JSONValue
{
enforce!JSONException(type == JSONType.object,
"JSONValue is not an object");
- return store.object;
+ enforce!JSONException(!store.object.isOrdered,
+ "JSONValue object is ordered, cannot return by ref");
+ return store.object.unordered;
}
/// ditto
@property JSONValue[string] object(return scope JSONValue[string] v) pure nothrow @nogc @trusted // TODO make @safe
@@ -296,7 +316,7 @@ struct JSONValue
}
/***
- * Value getter for `JSONType.object`.
+ * Value getter for unordered `JSONType.object`.
* Unlike `object`, this retrieves the object by value
* and can be used in @safe code.
*
@@ -316,7 +336,71 @@ struct JSONValue
{
enforce!JSONException(type == JSONType.object,
"JSONValue is not an object");
- return store.object;
+ if (store.object.isOrdered)
+ {
+ // Convert to unordered
+ JSONValue[string] result;
+ foreach (pair; store.object.ordered)
+ result[pair.key] = pair.value;
+ return cast(inout) result;
+ }
+ else
+ return store.object.unordered;
+ }
+
+ /***
+ * Value getter/setter for ordered `JSONType.object`.
+ * Throws: `JSONException` for read access if `type` is not
+ * `JSONType.object` or the object is unordered.
+ * Note: This is @system because of the following pattern:
+ ---
+ auto a = &(json.orderedObject());
+ json.uinteger = 0; // overwrite AA pointer
+ (*a)["hello"] = "world"; // segmentation fault
+ ---
+ */
+ @property ref inout(OrderedObjectMember[]) orderedObject() inout pure @system return
+ {
+ enforce!JSONException(type == JSONType.object,
+ "JSONValue is not an object");
+ enforce!JSONException(store.object.isOrdered,
+ "JSONValue object is unordered, cannot return by ref");
+ return store.object.ordered;
+ }
+ /// ditto
+ @property OrderedObjectMember[] orderedObject(return scope OrderedObjectMember[] v) pure nothrow @nogc @trusted // TODO make @safe
+ {
+ assign(v);
+ return v;
+ }
+
+ /***
+ * Value getter for ordered `JSONType.object`.
+ * Unlike `orderedObject`, this retrieves the object by value
+ * and can be used in @safe code.
+ */
+ @property inout(OrderedObjectMember[]) orderedObjectNoRef() inout pure @trusted
+ {
+ enforce!JSONException(type == JSONType.object,
+ "JSONValue is not an object");
+ if (store.object.isOrdered)
+ return store.object.ordered;
+ else
+ {
+ // Convert to ordered
+ OrderedObjectMember[] result;
+ foreach (key, value; store.object.unordered)
+ result ~= OrderedObjectMember(key, value);
+ return cast(inout) result;
+ }
+ }
+
+ /// Returns `true` if the order of keys of the represented object is being preserved.
+ @property bool isOrdered() const pure @trusted
+ {
+ enforce!JSONException(type == JSONType.object,
+ "JSONValue is not an object");
+ return store.object.isOrdered;
}
/***
@@ -517,16 +601,30 @@ struct JSONValue
static if (is(Value : JSONValue))
{
JSONValue[string] t = arg;
- () @trusted { store.object = t; }();
+ () @trusted {
+ store.object.isOrdered = false;
+ store.object.unordered = t;
+ }();
}
else
{
JSONValue[string] aa;
foreach (key, value; arg)
aa[key] = JSONValue(value);
- () @trusted { store.object = aa; }();
+ () @trusted {
+ store.object.isOrdered = false;
+ store.object.unordered = aa;
+ }();
}
}
+ else static if (is(T : OrderedObjectMember[]))
+ {
+ type_tag = JSONType.object;
+ () @trusted {
+ store.object.isOrdered = true;
+ store.object.ordered = arg;
+ }();
+ }
else static if (isArray!T)
{
type_tag = JSONType.array;
@@ -554,7 +652,8 @@ struct JSONValue
}
}
- private void assignRef(T)(ref T arg) if (isStaticArray!T)
+ private void assignRef(T)(ref T arg)
+ if (isStaticArray!T)
{
type_tag = JSONType.array;
static if (is(ElementEncodingType!T : JSONValue))
@@ -582,12 +681,14 @@ struct JSONValue
* and `K` i.e. a JSON object, any array or `bool`. The type will
* be set accordingly.
*/
- this(T)(T arg) if (!isStaticArray!T)
+ this(T)(T arg)
+ if (!isStaticArray!T)
{
assign(arg);
}
/// Ditto
- this(T)(ref T arg) if (isStaticArray!T)
+ this(T)(ref T arg)
+ if (isStaticArray!T)
{
assignRef(arg);
}
@@ -631,6 +732,33 @@ struct JSONValue
/**
* An enum value that can be used to obtain a `JSONValue` representing
+ * an empty JSON object.
+ * Unlike `emptyObject`, the order of inserted keys is preserved.
+ */
+ enum emptyOrderedObject = {
+ JSONValue v = void;
+ v.orderedObject = null;
+ return v;
+ }();
+ ///
+ @system unittest
+ {
+ JSONValue obj = JSONValue.emptyOrderedObject;
+ assert(obj.type == JSONType.object);
+ assert(obj.isOrdered);
+ obj["b"] = JSONValue(2);
+ obj["a"] = JSONValue(1);
+ assert(obj["a"] == JSONValue(1));
+ assert(obj["b"] == JSONValue(2));
+
+ string[] keys;
+ foreach (string k, JSONValue v; obj)
+ keys ~= k;
+ assert(keys == ["b", "a"]);
+ }
+
+ /**
+ * An enum value that can be used to obtain a `JSONValue` representing
* an empty JSON array.
*/
enum emptyArray = JSONValue(JSONValue[].init);
@@ -649,12 +777,14 @@ struct JSONValue
assert(arr1 != arr2);
}
- void opAssign(T)(T arg) if (!isStaticArray!T && !is(T : JSONValue))
+ void opAssign(T)(T arg)
+ if (!isStaticArray!T && !is(T : JSONValue))
{
assign(arg);
}
- void opAssign(T)(ref T arg) if (isStaticArray!T)
+ void opAssign(T)(ref T arg)
+ if (isStaticArray!T)
{
assignRef(arg);
}
@@ -708,16 +838,33 @@ struct JSONValue
*/
void opIndexAssign(T)(auto ref T value, string key)
{
- enforce!JSONException(type == JSONType.object || type == JSONType.null_,
- "JSONValue must be object or null");
- JSONValue[string] aa = null;
- if (type == JSONType.object)
+ enforce!JSONException(
+ type == JSONType.object ||
+ type == JSONType.null_,
+ "JSONValue must be object or null");
+ if (type == JSONType.object && isOrdered)
{
- aa = this.objectNoRef;
+ auto arr = this.orderedObjectNoRef;
+ foreach (ref pair; arr)
+ if (pair.key == key)
+ {
+ pair.value = value;
+ return;
+ }
+ arr ~= OrderedObjectMember(key, JSONValue(value));
+ this.orderedObject = arr;
}
+ else
+ {
+ JSONValue[string] aa = null;
+ if (type == JSONType.object)
+ {
+ aa = this.objectNoRef;
+ }
- aa[key] = value;
- this.object = aa;
+ aa[key] = value;
+ this.object = aa;
+ }
}
///
@safe unittest
@@ -828,6 +975,8 @@ struct JSONValue
/// ditto
bool opEquals(ref const JSONValue rhs) const @nogc nothrow pure @trusted
{
+ import std.algorithm.searching : canFind;
+
// Default doesn't work well since store is a union. Compare only
// what should be in store.
// This is @trusted to remain nogc, nothrow, fast, and usable from @safe code.
@@ -873,7 +1022,45 @@ struct JSONValue
case JSONType.string:
return type_tag == rhs.type_tag && store.str == rhs.store.str;
case JSONType.object:
- return type_tag == rhs.type_tag && store.object == rhs.store.object;
+ if (rhs.type_tag != JSONType.object)
+ return false;
+ if (store.object.isOrdered)
+ {
+ if (rhs.store.object.isOrdered)
+ {
+ if (store.object.ordered.length != rhs.store.object.ordered.length)
+ return false;
+ foreach (ref pair; store.object.ordered)
+ if (!rhs.store.object.ordered.canFind(pair))
+ return false;
+ return true;
+ }
+ else
+ {
+ if (store.object.ordered.length != rhs.store.object.unordered.length)
+ return false;
+ foreach (ref pair; store.object.ordered)
+ if (pair.key !in rhs.store.object.unordered ||
+ rhs.store.object.unordered[pair.key] != pair.value)
+ return false;
+ return true;
+ }
+ }
+ else
+ {
+ if (rhs.store.object.isOrdered)
+ {
+ if (store.object.unordered.length != rhs.store.object.ordered.length)
+ return false;
+ foreach (ref pair; rhs.store.object.ordered)
+ if (pair.key !in store.object.unordered ||
+ store.object.unordered[pair.key] != pair.value)
+ return false;
+ return true;
+ }
+ else
+ return store.object.unordered == rhs.store.object.unordered;
+ }
case JSONType.array:
return type_tag == rhs.type_tag && store.array == rhs.store.array;
case JSONType.true_:
@@ -914,14 +1101,27 @@ struct JSONValue
int opApply(scope int delegate(string key, ref JSONValue) dg) @system
{
enforce!JSONException(type == JSONType.object,
- "JSONValue is not an object");
+ "JSONValue is not an object");
+
int result;
- foreach (string key, ref value; object)
+ if (isOrdered)
{
- result = dg(key, value);
- if (result)
- break;
+ foreach (ref pair; orderedObject)
+ {
+ result = dg(pair.key, pair.value);
+ if (result)
+ break;
+ }
+ }
+ else
+ {
+ foreach (string key, ref value; object)
+ {
+ result = dg(key, value);
+ if (result)
+ break;
+ }
}
return result;
@@ -1018,6 +1218,7 @@ if (isSomeFiniteCharInputRange!T)
Nullable!Char next;
int line = 1, pos = 0;
immutable bool strict = (options & JSONOptions.strictParsing) != 0;
+ immutable bool ordered = (options & JSONOptions.preserveObjectOrder) != 0;
void error(string msg)
{
@@ -1258,31 +1459,62 @@ if (isSomeFiniteCharInputRange!T)
switch (c)
{
case '{':
- if (testChar('}'))
+ if (ordered)
{
- value.object = null;
- break;
- }
+ if (testChar('}'))
+ {
+ value.orderedObject = null;
+ break;
+ }
- JSONValue[string] obj;
- do
+ JSONValue.OrderedObjectMember[] obj;
+ do
+ {
+ skipWhitespace();
+ if (!strict && peekChar() == '}')
+ {
+ break;
+ }
+ checkChar('"');
+ string name = parseString();
+ checkChar(':');
+ JSONValue member;
+ parseValue(member);
+ obj ~= JSONValue.OrderedObjectMember(name, member);
+ }
+ while (testChar(','));
+ value.orderedObject = obj;
+
+ checkChar('}');
+ }
+ else
{
- skipWhitespace();
- if (!strict && peekChar() == '}')
+ if (testChar('}'))
{
+ value.object = null;
break;
}
- checkChar('"');
- string name = parseString();
- checkChar(':');
- JSONValue member;
- parseValue(member);
- obj[name] = member;
- }
- while (testChar(','));
- value.object = obj;
- checkChar('}');
+ JSONValue[string] obj;
+ do
+ {
+ skipWhitespace();
+ if (!strict && peekChar() == '}')
+ {
+ break;
+ }
+ checkChar('"');
+ string name = parseString();
+ checkChar(':');
+ JSONValue member;
+ parseValue(member);
+ obj[name] = member;
+ }
+ while (testChar(','));
+ value.object = obj;
+
+ checkChar('}');
+ }
break;
case '[':
@@ -1638,49 +1870,82 @@ if (isOutputRange!(Out,char))
final switch (value.type)
{
case JSONType.object:
- auto obj = value.objectNoRef;
- if (!obj.length)
+ if (value.isOrdered)
{
- json.put("{}");
- }
- else
- {
- putCharAndEOL('{');
- bool first = true;
-
- void emit(R)(R names)
+ auto obj = value.orderedObjectNoRef;
+ if (!obj.length)
{
- foreach (name; names)
+ json.put("{}");
+ }
+ else
+ {
+ putCharAndEOL('{');
+ bool first = true;
+
+ foreach (pair; obj)
{
- auto member = obj[name];
if (!first)
putCharAndEOL(',');
first = false;
putTabs(1);
- toString(name);
+ toString(pair.key);
json.put(':');
if (pretty)
json.put(' ');
- toValueImpl(member, indentLevel + 1);
+ toValueImpl(pair.value, indentLevel + 1);
}
- }
- import std.algorithm.sorting : sort;
- // https://issues.dlang.org/show_bug.cgi?id=14439
- // auto names = obj.keys; // aa.keys can't be called in @safe code
- auto names = new string[obj.length];
- size_t i = 0;
- foreach (k, v; obj)
+ putEOL();
+ putTabs();
+ json.put('}');
+ }
+ }
+ else
+ {
+ auto obj = value.objectNoRef;
+ if (!obj.length)
{
- names[i] = k;
- i++;
+ json.put("{}");
}
- sort(names);
- emit(names);
+ else
+ {
+ putCharAndEOL('{');
+ bool first = true;
- putEOL();
- putTabs();
- json.put('}');
+ void emit(R)(R names)
+ {
+ foreach (name; names)
+ {
+ auto member = obj[name];
+ if (!first)
+ putCharAndEOL(',');
+ first = false;
+ putTabs(1);
+ toString(name);
+ json.put(':');
+ if (pretty)
+ json.put(' ');
+ toValueImpl(member, indentLevel + 1);
+ }
+ }
+
+ import std.algorithm.sorting : sort;
+ // https://issues.dlang.org/show_bug.cgi?id=14439
+ // auto names = obj.keys; // aa.keys can't be called in @safe code
+ auto names = new string[obj.length];
+ size_t i = 0;
+ foreach (k, v; obj)
+ {
+ names[i] = k;
+ i++;
+ }
+ sort(names);
+ emit(names);
+
+ putEOL();
+ putTabs();
+ json.put('}');
+ }
}
break;
@@ -2469,3 +2734,17 @@ pure nothrow @safe unittest
assert(app.data == s, app.data);
}
+
+// https://issues.dlang.org/show_bug.cgi?id=24823 - JSONOptions.preserveObjectOrder
+@safe unittest
+{
+ import std.array : appender;
+
+ string s = `{"b":2,"a":1}`;
+ JSONValue j = parseJSON(s, -1, JSONOptions.preserveObjectOrder);
+
+ auto app = appender!string();
+ j.toString(app);
+
+ assert(app.data == s, app.data);
+}
diff --git a/libphobos/src/std/logger/core.d b/libphobos/src/std/logger/core.d
index 0633bdd..cc938d4 100644
--- a/libphobos/src/std/logger/core.d
+++ b/libphobos/src/std/logger/core.d
@@ -293,7 +293,7 @@ template defaultLogFunction(LogLevel ll)
string funcName = __FUNCTION__,
string prettyFuncName = __PRETTY_FUNCTION__,
string moduleName = __MODULE__, A...)(lazy A args)
- if ((args.length > 0 && !is(Unqual!(A[0]) : bool)) || args.length == 0)
+ if ((args.length > 0 && !is(Unqual!(A[0]) : bool)) || args.length == 0)
{
stdThreadLocalLog.memLogFunctions!(ll).logImpl!(line, file, funcName,
prettyFuncName, moduleName)(args);
@@ -446,7 +446,7 @@ private struct MsgRange
}
void put(T)(T msg) @safe
- if (isSomeString!T)
+ if (isSomeString!T)
{
log.logMsgPart(msg);
}
@@ -735,7 +735,7 @@ abstract class Logger
string funcName = __FUNCTION__,
string prettyFuncName = __PRETTY_FUNCTION__,
string moduleName = __MODULE__, A...)(lazy A args)
- if (args.length == 0 || (args.length > 0 && !is(A[0] : bool)))
+ if (args.length == 0 || (args.length > 0 && !is(A[0] : bool)))
{
synchronized (mutex)
{
@@ -948,7 +948,7 @@ abstract class Logger
string prettyFuncName = __PRETTY_FUNCTION__,
string moduleName = __MODULE__, A...)(const LogLevel ll,
lazy bool condition, lazy A args)
- if (args.length != 1)
+ if (args.length != 1)
{
synchronized (mutex)
{
@@ -1016,7 +1016,7 @@ abstract class Logger
string funcName = __FUNCTION__,
string prettyFuncName = __PRETTY_FUNCTION__,
string moduleName = __MODULE__, A...)(const LogLevel ll, lazy A args)
- if ((args.length > 1 && !is(Unqual!(A[0]) : bool)) || args.length == 0)
+ if ((args.length > 1 && !is(Unqual!(A[0]) : bool)) || args.length == 0)
{
synchronized (mutex)
{
@@ -1085,7 +1085,7 @@ abstract class Logger
string funcName = __FUNCTION__,
string prettyFuncName = __PRETTY_FUNCTION__,
string moduleName = __MODULE__, A...)(lazy bool condition, lazy A args)
- if (args.length != 1)
+ if (args.length != 1)
{
synchronized (mutex)
{
@@ -1154,10 +1154,10 @@ abstract class Logger
string funcName = __FUNCTION__,
string prettyFuncName = __PRETTY_FUNCTION__,
string moduleName = __MODULE__, A...)(lazy A args)
- if ((args.length > 1
- && !is(Unqual!(A[0]) : bool)
- && !is(immutable A[0] == immutable LogLevel))
- || args.length == 0)
+ if ((args.length > 1
+ && !is(Unqual!(A[0]) : bool)
+ && !is(immutable A[0] == immutable LogLevel))
+ || args.length == 0)
{
synchronized (mutex)
{
diff --git a/libphobos/src/std/numeric.d b/libphobos/src/std/numeric.d
index 9f0fb56..3fef8e4 100644
--- a/libphobos/src/std/numeric.d
+++ b/libphobos/src/std/numeric.d
@@ -496,7 +496,8 @@ public:
static @property CustomFloat im() { return CustomFloat(0.0f); }
/// Initialize from any `real` compatible type.
- this(F)(F input) if (__traits(compiles, cast(real) input ))
+ this(F)(F input)
+ if (__traits(compiles, cast(real) input ))
{
this = input;
}
@@ -512,7 +513,7 @@ public:
/// Assigns from any `real` compatible type.
void opAssign(F)(F input)
- if (__traits(compiles, cast(real) input))
+ if (__traits(compiles, cast(real) input))
{
import std.conv : text;
@@ -546,7 +547,7 @@ public:
/// Fetches the stored value either as a `float`, `double` or `real`.
@property F get(F)()
- if (staticIndexOf!(immutable F, immutable float, immutable double, immutable real) >= 0)
+ if (staticIndexOf!(immutable F, immutable float, immutable double, immutable real) >= 0)
{
import std.conv : text;
@@ -574,7 +575,7 @@ public:
/// Convert the CustomFloat to a real and perform the relevant operator on the result
real opUnary(string op)()
- if (__traits(compiles, mixin(op~`(get!real)`)) || op=="++" || op=="--")
+ if (__traits(compiles, mixin(op~`(get!real)`)) || op=="++" || op=="--")
{
static if (op=="++" || op=="--")
{
@@ -591,31 +592,31 @@ public:
// do not match equally, which is disallowed by the spec:
// https://dlang.org/spec/operatoroverloading.html#binary
real opBinary(string op,T)(T b)
- if (__traits(compiles, mixin(`get!real`~op~`b.get!real`)))
- {
- return mixin(`get!real`~op~`b.get!real`);
- }
+ if (__traits(compiles, mixin(`get!real`~op~`b.get!real`)))
+ {
+ return mixin(`get!real`~op~`b.get!real`);
+ }
/// ditto
real opBinary(string op,T)(T b)
- if ( __traits(compiles, mixin(`get!real`~op~`b`)) &&
- !__traits(compiles, mixin(`get!real`~op~`b.get!real`)))
+ if ( __traits(compiles, mixin(`get!real`~op~`b`)) &&
+ !__traits(compiles, mixin(`get!real`~op~`b.get!real`)))
{
return mixin(`get!real`~op~`b`);
}
/// ditto
real opBinaryRight(string op,T)(T a)
- if ( __traits(compiles, mixin(`a`~op~`get!real`)) &&
- !__traits(compiles, mixin(`get!real`~op~`b`)) &&
- !__traits(compiles, mixin(`get!real`~op~`b.get!real`)))
+ if ( __traits(compiles, mixin(`a`~op~`get!real`)) &&
+ !__traits(compiles, mixin(`get!real`~op~`b`)) &&
+ !__traits(compiles, mixin(`get!real`~op~`b.get!real`)))
{
return mixin(`a`~op~`get!real`);
}
/// ditto
int opCmp(T)(auto ref T b)
- if (__traits(compiles, cast(real) b))
+ if (__traits(compiles, cast(real) b))
{
auto x = get!real;
auto y = cast(real) b;
@@ -624,7 +625,7 @@ public:
/// ditto
void opOpAssign(string op, T)(auto ref T b)
- if (__traits(compiles, mixin(`get!real`~op~`cast(real) b`)))
+ if (__traits(compiles, mixin(`get!real`~op~`cast(real) b`)))
{
return mixin(`this = this `~op~` cast(real) b`);
}
@@ -3687,7 +3688,7 @@ public:
* i.e., output[j] := sum[ exp(-2 PI i j k / N) input[k] ].
*/
Complex!F[] fft(F = double, R)(R range) const
- if (isFloatingPoint!F && isRandomAccessRange!R)
+ if (isFloatingPoint!F && isRandomAccessRange!R)
{
enforceSize(range);
Complex!F[] ret;
@@ -3710,7 +3711,7 @@ public:
* property that can be both read and written and are floating point numbers.
*/
void fft(Ret, R)(R range, Ret buf) const
- if (isRandomAccessRange!Ret && isComplexLike!(ElementType!Ret) && hasSlicing!Ret)
+ if (isRandomAccessRange!Ret && isComplexLike!(ElementType!Ret) && hasSlicing!Ret)
{
assert(buf.length == range.length);
enforceSize(range);
@@ -3759,7 +3760,7 @@ public:
* output[j] := (1 / N) sum[ exp(+2 PI i j k / N) input[k] ].
*/
Complex!F[] inverseFft(F = double, R)(R range) const
- if (isRandomAccessRange!R && isComplexLike!(ElementType!R) && isFloatingPoint!F)
+ if (isRandomAccessRange!R && isComplexLike!(ElementType!R) && isFloatingPoint!F)
{
enforceSize(range);
Complex!F[] ret;
@@ -3781,7 +3782,7 @@ public:
* must be some complex-like type.
*/
void inverseFft(Ret, R)(R range, Ret buf) const
- if (isRandomAccessRange!Ret && isComplexLike!(ElementType!Ret) && hasSlicing!Ret)
+ if (isRandomAccessRange!Ret && isComplexLike!(ElementType!Ret) && hasSlicing!Ret)
{
enforceSize(range);
diff --git a/libphobos/src/std/parallelism.d b/libphobos/src/std/parallelism.d
index 7525d9b..bafdbb9 100644
--- a/libphobos/src/std/parallelism.d
+++ b/libphobos/src/std/parallelism.d
@@ -2269,7 +2269,8 @@ public:
call to `popFront` or, if thrown during construction, simply
allowed to propagate to the caller.
*/
- auto asyncBuf(S)(S source, size_t bufSize = 100) if (isInputRange!S)
+ auto asyncBuf(S)(S source, size_t bufSize = 100)
+ if (isInputRange!S)
{
static final class AsyncBuf
{
diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d
index a45865a..9dae2a6 100644
--- a/libphobos/src/std/path.d
+++ b/libphobos/src/std/path.d
@@ -1446,9 +1446,8 @@ private auto _withDefaultExtension(R, C)(R path, C[] ext)
of segments to assemble the path from.
Returns: The assembled path.
*/
-immutable(ElementEncodingType!(ElementType!Range))[]
- buildPath(Range)(scope Range segments)
- if (isInputRange!Range && !isInfinite!Range && isSomeString!(ElementType!Range))
+immutable(ElementEncodingType!(ElementType!Range))[] buildPath(Range)(scope Range segments)
+if (isInputRange!Range && !isInfinite!Range && isSomeString!(ElementType!Range))
{
if (segments.empty) return null;
@@ -3396,7 +3395,10 @@ do
}
else
{
+ import core.memory : pureMalloc, pureFree;
C[] pattmp;
+ scope(exit) if (pattmp !is null) (() @trusted => pureFree(pattmp.ptr))();
+
for (size_t pi = 0; pi < pattern.length; pi++)
{
const pc = pattern[pi];
@@ -3482,9 +3484,12 @@ do
* pattern[pi0 .. pi-1] ~ pattern[piRemain..$]
*/
if (pattmp is null)
+ {
// Allocate this only once per function invocation.
- // Should do it with malloc/free, but that would make it impure.
- pattmp = new C[pattern.length];
+ pattmp = (() @trusted =>
+ (cast(C*) pureMalloc(C.sizeof * pattern.length))[0 .. pattern.length])
+ ();
+ }
const len1 = pi - 1 - pi0;
pattmp[0 .. len1] = pattern[pi0 .. pi - 1];
@@ -3518,7 +3523,7 @@ do
}
///
-@safe unittest
+@safe @nogc unittest
{
assert(globMatch("foo.bar", "*"));
assert(globMatch("foo.bar", "*.*"));
diff --git a/libphobos/src/std/process.d b/libphobos/src/std/process.d
index 41f788d..4f593bd 100644
--- a/libphobos/src/std/process.d
+++ b/libphobos/src/std/process.d
@@ -1050,54 +1050,103 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
static if (!__traits(compiles, closefrom))
{
- // FIXME: This implementation crashes the system when RLIMIT_NOFILE
- // has a big value. For a possible solution see:
- // https://github.com/dlang/phobos/pull/8990
- void fallback (int lowfd) {
- // NOTE: malloc() and getrlimit() are not on the POSIX async
- // signal safe functions list, but practically this should
- // not be a problem. Java VM and CPython also use malloc()
- // in its own implementation via opendir().
- import core.stdc.stdlib : malloc;
- import core.sys.posix.poll : pollfd, poll, POLLNVAL;
+ void fallback (int lowfd)
+ {
+ import core.sys.posix.dirent : dirent, opendir, readdir, closedir, DIR;
+ import core.sys.posix.unistd : close;
+ import core.sys.posix.stdlib : atoi, malloc, free;
import core.sys.posix.sys.resource : rlimit, getrlimit, RLIMIT_NOFILE;
// Get the maximum number of file descriptors that could be open.
rlimit r;
if (getrlimit(RLIMIT_NOFILE, &r) != 0)
- {
abortOnError(forkPipeOut, InternalError.getrlimit, .errno);
- }
+
immutable maxDescriptors = cast(int) r.rlim_cur;
- immutable maxToClose = maxDescriptors - lowfd;
+ // Missing druntime declaration
+ pragma(mangle, "dirfd")
+ extern(C) nothrow @nogc int dirfd(DIR* dir);
- // Call poll() to see which ones are actually open:
- auto pfds = cast(pollfd*) malloc(pollfd.sizeof * maxToClose);
- if (pfds is null)
- {
- abortOnError(forkPipeOut, InternalError.malloc, .errno);
- }
- foreach (i; 0 .. maxToClose)
+ DIR* dir = null;
+
+ // We read from /dev/fd or /proc/self/fd only if the limit is high enough
+ if (maxDescriptors > 128*1024)
{
- pfds[i].fd = i + lowfd;
- pfds[i].events = 0;
- pfds[i].revents = 0;
+ // Try to open the directory /dev/fd or /proc/self/fd
+ dir = opendir("/dev/fd");
+ if (dir is null) dir = opendir("/proc/self/fd");
}
- if (poll(pfds, maxToClose, 0) >= 0)
+
+ // If we have a directory, close all file descriptors except stdin, stdout, and stderr
+ if (dir)
{
- foreach (i; 0 .. maxToClose)
+ scope(exit) closedir(dir);
+
+ int opendirfd = dirfd(dir);
+
+ // Iterate over all file descriptors
+ while (true)
{
- // POLLNVAL will be set if the file descriptor is invalid.
- if (!(pfds[i].revents & POLLNVAL)) close(pfds[i].fd);
+ dirent* entry = readdir(dir);
+
+ if (entry is null) break;
+ if (entry.d_name[0] == '.') continue;
+
+ int fd = atoi(cast(char*) entry.d_name);
+
+ // Don't close stdin, stdout, stderr, or the directory file descriptor
+ if (fd < lowfd || fd == opendirfd) continue;
+
+ close(fd);
}
}
else
{
- // Fall back to closing everything.
- foreach (i; lowfd .. maxDescriptors)
+ // This is going to allocate 8 bytes for each possible file descriptor from lowfd to r.rlim_cur
+ if (maxDescriptors <= 128*1024)
{
- close(i);
+ // NOTE: malloc() and getrlimit() are not on the POSIX async
+ // signal safe functions list, but practically this should
+ // not be a problem. Java VM and CPython also use malloc()
+ // in its own implementation via opendir().
+ import core.stdc.stdlib : malloc;
+ import core.sys.posix.poll : pollfd, poll, POLLNVAL;
+
+ immutable maxToClose = maxDescriptors - lowfd;
+
+ // Call poll() to see which ones are actually open:
+ auto pfds = cast(pollfd*) malloc(pollfd.sizeof * maxToClose);
+ if (pfds is null)
+ {
+ abortOnError(forkPipeOut, InternalError.malloc, .errno);
+ }
+
+ foreach (i; 0 .. maxToClose)
+ {
+ pfds[i].fd = i + lowfd;
+ pfds[i].events = 0;
+ pfds[i].revents = 0;
+ }
+
+ if (poll(pfds, maxToClose, 0) < 0)
+ // couldn't use poll, use the slow path.
+ goto LslowClose;
+
+ foreach (i; 0 .. maxToClose)
+ {
+ // POLLNVAL will be set if the file descriptor is invalid.
+ if (!(pfds[i].revents & POLLNVAL)) close(pfds[i].fd);
+ }
+ }
+ else
+ {
+ LslowClose:
+ // Fall back to closing everything.
+ foreach (i; lowfd .. maxDescriptors)
+ {
+ close(i);
+ }
}
}
}
@@ -1106,6 +1155,7 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
// Until we find a way to perform this check we will try to use dlsym to
// check for the function. See: https://github.com/dlang/phobos/pull/9048
version (CRuntime_Glibc)
+ {
void closefrom (int lowfd) {
static bool tryGlibcClosefrom (int lowfd) {
import core.sys.posix.dlfcn : dlopen, dlclose, dlsym, dlerror, RTLD_LAZY;
@@ -1129,6 +1179,7 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
if (!tryGlibcClosefrom(lowfd))
fallback(lowfd);
}
+ }
else
alias closefrom = fallback;
}
diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d
index 87e63f3..c221024 100644
--- a/libphobos/src/std/random.d
+++ b/libphobos/src/std/random.d
@@ -935,7 +935,8 @@ Parameters for the generator.
`Exception` if the InputRange didn't provide enough elements to seed the generator.
The number of elements required is the 'n' template parameter of the MersenneTwisterEngine struct.
*/
- void seed(T)(T range) if (isInputRange!T && is(immutable ElementType!T == immutable UIntType))
+ void seed(T)(T range)
+ if (isInputRange!T && is(immutable ElementType!T == immutable UIntType))
{
this.seedImpl(range, this.state);
}
@@ -945,7 +946,7 @@ Parameters for the generator.
which can be used with an arbitrary `State` instance
*/
private static void seedImpl(T)(T range, ref State mtState)
- if (isInputRange!T && is(immutable ElementType!T == immutable UIntType))
+ if (isInputRange!T && is(immutable ElementType!T == immutable UIntType))
{
size_t j;
for (j = 0; j < n && !range.empty; ++j, range.popFront())
@@ -2215,6 +2216,7 @@ at least that number won't be represented fairly.
Hence, our condition to reroll is
`bucketFront > (UpperType.max - (upperDist - 1))`
+/
+/// ditto
auto uniform(string boundaries = "[)", T1, T2, RandomGen)
(T1 a, T2 b, ref RandomGen rng)
if ((isIntegral!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2))) &&
@@ -2277,9 +2279,14 @@ if ((isIntegral!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2))) &&
return cast(ResultType)(lower + offset);
}
+///
@safe unittest
{
import std.conv : to;
+ import std.meta : AliasSeq;
+ import std.range.primitives : isForwardRange;
+ import std.traits : isIntegral, isSomeChar;
+
auto gen = Mt19937(123_456_789);
static assert(isForwardRange!(typeof(gen)));
@@ -2290,7 +2297,7 @@ if ((isIntegral!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2))) &&
auto c = uniform(0.0, 1.0);
assert(0 <= c && c < 1);
- static foreach (T; std.meta.AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort,
+ static foreach (T; AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort,
int, uint, long, ulong, float, double, real))
{{
T lo = 0, hi = 100;
@@ -2344,7 +2351,7 @@ if ((isIntegral!(CommonType!(T1, T2)) || isSomeChar!(CommonType!(T1, T2))) &&
auto reproRng = Xorshift(239842);
- static foreach (T; std.meta.AliasSeq!(char, wchar, dchar, byte, ubyte, short,
+ static foreach (T; AliasSeq!(char, wchar, dchar, byte, ubyte, short,
ushort, int, uint, long, ulong))
{{
T lo = T.min + 10, hi = T.max - 10;
diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d
index e2a2d7d..3a135eb 100644
--- a/libphobos/src/std/range/package.d
+++ b/libphobos/src/std/range/package.d
@@ -6095,8 +6095,10 @@ private struct LockstepMixin(Ranges...)
{
indexDef = q{
size_t index = ranges[0].length - 1;
- enforce(this.stoppingPolicy == StoppingPolicy.requireSameLength,
- "lockstep can only be used with foreach_reverse when stoppingPolicy == requireSameLength");
+ enforce(
+ this.stoppingPolicy == StoppingPolicy.requireSameLength,
+ "Indexed lockstep can only be used with foreach_reverse when " ~
+ "stoppingPolicy == requireSameLength");
foreach (range; ranges[1 .. $])
enforce(range.length == ranges[0].length);
@@ -7490,7 +7492,8 @@ if (!isIntegral!(CommonType!(B, E)) &&
bool opEquals(Cyclic c) const { return current == c.current; }
bool opEquals(int i) const { return current == i; }
- void opUnary(string op)() if (op == "++")
+ void opUnary(string op)()
+ if (op == "++")
{
current = (current + 1) % wrapAround;
}
@@ -12444,7 +12447,7 @@ public:
return (*_range).front;
}
- static if (is(typeof((*(cast(const R*)_range)).front))) @property auto front() const
+ static if (is(typeof(((const R* r) => (*r).front)(null)))) @property auto front() const
{
return (*_range).front;
}
@@ -12470,7 +12473,7 @@ public:
return (*_range).empty;
}
- static if (is(typeof((*cast(const R*)_range).empty))) @property bool empty() const
+ static if (is(typeof(((const R* r) => (*r).empty)(null)))) @property bool empty() const
{
return (*_range).empty;
}
@@ -12500,10 +12503,11 @@ public:
else static if (isForwardRange!R)
{
import std.traits : isSafe;
- private alias S = typeof((*_range).save);
+ private alias S = typeof((() => (*_range).save)());
+
+ static if (is(typeof(((const R* r) => (*r).save)(null))))
+ private alias CS = typeof(((const R* r) => (*r).save)(null));
- static if (is(typeof((*cast(const R*)_range).save)))
- private alias CS = typeof((*cast(const R*)_range).save);
static if (isSafe!((R* r) => (*r).save))
{
@@ -12512,7 +12516,7 @@ public:
mixin(_genSave());
}
- static if (is(typeof((*cast(const R*)_range).save))) @property RefRange!CS save() @trusted const
+ static if (is(typeof(((const R* r) => (*r).save)(null)))) @property RefRange!CS save() @trusted const
{
mixin(_genSave());
}
@@ -12524,7 +12528,7 @@ public:
mixin(_genSave());
}
- static if (is(typeof((*cast(const R*)_range).save))) @property RefRange!CS save() const
+ static if (is(typeof(((const R* r) => (*r).save)(null)))) @property RefRange!CS save() const
{
mixin(_genSave());
}
@@ -12543,7 +12547,7 @@ public:
private static string _genSave() @safe pure nothrow
{
return `import core.lifetime : emplace;` ~
- `alias S = typeof((*_range).save);` ~
+ `alias S = typeof((() => (*_range).save)());` ~
`static assert(isForwardRange!S, S.stringof ~ " is not a forward range.");` ~
`auto mem = new void[S.sizeof];` ~
`emplace!S(mem, cast(S)(*_range).save);` ~
@@ -12572,7 +12576,7 @@ public:
return (*_range).back;
}
- static if (is(typeof((*(cast(const R*)_range)).back))) @property auto back() const
+ static if (is(typeof(((const R* r) => (*r).back)(null)))) @property auto back() const
{
return (*_range).back;
}
@@ -12604,13 +12608,13 @@ public:
else static if (isRandomAccessRange!R)
{
auto ref opIndex(IndexType)(IndexType index)
- if (is(typeof((*_range)[index])))
+ if (is(typeof((*_range)[index])))
{
return (*_range)[index];
}
auto ref opIndex(IndexType)(IndexType index) const
- if (is(typeof((*cast(const R*)_range)[index])))
+ if (is(typeof((*cast(const R*)_range)[index])))
{
return (*_range)[index];
}
@@ -12662,7 +12666,7 @@ public:
{
return (*_range).length;
}
- static if (is(typeof((*cast(const R*)_range).length))) @property auto length() const
+ static if (is(typeof(((const R* r) => (*r).length)(null)))) @property auto length() const
{
return (*_range).length;
}
@@ -12692,14 +12696,14 @@ public:
RefRange!T opSlice(IndexType1, IndexType2)
(IndexType1 begin, IndexType2 end)
- if (is(typeof((*_range)[begin .. end])))
+ if (is(typeof((*_range)[begin .. end])))
{
mixin(_genOpSlice());
}
RefRange!CT opSlice(IndexType1, IndexType2)
(IndexType1 begin, IndexType2 end) const
- if (is(typeof((*cast(const R*)_range)[begin .. end])))
+ if (is(typeof((*cast(const R*)_range)[begin .. end])))
{
mixin(_genOpSlice());
}
@@ -13105,6 +13109,44 @@ private:
auto rr2 = refRange(&r2);
}
+// https://issues.dlang.org/show_bug.cgi?id=24801
+@safe unittest
+{
+
+ {
+ static struct R
+ {
+ int front() => 0;
+ void popFront() {}
+ bool empty() => false;
+ }
+ R range;
+ auto r = RefRange!R(&range);
+ }
+
+ {
+ static struct R
+ {
+ size_t start, end;
+ size_t length() => end - start;
+ int opIndex(size_t i) => 0;
+
+
+ int front() => this[0];
+ int back() => this[length-1];
+ void popFront() { start++; }
+ void popBack() { end--; }
+ bool empty() => length == 0;
+ R save() const => R();
+ }
+
+ R range;
+ auto r = RefRange!R(&range);
+ }
+
+
+}
+
/// ditto
auto refRange(R)(R* range)
if (isInputRange!R)
diff --git a/libphobos/src/std/range/primitives.d b/libphobos/src/std/range/primitives.d
index dddcae9..8436625 100644
--- a/libphobos/src/std/range/primitives.d
+++ b/libphobos/src/std/range/primitives.d
@@ -474,7 +474,8 @@ void put(R, E)(ref R r, E e)
{
string data;
- void put(C)(C c) if (isSomeChar!C)
+ void put(C)(C c)
+ if (isSomeChar!C)
{
data ~= c;
}
diff --git a/libphobos/src/std/regex/internal/backtracking.d b/libphobos/src/std/regex/internal/backtracking.d
index a488e06..605ec03 100644
--- a/libphobos/src/std/regex/internal/backtracking.d
+++ b/libphobos/src/std/regex/internal/backtracking.d
@@ -702,7 +702,7 @@ final:
}
void stackPush(T)(T val)
- if (!isDynamicArray!T)
+ if (!isDynamicArray!T)
{
*cast(T*)&memory[lastState] = val;
enum delta = (T.sizeof+size_t.sizeof/2)/size_t.sizeof;
@@ -720,7 +720,7 @@ final:
}
void stackPop(T)(ref T val)
- if (!isDynamicArray!T)
+ if (!isDynamicArray!T)
{
enum delta = (T.sizeof+size_t.sizeof/2)/size_t.sizeof;
lastState -= delta;
diff --git a/libphobos/src/std/regex/internal/parser.d b/libphobos/src/std/regex/internal/parser.d
index ab2b297..d8ebe59 100644
--- a/libphobos/src/std/regex/internal/parser.d
+++ b/libphobos/src/std/regex/internal/parser.d
@@ -542,7 +542,7 @@ if (isForwardRange!R && is(ElementType!R : dchar))
Generator g;
@trusted this(S)(R pattern, S flags)
- if (isSomeString!S)
+ if (isSomeString!S)
{
pat = origin = pattern;
//reserve slightly more then avg as sampled from unittests
diff --git a/libphobos/src/std/regex/internal/thompson.d b/libphobos/src/std/regex/internal/thompson.d
index f4643ae..195625f 100644
--- a/libphobos/src/std/regex/internal/thompson.d
+++ b/libphobos/src/std/regex/internal/thompson.d
@@ -276,7 +276,7 @@ template ThompsonOps(E, S, bool withInput:true)
}
static bool op(IR code)(E e, S* state)
- if (code == IR.RepeatEnd || code == IR.RepeatQEnd)
+ if (code == IR.RepeatEnd || code == IR.RepeatQEnd)
{
with(e) with(state)
{
@@ -331,7 +331,7 @@ template ThompsonOps(E, S, bool withInput:true)
}
static bool op(IR code)(E e, S* state)
- if (code == IR.InfiniteEnd || code == IR.InfiniteQEnd)
+ if (code == IR.InfiniteEnd || code == IR.InfiniteQEnd)
{
with(e) with(state)
{
@@ -366,7 +366,7 @@ template ThompsonOps(E, S, bool withInput:true)
}
static bool op(IR code)(E e, S* state)
- if (code == IR.InfiniteBloomEnd)
+ if (code == IR.InfiniteBloomEnd)
{
with(e) with(state)
{
@@ -507,7 +507,7 @@ template ThompsonOps(E, S, bool withInput:true)
static bool op(IR code)(E e, S* state)
- if (code == IR.LookbehindStart || code == IR.NeglookbehindStart)
+ if (code == IR.LookbehindStart || code == IR.NeglookbehindStart)
{
with(e) with(state)
{
@@ -534,7 +534,7 @@ template ThompsonOps(E, S, bool withInput:true)
}
static bool op(IR code)(E e, S* state)
- if (code == IR.LookaheadStart || code == IR.NeglookaheadStart)
+ if (code == IR.LookaheadStart || code == IR.NeglookaheadStart)
{
with(e) with(state)
{
@@ -563,8 +563,8 @@ template ThompsonOps(E, S, bool withInput:true)
}
static bool op(IR code)(E e, S* state)
- if (code == IR.LookaheadEnd || code == IR.NeglookaheadEnd ||
- code == IR.LookbehindEnd || code == IR.NeglookbehindEnd)
+ if (code == IR.LookaheadEnd || code == IR.NeglookaheadEnd ||
+ code == IR.LookbehindEnd || code == IR.NeglookbehindEnd)
{
with(e) with(state)
{
@@ -675,7 +675,7 @@ template ThompsonOps(E,S, bool withInput:false)
@trusted:
// can't match these without input
static bool op(IR code)(E e, S* state)
- if (code == IR.Char || code == IR.OrChar || code == IR.CodepointSet
+ if (code == IR.Char || code == IR.OrChar || code == IR.CodepointSet
|| code == IR.Trie || code == IR.Char || code == IR.Any)
{
return state.popState(e);
@@ -701,7 +701,7 @@ template ThompsonOps(E,S, bool withInput:false)
// forward all control flow to normal versions
static bool op(IR code)(E e, S* state)
- if (code != IR.Char && code != IR.OrChar && code != IR.CodepointSet
+ if (code != IR.Char && code != IR.OrChar && code != IR.CodepointSet
&& code != IR.Trie && code != IR.Char && code != IR.Any && code != IR.Backref)
{
return ThompsonOps!(E,S,true).op!code(e,state);
diff --git a/libphobos/src/std/regex/package.d b/libphobos/src/std/regex/package.d
index d6a01e2..143b683 100644
--- a/libphobos/src/std/regex/package.d
+++ b/libphobos/src/std/regex/package.d
@@ -688,7 +688,7 @@ public:
----
+/
R opIndex(String)(String i) /*const*/ //@@@BUG@@@
- if (isSomeString!String)
+ if (isSomeString!String)
{
size_t index = lookupNamedGroup(_names, i);
return getMatch(index);
diff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d
index e86a51f..52fd33b 100644
--- a/libphobos/src/std/socket.d
+++ b/libphobos/src/std/socket.d
@@ -702,7 +702,7 @@ class InternetHost
// must synchronize across all threads
private bool getHost(string opMixin, T)(T param) @system
{
- synchronized(this.classinfo)
+ synchronized(typeid(this))
return getHostNoSync!(opMixin, T)(param);
}
}
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index b474460..e844297 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -447,7 +447,7 @@ Throws: `ErrnoException` if the file could not be opened.
/// ditto
this(R1, R2)(R1 name)
- if (isSomeFiniteCharInputRange!R1)
+ if (isSomeFiniteCharInputRange!R1)
{
import std.conv : to;
this(name.to!string, "rb");
@@ -455,8 +455,8 @@ Throws: `ErrnoException` if the file could not be opened.
/// ditto
this(R1, R2)(R1 name, R2 mode)
- if (isSomeFiniteCharInputRange!R1 &&
- isSomeFiniteCharInputRange!R2)
+ if (isSomeFiniteCharInputRange!R1 &&
+ isSomeFiniteCharInputRange!R2)
{
import std.conv : to;
this(name.to!string, mode.to!string);
@@ -2340,6 +2340,24 @@ void main()
Notice that neither example accesses the line data returned by
`front` after the corresponding `popFront` call is made (because
the contents may well have changed).
+----
+
+Windows specific Example:
+----
+import std.stdio;
+
+version (Windows)
+void main()
+{
+
+ foreach (line; File("file.txt").byLine(No.keepTerminator, "\r\n"))
+ {
+ writeln("|"~line~"|");
+ if (line == "HelloWorld")
+ writeln("^This Line is here.");
+ }
+
+}
*/
auto byLine(Terminator = char, Char = char)
(KeepTerminator keepTerminator = No.keepTerminator,
@@ -2997,10 +3015,10 @@ is empty, throws an `Exception`. In case of an I/O error throws
/// Range primitive implementations.
void put(A)(scope A writeme)
- if ((isSomeChar!(ElementType!A) ||
- is(ElementType!A : const(ubyte))) &&
- isInputRange!A &&
- !isInfinite!A)
+ if ((isSomeChar!(ElementType!A) ||
+ is(ElementType!A : const(ubyte))) &&
+ isInputRange!A &&
+ !isInfinite!A)
{
import std.exception : errnoEnforce;
@@ -3026,7 +3044,8 @@ is empty, throws an `Exception`. In case of an I/O error throws
}
/// ditto
- void put(C)(scope C c) @safe if (isSomeChar!C || is(C : const(ubyte)))
+ void put(C)(scope C c) @safe
+ if (isSomeChar!C || is(C : const(ubyte)))
{
import std.utf : decodeFront, encode, stride;
diff --git a/libphobos/src/std/string.d b/libphobos/src/std/string.d
index 21e1ca3..bcc9d7c 100644
--- a/libphobos/src/std/string.d
+++ b/libphobos/src/std/string.d
@@ -457,26 +457,26 @@ pure nothrow @system unittest // https://issues.dlang.org/show_bug.cgi?id=15136
alias CaseSensitive = Flag!"caseSensitive";
/++
- Searches for character in range.
+ Searches for a character in a string or range.
Params:
- s = string or InputRange of characters to search in correct UTF format
- c = character to search for
- startIdx = starting index to a well-formed code point
- cs = `Yes.caseSensitive` or `No.caseSensitive`
+ s = string or InputRange of characters to search for `c` in
+ c = character to search for in `s`
+ startIdx = index to a well-formed code point in `s` to start
+ searching from; defaults to 0
+ cs = specifies whether comparisons are case-sensitive
+ (`Yes.caseSensitive`) or not (`No.caseSensitive`).
Returns:
- the index of the first occurrence of `c` in `s` with
- respect to the start index `startIdx`. If `c`
- is not found, then `-1` is returned.
- If `c` is found the value of the returned index is at least
- `startIdx`.
- If the parameters are not valid UTF, the result will still
- be in the range [-1 .. s.length], but will not be reliable otherwise.
+ If `c` is found in `s`, then the index of its first occurrence is
+ returned. If `c` is not found or `startIdx` is greater than or equal to
+ `s.length`, then -1 is returned. If the parameters are not valid UTF,
+ the result will still be either -1 or in the range [`startIdx` ..
+ `s.length`], but will not be reliable otherwise.
Throws:
- If the sequence starting at `startIdx` does not represent a well
- formed codepoint, then a $(REF UTFException, std,utf) may be thrown.
+ If the sequence starting at `startIdx` does not represent a well-formed
+ code point, then a $(REF UTFException, std,utf) may be thrown.
See_Also: $(REF countUntil, std,algorithm,searching)
+/
@@ -901,30 +901,30 @@ private template _indexOfStr(CaseSensitive cs)
}
/++
- Searches for substring in `s`.
+ Searches for a substring in a string or range.
Params:
- s = string or ForwardRange of characters to search in correct UTF format
- sub = substring to search for
- startIdx = the index into s to start searching from
- cs = `Yes.caseSensitive` (default) or `No.caseSensitive`
+ s = string or ForwardRange of characters to search for `sub` in
+ sub = substring to search for in `s`
+ startIdx = index to a well-formed code point in `s` to start
+ searching from; defaults to 0
+ cs = specifies whether comparisons are case-sensitive
+ (`Yes.caseSensitive`) or not (`No.caseSensitive`)
Returns:
- the index of the first occurrence of `sub` in `s` with
- respect to the start index `startIdx`. If `sub` is not found,
- then `-1` is returned.
- If the arguments are not valid UTF, the result will still
- be in the range [-1 .. s.length], but will not be reliable otherwise.
- If `sub` is found the value of the returned index is at least
- `startIdx`.
+ The index of the first occurrence of `sub` in `s`. If `sub` is not found
+ or `startIdx` is greater than or equal to `s.length`, then -1 is
+ returned. If the arguments are not valid UTF, the result will still be
+ either -1 or in the range [`startIdx` .. `s.length`], but will not be
+ reliable otherwise.
Throws:
- If the sequence starting at `startIdx` does not represent a well
- formed codepoint, then a $(REF UTFException, std,utf) may be thrown.
+ If the sequence starting at `startIdx` does not represent a well-formed
+ code point, then a $(REF UTFException, std,utf) may be thrown.
Bugs:
- Does not work with case insensitive strings where the mapping of
- tolower and toupper is not 1:1.
+ Does not work with case-insensitive strings where the mapping of
+ $(REF toLower, std,uni) and $(REF toUpper, std,uni) is not 1:1.
+/
ptrdiff_t indexOf(Range, Char)(Range s, const(Char)[] sub)
if (isForwardRange!Range && isSomeChar!(ElementEncodingType!Range) &&
@@ -1156,23 +1156,26 @@ unittest
}
/++
+ Searches for the last occurrence of a character in a string.
+
Params:
- s = string to search
- c = character to search for
- startIdx = the index into s to start searching from
- cs = `Yes.caseSensitive` or `No.caseSensitive`
+ s = string to search for `c` in
+ c = character to search for in `s`
+ startIdx = index of a well-formed code point in `s` to start searching
+ from; defaults to 0
+ cs = specifies whether comparisons are case-sensitive
+ (`Yes.caseSensitive`) or not (`No.caseSensitive`)
Returns:
- The index of the last occurrence of `c` in `s`. If `c` is not
- found, then `-1` is returned. The `startIdx` slices `s` in
- the following way $(D s[0 .. startIdx]). `startIdx` represents a
- codeunit index in `s`.
+ If `c` is found in `s`, then the index of its last occurrence is
+ returned. If `c` is not found or `startIdx` is greater than or equal to
+ `s.length`, then -1 is returned. If the parameters are not valid UTF,
+ the result will still be either -1 or in the range [`startIdx` ..
+ `s.length`], but will not be reliable otherwise.
Throws:
- If the sequence ending at `startIdx` does not represent a well
- formed codepoint, then a $(REF UTFException, std,utf) may be thrown.
-
- `cs` indicates whether the comparisons are case sensitive.
+ If the sequence ending at `startIdx` does not represent a well-formed
+ code point, then a $(REF UTFException, std,utf) may be thrown.
+/
ptrdiff_t lastIndexOf(Char)(const(Char)[] s, in dchar c,
in CaseSensitive cs = Yes.caseSensitive) @safe pure
@@ -1345,23 +1348,30 @@ if (isSomeChar!Char)
}
/++
+ Searches for the last occurrence of a substring in a string.
+
Params:
- s = string to search
- sub = substring to search for
- startIdx = the index into s to start searching from
- cs = `Yes.caseSensitive` or `No.caseSensitive`
+ s = string to search for `sub` in
+ sub = substring to search for in `s`
+ startIdx = index to a well-formed code point in `s` to start
+ searching from; defaults to 0
+ cs = specifies whether comparisons are case-sensitive
+ (`Yes.caseSensitive`) or not (`No.caseSensitive`)
Returns:
- the index of the last occurrence of `sub` in `s`. If `sub` is
- not found, then `-1` is returned. The `startIdx` slices `s`
- in the following way $(D s[0 .. startIdx]). `startIdx` represents a
- codeunit index in `s`.
+ The index of the last occurrence of `sub` in `s`. If `sub` is not found
+ or `startIdx` is greater than or equal to `s.length`, then -1 is
+ returned. If the parameters are not valid UTF, the result will still be
+ either -1 or in the range [`startIdx` .. `s.length`], but will not be
+ reliable otherwise.
Throws:
- If the sequence ending at `startIdx` does not represent a well
- formed codepoint, then a $(REF UTFException, std,utf) may be thrown.
+ If the sequence starting at `startIdx` does not represent a well-formed
+ code point, then a $(REF UTFException, std,utf) may be thrown.
- `cs` indicates whether the comparisons are case sensitive.
+ Bugs:
+ Does not work with case-insensitive strings where the mapping of
+ $(REF toLower, std,uni) and $(REF toUpper, std,uni) is not 1:1.
+/
ptrdiff_t lastIndexOf(Char1, Char2)(const(Char1)[] s, const(Char2)[] sub,
in CaseSensitive cs = Yes.caseSensitive) @safe pure
@@ -1747,21 +1757,28 @@ if (isSomeChar!Char && isSomeChar!Char2)
}
/**
- Returns the index of the first occurrence of any of the elements in $(D
- needles) in `haystack`. If no element of `needles` is found,
- then `-1` is returned. The `startIdx` slices `haystack` in the
- following way $(D haystack[startIdx .. $]). `startIdx` represents a
- codeunit index in `haystack`. If the sequence ending at `startIdx`
- does not represent a well formed codepoint, then a $(REF UTFException, std,utf)
- may be thrown.
+ Searches the string `haystack` for one of the characters in `needles`
+ starting at index `startIdx`. If `startIdx` is not given, it defaults to 0.
Params:
- haystack = String to search for needles in.
- needles = Strings to search for in haystack.
- startIdx = slices haystack like this $(D haystack[startIdx .. $]). If
- the startIdx is greater than or equal to the length of haystack the
- functions returns `-1`.
- cs = Indicates whether the comparisons are case sensitive.
+ haystack = string to search for needles in
+ needles = characters to search for in `haystack`
+ startIdx = index of a well-formed code point in `haystack` to start
+ searching from; defaults to 0
+ cs = specifies whether comparisons are case-sensitive
+ (`Yes.caseSensitive`) or not (`No.caseSensitive`)
+
+ Returns:
+ The index of the first occurrence of any of the elements of `needles` in
+ `haystack`. If no element of `needles` is found or `startIdx` is greater
+ than or equal to `haystack.length`, then -1 is returned. If the
+ parameters are not valid UTF, the result will still be either -1 or in
+ the range [`startIdx` .. `haystack.length`], but will not be reliable
+ otherwise.
+
+ Throws:
+ If the sequence starting at `startIdx` does not represent a well-formed
+ code point, then a $(REF UTFException, std,utf) may be thrown.
*/
ptrdiff_t indexOfAny(Char,Char2)(const(Char)[] haystack, const(Char2)[] needles,
in CaseSensitive cs = Yes.caseSensitive) @safe pure
@@ -1914,21 +1931,23 @@ if (isSomeChar!Char && isSomeChar!Char2)
}
/**
- Returns the index of the last occurrence of any of the elements in $(D
- needles) in `haystack`. If no element of `needles` is found,
- then `-1` is returned. The `stopIdx` slices `haystack` in the
- following way $(D s[0 .. stopIdx]). `stopIdx` represents a codeunit
- index in `haystack`. If the sequence ending at `startIdx` does not
- represent a well formed codepoint, then a $(REF UTFException, std,utf) may be
- thrown.
+ Searches `haystack` for the last occurrence of any of the
+ characters in `needles`.
Params:
- haystack = String to search for needles in.
- needles = Strings to search for in haystack.
- stopIdx = slices haystack like this $(D haystack[0 .. stopIdx]). If
- the stopIdx is greater than or equal to the length of haystack the
- functions returns `-1`.
- cs = Indicates whether the comparisons are case sensitive.
+ haystack = string to search needles in
+ needles = characters to search for in `haystack`
+ stopIdx = index in `haystack` to stop searching at (exclusive); defaults
+ to `haystack.length`
+ cs = specifies whether comparisons are case-sensitive
+ (`Yes.caseSensitive`) or not (`No.caseSensitive`)
+
+ Returns:
+ The index of the last occurrence of any of the characters of `needles`
+ in `haystack`. If no character of `needles` is found or `stopIdx` is 0,
+ then -1 is returned. If the parameters are not valid UTF, the result
+ will still be in the range [-1 .. `stopIdx`], but will not be reliable
+ otherwise.
*/
ptrdiff_t lastIndexOfAny(Char,Char2)(const(Char)[] haystack,
const(Char2)[] needles, in CaseSensitive cs = Yes.caseSensitive)
@@ -2097,17 +2116,27 @@ if (isSomeChar!Char && isSomeChar!Char2)
}
/**
- Returns the index of the first occurrence of any character not an elements
- in `needles` in `haystack`. If all element of `haystack` are
- element of `needles` `-1` is returned.
+ Searches `haystack` for a character not in `needles`.
Params:
- haystack = String to search for needles in.
- needles = Strings to search for in haystack.
- startIdx = slices haystack like this $(D haystack[startIdx .. $]). If
- the startIdx is greater than or equal to the length of haystack the
- functions returns `-1`.
- cs = Indicates whether the comparisons are case sensitive.
+ haystack = string to search for needles in
+ needles = characters to search for in `haystack`
+ startIdx = index of a well-formed code point in `haystack` to start
+ searching from; defaults to 0
+ cs = specifies whether comparisons are case-sensitive
+ (`Yes.caseSensitive`) or not (`No.caseSensitive`)
+
+ Returns:
+ The index of the first character in `haystack` that is not an element of
+ `needles`. If all characters of `haystack` are elements of `needles` or
+ `startIdx` is greater than or equal to `haystack.length`, then -1 is
+ returned. If the parameters are not valid UTF, the result will still be
+ either -1 or in the range [`startIdx` .. `haystack.length`], but will
+ not be reliable otherwise.
+
+ Throws:
+ If the sequence starting at `startIdx` does not represent a well-formed
+ code point, then a $(REF UTFException, std,utf) may be thrown.
*/
ptrdiff_t indexOfNeither(Char,Char2)(const(Char)[] haystack,
const(Char2)[] needles, in CaseSensitive cs = Yes.caseSensitive)
@@ -2257,17 +2286,22 @@ if (isSomeChar!Char && isSomeChar!Char2)
}
/**
- Returns the last index of the first occurence of any character that is not
- an elements in `needles` in `haystack`. If all element of
- `haystack` are element of `needles` `-1` is returned.
+ Searches for the last character in `haystack` that is not in `needles`.
Params:
- haystack = String to search for needles in.
- needles = Strings to search for in haystack.
- stopIdx = slices haystack like this $(D haystack[0 .. stopIdx]) If
- the stopIdx is greater than or equal to the length of haystack the
- functions returns `-1`.
- cs = Indicates whether the comparisons are case sensitive.
+ haystack = string to search for needles in
+ needles = characters to search for in `haystack`
+ stopIdx = index in `haystack` to stop searching at (exclusive);
+ defaults to `haystack.length`
+ cs = specifies whether comparisons are case-sensitive
+ (`Yes.caseSensitive`) or not (`No.caseSensitive`)
+
+ Returns:
+ The index of the last character in `haystack` that is not an element of
+ `needles`. If all characters of `haystack` are in `needles` or `stopIdx`
+ is 0, then -1 is returned. If the parameters are not valid UTF, the
+ result will still be in the range [-1 .. `stopIdx`], but will not be
+ reliable otherwise.
*/
ptrdiff_t lastIndexOfNeither(Char,Char2)(const(Char)[] haystack,
const(Char2)[] needles, in CaseSensitive cs = Yes.caseSensitive)
diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d
index 5ed37a1..69362c0 100644
--- a/libphobos/src/std/traits.d
+++ b/libphobos/src/std/traits.d
@@ -7367,10 +7367,12 @@ template isInstanceOf(alias S, alias T)
static struct A(T = void)
{
// doesn't work as expected, only accepts A when T = void
- void func(B)(B b) if (isInstanceOf!(A, B)) {}
+ void func(B)(B b)
+ if (isInstanceOf!(A, B)) {}
// correct behavior
- void method(B)(B b) if (isInstanceOf!(TemplateOf!(A), B)) {}
+ void method(B)(B b)
+ if (isInstanceOf!(TemplateOf!(A), B)) {}
}
A!(void) a1;
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index aceb287..c874c0f 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -2235,12 +2235,14 @@ template tuple(Names...)
// e.g. Tuple!(int, "x", string, "y")
template Interleave(A...)
{
- template and(B...) if (B.length == 1)
+ template and(B...)
+ if (B.length == 1)
{
alias and = AliasSeq!(A[0], B[0]);
}
- template and(B...) if (B.length != 1)
+ template and(B...)
+ if (B.length != 1)
{
alias and = AliasSeq!(A[0], B[0],
Interleave!(A[1..$]).and!(B[1..$]));
@@ -5134,7 +5136,7 @@ Params:
non-release mode.
*/
void opAssign()(T value)
- if (isAssignable!T) //@@@9416@@@
+ if (isAssignable!T) //@@@9416@@@
{
enum message = "Called `opAssign' on null NullableRef!" ~ T.stringof ~ ".";
assert(!isNull, message);
@@ -5469,15 +5471,17 @@ nothrow pure @safe unittest
}
}
-// / ditto
+/// ditto
class NotImplementedError : Error
{
+ ///
this(string method) nothrow pure @safe
{
super(method ~ " is not implemented");
}
}
+///
@system unittest
{
import std.exception : assertThrown;
@@ -7498,7 +7502,8 @@ Constructor that initializes the payload.
Postcondition: `refCountedStore.isInitialized`
*/
- this(A...)(auto ref A args) if (A.length > 0)
+ this(A...)(auto ref A args)
+ if (A.length > 0)
out
{
assert(refCountedStore.isInitialized);
@@ -7931,7 +7936,8 @@ template borrow(alias fun)
{
import std.functional : unaryFun;
- auto ref borrow(RC)(RC refCount) if
+ auto ref borrow(RC)(RC refCount)
+ if
(
isInstanceOf!(SafeRefCounted, RC)
&& is(typeof(unaryFun!fun(refCount.refCountedPayload)))
@@ -8140,7 +8146,7 @@ mixin template Proxy(alias a)
}
bool opEquals(T)(T b)
- if (is(ValueType : T) || is(typeof(a.opEquals(b))) || is(typeof(b.opEquals(a))))
+ if (is(ValueType : T) || is(typeof(a.opEquals(b))) || is(typeof(b.opEquals(a))))
{
static if (is(typeof(a.opEquals(b))))
return a.opEquals(b);
@@ -8164,7 +8170,7 @@ mixin template Proxy(alias a)
}
int opCmp(T)(auto ref const T b)
- if (is(ValueType : T) || is(typeof(a.opCmp(b))) || is(typeof(b.opCmp(a))))
+ if (is(ValueType : T) || is(typeof(a.opCmp(b))) || is(typeof(b.opCmp(a))))
{
static if (is(typeof(a.opCmp(b))))
return a.opCmp(b);
@@ -8274,7 +8280,8 @@ mixin template Proxy(alias a)
}
}
- auto ref opAssign (this X, V )(auto ref V v) if (!is(V == typeof(this))) { return a = v; }
+ auto ref opAssign (this X, V )(auto ref V v)
+ if (!is(V == typeof(this))) { return a = v; }
auto ref opIndexAssign(this X, V, D...)(auto ref V v, auto ref D i) { return a[i] = v; }
auto ref opSliceAssign(this X, V )(auto ref V v) { return a[] = v; }
auto ref opSliceAssign(this X, V, B, E)(auto ref V v, auto ref B b, auto ref E e) { return a[b .. e] = v; }
@@ -9793,6 +9800,7 @@ Flag!"encryption".no).
*/
struct Yes
{
+ ///
template opDispatch(string name)
{
enum opDispatch = Flag!name.yes;
@@ -9803,6 +9811,7 @@ struct Yes
/// Ditto
struct No
{
+ ///
template opDispatch(string name)
{
enum opDispatch = Flag!name.no;
@@ -9941,7 +9950,7 @@ public:
}
this(T...)(T flags)
- if (allSatisfy!(isBaseEnumType, T))
+ if (allSatisfy!(isBaseEnumType, T))
{
this = flags;
}
@@ -9952,19 +9961,19 @@ public:
}
Base opCast(B)() const
- if (is(Base : B))
+ if (is(Base : B))
{
return mValue;
}
auto opUnary(string op)() const
- if (op == "~")
+ if (op == "~")
{
return BitFlags(cast(E) cast(Base) ~mValue);
}
auto ref opAssign(T...)(T flags)
- if (allSatisfy!(isBaseEnumType, T))
+ if (allSatisfy!(isBaseEnumType, T))
{
mValue = 0;
foreach (E flag; flags)
@@ -10005,7 +10014,7 @@ public:
}
auto opBinary(string op)(BitFlags flags) const
- if (op == "|" || op == "&")
+ if (op == "|" || op == "&")
{
BitFlags result = this;
result.opOpAssign!op(flags);
@@ -10013,7 +10022,7 @@ public:
}
auto opBinary(string op)(E flag) const
- if (op == "|" || op == "&")
+ if (op == "|" || op == "&")
{
BitFlags result = this;
result.opOpAssign!op(flag);
@@ -10021,7 +10030,7 @@ public:
}
auto opBinaryRight(string op)(E flag) const
- if (op == "|" || op == "&")
+ if (op == "|" || op == "&")
{
return opBinary!op(flag);
}
@@ -10653,25 +10662,29 @@ struct Ternary
$(TR $(TD `unknown`) $(TD `unknown`) $(TD) $(TD `unknown`) $(TD `unknown`) $(TD `unknown`))
)
*/
- Ternary opUnary(string s)() if (s == "~")
+ Ternary opUnary(string s)()
+ if (s == "~")
{
return make((386 >> value) & 6);
}
/// ditto
- Ternary opBinary(string s)(Ternary rhs) if (s == "|")
+ Ternary opBinary(string s)(Ternary rhs)
+ if (s == "|")
{
return make((25_512 >> (value + rhs.value)) & 6);
}
/// ditto
- Ternary opBinary(string s)(Ternary rhs) if (s == "&")
+ Ternary opBinary(string s)(Ternary rhs)
+ if (s == "&")
{
return make((26_144 >> (value + rhs.value)) & 6);
}
/// ditto
- Ternary opBinary(string s)(Ternary rhs) if (s == "^")
+ Ternary opBinary(string s)(Ternary rhs)
+ if (s == "^")
{
return make((26_504 >> (value + rhs.value)) & 6);
}
@@ -10937,7 +10950,8 @@ struct RefCounted(T, RefCountedAutoInitialize autoInit =
return _refCounted;
}
- this(A...)(auto ref A args) if (A.length > 0)
+ this(A...)(auto ref A args)
+ if (A.length > 0)
out
{
assert(refCountedStore.isInitialized);
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index f7610c0..34d15e0 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -16,6 +16,7 @@ $(TR $(TD Decode) $(TD
$(LREF byGrapheme)
$(LREF decodeGrapheme)
$(LREF graphemeStride)
+ $(LREF popGrapheme)
))
$(TR $(TD Comparison) $(TD
$(LREF icmp)
@@ -708,8 +709,8 @@ import std.meta : AliasSeq;
import std.range.primitives : back, ElementEncodingType, ElementType, empty,
front, hasLength, hasSlicing, isForwardRange, isInputRange,
isRandomAccessRange, popFront, put, save;
-import std.traits : isConvertibleToString, isIntegral, isSomeChar,
- isSomeString, Unqual, isDynamicArray;
+import std.traits : isAutodecodableString, isConvertibleToString, isIntegral,
+ isSomeChar, isSomeString, Unqual, isDynamicArray;
// debug = std_uni;
import std.internal.unicode_tables; // generated file
@@ -961,7 +962,7 @@ struct MultiArray(Types...)
}
void store(OutRange)(scope OutRange sink) const
- if (isOutputRange!(OutRange, char))
+ if (isOutputRange!(OutRange, char))
{
import std.format.write : formattedWrite;
formattedWrite(sink, "[%( 0x%x, %)]", offsets[]);
@@ -1652,7 +1653,7 @@ if (is(T : ElementType!Range))
template sharMethod(alias uniLowerBound)
{
size_t sharMethod(alias _pred="a<b", Range, T)(Range range, T needle)
- if (is(T : ElementType!Range))
+ if (is(T : ElementType!Range))
{
import std.functional : binaryFun;
import std.math.algebraic : nextPow2, truncPow2;
@@ -1768,19 +1769,19 @@ alias sharSwitchLowerBound = sharMethod!switchUniformLowerBound;
}
static void append(T, V)(ref T[] arr, V value)
- if (!isInputRange!V)
+ if (!isInputRange!V)
{
arr ~= force!T(value);
}
static void append(T, V)(ref T[] arr, V value)
- if (isInputRange!V)
+ if (isInputRange!V)
{
insertInPlace(arr, arr.length, value);
}
static void destroy(T)(ref T arr) pure // pure required for -dip25, inferred for -dip1000
- if (isDynamicArray!T && is(Unqual!T == T))
+ if (isDynamicArray!T && is(Unqual!T == T))
{
debug
{
@@ -1790,7 +1791,7 @@ alias sharSwitchLowerBound = sharMethod!switchUniformLowerBound;
}
static void destroy(T)(ref T arr) pure // pure required for -dip25, inferred for -dip1000
- if (isDynamicArray!T && !is(Unqual!T == T))
+ if (isDynamicArray!T && !is(Unqual!T == T))
{
arr = null;
}
@@ -1845,7 +1846,7 @@ alias sharSwitchLowerBound = sharMethod!switchUniformLowerBound;
}
static void append(T, V)(ref T[] arr, V value)
- if (!isInputRange!V)
+ if (!isInputRange!V)
{
if (arr.length == size_t.max) assert(0);
arr = realloc(arr, arr.length+1);
@@ -1862,7 +1863,7 @@ alias sharSwitchLowerBound = sharMethod!switchUniformLowerBound;
}
static void append(T, V)(ref T[] arr, V value)
- if (isInputRange!V && hasLength!V)
+ if (isInputRange!V && hasLength!V)
{
import core.checkedint : addu;
bool overflow;
@@ -2058,7 +2059,7 @@ public struct InversionList(SP=GcPolicy)
Construct from another code point set of any type.
*/
this(Set)(Set set) pure
- if (isCodepointSet!Set)
+ if (isCodepointSet!Set)
{
uint[] arr;
foreach (v; set.byInterval)
@@ -2073,7 +2074,7 @@ public struct InversionList(SP=GcPolicy)
Construct a set from a forward range of code point intervals.
*/
this(Range)(Range intervals) pure
- if (isForwardRange!Range && isIntegralPair!(ElementType!Range))
+ if (isForwardRange!Range && isIntegralPair!(ElementType!Range))
{
uint[] arr;
foreach (v; intervals)
@@ -2245,7 +2246,7 @@ public:
)
*/
This opBinary(string op, U)(U rhs)
- if (isCodepointSet!U || is(U:dchar))
+ if (isCodepointSet!U || is(U:dchar))
{
static if (op == "&" || op == "|" || op == "~")
{// symmetric ops thus can swap arguments to reuse r-value
@@ -2310,7 +2311,7 @@ public:
/// The 'op=' versions of the above overloaded operators.
ref This opOpAssign(string op, U)(U rhs)
- if (isCodepointSet!U || is(U:dchar))
+ if (isCodepointSet!U || is(U:dchar))
{
static if (op == "|") // union
{
@@ -2342,7 +2343,7 @@ public:
the same as $(LREF opIndex).
*/
bool opBinaryRight(string op: "in", U)(U ch) const
- if (is(U : dchar))
+ if (is(U : dchar))
{
return this[ch];
}
@@ -2522,7 +2523,7 @@ private:
package(std) // used from: std.regex.internal.parser
ref intersect(U)(U rhs)
- if (isCodepointSet!U)
+ if (isCodepointSet!U)
{
Marker mark;
foreach ( i; rhs.byInterval)
@@ -2556,7 +2557,7 @@ private:
// same as the above except that skip & drop parts are swapped
package(std) // used from: std.regex.internal.parser
ref sub(U)(U rhs)
- if (isCodepointSet!U)
+ if (isCodepointSet!U)
{
Marker mark;
foreach (i; rhs.byInterval)
@@ -2569,7 +2570,7 @@ private:
package(std) // used from: std.regex.internal.parse
ref add(U)(U rhs)
- if (isCodepointSet!U)
+ if (isCodepointSet!U)
{
Marker start;
foreach (i; rhs.byInterval)
@@ -3206,7 +3207,7 @@ struct CowArray(SP=GcPolicy)
}
this(Range)(Range range)
- if (isInputRange!Range && hasLength!Range)
+ if (isInputRange!Range && hasLength!Range)
{
import std.algorithm.mutation : copy;
length = range.length;
@@ -3214,7 +3215,7 @@ struct CowArray(SP=GcPolicy)
}
this(Range)(Range range)
- if (isForwardRange!Range && !hasLength!Range)
+ if (isForwardRange!Range && !hasLength!Range)
{
import std.algorithm.mutation : copy;
import std.range.primitives : walkLength;
@@ -3336,7 +3337,7 @@ struct CowArray(SP=GcPolicy)
}
void append(Range)(Range range)
- if (isInputRange!Range && hasLength!Range && is(ElementType!Range : uint))
+ if (isInputRange!Range && hasLength!Range && is(ElementType!Range : uint))
{
size_t nl = length + range.length;
length = nl;
@@ -3793,7 +3794,7 @@ auto arrayRepr(T)(T x)
template mapTrieIndex(Prefix...)
{
size_t mapTrieIndex(Key)(Key key)
- if (isValidPrefixForTrie!(Key, Prefix))
+ if (isValidPrefixForTrie!(Key, Prefix))
{
alias p = Prefix;
size_t idx;
@@ -4184,7 +4185,7 @@ if (isValidPrefixForTrie!(Key, Args)
///
void store(OutRange)(scope OutRange sink) const
- if (isOutputRange!(OutRange, char))
+ if (isOutputRange!(OutRange, char))
{
_table.store(sink);
}
@@ -4285,7 +4286,7 @@ public template codepointSetTrie(sizes...)
if (sumOfIntegerTuple!sizes == 21)
{
auto codepointSetTrie(Set)(Set set)
- if (isCodepointSet!Set)
+ if (isCodepointSet!Set)
{
auto builder = TrieBuilder!(bool, dchar, lastDchar+1, GetBitSlicing!(21, sizes))(false);
foreach (ival; set.byInterval)
@@ -4322,7 +4323,7 @@ if (sumOfIntegerTuple!sizes == 21)
static if (is(TypeOfBitPacked!T == bool))
{
auto codepointTrie(Set)(const scope Set set)
- if (isCodepointSet!Set)
+ if (isCodepointSet!Set)
{
return codepointSetTrie(set);
}
@@ -4337,9 +4338,9 @@ if (sumOfIntegerTuple!sizes == 21)
// unsorted range of pairs
///
auto codepointTrie(R)(R range, T defValue=T.init)
- if (isInputRange!R
- && is(typeof(ElementType!R.init[0]) : T)
- && is(typeof(ElementType!R.init[1]) : dchar))
+ if (isInputRange!R
+ && is(typeof(ElementType!R.init[0]) : T)
+ && is(typeof(ElementType!R.init[1]) : dchar))
{
// build from unsorted array of pairs
// TODO: expose index sorting functions for Trie
@@ -4467,8 +4468,8 @@ if (isValidArgsForTrie!(Key, Args))
$(REF setUnion, std,_algorithm).
*/
auto buildTrie(Range)(Range range, Value filler=Value.init)
- if (isInputRange!Range && is(typeof(Range.init.front[0]) : Value)
- && is(typeof(Range.init.front[1]) : Key))
+ if (isInputRange!Range && is(typeof(Range.init.front[0]) : Value)
+ && is(typeof(Range.init.front[1]) : Key))
{
auto builder = TrieBuilder!(Value, Key, Prefix)(filler);
foreach (v; range)
@@ -4487,9 +4488,9 @@ if (isValidArgsForTrie!(Key, Args))
and `filler` is false.
*/
auto buildTrie(Range)(Range range, Value filler=Value.init)
- if (is(TypeOfBitPacked!Value == bool)
- && isInputRange!Range && is(typeof(Range.init.front[0]) : Key)
- && is(typeof(Range.init.front[1]) : Key))
+ if (is(TypeOfBitPacked!Value == bool)
+ && isInputRange!Range && is(typeof(Range.init.front[0]) : Key)
+ && is(typeof(Range.init.front[1]) : Key))
{
auto builder = TrieBuilder!(Value, Key, Prefix)(filler);
foreach (ival; range)
@@ -4498,9 +4499,9 @@ if (isValidArgsForTrie!(Key, Args))
}
auto buildTrie(Range)(Range range, Value filler, bool unsorted)
- if (isInputRange!Range
- && is(typeof(Range.init.front[0]) : Value)
- && is(typeof(Range.init.front[1]) : Key))
+ if (isInputRange!Range
+ && is(typeof(Range.init.front[0]) : Value)
+ && is(typeof(Range.init.front[1]) : Key))
{
import std.algorithm.sorting : multiSort;
alias Comps = GetComparators!(Prefix.length);
@@ -4519,8 +4520,8 @@ if (isValidArgsForTrie!(Key, Args))
If no filler provided keys map to true, and `filler` is false.
*/
auto buildTrie(Range)(Range range, Value filler=Value.init)
- if (is(TypeOfBitPacked!Value == bool)
- && isInputRange!Range && is(typeof(Range.init.front) : Key))
+ if (is(TypeOfBitPacked!Value == bool)
+ && isInputRange!Range && is(typeof(Range.init.front) : Key))
{
auto builder = TrieBuilder!(Value, Key, Prefix)(filler);
foreach (v; range)
@@ -4533,7 +4534,7 @@ if (isValidArgsForTrie!(Key, Args))
of values where array index serves as key.
*/
auto buildTrie()(Value[] array, Value filler=Value.init)
- if (isUnsigned!Key)
+ if (isUnsigned!Key)
{
auto builder = TrieBuilder!(Value, Key, Prefix)(filler);
foreach (idx, v; array)
@@ -4595,21 +4596,21 @@ public struct MatcherConcept
of the result of test.)
*/
public bool match(Range)(ref Range inp)
- if (isRandomAccessRange!Range && is(ElementType!Range : char))
+ if (isRandomAccessRange!Range && is(ElementType!Range : char))
{
assert(false);
}
///ditto
public bool skip(Range)(ref Range inp)
- if (isRandomAccessRange!Range && is(ElementType!Range : char))
+ if (isRandomAccessRange!Range && is(ElementType!Range : char))
{
assert(false);
}
///ditto
public bool test(Range)(ref Range inp)
- if (isRandomAccessRange!Range && is(ElementType!Range : char))
+ if (isRandomAccessRange!Range && is(ElementType!Range : char))
{
assert(false);
}
@@ -4765,7 +4766,7 @@ template Utf8Matcher()
}
static auto encode(size_t sz)(dchar ch)
- if (sz > 1)
+ if (sz > 1)
{
import std.utf : encodeUTF = encode;
char[4] buf;
@@ -4821,8 +4822,8 @@ template Utf8Matcher()
enum dispatch = genDispatch();
public bool match(Range)(ref Range inp) const
- if (isRandomAccessRange!Range && is(ElementType!Range : char) &&
- !isDynamicArray!Range)
+ if (isRandomAccessRange!Range && is(ElementType!Range : char) &&
+ !isDynamicArray!Range)
{
enum mode = Mode.skipOnMatch;
assert(!inp.empty);
@@ -4846,8 +4847,8 @@ template Utf8Matcher()
static if (Sizes.length == 4) // can skip iff can detect all encodings
{
public bool skip(Range)(ref Range inp) const
- if (isRandomAccessRange!Range && is(ElementType!Range : char) &&
- !isDynamicArray!Range)
+ if (isRandomAccessRange!Range && is(ElementType!Range : char) &&
+ !isDynamicArray!Range)
{
enum mode = Mode.alwaysSkip;
assert(!inp.empty);
@@ -4868,8 +4869,8 @@ template Utf8Matcher()
}
public bool test(Range)(ref Range inp) const
- if (isRandomAccessRange!Range && is(ElementType!Range : char) &&
- !isDynamicArray!Range)
+ if (isRandomAccessRange!Range && is(ElementType!Range : char) &&
+ !isDynamicArray!Range)
{
enum mode = Mode.neverSkip;
assert(!inp.empty);
@@ -4887,19 +4888,19 @@ template Utf8Matcher()
}
bool match(C)(ref C[] str) const
- if (isSomeChar!C)
+ if (isSomeChar!C)
{
return fwdStr!"match"(str);
}
bool skip(C)(ref C[] str) const
- if (isSomeChar!C)
+ if (isSomeChar!C)
{
return fwdStr!"skip"(str);
}
bool test(C)(ref C[] str) const
- if (isSomeChar!C)
+ if (isSomeChar!C)
{
return fwdStr!"test"(str);
}
@@ -5056,8 +5057,8 @@ template Utf16Matcher()
mixin template DefMatcher()
{
public bool match(Range)(ref Range inp) const
- if (isRandomAccessRange!Range && is(ElementType!Range : wchar) &&
- !isDynamicArray!Range)
+ if (isRandomAccessRange!Range && is(ElementType!Range : wchar) &&
+ !isDynamicArray!Range)
{
enum mode = Mode.skipOnMatch;
assert(!inp.empty);
@@ -5083,8 +5084,8 @@ template Utf16Matcher()
static if (Sizes.length == 2)
{
public bool skip(Range)(ref Range inp) const
- if (isRandomAccessRange!Range && is(ElementType!Range : wchar) &&
- !isDynamicArray!Range)
+ if (isRandomAccessRange!Range && is(ElementType!Range : wchar) &&
+ !isDynamicArray!Range)
{
enum mode = Mode.alwaysSkip;
assert(!inp.empty);
@@ -5105,8 +5106,8 @@ template Utf16Matcher()
}
public bool test(Range)(ref Range inp) const
- if (isRandomAccessRange!Range && is(ElementType!Range : wchar) &&
- !isDynamicArray!Range)
+ if (isRandomAccessRange!Range && is(ElementType!Range : wchar) &&
+ !isDynamicArray!Range)
{
enum mode = Mode.neverSkip;
assert(!inp.empty);
@@ -5118,19 +5119,19 @@ template Utf16Matcher()
}
bool match(C)(ref C[] str) const
- if (isSomeChar!C)
+ if (isSomeChar!C)
{
return fwdStr!"match"(str);
}
bool skip(C)(ref C[] str) const
- if (isSomeChar!C)
+ if (isSomeChar!C)
{
return fwdStr!"skip"(str);
}
bool test(C)(ref C[] str) const
- if (isSomeChar!C)
+ if (isSomeChar!C)
{
return fwdStr!"test"(str);
}
@@ -5139,7 +5140,7 @@ template Utf16Matcher()
}
struct Impl(Sizes...)
- if (Sizes.length >= 1 && Sizes.length <= 2)
+ if (Sizes.length >= 1 && Sizes.length <= 2)
{
private:
import std.meta : allSatisfy;
@@ -5229,7 +5230,7 @@ template Utf16Matcher()
}
struct CherryPick(I, Sizes...)
- if (Sizes.length >= 1 && Sizes.length <= 2)
+ if (Sizes.length >= 1 && Sizes.length <= 2)
{
private:
import std.meta : allSatisfy;
@@ -6105,7 +6106,7 @@ template SetSearcher(alias table, string kind)
{
/// Run-time checked search.
static auto opCall(C)(const scope C[] name)
- if (is(C : dchar))
+ if (is(C : dchar))
{
import std.conv : to;
CodepointSet set;
@@ -6765,7 +6766,7 @@ struct UnicodeSetParser(Range)
sets.
*/
static auto opCall(C)(const scope C[] name)
- if (is(C : dchar))
+ if (is(C : dchar))
{
return loadAny(name);
}
@@ -7148,17 +7149,25 @@ private immutable TransformRes
TransformRes.goOn
];
-template genericDecodeGrapheme(bool getValue)
-{
- static if (getValue)
+enum GraphemeRet { none, step, value }
+
+template genericDecodeGrapheme(GraphemeRet retType)
+{ alias Ret = GraphemeRet;
+
+ static if (retType == Ret.value)
alias Value = Grapheme;
- else
+ else static if (retType == Ret.step)
+ alias Value = size_t;
+ else static if (retType == Ret.none)
alias Value = void;
Value genericDecodeGrapheme(Input)(ref Input range)
{
- static if (getValue)
- Grapheme grapheme;
+ static if (retType == Ret.value)
+ Grapheme result;
+ else static if (retType == Ret.step)
+ size_t result = 0;
+
auto state = GraphemeState.Start;
dchar ch;
@@ -7173,8 +7182,10 @@ template genericDecodeGrapheme(bool getValue)
with(TransformRes)
{
case goOn:
- static if (getValue)
- grapheme ~= ch;
+ static if (retType == Ret.value)
+ result ~= ch;
+ else static if (retType == Ret.step)
+ result++;
range.popFront();
continue;
@@ -7182,8 +7193,10 @@ template genericDecodeGrapheme(bool getValue)
goto rerun;
case retInclude:
- static if (getValue)
- grapheme ~= ch;
+ static if (retType == Ret.value)
+ result ~= ch;
+ else static if (retType == Ret.step)
+ result++;
range.popFront();
break outer;
@@ -7192,8 +7205,8 @@ template genericDecodeGrapheme(bool getValue)
}
}
- static if (getValue)
- return grapheme;
+ static if (retType != Ret.none)
+ return result;
}
}
@@ -7217,7 +7230,7 @@ if (is(C : dchar))
{
auto src = input[index..$];
auto n = src.length;
- genericDecodeGrapheme!(false)(src);
+ genericDecodeGrapheme!(GraphemeRet.none)(src);
return n - src.length;
}
@@ -7279,7 +7292,7 @@ if (is(C : dchar))
Grapheme decodeGrapheme(Input)(ref Input inp)
if (isInputRange!Input && is(immutable ElementType!Input == immutable dchar))
{
- return genericDecodeGrapheme!true(inp);
+ return genericDecodeGrapheme!(GraphemeRet.value)(inp);
}
@safe unittest
@@ -7305,6 +7318,73 @@ if (isInputRange!Input && is(immutable ElementType!Input == immutable dchar))
}
/++
+ Reads one full grapheme cluster from an
+ $(REF_ALTTEXT input range, isInputRange, std,range,primitives) of dchar `inp`,
+ but doesn't return it. Instead returns the number of code units read.
+ This differs from number of code points read only if `input` is an
+ autodecodable string.
+
+ Note:
+ This function modifies `inp` and thus `inp`
+ must be an L-value.
++/
+size_t popGrapheme(Input)(ref Input inp)
+if (isInputRange!Input && is(immutable ElementType!Input == immutable dchar))
+{
+ static if (isAutodecodableString!Input || hasLength!Input)
+ {
+ // Why count each step in the decoder when you can just
+ // measure the grapheme in one go?
+ auto n = inp.length;
+ genericDecodeGrapheme!(GraphemeRet.none)(inp);
+ return n - inp.length;
+ }
+ else return genericDecodeGrapheme!(GraphemeRet.step)(inp);
+}
+
+///
+@safe pure unittest
+{
+ // Two Union Jacks of the Great Britain in each
+ string s = "\U0001F1EC\U0001F1E7\U0001F1EC\U0001F1E7";
+ wstring ws = "\U0001F1EC\U0001F1E7\U0001F1EC\U0001F1E7";
+ dstring ds = "\U0001F1EC\U0001F1E7\U0001F1EC\U0001F1E7";
+
+ // String pop length in code units, not points.
+ assert(s.popGrapheme() == 8);
+ assert(ws.popGrapheme() == 4);
+ assert(ds.popGrapheme() == 2);
+
+ assert(s == "\U0001F1EC\U0001F1E7");
+ assert(ws == "\U0001F1EC\U0001F1E7");
+ assert(ds == "\U0001F1EC\U0001F1E7");
+
+ import std.algorithm.comparison : equal;
+ import std.algorithm.iteration : filter;
+
+ // Also works for non-random access ranges as long as the
+ // character type is 32-bit.
+ auto testPiece = "\r\nhello!"d.filter!(x => !x.isAlpha);
+ // Windows-style line ending is two code points in a single grapheme.
+ assert(testPiece.popGrapheme() == 2);
+ assert(testPiece.equal("!"d));
+}
+
+// Attribute compliance test. Should be nothrow `@nogc` when
+// no autodecoding needed.
+@safe pure nothrow @nogc unittest
+{
+ import std.algorithm.iteration : filter;
+
+ auto str = "abcdef"d;
+ assert(str.popGrapheme() == 1);
+
+ // also test with non-random access
+ auto filtered = "abcdef"d.filter!(x => x%2);
+ assert(filtered.popGrapheme() == 1);
+}
+
+/++
$(P Iterate a string by $(LREF Grapheme).)
$(P Useful for doing string manipulation that needs to be aware
@@ -7556,15 +7636,15 @@ if (isInputRange!Range && is(immutable ElementType!Range == immutable dchar))
public:
/// Ctor
this(C)(const scope C[] chars...)
- if (is(C : dchar))
+ if (is(C : dchar))
{
this ~= chars;
}
///ditto
this(Input)(Input seq)
- if (!isDynamicArray!Input
- && isInputRange!Input && is(ElementType!Input : dchar))
+ if (!isDynamicArray!Input
+ && isInputRange!Input && is(ElementType!Input : dchar))
{
this ~= seq;
}
@@ -7683,7 +7763,7 @@ public:
/// Append all $(CHARACTERS) from the input range `inp` to this Grapheme.
ref opOpAssign(string op, Input)(scope Input inp)
- if (isInputRange!Input && is(ElementType!Input : dchar))
+ if (isInputRange!Input && is(ElementType!Input : dchar))
{
static if (op == "~")
{
@@ -7722,7 +7802,7 @@ public:
@property bool valid()() /*const*/
{
auto r = this[];
- genericDecodeGrapheme!false(r);
+ genericDecodeGrapheme!(GraphemeRet.none)(r);
return r.length == 0;
}
@@ -9868,7 +9948,7 @@ private template toCaseInPlaceAlloc(alias indexFn, uint maxIdx, alias tableFn)
{
void toCaseInPlaceAlloc(C)(ref C[] s, size_t curIdx,
size_t destIdx) @trusted pure
- if (is(C == char) || is(C == wchar) || is(C == dchar))
+ if (is(C == char) || is(C == wchar) || is(C == dchar))
{
import std.utf : decode;
alias caseLength = toCaseLength!(indexFn, maxIdx, tableFn);
diff --git a/libphobos/src/std/utf.d b/libphobos/src/std/utf.d
index 9a326a5..7db120b 100644
--- a/libphobos/src/std/utf.d
+++ b/libphobos/src/std/utf.d
@@ -4303,13 +4303,13 @@ if (isSomeChar!C)
else:
auto ref byUTF(R)(R r)
- if (isAutodecodableString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R))
+ if (isAutodecodableString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R))
{
return byUTF(r.byCodeUnit());
}
auto ref byUTF(R)(R r)
- if (!isAutodecodableString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R))
+ if (!isAutodecodableString!R && isInputRange!R && isSomeChar!(ElementEncodingType!R))
{
static if (is(immutable ElementEncodingType!R == immutable RC, RC) && is(RC == C))
{
diff --git a/libphobos/src/std/uuid.d b/libphobos/src/std/uuid.d
index b8cac6e..09ce2f7 100644
--- a/libphobos/src/std/uuid.d
+++ b/libphobos/src/std/uuid.d
@@ -275,7 +275,7 @@ public struct UUID
* You need to pass exactly 16 ubytes.
*/
@safe pure this(T...)(T uuidData)
- if (uuidData.length == 16 && allSatisfy!(isIntegral, T))
+ if (uuidData.length == 16 && allSatisfy!(isIntegral, T))
{
import std.conv : to;
@@ -331,7 +331,8 @@ public struct UUID
*
* For a less strict parser, see $(LREF parseUUID)
*/
- this(T)(in T[] uuid) if (isSomeChar!T)
+ this(T)(in T[] uuid)
+ if (isSomeChar!T)
{
import std.conv : to, parse;
if (uuid.length < 36)
diff --git a/libphobos/src/std/variant.d b/libphobos/src/std/variant.d
index f7832104..a0b5644 100644
--- a/libphobos/src/std/variant.d
+++ b/libphobos/src/std/variant.d
@@ -658,7 +658,7 @@ public:
/// Allows assignment from a subset algebraic type
this(T : VariantN!(tsize, Types), size_t tsize, Types...)(T value)
- if (!is(T : VariantN) && Types.length > 0 && allSatisfy!(allowed, Types))
+ if (!is(T : VariantN) && Types.length > 0 && allSatisfy!(allowed, Types))
{
opAssign(value);
}
@@ -735,7 +735,7 @@ public:
// Allow assignment from another variant which is a subset of this one
VariantN opAssign(T : VariantN!(tsize, Types), size_t tsize, Types...)(T rhs)
- if (!is(T : VariantN) && Types.length > 0 && allSatisfy!(allowed, Types))
+ if (!is(T : VariantN) && Types.length > 0 && allSatisfy!(allowed, Types))
{
// discover which type rhs is actually storing
foreach (V; T.AllowedTypes)
@@ -1098,7 +1098,7 @@ public:
{ return opLogic!(T, op)(lhs); }
///ditto
VariantN opBinary(string op, T)(T rhs)
- if (op == "~")
+ if (op == "~")
{
auto temp = this;
temp ~= rhs;
@@ -1191,7 +1191,8 @@ public:
If the `VariantN` contains an array, applies `dg` to each
element of the array in turn. Otherwise, throws an exception.
*/
- int opApply(Delegate)(scope Delegate dg) if (is(Delegate == delegate))
+ int opApply(Delegate)(scope Delegate dg)
+ if (is(Delegate == delegate))
{
alias A = Parameters!(Delegate)[0];
if (type == typeid(A[]))
@@ -2410,7 +2411,7 @@ if (Handlers.length > 0)
{
///
auto visit(VariantType)(VariantType variant)
- if (isAlgebraic!VariantType)
+ if (isAlgebraic!VariantType)
{
return visitImpl!(true, VariantType, Handlers)(variant);
}
@@ -2553,7 +2554,7 @@ if (Handlers.length > 0)
{
///
auto tryVisit(VariantType)(VariantType variant)
- if (isAlgebraic!VariantType)
+ if (isAlgebraic!VariantType)
{
return visitImpl!(false, VariantType, Handlers)(variant);
}