aboutsummaryrefslogtreecommitdiff
path: root/libphobos
diff options
context:
space:
mode:
Diffstat (limited to 'libphobos')
-rw-r--r--libphobos/ChangeLog17
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/core/exception.d84
-rw-r--r--libphobos/libdruntime/core/int128.d156
-rw-r--r--libphobos/libdruntime/core/lifetime.d20
-rw-r--r--libphobos/libdruntime/gcc/emutls.d8
-rw-r--r--libphobos/libdruntime/object.d4
-rw-r--r--libphobos/libdruntime/rt/aaA.d4
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/Makefile.am2
-rw-r--r--libphobos/src/Makefile.in4
-rw-r--r--libphobos/src/etc/c/zlib.d211
-rw-r--r--libphobos/src/std/base64.d20
-rw-r--r--libphobos/src/std/int128.d374
-rw-r--r--libphobos/src/std/path.d2
-rw-r--r--libphobos/src/std/regex/internal/parser.d2
-rw-r--r--libphobos/src/std/traits.d21
17 files changed, 701 insertions, 232 deletions
diff --git a/libphobos/ChangeLog b/libphobos/ChangeLog
index 4b227d6..0a9d916 100644
--- a/libphobos/ChangeLog
+++ b/libphobos/ChangeLog
@@ -1,3 +1,20 @@
+2022-04-26 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * libdruntime/gcc/emutls.d (emutlsDestroyThread): Clear the per-thread
+ TLS array, don't call free().
+
+2022-04-21 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * libdruntime/MERGE: Merge upstream druntime 27834edb.
+ * src/MERGE: Merge upstream phobos ac296f80c.
+ * src/Makefile.am (PHOBOS_DSOURCES): Add std/int128.d.
+ * src/Makefile.in: Regenerate.
+
+2022-04-13 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * libdruntime/MERGE: Merge upstream druntime 9ba9a6ae.
+ * src/MERGE: Merge upstream phobos c0cc5e917.
+
2022-04-02 Iain Buclaw <ibuclaw@gdcproject.org>
* libdruntime/MERGE: Merge upstream druntime c52e28b7.
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index b1da32e..c94634f 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-c52e28b723ccfbe845a95e8e7b528e3cc0b9d790
+e361d200b287a68344095f306cf5ea3a63c080e1
The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository.
diff --git a/libphobos/libdruntime/core/exception.d b/libphobos/libdruntime/core/exception.d
index a692866..81aa43b 100644
--- a/libphobos/libdruntime/core/exception.d
+++ b/libphobos/libdruntime/core/exception.d
@@ -19,29 +19,6 @@ void __switch_errorT()(string file = __FILE__, size_t line = __LINE__) @trusted
assert(0, "No appropriate switch clause found");
}
-version (D_BetterC)
-{
- // When compiling with -betterC we use template functions so if they are
- // used the bodies are copied into the user's program so there is no need
- // for the D runtime during linking.
-
- // In the future we might want to convert all functions in this module to
- // templates even for ordinary builds instead of providing them as an
- // extern(C) library.
-
- void onOutOfMemoryError()(void* pretend_sideffect = null) @nogc nothrow pure @trusted
- {
- assert(0, "Memory allocation failed");
- }
- alias onOutOfMemoryErrorNoGC = onOutOfMemoryError;
-
- void onInvalidMemoryOperationError()(void* pretend_sideffect = null) @nogc nothrow pure @trusted
- {
- assert(0, "Invalid memory operation");
- }
-}
-else:
-
/**
* Thrown on a range error.
*/
@@ -218,17 +195,17 @@ private void rangeMsgPut(ref char[] r, scope const(char)[] e) @nogc nothrow pure
*/
class AssertError : Error
{
- @safe pure nothrow this( string file, size_t line )
+ @safe pure nothrow @nogc this( string file, size_t line )
{
this(cast(Throwable)null, file, line);
}
- @safe pure nothrow this( Throwable next, string file = __FILE__, size_t line = __LINE__ )
+ @safe pure nothrow @nogc this( Throwable next, string file = __FILE__, size_t line = __LINE__ )
{
this( "Assertion failure", file, line, next);
}
- @safe pure nothrow this( string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null )
+ @safe pure nothrow @nogc this( string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null )
{
super( msg, file, line, next );
}
@@ -692,26 +669,49 @@ extern (C) void onFinalizeError( TypeInfo info, Throwable e, string file = __FIL
throw staticError!FinalizeError(info, e, file, line);
}
-/**
- * A callback for out of memory errors in D. An $(LREF OutOfMemoryError) will be
- * thrown.
- *
- * Throws:
- * $(LREF OutOfMemoryError).
- */
-extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */
+version (D_BetterC)
{
- // NOTE: Since an out of memory condition exists, no allocation must occur
- // while generating this object.
- throw staticError!OutOfMemoryError();
-}
+ // When compiling with -betterC we use template functions so if they are
+ // used the bodies are copied into the user's program so there is no need
+ // for the D runtime during linking.
-extern (C) void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc
-{
- // suppress stacktrace until they are @nogc
- throw staticError!OutOfMemoryError(false);
+ // In the future we might want to convert all functions in this module to
+ // templates even for ordinary builds instead of providing them as an
+ // extern(C) library.
+
+ void onOutOfMemoryError()(void* pretend_sideffect = null) @nogc nothrow pure @trusted
+ {
+ assert(0, "Memory allocation failed");
+ }
+ alias onOutOfMemoryErrorNoGC = onOutOfMemoryError;
+
+ void onInvalidMemoryOperationError()(void* pretend_sideffect = null) @nogc nothrow pure @trusted
+ {
+ assert(0, "Invalid memory operation");
+ }
}
+else
+{
+ /**
+ * A callback for out of memory errors in D. An $(LREF OutOfMemoryError) will be
+ * thrown.
+ *
+ * Throws:
+ * $(LREF OutOfMemoryError).
+ */
+ extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */
+ {
+ // NOTE: Since an out of memory condition exists, no allocation must occur
+ // while generating this object.
+ throw staticError!OutOfMemoryError();
+ }
+ extern (C) void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc
+ {
+ // suppress stacktrace until they are @nogc
+ throw staticError!OutOfMemoryError(false);
+ }
+}
/**
* A callback for invalid memory operations in D. An
diff --git a/libphobos/libdruntime/core/int128.d b/libphobos/libdruntime/core/int128.d
index 2f628c0..e4326fd 100644
--- a/libphobos/libdruntime/core/int128.d
+++ b/libphobos/libdruntime/core/int128.d
@@ -18,15 +18,26 @@ alias I = long;
alias U = ulong;
enum Ubits = uint(U.sizeof * 8);
-align(16) struct Cent
+version (X86_64) private enum Cent_alignment = 16;
+else private enum Cent_alignment = (size_t.sizeof * 2);
+
+align(Cent_alignment) struct Cent
{
- U lo; // low 64 bits
- U hi; // high 64 bits
+ version (LittleEndian)
+ {
+ U lo; // low 64 bits
+ U hi; // high 64 bits
+ }
+ else
+ {
+ U hi; // high 64 bits
+ U lo; // low 64 bits
+ }
}
-enum One = Cent(1);
-enum Zero = Cent();
-enum MinusOne = neg(One);
+enum Cent One = { lo:1 };
+enum Cent Zero = { lo:0 };
+enum Cent MinusOne = neg(One);
/*****************************
* Test against 0
@@ -320,7 +331,8 @@ Cent ror(Cent c, uint n)
pure
Cent and(Cent c1, Cent c2)
{
- return Cent(c1.lo & c2.lo, c1.hi & c2.hi);
+ const Cent ret = { lo:c1.lo & c2.lo, hi:c1.hi & c2.hi };
+ return ret;
}
/****************************
@@ -334,7 +346,8 @@ Cent and(Cent c1, Cent c2)
pure
Cent or(Cent c1, Cent c2)
{
- return Cent(c1.lo | c2.lo, c1.hi | c2.hi);
+ const Cent ret = { lo:c1.lo | c2.lo, hi:c1.hi | c2.hi };
+ return ret;
}
/****************************
@@ -348,7 +361,8 @@ Cent or(Cent c1, Cent c2)
pure
Cent xor(Cent c1, Cent c2)
{
- return Cent(c1.lo ^ c2.lo, c1.hi ^ c2.hi);
+ const Cent ret = { lo:c1.lo ^ c2.lo, hi:c1.hi ^ c2.hi };
+ return ret;
}
/****************************
@@ -363,7 +377,8 @@ pure
Cent add(Cent c1, Cent c2)
{
U r = cast(U)(c1.lo + c2.lo);
- return Cent(r, cast(U)(c1.hi + c2.hi + (r < c1.lo)));
+ const Cent ret = { lo:r, hi:cast(U)(c1.hi + c2.hi + (r < c1.lo)) };
+ return ret;
}
/****************************
@@ -419,9 +434,9 @@ Cent mul(Cent c1, Cent c2)
const c1h1 = c1.hi >> mulshift;
r3 = c1h1 * c2l0 + (r3 & mulmask);
- return Cent((r0 & mulmask) + (r1 & mulmask) * (mulmask + 1),
- (r2 & mulmask) + (r3 & mulmask) * (mulmask + 1));
-
+ const Cent ret = { lo:(r0 & mulmask) + (r1 & mulmask) * (mulmask + 1),
+ hi:(r2 & mulmask) + (r3 & mulmask) * (mulmask + 1) };
+ return ret;
}
@@ -523,8 +538,10 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
if (c1.hi == 0 && c2.hi == 0)
{
// Single precision divide
- modulus = Cent(c1.lo % c2.lo);
- return Cent(c1.lo / c2.lo);
+ const Cent rem = { lo:c1.lo % c2.lo };
+ modulus = rem;
+ const Cent ret = { lo:c1.lo / c2.lo };
+ return ret;
}
if (c1.hi == 0)
{
@@ -539,10 +556,11 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
const q1 = (c1.hi < c2.lo) ? 0 : (c1.hi / c2.lo);
if (q1)
c1.hi = c1.hi % c2.lo;
- U rem;
- const q0 = udivmod128_64(c1, c2.lo, rem);
- modulus = Cent(rem);
- return Cent(q0, q1);
+ Cent rem;
+ const q0 = udivmod128_64(c1, c2.lo, rem.lo);
+ modulus = rem;
+ const Cent ret = { lo:q0, hi:q1 };
+ return ret;
}
// Full cent precision division.
@@ -560,10 +578,10 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus)
// Get quotient from divide unsigned operation.
U rem_ignored;
- const q1 = udivmod128_64(u1, v1, rem_ignored);
+ const Cent q1 = { lo:udivmod128_64(u1, v1, rem_ignored) };
// Undo normalization and division of c1 by 2.
- Cent quotient = shr(shl(Cent(q1), shift), 63);
+ Cent quotient = shr(shl(q1, shift), 63);
// Make quotient correct or too small by 1
if (tst(quotient))
@@ -770,44 +788,44 @@ version (unittest)
unittest
{
- const C0 = Zero;
- const C1 = One;
- const C2 = Cent(2);
- const C3 = Cent(3);
- const C5 = Cent(5);
- const C10 = Cent(10);
- const C20 = Cent(20);
- const C30 = Cent(30);
- const C100 = Cent(100);
-
- const Cm1 = neg(One);
- const Cm3 = neg(C3);
- const Cm10 = neg(C10);
-
- const C3_1 = Cent(1,3);
- const C3_2 = Cent(2,3);
- const C4_8 = Cent(8, 4);
- const C5_0 = Cent(0, 5);
- const C7_1 = Cent(1,7);
- const C7_9 = Cent(9,7);
- const C9_3 = Cent(3,9);
- const C10_0 = Cent(0,10);
- const C10_1 = Cent(1,10);
- const C10_3 = Cent(3,10);
- const C11_3 = Cent(3,11);
- const C20_0 = Cent(0,20);
- const C90_30 = Cent(30,90);
-
- const Cm10_0 = inc(com(C10_0)); // Cent(0, -10);
- const Cm10_1 = inc(com(C10_1)); // Cent(-1, -11);
- const Cm10_3 = inc(com(C10_3)); // Cent(-3, -11);
- const Cm20_0 = inc(com(C20_0)); // Cent(0, -20);
-
- enum Cs_3 = Cent(3, I.min);
-
- const Cbig_1 = Cent(0xa3ccac1832952398, 0xc3ac542864f652f8);
- const Cbig_2 = Cent(0x5267b85f8a42fc20, 0);
- const Cbig_3 = Cent(0xf0000000ffffffff, 0);
+ const Cent C0 = Zero;
+ const Cent C1 = One;
+ const Cent C2 = { lo:2 };
+ const Cent C3 = { lo:3 };
+ const Cent C5 = { lo:5 };
+ const Cent C10 = { lo:10 };
+ const Cent C20 = { lo:20 };
+ const Cent C30 = { lo:30 };
+ const Cent C100 = { lo:100 };
+
+ const Cent Cm1 = neg(One);
+ const Cent Cm3 = neg(C3);
+ const Cent Cm10 = neg(C10);
+
+ const Cent C3_1 = { lo:1, hi:3 };
+ const Cent C3_2 = { lo:2, hi:3 };
+ const Cent C4_8 = { lo:8, hi:4 };
+ const Cent C5_0 = { lo:0, hi:5 };
+ const Cent C7_1 = { lo:1, hi:7 };
+ const Cent C7_9 = { lo:9, hi:7 };
+ const Cent C9_3 = { lo:3, hi:9 };
+ const Cent C10_0 = { lo:0, hi:10 };
+ const Cent C10_1 = { lo:1, hi:10 };
+ const Cent C10_3 = { lo:3, hi:10 };
+ const Cent C11_3 = { lo:3, hi:11 };
+ const Cent C20_0 = { lo:0, hi:20 };
+ const Cent C90_30 = { lo:30, hi:90 };
+
+ const Cent Cm10_0 = inc(com(C10_0)); // Cent(lo=0, hi=-10);
+ const Cent Cm10_1 = inc(com(C10_1)); // Cent(lo=-1, hi=-11);
+ const Cent Cm10_3 = inc(com(C10_3)); // Cent(lo=-3, hi=-11);
+ const Cent Cm20_0 = inc(com(C20_0)); // Cent(lo=0, hi=-20);
+
+ enum Cent Cs_3 = { lo:3, hi:I.min };
+
+ const Cent Cbig_1 = { lo:0xa3ccac1832952398, hi:0xc3ac542864f652f8 };
+ const Cent Cbig_2 = { lo:0x5267b85f8a42fc20, hi:0 };
+ const Cent Cbig_3 = { lo:0xf0000000ffffffff, hi:0 };
/************************/
@@ -893,12 +911,20 @@ unittest
assert(div(mul(C90_30, C2), C2) == C90_30);
assert(div(mul(C90_30, C2), C90_30) == C2);
- assert(divmod(Cbig_1, Cbig_2, modulus) == Cent(0x4496aa309d4d4a2f, U.max));
- assert(modulus == Cent(0xd83203d0fdc799b8, U.max));
- assert(udivmod(Cbig_1, Cbig_2, modulus) == Cent(0x5fe0e9bace2bedad, 2));
- assert(modulus == Cent(0x2c923125a68721f8, 0));
- assert(div(Cbig_1, Cbig_3) == Cent(0xbfa6c02b5aff8b86, U.max));
- assert(udiv(Cbig_1, Cbig_3) == Cent(0xd0b7d13b48cb350f, 0));
+ const Cent Cb1divb2 = { lo:0x4496aa309d4d4a2f, hi:U.max };
+ const Cent Cb1modb2 = { lo:0xd83203d0fdc799b8, hi:U.max };
+ assert(divmod(Cbig_1, Cbig_2, modulus) == Cb1divb2);
+ assert(modulus == Cb1modb2);
+
+ const Cent Cb1udivb2 = { lo:0x5fe0e9bace2bedad, hi:2 };
+ const Cent Cb1umodb2 = { lo:0x2c923125a68721f8, hi:0 };
+ assert(udivmod(Cbig_1, Cbig_2, modulus) == Cb1udivb2);
+ assert(modulus == Cb1umodb2);
+
+ const Cent Cb1divb3 = { lo:0xbfa6c02b5aff8b86, hi:U.max };
+ const Cent Cb1udivb3 = { lo:0xd0b7d13b48cb350f, hi:0 };
+ assert(div(Cbig_1, Cbig_3) == Cb1divb3);
+ assert(udiv(Cbig_1, Cbig_3) == Cb1udivb3);
assert(mul(Cm10, C1) == Cm10);
assert(mul(C1, Cm10) == Cm10);
diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d
index 3a7c8e0..47fed9d 100644
--- a/libphobos/libdruntime/core/lifetime.d
+++ b/libphobos/libdruntime/core/lifetime.d
@@ -1273,7 +1273,9 @@ void copyEmplace(S, T)(ref S source, ref T target) @system
}
else static if (__traits(hasCopyConstructor, T))
{
- emplace(cast(Unqual!(T)*) &target); // blit T.init
+ // https://issues.dlang.org/show_bug.cgi?id=22766
+ import core.internal.lifetime : emplaceInitializer;
+ emplaceInitializer(*(cast(Unqual!T*)&target));
static if (__traits(isNested, T))
{
// copy context pointer
@@ -1373,6 +1375,22 @@ void copyEmplace(S, T)(ref S source, ref T target) @system
static assert(!__traits(compiles, copyEmplace(ss, t)));
}
+// https://issues.dlang.org/show_bug.cgi?id=22766
+@system pure nothrow @nogc unittest
+{
+ static struct S
+ {
+ @disable this();
+ this(int) @safe pure nothrow @nogc{}
+ this(ref const(S) other) @safe pure nothrow @nogc {}
+ }
+
+ S s1 = S(1);
+ S s2 = void;
+ copyEmplace(s1, s2);
+ assert(s2 == S(1));
+}
+
version (DigitalMars) version (X86) version (Posix) version = DMD_X86_Posix;
// don't violate immutability for reference types
diff --git a/libphobos/libdruntime/gcc/emutls.d b/libphobos/libdruntime/gcc/emutls.d
index 6d9fb30..ee36032 100644
--- a/libphobos/libdruntime/gcc/emutls.d
+++ b/libphobos/libdruntime/gcc/emutls.d
@@ -223,9 +223,9 @@ void** emutlsAlloc(shared __emutls_object* obj) nothrow @nogc
}
/*
- * When a thread has finished, remove the TLS array from the GC
- * scan list emutlsArrays, free all allocated TLS variables and
- * finally free the array.
+ * When a thread has finished, free all allocated TLS variables and empty the
+ * array. The pointer is not free'd as it is stil referenced by the GC scan
+ * list emutlsArrays, which gets destroyed when druntime is unloaded.
*/
extern (C) void emutlsDestroyThread(void* ptr) nothrow @nogc
{
@@ -237,7 +237,7 @@ extern (C) void emutlsDestroyThread(void* ptr) nothrow @nogc
free(entry[-1]);
}
- free(arr);
+ arr.length = 0;
}
/*
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index a15616c..e58afa2 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -2830,8 +2830,8 @@ extern (C)
private struct AA { void* impl; }
// size_t _aaLen(in AA aa) pure nothrow @nogc;
- private void* _aaGetY(AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey) pure nothrow;
- private void* _aaGetX(AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey, out bool found) pure nothrow;
+ private void* _aaGetY(scope AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey) pure nothrow;
+ private void* _aaGetX(scope AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey, out bool found) pure nothrow;
// inout(void)* _aaGetRvalueX(inout AA aa, in TypeInfo keyti, in size_t valsz, in void* pkey);
inout(void[]) _aaValues(inout AA aa, const size_t keysz, const size_t valsz, const TypeInfo tiValueArray) pure nothrow;
inout(void[]) _aaKeys(inout AA aa, const size_t keysz, const TypeInfo tiKeyArray) pure nothrow;
diff --git a/libphobos/libdruntime/rt/aaA.d b/libphobos/libdruntime/rt/aaA.d
index 0c38622..ab93f19 100644
--- a/libphobos/libdruntime/rt/aaA.d
+++ b/libphobos/libdruntime/rt/aaA.d
@@ -504,7 +504,7 @@ extern (C) size_t _aaLen(scope const AA aa) pure nothrow @nogc
* If key was not in the aa, a mutable pointer to newly inserted value which
* is set to all zeros
*/
-extern (C) void* _aaGetY(AA* paa, const TypeInfo_AssociativeArray ti,
+extern (C) void* _aaGetY(scope AA* paa, const TypeInfo_AssociativeArray ti,
const size_t valsz, scope const void* pkey)
{
bool found;
@@ -525,7 +525,7 @@ extern (C) void* _aaGetY(AA* paa, const TypeInfo_AssociativeArray ti,
* If key was not in the aa, a mutable pointer to newly inserted value which
* is set to all zeros
*/
-extern (C) void* _aaGetX(AA* paa, const TypeInfo_AssociativeArray ti,
+extern (C) void* _aaGetX(scope AA* paa, const TypeInfo_AssociativeArray ti,
const size_t valsz, scope const void* pkey, out bool found)
{
// lazily alloc implementation
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 7306c10..3218ace 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-99e9c1b7741e0f4e6f2a8c14883c4828d092701d
+ac296f80cda437483b743f953dc69cb1271c82df
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
diff --git a/libphobos/src/Makefile.am b/libphobos/src/Makefile.am
index 75f8397..da7a200 100644
--- a/libphobos/src/Makefile.am
+++ b/libphobos/src/Makefile.am
@@ -130,7 +130,7 @@ PHOBOS_DSOURCES = etc/c/curl.d etc/c/zlib.d std/algorithm/comparison.d \
std/experimental/typecons.d std/file.d std/format/internal/floats.d \
std/format/internal/read.d std/format/internal/write.d \
std/format/package.d std/format/read.d std/format/spec.d \
- std/format/write.d std/functional.d std/getopt.d \
+ std/format/write.d std/functional.d std/getopt.d std/int128.d \
std/internal/attributes.d std/internal/cstring.d \
std/internal/math/biguintcore.d std/internal/math/biguintnoasm.d \
std/internal/math/errorfunction.d std/internal/math/gammafunction.d \
diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in
index f2395e2..6f58fee 100644
--- a/libphobos/src/Makefile.in
+++ b/libphobos/src/Makefile.in
@@ -228,6 +228,7 @@ am__dirstamp = $(am__leading_dot)dirstamp
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/format/spec.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/format/write.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/functional.lo std/getopt.lo \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/int128.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/attributes.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/cstring.lo \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/math/biguintcore.lo \
@@ -591,7 +592,7 @@ libgphobos_la_LINK = $(LIBTOOL) --tag=D $(libgphobos_la_LIBTOOLFLAGS) \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/experimental/typecons.d std/file.d std/format/internal/floats.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/format/internal/read.d std/format/internal/write.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/format/package.d std/format/read.d std/format/spec.d \
-@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/format/write.d std/functional.d std/getopt.d \
+@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/format/write.d std/functional.d std/getopt.d std/int128.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/attributes.d std/internal/cstring.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/math/biguintcore.d std/internal/math/biguintnoasm.d \
@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/math/errorfunction.d std/internal/math/gammafunction.d \
@@ -846,6 +847,7 @@ std/format/spec.lo: std/format/$(am__dirstamp)
std/format/write.lo: std/format/$(am__dirstamp)
std/functional.lo: std/$(am__dirstamp)
std/getopt.lo: std/$(am__dirstamp)
+std/int128.lo: std/$(am__dirstamp)
std/internal/$(am__dirstamp):
@$(MKDIR_P) std/internal
@: > std/internal/$(am__dirstamp)
diff --git a/libphobos/src/etc/c/zlib.d b/libphobos/src/etc/c/zlib.d
index a1b20fe..73c6534 100644
--- a/libphobos/src/etc/c/zlib.d
+++ b/libphobos/src/etc/c/zlib.d
@@ -2,15 +2,16 @@
/* updated from 1.2.1 to 1.2.3 by Thomas Kuehne */
/* updated from 1.2.3 to 1.2.8 by Dmitry Atamanov */
/* updated from 1.2.8 to 1.2.11 by Iain Buclaw */
+/* updated from 1.2.11 to 1.2.12 by Brian Callahan */
module etc.c.zlib;
import core.stdc.config;
/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.2.11, January 15th, 2017
+ version 1.2.12, March 11th, 2022
- Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+ Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -42,8 +43,8 @@ nothrow:
extern (C):
// Those are extern(D) as they should be mangled
-extern(D) immutable string ZLIB_VERSION = "1.2.11";
-extern(D) immutable ZLIB_VERNUM = 0x12b0;
+extern(D) immutable string ZLIB_VERSION = "1.2.12";
+extern(D) immutable ZLIB_VERNUM = 0x12c0;
/*
The 'zlib' compression library provides in-memory compression and
@@ -566,8 +567,7 @@ int deflateInit2(z_streamp strm,
}
/*
This is another version of deflateInit with more compression options. The
- fields next_in, zalloc, zfree and opaque must be initialized before by the
- caller.
+ fields zalloc, zfree and opaque must be initialized before by the caller.
The method parameter is the compression method. It must be Z_DEFLATED in
this version of the library.
@@ -586,7 +586,7 @@ int deflateInit2(z_streamp strm,
with deflateInit2() with this initialization, or at least in that case use 9
with inflateInit2().
- windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ windowBits can also be -8 .. -15 for raw deflate. In this case, -windowBits
determines the window size. deflate() will then generate raw deflate data
with no zlib header or trailer, and will not compute a check value.
@@ -728,11 +728,12 @@ int deflateParams(z_streamp strm, int level, int strategy);
used to switch between compression and straight copy of the input data, or
to switch to a different kind of input data requiring a different strategy.
If the compression approach (which is a function of the level) or the
- strategy is changed, and if any input has been consumed in a previous
- deflate() call, then the input available so far is compressed with the old
- level and strategy using deflate(strm, Z_BLOCK). There are three approaches
- for the compression levels 0, 1 .. 3, and 4 .. 9 respectively. The new level
- and strategy will take effect at the next call of deflate().
+ strategy is changed, and if there have been any deflate() calls since the
+ state was initialized or reset, then the input available so far is
+ compressed with the old level and strategy using deflate(strm, Z_BLOCK).
+ There are three approaches for the compression levels 0, 1 .. 3, and 4 .. 9
+ respectively. The new level and strategy will take effect at the next call
+ of deflate().
If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
not have enough output space to complete, then the parameter change will not
@@ -856,7 +857,7 @@ int inflateInit2(z_streamp strm, int windowBits)
windowBits can also be zero to request that inflate use the window size in
the zlib header of the compressed stream.
- windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ windowBits can also be -8 .. -15 for raw inflate. In this case, -windowBits
determines the window size. inflate() will then process raw deflate data,
not looking for a zlib or gzip header, not generating a check value, and not
looking for any check values for comparison at the end of the stream. This
@@ -873,9 +874,11 @@ int inflateInit2(z_streamp strm, int windowBits)
detection, or add 16 to decode only the gzip format (the zlib format will
return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
- below), inflate() will not automatically decode concatenated gzip streams.
- inflate() will return Z_STREAM_END at the end of the gzip stream. The state
- would need to be reset to continue decoding a subsequent gzip stream.
+ below), inflate() will *not* automatically decode concatenated gzip members.
+ inflate() will return Z_STREAM_END at the end of the gzip member. The state
+ would need to be reset to continue decoding a subsequent gzip member. This
+ *must* be done if there is more data after a gzip member, in order for the
+ decompression to be compliant with the gzip standard (RFC 1952).
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
@@ -1311,14 +1314,14 @@ alias z_size_t = size_t;
gzFile gzopen(const(char)* path, const(char)* mode);
/*
- Opens a gzip (.gz) file for reading or writing. The mode parameter is as
- in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
- a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
- compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
- for fixed code compression as in "wb9F". (See the description of
- deflateInit2 for more information about the strategy parameter.) 'T' will
- request transparent writing or appending with no compression and not using
- the gzip format.
+ Open the gzip (.gz) file at path for reading and decompressing, or
+ compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
+ but can also include a compression level ("wb9") or a strategy: 'f' for
+ filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
+ 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
+ as in "wb9F". (See the description of deflateInit2 for more information
+ about the strategy parameter.) 'T' will request transparent writing or
+ appending with no compression and not using the gzip format.
"a" can be used instead of "w" to request that the gzip stream that will
be written be appended to the file. "+" will result in an error, since
@@ -1348,9 +1351,9 @@ gzFile gzopen(const(char)* path, const(char)* mode);
gzFile gzdopen(int fd, const(char)* mode);
/*
- gzdopen associates a gzFile with the file descriptor fd. File descriptors
- are obtained from calls like open, dup, creat, pipe or fileno (if the file
- has been previously opened with fopen). The mode parameter is as in gzopen.
+ Associate a gzFile with the file descriptor fd. File descriptors are
+ obtained from calls like open, dup, creat, pipe or fileno (if the file has
+ been previously opened with fopen). The mode parameter is as in gzopen.
The next call of gzclose on the returned gzFile will also close the file
descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
@@ -1371,13 +1374,13 @@ gzFile gzdopen(int fd, const(char)* mode);
int gzbuffer(gzFile file, uint size);
/*
- Set the internal buffer size used by this library's functions. The
- default buffer size is 8192 bytes. This function must be called after
- gzopen() or gzdopen(), and before any other calls that read or write the
- file. The buffer memory allocation is always deferred to the first read or
- write. Three times that size in buffer space is allocated. A larger buffer
- size of, for example, 64K or 128K bytes will noticeably increase the speed
- of decompression (reading).
+ Set the internal buffer size used by this library's functions for file to
+ size. The default buffer size is 8192 bytes. This function must be called
+ after gzopen() or gzdopen(), and before any other calls that read or write
+ the file. The buffer memory allocation is always deferred to the first read
+ or write. Three times that size in buffer space is allocated. A larger
+ buffer size of, for example, 64K or 128K bytes will noticeably increase the
+ speed of decompression (reading).
The new buffer size also affects the maximum length for gzprintf().
@@ -1387,9 +1390,9 @@ int gzbuffer(gzFile file, uint size);
int gzsetparams(gzFile file, int level, int strategy);
/*
- Dynamically update the compression level or strategy. See the description
- of deflateInit2 for the meaning of these parameters. Previously provided
- data is flushed before the parameter change.
+ Dynamically update the compression level and strategy for file. See the
+ description of deflateInit2 for the meaning of these parameters. Previously
+ provided data is flushed before applying the parameter changes.
gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
opened for writing, Z_ERRNO if there is an error writing the flushed data,
@@ -1398,7 +1401,7 @@ int gzsetparams(gzFile file, int level, int strategy);
int gzread(gzFile file, void* buf, uint len);
/*
- Reads the given number of uncompressed bytes from the compressed file. If
+ Read and decompress up to len uncompressed bytes from file into buf. If
the input file is not in gzip format, gzread copies the given number of
bytes into the buffer directly from the file.
@@ -1428,11 +1431,11 @@ int gzread(gzFile file, void* buf, uint len);
z_size_t gzfread(void* buf, z_size_t size, z_size_t nitems, gzFile file);
/*
- Read up to nitems items of size size from file to buf, otherwise operating
- as gzread() does. This duplicates the interface of stdio's fread(), with
- size_t request and return types. If the library defines size_t, then
- z_size_t is identical to size_t. If not, then z_size_t is an unsigned
- integer type that can contain a pointer.
+ Read and decompress up to nitems items of size size from file into buf,
+ otherwise operating as gzread() does. This duplicates the interface of
+ stdio's fread(), with size_t request and return types. If the library
+ defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
+ is an unsigned integer type that can contain a pointer.
gzfread() returns the number of full items read of size size, or zero if
the end of the file was reached and a full item could not be read, or if
@@ -1453,14 +1456,13 @@ z_size_t gzfread(void* buf, z_size_t size, z_size_t nitems, gzFile file);
int gzwrite(gzFile file, void* buf, uint len);
/*
- Writes the given number of uncompressed bytes into the compressed file.
- gzwrite returns the number of uncompressed bytes written or 0 in case of
- error.
+ Compress and write the len uncompressed bytes at buf to file. gzwrite
+ returns the number of uncompressed bytes written or 0 in case of error.
*/
z_size_t gzfwrite(void* buf, z_size_t size, z_size_t nitems, gzFile file);
/*
- gzfwrite() writes nitems items of size size from buf to file, duplicating
+ Compress and write nitems items of size size from buf to file, duplicating
the interface of stdio's fwrite(), with size_t request and return types. If
the library defines size_t, then z_size_t is identical to size_t. If not,
then z_size_t is an unsigned integer type that can contain a pointer.
@@ -1473,22 +1475,22 @@ z_size_t gzfwrite(void* buf, z_size_t size, z_size_t nitems, gzFile file);
int gzprintf(gzFile file, const(char)* format, ...);
/*
- Converts, formats, and writes the arguments to the compressed file under
- control of the format string, as in fprintf. gzprintf returns the number of
+ Convert, format, compress, and write the arguments (...) to file under
+ control of the string format, as in fprintf. gzprintf returns the number of
uncompressed bytes actually written, or a negative zlib error code in case
of error. The number of uncompressed bytes written is limited to 8191, or
one less than the buffer size given to gzbuffer(). The caller should assure
that this limit is not exceeded. If it is exceeded, then gzprintf() will
return an error (0) with nothing written. In this case, there may also be a
buffer overflow with unpredictable consequences, which is possible only if
- zlib was compiled with the insecure functions sprintf() or vsprintf()
+ zlib was compiled with the insecure functions sprintf() or vsprintf(),
because the secure snprintf() or vsnprintf() functions were not available.
This can be determined using zlibCompileFlags().
*/
int gzputs(gzFile file, const(char)* s);
/*
- Writes the given null-terminated string to the compressed file, excluding
+ Compress and write the given null-terminated string s to file, excluding
the terminating null character.
gzputs returns the number of characters written, or -1 in case of error.
@@ -1496,11 +1498,12 @@ int gzputs(gzFile file, const(char)* s);
const(char)* gzgets(gzFile file, const(char)* buf, int len);
/*
- Reads bytes from the compressed file until len-1 characters are read, or a
- newline character is read and transferred to buf, or an end-of-file
- condition is encountered. If any characters are read or if len == 1, the
- string is terminated with a null character. If no characters are read due
- to an end-of-file or len < 1, then the buffer is left untouched.
+ Read and decompress bytes from file into buf, until len-1 characters are
+ read, or until a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. If any characters are read or if len
+ is one, the string is terminated with a null character. If no characters
+ are read due to an end-of-file or len is less than one, then the buffer is
+ left untouched.
gzgets returns buf which is a null-terminated string, or it returns NULL
for end-of-file or in case of error. If there was an error, the contents at
@@ -1509,13 +1512,13 @@ const(char)* gzgets(gzFile file, const(char)* buf, int len);
int gzputc(gzFile file, int c);
/*
- Writes c, converted to an unsigned char, into the compressed file. gzputc
+ Compress and write c, converted to an unsigned char, into file. gzputc
returns the value that was written, or -1 in case of error.
*/
int gzgetc(gzFile file);
/*
- Reads one byte from the compressed file. gzgetc returns this byte or -1
+ Read and decompress one byte from file. gzgetc returns this byte or -1
in case of end of file or error. This is implemented as a macro for speed.
As such, it does not do all of the checking the other functions do. I.e.
it does not check to see if file is NULL, nor whether the structure file
@@ -1524,8 +1527,8 @@ int gzgetc(gzFile file);
int gzungetc(int c, gzFile file);
/*
- Push one character back onto the stream to be read as the first character
- on the next read. At least one character of push-back is allowed.
+ Push c back onto the stream for file to be read as the first character on
+ the next read. At least one character of push-back is always allowed.
gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
fail if c is -1, and may fail if a character has been pushed but not read
yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
@@ -1536,9 +1539,9 @@ int gzungetc(int c, gzFile file);
int gzflush(gzFile file, int flush);
/*
- Flushes all pending output into the compressed file. The parameter flush
- is as in the deflate() function. The return value is the zlib error number
- (see function gzerror below). gzflush is only permitted when writing.
+ Flush all pending output to file. The parameter flush is as in the
+ deflate() function. The return value is the zlib error number (see function
+ gzerror below). gzflush is only permitted when writing.
If the flush parameter is Z_FINISH, the remaining data is written and the
gzip stream is completed in the output. If gzwrite() is called again, a new
@@ -1551,8 +1554,8 @@ int gzflush(gzFile file, int flush);
z_off_t gzseek(gzFile file, z_off_t offset, int whence);
/*
- Sets the starting position for the next gzread or gzwrite on the given
- compressed file. The offset represents a number of bytes in the
+ Set the starting position to offset relative to whence for the next gzread
+ or gzwrite on file. The offset represents a number of bytes in the
uncompressed data stream. The whence parameter is defined as in lseek(2);
the value SEEK_END is not supported.
@@ -1569,39 +1572,39 @@ z_off_t gzseek(gzFile file, z_off_t offset, int whence);
int gzrewind(gzFile file);
/*
- Rewinds the given file. This function is supported only for reading.
+ Rewind file. This function is supported only for reading.
- gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
*/
z_off_t gztell(gzFile file);
/*
- Returns the starting position for the next gzread or gzwrite on the given
- compressed file. This position represents a number of bytes in the
- uncompressed data stream, and is zero when starting, even if appending or
- reading a gzip stream from the middle of a file using gzdopen().
+ Return the starting position for the next gzread or gzwrite on file.
+ This position represents a number of bytes in the uncompressed data stream,
+ and is zero when starting, even if appending or reading a gzip stream from
+ the middle of a file using gzdopen().
gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
*/
z_off_t gzoffset(gzFile file);
/*
- Returns the current offset in the file being read or written. This offset
- includes the count of bytes that precede the gzip stream, for example when
- appending or when using gzdopen() for reading. When reading, the offset
- does not include as yet unused buffered input. This information can be used
- for a progress indicator. On error, gzoffset() returns -1.
+ Return the current compressed (actual) read or write offset of file. This
+ offset includes the count of bytes that precede the gzip stream, for example
+ when appending or when using gzdopen() for reading. When reading, the
+ offset does not include as yet unused buffered input. This information can
+ be used for a progress indicator. On error, gzoffset() returns -1.
*/
int gzeof(gzFile file);
/*
- Returns true (1) if the end-of-file indicator has been set while reading,
- false (0) otherwise. Note that the end-of-file indicator is set only if the
- read tried to go past the end of the input, but came up short. Therefore,
- just like feof(), gzeof() may return false even if there is no more data to
- read, in the event that the last read request was for the exact number of
- bytes remaining in the input file. This will happen if the input file size
- is an exact multiple of the buffer size.
+ Return true (1) if the end-of-file indicator for file has been set while
+ reading, false (0) otherwise. Note that the end-of-file indicator is set
+ only if the read tried to go past the end of the input, but came up short.
+ Therefore, just like feof(), gzeof() may return false even if there is no
+ more data to read, in the event that the last read request was for the exact
+ number of bytes remaining in the input file. This will happen if the input
+ file size is an exact multiple of the buffer size.
If gzeof() returns true, then the read functions will return no more data,
unless the end-of-file indicator is reset by gzclearerr() and the input file
@@ -1610,7 +1613,7 @@ int gzeof(gzFile file);
int gzdirect(gzFile file);
/*
- Returns true (1) if file is being copied directly while reading, or false
+ Return true (1) if file is being copied directly while reading, or false
(0) if file is a gzip stream being decompressed.
If the input file is empty, gzdirect() will return true, since the input
@@ -1631,8 +1634,8 @@ int gzdirect(gzFile file);
int gzclose(gzFile file);
/*
- Flushes all pending output if necessary, closes the compressed file and
- deallocates the (de)compression state. Note that once file is closed, you
+ Flush all pending output for file, if necessary, close file and
+ deallocate the (de)compression state. Note that once file is closed, you
cannot call gzerror with file, since its structures have been deallocated.
gzclose must not be called more than once on the same file, just as free
must not be called more than once on the same allocation.
@@ -1656,10 +1659,10 @@ int gzclose_w(gzFile file);
const(char)* gzerror(gzFile file, int* errnum);
/*
- Returns the error message for the last error which occurred on the given
- compressed file. errnum is set to zlib error number. If an error occurred
- in the file system and not in the compression library, errnum is set to
- Z_ERRNO and the application may consult errno to get the exact error code.
+ Return the error message for the last error which occurred on file.
+ errnum is set to zlib error number. If an error occurred in the file system
+ and not in the compression library, errnum is set to Z_ERRNO and the
+ application may consult errno to get the exact error code.
The application must not modify the returned string. Future calls to
this function may invalidate the previously returned string. If file is
@@ -1672,7 +1675,7 @@ const(char)* gzerror(gzFile file, int* errnum);
void gzclearerr(gzFile file);
/*
- Clears the error and end-of-file flags for file. This is analogous to the
+ Clear the error and end-of-file flags for file. This is analogous to the
clearerr() function in stdio. This is useful for continuing to read a gzip
file that is being written concurrently.
*/
@@ -1688,8 +1691,9 @@ void gzclearerr(gzFile file);
uint adler32(uint adler, const(ubyte)* buf, uint len);
/*
Update a running Adler-32 checksum with the bytes buf[0 .. len-1] and
- return the updated checksum. If buf is Z_NULL, this function returns the
- required initial value for the checksum.
+ return the updated checksum. An Adler-32 value is in the range of a 32-bit
+ unsigned integer. If buf is Z_NULL, this function returns the required
+ initial value for the checksum.
An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
much faster.
@@ -1722,9 +1726,10 @@ uint adler32_combine(uint adler1, uint adler2, z_off_t len2);
uint crc32(uint crc, const(ubyte)* buf, uint len);
/*
Update a running CRC-32 with the bytes buf[0 .. len-1] and return the
- updated CRC-32. If buf is Z_NULL, this function returns the required
- initial value for the crc. Pre- and post-conditioning (one's complement) is
- performed within this function so it shouldn't be done by the application.
+ updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
+ If buf is Z_NULL, this function returns the required initial value for the
+ crc. Pre- and post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the application.
Usage example:
@@ -1736,7 +1741,7 @@ uint crc32(uint crc, const(ubyte)* buf, uint len);
if (crc != original_crc) error();
*/
-uint crc32_z(uint adler, const(ubyte)* buf, z_size_t len);
+uint crc32_z(uint crc, const(ubyte)* buf, z_size_t len);
/*
Same as crc32(), but with a size_t length.
*/
@@ -1751,6 +1756,18 @@ uint crc32_combine(uint crc1, uint crc2, z_off_t len2);
len2.
*/
+uint crc32_combine_gen(z_off_t len2);
+/*
+ Return the operator corresponding to length len2, to be used with
+ crc32_combine_op().
+*/
+
+uint crc32_combine_op(uint crc1, uint crc2, uint op);
+/*
+ Give the same result as crc32_combine(), using op in place of len2. op is
+ is generated from len2 by crc32_combine_gen(). This will be faster than
+ crc32_combine() if the generated op is used more than once.
+*/
/* various hacks, don't look :) */
diff --git a/libphobos/src/std/base64.d b/libphobos/src/std/base64.d
index 866f700..d971dba 100644
--- a/libphobos/src/std/base64.d
+++ b/libphobos/src/std/base64.d
@@ -63,7 +63,7 @@ import std.range.primitives : empty, front, isInputRange, isOutputRange,
import std.traits : isArray;
// Make sure module header code examples work correctly.
-@safe unittest
+pure @safe unittest
{
ubyte[] data = [0x14, 0xfb, 0x9c, 0x03, 0xd9, 0x7e];
@@ -82,7 +82,7 @@ import std.traits : isArray;
alias Base64 = Base64Impl!('+', '/');
///
-@safe unittest
+pure @safe unittest
{
ubyte[] data = [0x83, 0xd7, 0x30, 0x7a, 0x01, 0x3f];
assert(Base64.encode(data) == "g9cwegE/");
@@ -98,7 +98,7 @@ alias Base64 = Base64Impl!('+', '/');
alias Base64URL = Base64Impl!('-', '_');
///
-@safe unittest
+pure @safe unittest
{
ubyte[] data = [0x83, 0xd7, 0x30, 0x7a, 0x01, 0x3f];
assert(Base64URL.encode(data) == "g9cwegE_");
@@ -114,7 +114,7 @@ alias Base64URL = Base64Impl!('-', '_');
alias Base64URLNoPadding = Base64Impl!('-', '_', Base64.NoPadding);
///
-@safe unittest
+pure @safe unittest
{
ubyte[] data = [0x83, 0xd7, 0x30, 0x7b, 0xef];
assert(Base64URLNoPadding.encode(data) == "g9cwe-8");
@@ -180,7 +180,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* Returns:
* The length of a Base64 encoding of an array of the given length.
*/
- @safe
+ @safe @nogc
pure nothrow size_t encodeLength(in size_t sourceLength)
{
static if (Padding == NoPadding)
@@ -218,8 +218,8 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
* The slice of $(D_PARAM buffer) that contains the encoded string.
*/
@trusted
- pure char[] encode(R1, R2)(in R1 source, return scope R2 buffer) if (isArray!R1 && is(ElementType!R1 : ubyte) &&
- is(R2 == char[]))
+ pure char[] encode(R1, R2)(const scope R1 source, return scope R2 buffer)
+ if (isArray!R1 && is(ElementType!R1 : ubyte) && is(R2 == char[]))
in
{
assert(buffer.length >= encodeLength(source.length), "Insufficient buffer for encoding");
@@ -277,9 +277,9 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
}
///
- @safe unittest
+ @nogc nothrow @safe unittest
{
- ubyte[] data = [0x83, 0xd7, 0x30, 0x7a, 0x01, 0x3f];
+ ubyte[6] data = [0x83, 0xd7, 0x30, 0x7a, 0x01, 0x3f];
char[32] buffer; // much bigger than necessary
// Just to be sure...
@@ -287,7 +287,7 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
assert(buffer.length >= encodedLength);
// encode() returns a slice to the provided buffer.
- auto encoded = Base64.encode(data, buffer[]);
+ auto encoded = Base64.encode(data[], buffer[]);
assert(encoded is buffer[0 .. encodedLength]);
assert(encoded == "g9cwegE/");
}
diff --git a/libphobos/src/std/int128.d b/libphobos/src/std/int128.d
new file mode 100644
index 0000000..fc992f8
--- /dev/null
+++ b/libphobos/src/std/int128.d
@@ -0,0 +1,374 @@
+// Written in the D programming language
+/**
+ * Implements a signed 128 bit integer type.
+ *
+ Author: Walter Bright
+ Copyright: Copyright (c) 2022, D Language Foundation
+ License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ Source: $(PHOBOSSRC std/int128.d)
+ */
+module std.int128;
+
+private import core.int128;
+
+
+/***********************************
+ * 128 bit signed integer type.
+ */
+
+public struct Int128
+{
+ @safe pure nothrow @nogc:
+
+ Cent data; /// core.int128.Cent
+
+ /****************
+ * Construct an `Int128` from a `long` value.
+ * The upper 64 bits are formed by sign extension.
+ * Params:
+ * lo = signed lower 64 bits
+ */
+ this(long lo)
+ {
+ data.lo = lo;
+ data.hi = lo < 0 ? ~0L : 0;
+ }
+
+ /****************
+ * Construct an `Int128` from a `ulong` value.
+ * The upper 64 bits are set to zero.
+ * Params:
+ * lo = unsigned lower 64 bits
+ */
+ this(ulong lo)
+ {
+ data.lo = lo;
+ data.hi = 0;
+ }
+
+ /****************
+ * Construct an `Int128` from a `long` value.
+ * Params:
+ * hi = upper 64 bits
+ * lo = lower 64 bits
+ */
+ this(long hi, long lo)
+ {
+ data.hi = hi;
+ data.lo = lo;
+ }
+
+ /********************
+ * Construct an `Int128` from a `Cent`.
+ * Params:
+ * data = Cent data
+ */
+ this(Cent data)
+ {
+ this.data = data;
+ }
+
+ /********************
+ * Returns: hash value for Int128
+ */
+ size_t toHash() const
+ {
+ return cast(size_t)((data.lo & 0xFFFF_FFFF) + (data.hi & 0xFFFF_FFFF) + (data.lo >> 32) + (data.hi >> 32));
+ }
+
+ /************************
+ * Compare for equality
+ * Params: lo = signed value to compare with
+ * Returns: true if Int128 equals value
+ */
+ bool opEquals(long lo) const
+ {
+ return data.lo == lo && data.hi == (lo >> 63);
+ }
+
+ /************************
+ * Compare for equality
+ * Params: lo = unsigned value to compare with
+ * Returns: true if Int128 equals value
+ */
+ bool opEquals(ulong lo) const
+ {
+ return data.hi == 0 && data.lo == lo;
+ }
+
+ /************************
+ * Compare for equality
+ * Params: op2 = value to compare with
+ * Returns: true if Int128 equals value
+ */
+ bool opEquals(Int128 op2) const
+ {
+ return data.hi == op2.data.hi && data.lo == op2.data.lo;
+ }
+
+ /** Support unary arithmentic operator +
+ * Params: op = "+"
+ * Returns: lvalue of result
+ */
+ Int128 opUnary(string op)() const
+ if (op == "+")
+ {
+ return this;
+ }
+
+ /** Support unary arithmentic operator - ~
+ * Params: op = "-", "~"
+ * Returns: lvalue of result
+ */
+ Int128 opUnary(string op)() const
+ if (op == "-" || op == "~")
+ {
+ static if (op == "-")
+ return Int128(neg(this.data));
+ else static if (op == "~")
+ return Int128(com(this.data));
+ }
+
+ /** Support unary arithmentic operator ++ --
+ * Params: op = "++", "--"
+ * Returns: lvalue of result
+ */
+ Int128 opUnary(string op)()
+ if (op == "++" || op == "--")
+ {
+ static if (op == "++")
+ this.data = inc(this.data);
+ else static if (op == "--")
+ this.data = dec(this.data);
+ else
+ static assert(0, op);
+ return this;
+ }
+
+ /** Support casting to a bool
+ * Params: T = bool
+ * Returns: boolean result
+ */
+ bool opCast(T : bool)() const
+ {
+ return tst(this.data);
+ }
+
+ /** Support binary arithmetic operators + - * / % & | ^ << >> >>>
+ * Params:
+ * op = one of the arithmetic binary operators
+ * op2 = second operand
+ * Returns: value after the operation is applied
+ */
+ Int128 opBinary(string op)(Int128 op2) const
+ if (op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^")
+ {
+ static if (op == "+")
+ return Int128(add(this.data, op2.data));
+ else static if (op == "-")
+ return Int128(sub(this.data, op2.data));
+ else static if (op == "*")
+ return Int128(mul(this.data, op2.data));
+ else static if (op == "/")
+ return Int128(div(this.data, op2.data));
+ else static if (op == "%")
+ {
+ Cent modulus;
+ divmod(this.data, op2.data, modulus);
+ return Int128(modulus);
+ }
+ else static if (op == "&")
+ return Int128(and(this.data, op2.data));
+ else static if (op == "|")
+ return Int128(or(this.data, op2.data));
+ else static if (op == "^")
+ return Int128(xor(this.data, op2.data));
+ else
+ static assert(0, "wrong op value");
+ }
+
+ /// ditto
+ Int128 opBinary(string op)(long op2) const
+ if (op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^")
+ {
+ return mixin("this " ~ op ~ " Int128(0, op2)");
+ }
+
+ /// ditto
+ Int128 opBinaryRight(string op)(long op2) const
+ if (op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^")
+ {
+ mixin("return Int128(0, op2) " ~ op ~ " this;");
+ }
+
+ /// ditto
+ Int128 opBinary(string op)(long op2) const
+ if (op == "<<")
+ {
+ return Int128(shl(this.data, cast(uint) op2));
+ }
+
+ /// ditto
+ Int128 opBinary(string op)(long op2) const
+ if (op == ">>")
+ {
+ return Int128(sar(this.data, cast(uint) op2));
+ }
+
+ /// ditto
+ Int128 opBinary(string op)(long op2) const
+ if (op == ">>>")
+ {
+ return Int128(shr(this.data, cast(uint) op2));
+ }
+
+ /** arithmetic assignment operators += -= *= /= %= &= |= ^= <<= >>= >>>=
+ * Params: op = one of +, -, etc.
+ * op2 = second operand
+ * 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 == ">>>")
+ {
+ mixin("this = this " ~ op ~ " op2;");
+ return this;
+ }
+
+ /// ditto
+ ref Int128 opOpAssign(string op)(long op2)
+ if (op == "+" || op == "-" ||
+ op == "*" || op == "/" || op == "%" ||
+ op == "&" || op == "|" || op == "^" ||
+ op == "<<" || op == ">>" || op == ">>>")
+ {
+ mixin("this = this " ~ op ~ " op2;");
+ return this;
+ }
+
+ /** support signed arithmentic comparison operators < <= > >=
+ * Params: op2 = right hand operand
+ * Returns: -1 for less than, 0 for equals, 1 for greater than
+ */
+ int opCmp(Int128 op2) const
+ {
+ return this == op2 ? 0 : gt(this.data, op2.data) * 2 - 1;
+ }
+
+ /** support signed arithmentic comparison operators < <= > >=
+ * Params: op2 = right hand operand
+ * Returns: -1 for less than, 0 for equals, 1 for greater than
+ */
+ int opCmp(long op2) const
+ {
+ return opCmp(Int128(0, op2));
+ }
+
+ enum min = Int128(long.min, 0); /// minimum value
+ enum max = Int128(long.max, ulong.max); /// maximum value
+}
+
+/********************************************* Tests ************************************/
+
+version (unittest)
+{
+import core.stdc.stdio;
+
+@trusted void print(Int128 c)
+{
+ printf("%lld, %lld\n", c.data.hi, c.data.lo);
+}
+
+@trusted void printx(Int128 c)
+{
+ printf("%llx, %llx\n", c.data.hi, c.data.lo);
+}
+}
+
+/// Int128 tests
+@safe pure nothrow @nogc
+unittest
+{
+ Int128 c = Int128(5, 6);
+ assert(c == c);
+ assert(c == +c);
+ assert(c == - -c);
+ assert(~c == Int128(~5, ~6));
+ ++c;
+ assert(c == Int128(5, 7));
+ assert(--c == Int128(5, 6));
+ assert(!!c);
+ assert(!Int128());
+
+ assert(c + Int128(10, 20) == Int128(15, 26));
+ assert(c - Int128(1, 2) == Int128(4, 4));
+ assert(c * Int128(100, 2) == Int128(610, 12));
+ assert(c / Int128(3, 2) == Int128(0, 1));
+ assert(c % Int128(3, 2) == Int128(2, 4));
+ assert((c & Int128(3, 2)) == Int128(1, 2));
+ assert((c | Int128(3, 2)) == Int128(7, 6));
+ assert((c ^ Int128(3, 2)) == Int128(6, 4));
+
+ assert(c + 15 == Int128(5, 21));
+ assert(c - 15 == Int128(4, -9));
+ assert(c * 15 == Int128(75, 90));
+ assert(c / 15 == Int128(0, 6148914691236517205));
+ assert(c % 15 == Int128(0, 11));
+ assert((c & 15) == Int128(0, 6));
+ assert((c | 15) == Int128(5, 15));
+ assert((c ^ 15) == Int128(5, 9));
+
+ assert(15 + c == Int128(5, 21));
+ assert(15 - c == Int128(-5, 9));
+ assert(15 * c == Int128(75, 90));
+ assert(15 / c == Int128(0, 0));
+ assert(15 % c == Int128(0, 15));
+ assert((15 & c) == Int128(0, 6));
+ assert((15 | c) == Int128(5, 15));
+ assert((15 ^ c) == Int128(5, 9));
+
+ assert(c << 1 == Int128(10, 12));
+ assert(-c >> 1 == Int128(-3, 9223372036854775805));
+ assert(-c >>> 1 == Int128(9223372036854775805, 9223372036854775805));
+
+ assert((c += 1) == Int128(5, 7));
+ assert((c -= 1) == Int128(5, 6));
+ assert((c += Int128(0, 1)) == Int128(5, 7));
+ assert((c -= Int128(0, 1)) == Int128(5, 6));
+ assert((c *= 2) == Int128(10, 12));
+ assert((c /= 2) == Int128(5, 6));
+ assert((c %= 2) == Int128());
+ c += Int128(5, 6);
+ assert((c *= Int128(10, 20)) == Int128(160, 120));
+ assert((c /= Int128(10, 20)) == Int128(0, 15));
+ c += Int128(72, 0);
+ assert((c %= Int128(10, 20)) == Int128(1, -125));
+ assert((c &= Int128(3, 20)) == Int128(1, 0));
+ assert((c |= Int128(8, 2)) == Int128(9, 2));
+ assert((c ^= Int128(8, 2)) == Int128(1, 0));
+ c |= Int128(10, 5);
+ assert((c <<= 1) == Int128(11 * 2, 5 * 2));
+ assert((c >>>= 1) == Int128(11, 5));
+ c = Int128(long.min, long.min);
+ assert((c >>= 1) == Int128(long.min >> 1, cast(ulong) long.min >> 1));
+
+ assert(-Int128.min == Int128.min);
+ assert(Int128.max + 1 == Int128.min);
+
+ c = Int128(5, 6);
+ assert(c < Int128(6, 5));
+ assert(c > 10);
+
+ c = Int128(-1UL);
+ assert(c == -1UL);
+ c = Int128(-1L);
+ assert(c == -1L);
+}
diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d
index 20518b8..de180fc 100644
--- a/libphobos/src/std/path.d
+++ b/libphobos/src/std/path.d
@@ -1519,7 +1519,7 @@ if (isSomeChar!C)
import std.range;
// ir() wraps an array in a plain (i.e. non-forward) input range, so that
// we can test both code paths
- InputRange!(C[]) ir(C)(C[][] p...) { return inputRangeObject(p); }
+ InputRange!(C[]) ir(C)(C[][] p...) { return inputRangeObject(p.dup); }
version (Posix)
{
assert(buildPath("foo") == "foo");
diff --git a/libphobos/src/std/regex/internal/parser.d b/libphobos/src/std/regex/internal/parser.d
index 41ca687..448bb99 100644
--- a/libphobos/src/std/regex/internal/parser.d
+++ b/libphobos/src/std/regex/internal/parser.d
@@ -841,7 +841,7 @@ if (isForwardRange!R && is(ElementType!R : dchar))
switch (front)
{
case '*', '?', '+', '|', '{', '}':
- error("'*', '+', '?', '{', '}' not allowed in atom");
+ return error("'*', '+', '?', '{', '}' not allowed in atom");
case '.':
if (re_flags & RegexOption.singleline)
g.put(Bytecode(IR.Any, 0));
diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d
index 9ca676d..18400e3 100644
--- a/libphobos/src/std/traits.d
+++ b/libphobos/src/std/traits.d
@@ -1422,6 +1422,11 @@ if (isCallable!func)
enum val = "val" ~ (name == "val" ? "_" : "");
enum ptr = "ptr" ~ (name == "ptr" ? "_" : "");
mixin("
+ enum hasDefaultArg = (PT[i .. i+1] " ~ args ~ ") { return true; };
+ ");
+ static if (is(typeof(hasDefaultArg())))
+ {
+ mixin("
// workaround scope escape check, see
// https://issues.dlang.org/show_bug.cgi?id=16582
// should use return scope once available
@@ -1432,10 +1437,9 @@ if (isCallable!func)
auto " ~ val ~ " = " ~ args ~ "[0];
auto " ~ ptr ~ " = &" ~ val ~ ";
return *" ~ ptr ~ ";
- };
- ");
- static if (is(typeof(get())))
+ };");
enum Get = get();
+ }
else
alias Get = void;
// If default arg doesn't exist, returns void instead.
@@ -1483,6 +1487,17 @@ if (isCallable!func)
static foreach (V; Voids) static assert(is(V == void));
}
+// https://issues.dlang.org/show_bug.cgi?id=20182
+@safe pure nothrow @nogc unittest
+{
+ struct S
+ {
+ this(ref S) {}
+ }
+
+ static assert(__traits(compiles, ParameterDefaults!(S.__ctor)));
+}
+
/**
* Alternate name for $(LREF ParameterDefaults), kept for legacy compatibility.
*/