aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2023-12-07 11:55:12 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2023-12-11 11:06:23 +0100
commitf9b4dbb8ac75f96c4897ba9aafcaf0bbad4fbe44 (patch)
tree0cbb768778c3ece2ccdae2f1e34aceb483917c1d /libphobos/src/std
parent63194a0e8ede9e15dfa01c6ec7aeea8f7702d3b7 (diff)
downloadgcc-f9b4dbb8ac75f96c4897ba9aafcaf0bbad4fbe44.zip
gcc-f9b4dbb8ac75f96c4897ba9aafcaf0bbad4fbe44.tar.gz
gcc-f9b4dbb8ac75f96c4897ba9aafcaf0bbad4fbe44.tar.bz2
d: Merge upstream dmd, druntime 2bbf64907c, phobos b64bfbf91
D front-end changes: - Import dmd v2.106.0. D runtime changes: - Import druntime v2.106.0. Phobos changes: - Import phobos v2.106.0. gcc/d/ChangeLog: * Make-lang.in (D_FRONTEND_OBJS): Rename d/common-string.o to d/common-smallbuffer.o. * dmd/MERGE: Merge upstream dmd 2bbf64907c. * dmd/VERSION: Bump version to v2.106.0. * modules.cc (layout_moduleinfo_fields): Update for new front-end interface. (layout_moduleinfo): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 2bbf64907c. * src/MERGE: Merge upstream phobos b64bfbf91.
Diffstat (limited to 'libphobos/src/std')
-rw-r--r--libphobos/src/std/algorithm/searching.d218
-rw-r--r--libphobos/src/std/conv.d5
-rw-r--r--libphobos/src/std/range/package.d24
-rw-r--r--libphobos/src/std/uni/package.d12
4 files changed, 120 insertions, 139 deletions
diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d
index 6897905..4526aa2 100644
--- a/libphobos/src/std/algorithm/searching.d
+++ b/libphobos/src/std/algorithm/searching.d
@@ -2895,94 +2895,100 @@ if (isForwardRange!R1 && ifTestable!(typeof(haystack.front), unaryFun!pred))
assert(findSkip!isWhite(s) == 2);
}
+private struct FindSplitResult(ubyte emptyRangeIndex, Types...)
+{
+ this(Types vals)
+ {
+ asTuple = typeof(asTuple)(vals);
+ }
+ void opAssign(typeof(asTuple) rhs)
+ {
+ asTuple = rhs;
+ }
+ Tuple!Types asTuple;
+ alias asTuple this;
+
+ static if (hasConstEmptyMember!(typeof(asTuple[emptyRangeIndex])))
+ {
+ bool opCast(T : bool)() const => !asTuple[emptyRangeIndex].empty;
+ }
+ else
+ {
+ bool opCast(T : bool)() => !asTuple[emptyRangeIndex].empty;
+ }
+}
+
/**
These functions find the first occurrence of `needle` in `haystack` and then
split `haystack` as follows.
-`findSplit` returns a tuple `result` containing $(I three) ranges. `result[0]`
-is the portion of `haystack` before `needle`, `result[1]` is the portion of
-`haystack` that matches `needle`, and `result[2]` is the portion of `haystack`
-after the match. If `needle` was not found, `result[0]` comprehends `haystack`
+$(PANEL
+`findSplit` returns a tuple `result` containing $(I three) ranges.
+$(UL
+$(LI `result[0]` is the portion of `haystack` before `needle`)
+$(LI `result[1]` is the portion of
+`haystack` that matches `needle`)
+$(LI `result[2]` is the portion of `haystack`
+after the match.)
+)
+If `needle` was not found, `result[0]` comprehends `haystack`
entirely and `result[1]` and `result[2]` are empty.
-`findSplitBefore` returns a tuple `result` containing two ranges. `result[0]` is
-the portion of `haystack` before `needle`, and `result[1]` is the balance of
-`haystack` starting with the match. If `needle` was not found, `result[0]`
+`findSplitBefore` returns a tuple `result` containing two ranges.
+$(UL
+$(LI `result[0]` is the portion of `haystack` before `needle`)
+$(LI `result[1]` is the balance of `haystack` starting with the match.)
+)
+If `needle` was not found, `result[0]`
comprehends `haystack` entirely and `result[1]` is empty.
`findSplitAfter` returns a tuple `result` containing two ranges.
-`result[0]` is the portion of `haystack` up to and including the
-match, and `result[1]` is the balance of `haystack` starting
-after the match. If `needle` was not found, `result[0]` is empty
+$(UL
+$(LI `result[0]` is the portion of `haystack` up to and including the
+match)
+$(LI `result[1]` is the balance of `haystack` starting
+after the match.)
+)
+If `needle` was not found, `result[0]` is empty
and `result[1]` is `haystack`.
-
+)
+$(P
In all cases, the concatenation of the returned ranges spans the
entire `haystack`.
If `haystack` is a random-access range, all three components of the tuple have
the same type as `haystack`. Otherwise, `haystack` must be a
$(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) and
-the type of `result[0]` and `result[1]` is the same as $(REF takeExactly,
-std,range).
+the type of `result[0]` (and `result[1]` for `findSplit`) is the same as
+the result of $(REF takeExactly, std,range).
For more information about `pred` see $(LREF find).
-
+)
Params:
- pred = Predicate to use for comparing needle against haystack.
- haystack = The range to search.
- needle = What to look for.
+ pred = Predicate to compare 2 elements.
+ haystack = The forward range to search.
+ needle = The forward range to look for.
Returns:
-A sub-type of `Tuple!()` of the split portions of `haystack` (see above for
-details). This sub-type of `Tuple!()` has `opCast` defined for `bool`. This
-`opCast` returns `true` when the separating `needle` was found
-and `false` otherwise.
+A sub-type of $(REF Tuple, std, typecons) of the split portions of `haystack` (see above for
+details). This sub-type of `Tuple` defines `opCast!bool`, which
+returns `true` when the separating `needle` was found and `false` otherwise.
See_Also: $(LREF find)
*/
auto findSplit(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isForwardRange!R1 && isForwardRange!R2)
{
- static struct Result(S1, S2) if (isForwardRange!S1 &&
- isForwardRange!S2)
- {
- this(S1 pre, S1 separator, S2 post)
- {
- asTuple = typeof(asTuple)(pre, separator, post);
- }
- void opAssign(typeof(asTuple) rhs)
- {
- asTuple = rhs;
- }
- Tuple!(S1, S1, S2) asTuple;
- static if (hasConstEmptyMember!(typeof(asTuple[1])))
- {
- bool opCast(T : bool)() const
- {
- return !asTuple[1].empty;
- }
- }
- else
- {
- bool opCast(T : bool)()
- {
- return !asTuple[1].empty;
- }
- }
- alias asTuple this;
- }
-
static if (isSomeString!R1 && isSomeString!R2
|| (isRandomAccessRange!R1 && hasSlicing!R1 && hasLength!R1 && hasLength!R2))
{
auto balance = find!pred(haystack, needle);
immutable pos1 = haystack.length - balance.length;
immutable pos2 = balance.empty ? pos1 : pos1 + needle.length;
- return Result!(typeof(haystack[0 .. pos1]),
- typeof(haystack[pos2 .. haystack.length]))(haystack[0 .. pos1],
- haystack[pos1 .. pos2],
- haystack[pos2 .. haystack.length]);
+ alias Slice = typeof(haystack[0 .. pos1]);
+ return FindSplitResult!(1, Slice, Slice, Slice)(
+ haystack[0 .. pos1], haystack[pos1 .. pos2], haystack[pos2 .. haystack.length]);
}
else
{
@@ -3011,10 +3017,11 @@ if (isForwardRange!R1 && isForwardRange!R2)
{
pos1 = pos2;
}
- return Result!(typeof(takeExactly(original, pos1)),
- typeof(h))(takeExactly(original, pos1),
- takeExactly(haystack, pos2 - pos1),
- h);
+ return FindSplitResult!(1,
+ typeof(takeExactly(original, pos1)),
+ typeof(takeExactly(original, pos1)), typeof(h))(
+ takeExactly(original, pos1),
+ takeExactly(haystack, pos2 - pos1), h);
}
}
@@ -3022,43 +3029,14 @@ if (isForwardRange!R1 && isForwardRange!R2)
auto findSplitBefore(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isForwardRange!R1 && isForwardRange!R2)
{
- static struct Result(S1, S2) if (isForwardRange!S1 &&
- isForwardRange!S2)
- {
- this(S1 pre, S2 post)
- {
- asTuple = typeof(asTuple)(pre, post);
- }
- void opAssign(typeof(asTuple) rhs)
- {
- asTuple = rhs;
- }
- Tuple!(S1, S2) asTuple;
- static if (hasConstEmptyMember!(typeof(asTuple[1])))
- {
- bool opCast(T : bool)() const
- {
- return !asTuple[1].empty;
- }
- }
- else
- {
- bool opCast(T : bool)()
- {
- return !asTuple[1].empty;
- }
- }
- alias asTuple this;
- }
-
static if (isSomeString!R1 && isSomeString!R2
|| (isRandomAccessRange!R1 && hasLength!R1 && hasSlicing!R1 && hasLength!R2))
{
auto balance = find!pred(haystack, needle);
immutable pos = haystack.length - balance.length;
- return Result!(typeof(haystack[0 .. pos]),
- typeof(haystack[pos .. haystack.length]))(haystack[0 .. pos],
- haystack[pos .. haystack.length]);
+ return FindSplitResult!(1,
+ typeof(haystack[0 .. pos]), typeof(haystack[0 .. pos]))(
+ haystack[0 .. pos], haystack[pos .. haystack.length]);
}
else
{
@@ -3088,9 +3066,9 @@ if (isForwardRange!R1 && isForwardRange!R2)
pos1 = pos2;
haystack = h;
}
- return Result!(typeof(takeExactly(original, pos1)),
- typeof(haystack))(takeExactly(original, pos1),
- haystack);
+ return FindSplitResult!(1,
+ typeof(takeExactly(original, pos1)), typeof(haystack))(
+ takeExactly(original, pos1), haystack);
}
}
@@ -3098,47 +3076,19 @@ if (isForwardRange!R1 && isForwardRange!R2)
auto findSplitAfter(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
if (isForwardRange!R1 && isForwardRange!R2)
{
- static struct Result(S1, S2) if (isForwardRange!S1 &&
- isForwardRange!S2)
- {
- this(S1 pre, S2 post)
- {
- asTuple = typeof(asTuple)(pre, post);
- }
- void opAssign(typeof(asTuple) rhs)
- {
- asTuple = rhs;
- }
- Tuple!(S1, S2) asTuple;
- static if (hasConstEmptyMember!(typeof(asTuple[1])))
- {
- bool opCast(T : bool)() const
- {
- return !asTuple[0].empty;
- }
- }
- else
- {
- bool opCast(T : bool)()
- {
- return !asTuple[0].empty;
- }
- }
- alias asTuple this;
- }
-
static if (isSomeString!R1 && isSomeString!R2
|| isRandomAccessRange!R1 && hasLength!R1 && hasSlicing!R1 && hasLength!R2)
{
auto balance = find!pred(haystack, needle);
immutable pos = balance.empty ? 0 : haystack.length - balance.length + needle.length;
- return Result!(typeof(haystack[0 .. pos]),
- typeof(haystack[pos .. haystack.length]))(haystack[0 .. pos],
- haystack[pos .. haystack.length]);
+ return FindSplitResult!(0,
+ typeof(haystack[0 .. pos]), typeof(haystack[0 .. pos]))(
+ haystack[0 .. pos], haystack[pos .. haystack.length]);
}
else
{
import std.range : takeExactly;
+ alias Res = FindSplitResult!(0, typeof(takeExactly(haystack, 0)), typeof(haystack));
auto original = haystack.save;
auto h = haystack.save;
auto n = needle.save;
@@ -3148,9 +3098,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
if (h.empty)
{
// Failed search
- return Result!(typeof(takeExactly(original, 0)),
- typeof(original))(takeExactly(original, 0),
- original);
+ return Res(takeExactly(original, 0), original);
}
if (binaryFun!pred(h.front, n.front))
{
@@ -3166,9 +3114,7 @@ if (isForwardRange!R1 && isForwardRange!R2)
pos2 = ++pos1;
}
}
- return Result!(typeof(takeExactly(original, pos2)),
- typeof(h))(takeExactly(original, pos2),
- h);
+ return Res(takeExactly(original, pos2), h);
}
}
@@ -3185,12 +3131,12 @@ if (isForwardRange!R1 && isForwardRange!R2)
}
else assert(0);
- // works with const aswell
- if (const split = "dlang-rocks".findSplit("-"))
+ // findSplitBefore returns 2 ranges
+ if (const split = [2, 3, 2, 3, 4, 1].findSplitBefore!"a > b"([2, 2]))
{
- assert(split[0] == "dlang");
- assert(split[1] == "-");
- assert(split[2] == "rocks");
+ assert(split[0] == [2, 3, 2]);
+ // [3, 4] each greater than [2, 2]
+ assert(split[1] == [3, 4, 1]);
}
else assert(0);
}
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index 4248e4b9..3a53381 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -4848,8 +4848,9 @@ private S textImpl(S, U...)(U args)
static foreach (arg; args)
{
static if (
- isSomeChar!(typeof(arg)) || isSomeString!(typeof(arg)) ||
- ( isInputRange!(typeof(arg)) && isSomeChar!(ElementType!(typeof(arg))) )
+ isSomeChar!(typeof(arg))
+ || isSomeString!(typeof(arg))
+ || ( isInputRange!(typeof(arg)) && isSomeChar!(ElementType!(typeof(arg))) )
)
app.put(arg);
else static if (
diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d
index 1b4f233..c985015 100644
--- a/libphobos/src/std/range/package.d
+++ b/libphobos/src/std/range/package.d
@@ -1025,7 +1025,18 @@ if (Ranges.length > 0 &&
}
else
{
- @property bool empty() => frontIndex >= backIndex;
+ @property bool empty()
+ {
+ if (frontIndex == 0)
+ {
+ // special handling: we might be in Range.init state!
+ // For instance, `format!"%s"` uses Range.init to ensure
+ // that formatting is possible.
+ // In that case, we must still behave in an internally consistent way.
+ return source[0].empty;
+ }
+ return frontIndex >= backIndex;
+ }
}
static if (allSatisfy!(isForwardRange, R))
@@ -1705,6 +1716,17 @@ pure @safe nothrow @nogc unittest
}
}
+/// https://issues.dlang.org/show_bug.cgi?id=24243
+pure @safe nothrow unittest
+{
+ import std.algorithm.iteration : filter;
+
+ auto range = chain([2], [3].filter!"a");
+
+ // This might happen in format!"%s"(range), for instance.
+ assert(typeof(range).init.empty);
+}
+
/**
Choose one of two ranges at runtime depending on a Boolean condition.
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index 9903d6c..fec7e5f 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -7706,6 +7706,12 @@ public:
return this.tupleof == other.tupleof;
}
+ // Define a default toHash to allow AA usage
+ size_t toHash() const @trusted
+ {
+ return hashOf(slen_, hashOf(small_));
+ }
+
/++
True if this object contains valid extended grapheme cluster.
Decoding primitives of this module always return a valid `Grapheme`.
@@ -7907,6 +7913,12 @@ static assert(Grapheme.sizeof == size_t.sizeof*4);
assert(equal(h[], iota(cast(int)'A', cast(int)'Z'+1)));
}
+// ensure Grapheme can be used as an AA key.
+@safe unittest
+{
+ int[Grapheme] aa;
+}
+
/++
$(P Does basic case-insensitive comparison of `r1` and `r2`.
This function uses simpler comparison rule thus achieving better performance