aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std
diff options
context:
space:
mode:
Diffstat (limited to 'libphobos/src/std')
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d18
-rw-r--r--libphobos/src/std/experimental/allocator/common.d3
-rw-r--r--libphobos/src/std/file.d4
-rw-r--r--libphobos/src/std/format/spec.d35
-rw-r--r--libphobos/src/std/format/write.d32
-rw-r--r--libphobos/src/std/internal/windows/bcrypt.d65
-rw-r--r--libphobos/src/std/numeric.d2
-rw-r--r--libphobos/src/std/random.d84
8 files changed, 195 insertions, 48 deletions
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d b/libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d
index c6d5fca..9d30b5e 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/allocator_list.d
@@ -1140,7 +1140,6 @@ template SharedAllocatorList(alias factoryFunction,
import std.algorithm.comparison : max;
import std.typecons : Ternary;
- enum pageSize = 4096;
enum numPages = 2;
static void testrw(void[] b)
@@ -1269,8 +1268,6 @@ template SharedAllocatorList(alias factoryFunction,
import std.algorithm.comparison : max;
import std.typecons : Ternary;
- enum pageSize = 4096;
-
static void testrw(void[] b)
{
ubyte* buf = cast(ubyte*) b.ptr;
@@ -1283,17 +1280,17 @@ template SharedAllocatorList(alias factoryFunction,
enum numPages = 5;
AllocatorList!((n) => AscendingPageAllocator(max(n, numPages * pageSize)), NullAllocator) a;
- auto b = a.alignedAllocate(1, pageSize * 2);
+ auto b = a.alignedAllocate(1, cast(uint) (pageSize * 2));
assert(b.length == 1);
- assert(a.expand(b, 4095));
- assert(b.ptr.alignedAt(2 * 4096));
- assert(b.length == 4096);
+ assert(a.expand(b, pageSize - 1));
+ assert(b.ptr.alignedAt(cast(uint) (pageSize * 2)));
+ assert(b.length == pageSize);
- b = a.allocate(4096);
- assert(b.length == 4096);
+ b = a.allocate(pageSize);
+ assert(b.length == pageSize);
assert(a.allocators.length == 1);
- assert(a.allocate(4096 * 5).length == 4096 * 5);
+ assert(a.allocate(pageSize * 5).length == pageSize * 5);
assert(a.allocators.length == 2);
assert(a.deallocateAll());
@@ -1339,7 +1336,6 @@ template SharedAllocatorList(alias factoryFunction,
import std.algorithm.comparison : max;
enum numThreads = 100;
- enum pageSize = 4096;
enum numPages = 10;
SharedAllocatorList!((n) => SharedAscendingPageAllocator(max(n, pageSize * numPages)), Mallocator) a;
diff --git a/libphobos/src/std/experimental/allocator/common.d b/libphobos/src/std/experimental/allocator/common.d
index b06fb62..2451572 100644
--- a/libphobos/src/std/experimental/allocator/common.d
+++ b/libphobos/src/std/experimental/allocator/common.d
@@ -63,7 +63,8 @@ unittest
class C2 { char c; }
static assert(stateSize!C2 == 4 * size_t.sizeof);
static class C3 { char c; }
- static assert(stateSize!C3 == 2 * size_t.sizeof + char.sizeof);
+ // Uncomment test after dmd issue closed https://github.com/dlang/dmd/issues/21065
+ //static assert(stateSize!C3 == 3 * size_t.sizeof);
}
/**
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index c3466ac..0b8da50 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -983,10 +983,10 @@ private void renameImpl(scope const(char)[] f, scope const(char)[] t,
import std.conv : to, text;
if (!f)
- f = to!(typeof(f))(fromz[0 .. wcslen(fromz)]);
+ f = fromz ? to!(typeof(f))(fromz[0 .. wcslen(fromz)]) : "(null)";
if (!t)
- t = to!(typeof(t))(toz[0 .. wcslen(toz)]);
+ t = toz ? to!(typeof(t))(toz[0 .. wcslen(toz)]) : "(null)";
enforce(false,
new FileException(
diff --git a/libphobos/src/std/format/spec.d b/libphobos/src/std/format/spec.d
index e5564c9..b828bb6 100644
--- a/libphobos/src/std/format/spec.d
+++ b/libphobos/src/std/format/spec.d
@@ -127,14 +127,16 @@ if (is(Unqual!Char == Char))
Counting starts with `1`. Set to `0` if not used. Default: `0`.
*/
- ubyte indexStart;
+ ushort indexStart;
/**
Index of the last argument for positional parameter ranges.
Counting starts with `1`. Set to `0` if not used. Default: `0`.
+
+ The maximum value of this field is used as a sentinel to indicate the arguments' length.
*/
- ubyte indexEnd;
+ ushort indexEnd;
version (StdDdoc)
{
@@ -296,6 +298,8 @@ if (is(Unqual!Char == Char))
}
width = 0;
+ indexStart = 0;
+ indexEnd = 0;
precision = UNSPECIFIED;
nested = null;
// Parse the spec (we assume we're past '%' already)
@@ -834,6 +838,33 @@ if (is(Unqual!Char == Char))
== "$ expected after '*10' in format string");
}
+// https://github.com/dlang/phobos/issues/10713
+@safe pure unittest
+{
+ import std.array : appender;
+ auto f = FormatSpec!char("%3$d%d");
+
+ auto w = appender!(char[])();
+ f.writeUpToNextSpec(w);
+ assert(f.indexStart == 3);
+
+ f.writeUpToNextSpec(w);
+ assert(w.data.length == 0);
+ assert(f.indexStart == 0);
+}
+
+// https://github.com/dlang/phobos/issues/10699
+@safe pure unittest
+{
+ import std.array : appender;
+ auto f = FormatSpec!char("%1:$d");
+ auto w = appender!(char[])();
+
+ f.writeUpToNextSpec(w);
+ assert(f.indexStart == 1);
+ assert(f.indexEnd == ushort.max);
+}
+
/**
Helper function that returns a `FormatSpec` for a single format specifier.
diff --git a/libphobos/src/std/format/write.d b/libphobos/src/std/format/write.d
index 078fa78..68a96d4 100644
--- a/libphobos/src/std/format/write.d
+++ b/libphobos/src/std/format/write.d
@@ -534,6 +534,8 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
// Are we already done with formats? Then just dump each parameter in turn
uint currentArg = 0;
+ bool lastWasConsumeAll;
+
while (spec.writeUpToNextSpec(w))
{
if (currentArg == Args.length && !spec.indexStart)
@@ -648,12 +650,23 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]
break SWITCH;
}
default:
- throw new FormatException(
- text("Positional specifier %", spec.indexStart, '$', spec.spec,
- " index exceeds ", Args.length));
+ if (spec.indexEnd == spec.indexEnd.max)
+ {
+ lastWasConsumeAll = true;
+ break;
+ }
+ else if (spec.indexEnd == spec.indexStart)
+ throw new FormatException(
+ text("Positional specifier %", spec.indexStart, '$', spec.spec,
+ " index exceeds ", Args.length));
+ else
+ throw new FormatException(
+ text("Positional specifier %", spec.indexStart, ":", spec.indexEnd, '$', spec.spec,
+ " index exceeds ", Args.length));
}
}
- return currentArg;
+
+ return lastWasConsumeAll ? Args.length : currentArg;
}
///
@@ -1199,6 +1212,17 @@ if (isSomeString!(typeof(fmt)))
formattedWrite(stream, "%s", aa);
}
+// https://github.com/dlang/phobos/issues/10699
+@safe pure unittest
+{
+ import std.array : appender;
+ auto w = appender!(char[])();
+
+ uint count = formattedWrite(w, "%1:$d", 1, 2, 3);
+ assert(count == 3);
+ assert(w.data == "123");
+}
+
/**
Formats a value of any type according to a format specifier and
writes the result to an output range.
diff --git a/libphobos/src/std/internal/windows/bcrypt.d b/libphobos/src/std/internal/windows/bcrypt.d
new file mode 100644
index 0000000..239dcd5
--- /dev/null
+++ b/libphobos/src/std/internal/windows/bcrypt.d
@@ -0,0 +1,65 @@
+module std.internal.windows.bcrypt;
+
+version (Windows):
+
+import core.sys.windows.bcrypt : BCryptGenRandom, BCRYPT_USE_SYSTEM_PREFERRED_RNG;
+import core.sys.windows.windef : HMODULE, PUCHAR, ULONG;
+import core.sys.windows.ntdef : NT_SUCCESS;
+
+pragma(lib, "Bcrypt.lib");
+
+package(std) bool bcryptGenRandom(T)(out T result) @trusted
+{
+ loadBcrypt();
+
+ const gotRandom = ptrBCryptGenRandom(
+ null,
+ cast(PUCHAR) &result,
+ ULONG(T.sizeof),
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG,
+ );
+
+ return NT_SUCCESS(gotRandom);
+}
+
+private
+{
+ HMODULE hBcrypt = null;
+ typeof(BCryptGenRandom)* ptrBCryptGenRandom;
+}
+
+private void loadBcrypt() @nogc nothrow
+{
+ import core.sys.windows.winbase : GetProcAddress, LoadLibraryA;
+
+ if (!hBcrypt)
+ {
+ hBcrypt = LoadLibraryA("Bcrypt.dll");
+ if (!hBcrypt)
+ assert(false, `LoadLibraryA("Bcrypt.dll") failed.`); // `@nogc`
+
+ ptrBCryptGenRandom = cast(typeof(ptrBCryptGenRandom)) GetProcAddress(hBcrypt , "BCryptGenRandom");
+ if (!ptrBCryptGenRandom)
+ assert(false, `GetProcAddress(hBcrypt , "BCryptGenRandom") failed.`); // `@nogc`
+ }
+}
+
+// Will free `Bcrypt.dll`.
+private void freeBcrypt() @nogc nothrow
+{
+ import core.sys.windows.winbase : FreeLibrary;
+
+ if (hBcrypt)
+ {
+ if (!FreeLibrary(hBcrypt))
+ assert(false, `FreeLibrary("Bcrypt.dll") failed.`); // `@nogc`
+
+ hBcrypt = null;
+ ptrBCryptGenRandom = null;
+ }
+}
+
+static ~this()
+{
+ freeBcrypt();
+}
diff --git a/libphobos/src/std/numeric.d b/libphobos/src/std/numeric.d
index 9966b1c..918984f 100644
--- a/libphobos/src/std/numeric.d
+++ b/libphobos/src/std/numeric.d
@@ -37,7 +37,7 @@ public enum CustomFloatFlags
* Store values in normalized form by default. The actual precision of the
* significand is extended by 1 bit by assuming an implicit leading bit of 1
* instead of 0. i.e. `1.nnnn` instead of `0.nnnn`.
- * True for all $(LINK2 https://en.wikipedia.org/wiki/IEEE_floating_point, IEE754) types
+ * True for all $(LINK2 https://en.wikipedia.org/wiki/IEEE_floating_point, IEEE754) types
*/
storeNormalized = 2,
diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d
index fb4e546..edb8902c 100644
--- a/libphobos/src/std/random.d
+++ b/libphobos/src/std/random.d
@@ -1774,41 +1774,71 @@ else
version (linux)
{
- // `getrandom()` was introduced in Linux 3.17.
+ version (linux_legacy_emulate_getrandom)
+ {
+ /+
+ Emulates `getrandom()` for backwards compatibility
+ with outdated kernels and legacy libc versions.
+
+ `getrandom()` was added to the GNU C Library in v2.25.
+ +/
+ pragma(msg, "`getrandom()` emulation for legacy Linux targets is enabled.");
+
+ /+
+ On modern kernels (5.6+), `/dev/random` would behave more similar
+ to `getrandom()`.
+ However, this emulator was specifically written for systems older
+ than that. Hence, `/dev/urandom` is the CSPRNG of choice.
+
+ <https://web.archive.org/web/20200914181930/https://www.2uo.de/myths-about-urandom/>
+ +/
+ private static immutable _pathLinuxSystemCSPRNG = "/dev/urandom";
+
+ import core.sys.posix.sys.types : ssize_t;
+
+ /+
+ Linux `getrandom()` emulation built upon `/dev/urandom`.
+ The fourth parameter (`uint flags`) is happily ignored.
+ +/
+ private ssize_t getrandom(
+ void* buf,
+ size_t buflen,
+ uint,
+ ) @system nothrow @nogc
+ {
+ import core.stdc.stdio : fclose, fopen, fread;
- // Shim for missing bindings in druntime
- version (none)
- import core.sys.linux.sys.random : getrandom;
+ auto blockDev = fopen(_pathLinuxSystemCSPRNG.ptr, "r");
+ if (blockDev is null)
+ assert(false, "System CSPRNG unavailable: `fopen(\"" ~ _pathLinuxSystemCSPRNG ~ "\")` failed.");
+ scope (exit) fclose(blockDev);
+
+ const bytesRead = fread(buf, 1, buflen, blockDev);
+ return bytesRead;
+ }
+ }
else
{
- import core.sys.posix.sys.types : ssize_t;
- extern extern(C) ssize_t getrandom(
- void* buf,
- size_t buflen,
- uint flags,
- ) @system nothrow @nogc;
+ // `getrandom()` was introduced in Linux 3.17.
+
+ // Shim for missing bindings in druntime
+ version (none)
+ import core.sys.linux.sys.random : getrandom;
+ else
+ {
+ import core.sys.posix.sys.types : ssize_t;
+ private extern extern(C) ssize_t getrandom(
+ void* buf,
+ size_t buflen,
+ uint flags,
+ ) @system nothrow @nogc;
+ }
}
}
version (Windows)
{
- pragma(lib, "Bcrypt.lib");
-
- private bool bcryptGenRandom(T)(out T result) @trusted
- {
- import core.sys.windows.windef : PUCHAR, ULONG;
- import core.sys.windows.ntdef : NT_SUCCESS;
- import core.sys.windows.bcrypt : BCryptGenRandom, BCRYPT_USE_SYSTEM_PREFERRED_RNG;
-
- const gotRandom = BCryptGenRandom(
- null,
- cast(PUCHAR) &result,
- ULONG(T.sizeof),
- BCRYPT_USE_SYSTEM_PREFERRED_RNG,
- );
-
- return NT_SUCCESS(gotRandom);
- }
+ import std.internal.windows.bcrypt : bcryptGenRandom;
}
/**