mirror of
https://github.com/dlang/phobos.git
synced 2025-04-26 13:10:35 +03:00
commit
ff612b867c
16 changed files with 119 additions and 261 deletions
|
@ -1,14 +0,0 @@
|
|||
Added `std.conv.bitCast`
|
||||
|
||||
This convenience function allows reinterpreting casts to be written in a more
|
||||
readable way.
|
||||
|
||||
---
|
||||
uint n = 0xDEADBEEF;
|
||||
|
||||
// Before
|
||||
writeln("Bytes of n are: ", *cast(const ubyte[4]*) &n);
|
||||
|
||||
// After
|
||||
writeln("Bytes of n are: ", n.bitCast!(const ubyte[4]));
|
||||
---
|
|
@ -1,30 +0,0 @@
|
|||
Extend the functionality of formattedRead to permit a std.file.slurp like execution.
|
||||
|
||||
Template argument types can now be passed to formattedRead along with a
|
||||
format string to parse and read the input range as a Tuple of those arguments.
|
||||
All arguments must be read successfully, otherwise, and unlike std.file.slurp
|
||||
which has non exhaustive option for partial reads, it'll throw a std.format.FormatException.
|
||||
|
||||
---
|
||||
import std.exception : assertThrown;
|
||||
import std.format : FormatException;
|
||||
import std.typecons : tuple;
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
auto complete = "hello!34.5:124".formattedRead!(string, double, int)("%s!%s:%s");
|
||||
assert(complete == tuple("hello", 34.5, 124));
|
||||
|
||||
assertThrown!FormatException("hello!34.5:".formattedRead!(string, double, int)("%s!%s:%s"));
|
||||
}
|
||||
|
||||
/// The format string can be checked at compile-time:
|
||||
@safe pure unittest
|
||||
{
|
||||
auto expected = tuple("hello", 124, 34.5);
|
||||
auto result = "hello!124:34.5".formattedRead!("%s!%s:%s", string, int, double);
|
||||
assert(result == expected);
|
||||
|
||||
assertThrown!FormatException("hello!34.5:".formattedRead!("%s!%s:%s", string, double, int));
|
||||
}
|
||||
---
|
|
@ -1,15 +0,0 @@
|
|||
Added fromHexString and fromHexStringAsRange functions to std.digest.
|
||||
|
||||
This new function enables the converion of a hex string to a range of bytes.
|
||||
Unlike the template $(REF hexString, std, conv) that was designed to supersede
|
||||
a language feature, this function is usable with runtime input.
|
||||
|
||||
The `std.conv` module lacks facilities to conveniently transform the input
|
||||
to a series of bytes directly. Both $(REF parse, std, conv) and $(REF to, std,
|
||||
conv) can only handle the conversion for a single value of the requested target
|
||||
integer type. Furthermore, said functions would allocate a new buffer for the
|
||||
result, while `fromHexStringAsRange` operates lazily by implementing a forward
|
||||
range.
|
||||
|
||||
For further convenience, a validation function $(REF isHexString, std, digest)
|
||||
was added as well.
|
|
@ -1,11 +0,0 @@
|
|||
ODBC Bindings in `etc.c.odbc` have been updated to ODBC 4.0.
|
||||
|
||||
ODBC 4.0, via these new bindings, adds the following functionality:
|
||||
|
||||
1. Support for semi-structured data, such as JSON.
|
||||
2. Collection valued columns.
|
||||
3. Web-based Authorization flows.
|
||||
|
||||
A full list of new features can be found here: https://github.com/Microsoft/ODBC-Specification/blob/master/ODBC%204.0.md
|
||||
|
||||
Additionally these modules add support for 64-bit ODBC interfaces.
|
|
@ -1,38 +0,0 @@
|
|||
Added popGrapheme function to std.uni.
|
||||
|
||||
The new function is a cross between the existing $(REF graphemeStride, std,
|
||||
uni) and $(REF decodeGrapheme, std, uni) functions. The new function both
|
||||
supports `@safe pure nothrow @nogc` like `graphemeStride` does as long as you
|
||||
don't rely on autodecoding (side node: `@nogc` support for `graphemeStride`
|
||||
added in this release), and works with any non-array ranges just like
|
||||
`decodeGrapheme` does.
|
||||
|
||||
Example:
|
||||
|
||||
-------
|
||||
import std.uni;
|
||||
|
||||
// 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 point in a single grapheme.
|
||||
assert(testPiece.popGrapheme() == 2);
|
||||
assert(testPiece.equal("!"d));
|
||||
-------
|
|
@ -1,6 +0,0 @@
|
|||
Added `readfln` and `File.readfln` to `std.stdio`
|
||||
|
||||
These functions read a single line of input and parse it using a format string.
|
||||
Unlike `readf`, they will not accidentally read multiple lines if the user
|
||||
forgets to include a line terminator in the format string—a common mistake for
|
||||
beginners.
|
|
@ -1,13 +0,0 @@
|
|||
Added the `SharedAllocatorList`, as the thread-safe version of the regular `AllocatorList`.
|
||||
|
||||
The new $(REF SharedAllocatorList, std,experimental,allocator,building_blocks,allocator_list) has the same semantics as the regular `AllocatorList`.
|
||||
Just as the regular `AllocatorList`, if the `BookkeepingAllocator` is `NullAllocator`, the `SharedAllocatorList` will switch to `ouroboros` mode,
|
||||
allocationg memory for its own metadata.
|
||||
|
||||
---
|
||||
SharedAllocatorList!((n) => SharedAscendingPageAllocator(max(n, numPages * pageSize)), NullAllocator) a;
|
||||
auto b = a.allocate(100);
|
||||
assert(b.length == 100);
|
||||
|
||||
assert(a.deallocate(b));
|
||||
---
|
|
@ -1,39 +0,0 @@
|
|||
New procedural API for `std.sumtype`
|
||||
|
||||
`std.sumtype` has three new convenience functions for querying and retrieving
|
||||
the value of a `SumType` object.
|
||||
|
||||
* `has!T` returns `true` if the `SumType` object has a value of type `T`.
|
||||
* `get!T` returns the value if its type is `T`, or asserts if it is not.
|
||||
* `tryGet!T` returns the value if its type is `T`, or throws an exception if it
|
||||
is not.
|
||||
|
||||
These functions make it easier to write code using `SumType` in a procedural
|
||||
style, as opposed to the functional style encouraged by `match`.
|
||||
|
||||
Example:
|
||||
|
||||
---
|
||||
import std.sumtype;
|
||||
import std.stdio;
|
||||
|
||||
SumType!(string, double) example = "hello";
|
||||
|
||||
if (example.has!string)
|
||||
{
|
||||
writeln("string: ", example.get!string);
|
||||
}
|
||||
else if (example.has!double)
|
||||
{
|
||||
writeln("double: ", example.get!double);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
writeln("double: ", example.tryGet!double);
|
||||
}
|
||||
catch (MatchException e)
|
||||
{
|
||||
writeln("Couldn't get a double.");
|
||||
}
|
||||
---
|
|
@ -1,16 +0,0 @@
|
|||
std.uni has been upgraded from Unicode 15.1.0 to 16.0.0
|
||||
|
||||
This Unicode update was released September 10, 2024, and adds new blocks with characters.
|
||||
See: https://www.unicode.org/versions/Unicode16.0.0/
|
||||
|
||||
```
|
||||
import std;
|
||||
|
||||
void main()
|
||||
{
|
||||
const alphaCount = iota(0, dchar.max).filter!(std.uni.isAlpha).walkLength;
|
||||
writeln(alphaCount);
|
||||
// formerly: 138387
|
||||
// now: 142759
|
||||
}
|
||||
```
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -648,9 +648,16 @@ 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)
|
||||
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;
|
||||
|
@ -1199,6 +1206,16 @@ 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[])();
|
||||
|
||||
formattedWrite(w, "%1:$d", 1, 2, 3);
|
||||
assert(w.data == "123");
|
||||
}
|
||||
|
||||
/**
|
||||
Formats a value of any type according to a format specifier and
|
||||
writes the result to an output range.
|
||||
|
|
73
std/getopt.d
73
std/getopt.d
|
@ -610,14 +610,14 @@ private template optionValidator(A...)
|
|||
alias optionValidator = message;
|
||||
}
|
||||
|
||||
private void handleConversion(R)(string option, string value, R* receiver,
|
||||
private auto getoptTo(R)(string option, string value,
|
||||
size_t idx, string file = __FILE__, size_t line = __LINE__)
|
||||
{
|
||||
import std.conv : to, ConvException;
|
||||
import std.format : format;
|
||||
try
|
||||
{
|
||||
*receiver = to!(typeof(*receiver))(value);
|
||||
return to!R(value);
|
||||
}
|
||||
catch (ConvException e)
|
||||
{
|
||||
|
@ -876,12 +876,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
|||
// (and potentially args[i + 1] too, but that comes later)
|
||||
args = args[0 .. i] ~ args[i + 1 .. $];
|
||||
|
||||
static if (is(typeof(*receiver) == bool))
|
||||
static if (is(typeof(*receiver)))
|
||||
alias Target = typeof(*receiver);
|
||||
else
|
||||
// delegate
|
||||
alias Target = void;
|
||||
|
||||
static if (is(Target == bool))
|
||||
{
|
||||
if (val.length)
|
||||
{
|
||||
// parse '--b=true/false'
|
||||
handleConversion(option, val, receiver, i);
|
||||
*receiver = getoptTo!(Target)(option, val, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -894,23 +900,23 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
|||
import std.exception : enforce;
|
||||
// non-boolean option, which might include an argument
|
||||
enum isCallbackWithLessThanTwoParameters =
|
||||
(is(typeof(receiver) == delegate) || is(typeof(*receiver) == function)) &&
|
||||
(is(R == delegate) || is(Target == function)) &&
|
||||
!is(typeof(receiver("", "")));
|
||||
if (!isCallbackWithLessThanTwoParameters && !(val.length) && !incremental)
|
||||
{
|
||||
// Eat the next argument too. Check to make sure there's one
|
||||
// to be eaten first, though.
|
||||
enforce!GetOptException(i < args.length,
|
||||
"Missing value for argument " ~ a ~ ".");
|
||||
"Missing value for argument " ~ a ~ ".");
|
||||
val = args[i];
|
||||
args = args[0 .. i] ~ args[i + 1 .. $];
|
||||
}
|
||||
static if (is(typeof(*receiver) == enum) ||
|
||||
is(typeof(*receiver) == string))
|
||||
static if (is(Target == enum) ||
|
||||
is(Target == string))
|
||||
{
|
||||
handleConversion(option, val, receiver, i);
|
||||
*receiver = getoptTo!Target(option, val, i);
|
||||
}
|
||||
else static if (is(typeof(*receiver) : real))
|
||||
else static if (is(Target : real))
|
||||
{
|
||||
// numeric receiver
|
||||
if (incremental)
|
||||
|
@ -919,16 +925,16 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
|||
}
|
||||
else
|
||||
{
|
||||
handleConversion(option, val, receiver, i);
|
||||
*receiver = getoptTo!Target(option, val, i);
|
||||
}
|
||||
}
|
||||
else static if (is(typeof(*receiver) == string))
|
||||
else static if (is(Target == string))
|
||||
{
|
||||
// string receiver
|
||||
*receiver = to!(typeof(*receiver))(val);
|
||||
*receiver = getoptTo!(Target)(option, val, i);
|
||||
}
|
||||
else static if (is(typeof(receiver) == delegate) ||
|
||||
is(typeof(*receiver) == function))
|
||||
else static if (is(R == delegate) ||
|
||||
is(Target == function))
|
||||
{
|
||||
static if (is(typeof(receiver("", "")) : void))
|
||||
{
|
||||
|
@ -952,29 +958,25 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
|||
receiver();
|
||||
}
|
||||
}
|
||||
else static if (isArray!(typeof(*receiver)))
|
||||
else static if (isArray!(Target))
|
||||
{
|
||||
// array receiver
|
||||
import std.range : ElementEncodingType;
|
||||
alias E = ElementEncodingType!(typeof(*receiver));
|
||||
alias E = ElementEncodingType!(Target);
|
||||
|
||||
if (arraySep == "")
|
||||
{
|
||||
E tmp;
|
||||
handleConversion(option, val, &tmp, i);
|
||||
*receiver ~= tmp;
|
||||
*receiver ~= getoptTo!E(option, val, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (elem; val.splitter(arraySep))
|
||||
{
|
||||
E tmp;
|
||||
handleConversion(option, elem, &tmp, i);
|
||||
*receiver ~= tmp;
|
||||
*receiver ~= getoptTo!E(option, elem, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else static if (isAssociativeArray!(typeof(*receiver)))
|
||||
else static if (isAssociativeArray!(Target))
|
||||
{
|
||||
// hash receiver
|
||||
alias K = typeof(receiver.keys[0]);
|
||||
|
@ -991,14 +993,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
|||
~ to!string(assignChar) ~ "' in argument '" ~ input ~ "'.");
|
||||
auto key = input[0 .. j];
|
||||
auto value = input[j + 1 .. $];
|
||||
|
||||
K k;
|
||||
handleConversion("", key, &k, 0);
|
||||
|
||||
V v;
|
||||
handleConversion("", value, &v, 0);
|
||||
|
||||
return tuple(k,v);
|
||||
return tuple(getoptTo!K("", key, 0), getoptTo!V("", value, 0));
|
||||
}
|
||||
|
||||
static void setHash(Range)(R receiver, Range range)
|
||||
|
@ -1013,7 +1008,7 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
|||
setHash(receiver, val.splitter(arraySep));
|
||||
}
|
||||
else
|
||||
static assert(false, "getopt does not know how to handle the type " ~ typeof(receiver).stringof);
|
||||
static assert(false, "getopt does not know how to handle the type " ~ R.stringof);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1099,6 +1094,18 @@ private bool handleOption(R)(string option, R receiver, ref string[] args,
|
|||
assert(values == ["foo":0, "bar":1, "baz":2], to!string(values));
|
||||
}
|
||||
|
||||
// https://github.com/dlang/phobos/issues/10680
|
||||
@safe unittest
|
||||
{
|
||||
arraySep = ",";
|
||||
scope(exit) arraySep = "";
|
||||
const(string)[] s;
|
||||
string[] args = ["program.name", "-s", "a", "-s", "b", "-s", "c,d,e"];
|
||||
getopt(args, "values|s", &s);
|
||||
assert(s == ["a", "b", "c", "d", "e"]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The option character (default '-').
|
||||
|
||||
|
|
44
std/json.d
44
std/json.d
|
@ -562,8 +562,7 @@ struct JSONValue
|
|||
else static if (is(T : string))
|
||||
{
|
||||
type_tag = JSONType.string;
|
||||
string t = arg;
|
||||
() @trusted { store.str = t; }();
|
||||
store = Store(str: arg);
|
||||
}
|
||||
// https://issues.dlang.org/show_bug.cgi?id=15884
|
||||
else static if (isSomeString!T)
|
||||
|
@ -572,7 +571,7 @@ struct JSONValue
|
|||
// FIXME: std.Array.Array(Range) is not deduced as 'pure'
|
||||
() @trusted {
|
||||
import std.utf : byUTF;
|
||||
store.str = cast(immutable)(arg.byUTF!char.array);
|
||||
store = Store(str: cast(immutable)(arg.byUTF!char.array));
|
||||
}();
|
||||
}
|
||||
else static if (is(T : bool))
|
||||
|
@ -582,17 +581,17 @@ struct JSONValue
|
|||
else static if (is(T : ulong) && isUnsigned!T)
|
||||
{
|
||||
type_tag = JSONType.uinteger;
|
||||
store.uinteger = arg;
|
||||
store = Store(uinteger: arg);
|
||||
}
|
||||
else static if (is(T : long))
|
||||
{
|
||||
type_tag = JSONType.integer;
|
||||
store.integer = arg;
|
||||
store = Store(integer: arg);
|
||||
}
|
||||
else static if (isFloatingPoint!T)
|
||||
{
|
||||
type_tag = JSONType.float_;
|
||||
store.floating = arg;
|
||||
store = Store(floating: arg);
|
||||
}
|
||||
else static if (is(T : Value[Key], Key, Value))
|
||||
{
|
||||
|
@ -600,45 +599,34 @@ struct JSONValue
|
|||
type_tag = JSONType.object;
|
||||
static if (is(Value : JSONValue))
|
||||
{
|
||||
JSONValue[string] t = arg;
|
||||
() @trusted {
|
||||
store.object.isOrdered = false;
|
||||
store.object.unordered = t;
|
||||
}();
|
||||
store = Store(object: Store.Object(false, unordered: arg));
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONValue[string] aa;
|
||||
foreach (key, value; arg)
|
||||
aa[key] = JSONValue(value);
|
||||
() @trusted {
|
||||
store.object.isOrdered = false;
|
||||
store.object.unordered = aa;
|
||||
}();
|
||||
store = Store(object: Store.Object(false, unordered: aa));
|
||||
}
|
||||
}
|
||||
else static if (is(T : OrderedObjectMember[]))
|
||||
{
|
||||
type_tag = JSONType.object;
|
||||
() @trusted {
|
||||
store.object.isOrdered = true;
|
||||
store.object.ordered = arg;
|
||||
}();
|
||||
store = Store(object: Store.Object(true, ordered: arg));
|
||||
}
|
||||
else static if (isArray!T)
|
||||
{
|
||||
type_tag = JSONType.array;
|
||||
static if (is(ElementEncodingType!T : JSONValue))
|
||||
{
|
||||
JSONValue[] t = arg;
|
||||
() @trusted { store.array = t; }();
|
||||
store = Store(array: arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONValue[] new_arg = new JSONValue[arg.length];
|
||||
foreach (i, e; arg)
|
||||
new_arg[i] = JSONValue(e);
|
||||
() @trusted { store.array = new_arg; }();
|
||||
store = Store(array: new_arg);
|
||||
}
|
||||
}
|
||||
else static if (is(T : JSONValue))
|
||||
|
@ -658,14 +646,14 @@ struct JSONValue
|
|||
type_tag = JSONType.array;
|
||||
static if (is(ElementEncodingType!T : JSONValue))
|
||||
{
|
||||
store.array = arg;
|
||||
store = Store(array: arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
JSONValue[] new_arg = new JSONValue[arg.length];
|
||||
foreach (i, e; arg)
|
||||
new_arg[i] = JSONValue(e);
|
||||
store.array = new_arg;
|
||||
store = Store(array: new_arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1651,13 +1639,13 @@ if (isSomeFiniteCharInputRange!T)
|
|||
if (isFloat)
|
||||
{
|
||||
value.type_tag = JSONType.float_;
|
||||
value.store.floating = parse!double(data);
|
||||
value.store = JSONValue.Store(floating: parse!double(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isNegative)
|
||||
{
|
||||
value.store.integer = parse!long(data);
|
||||
value.store = JSONValue.Store(integer: parse!long(data));
|
||||
value.type_tag = JSONType.integer;
|
||||
}
|
||||
else
|
||||
|
@ -1666,12 +1654,12 @@ if (isSomeFiniteCharInputRange!T)
|
|||
ulong u = parse!ulong(data);
|
||||
if (u & (1UL << 63))
|
||||
{
|
||||
value.store.uinteger = u;
|
||||
value.store = JSONValue.Store(uinteger: u);
|
||||
value.type_tag = JSONType.uinteger;
|
||||
}
|
||||
else
|
||||
{
|
||||
value.store.integer = u;
|
||||
value.store = JSONValue.Store(integer: u);
|
||||
value.type_tag = JSONType.integer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue