mirror of
https://github.com/dlang/phobos.git
synced 2025-04-30 15:10:46 +03:00
Merge remote-tracking branch 'upstream/stable' into merge_stable
# Conflicts: # std/bitmanip.d
This commit is contained in:
commit
9fdcf660dd
5 changed files with 791 additions and 608 deletions
|
@ -119,16 +119,16 @@ if (fun.length >= 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
`cache` eagerly evaluates `front` of `range`
|
`cache` eagerly evaluates $(REF_ALTTEXT front, front, std,_range,primitives) of `range`
|
||||||
on each construction or call to `popFront`,
|
on each construction or call to $(REF_ALTTEXT popFront, popFront, std,_range,primitives),
|
||||||
to store the result in a _cache.
|
to store the result in a _cache.
|
||||||
The result is then directly returned when `front` is called,
|
The result is then directly returned when $(REF_ALTTEXT front, front, std,_range,primitives) is called,
|
||||||
rather than re-evaluated.
|
rather than re-evaluated.
|
||||||
|
|
||||||
This can be a useful function to place in a chain, after functions
|
This can be a useful function to place in a chain, after functions
|
||||||
that have expensive evaluation, as a lazy alternative to $(REF array, std,array).
|
that have expensive evaluation, as a lazy alternative to $(REF array, std,array).
|
||||||
In particular, it can be placed after a call to `map`, or before a call
|
In particular, it can be placed after a call to $(LREF map), or before a call
|
||||||
to `filter`.
|
$(REF filter, std,_range) or $(REF tee, std,_range)
|
||||||
|
|
||||||
`cache` may provide
|
`cache` may provide
|
||||||
$(REF_ALTTEXT bidirectional _range, isBidirectionalRange, std,_range,primitives)
|
$(REF_ALTTEXT bidirectional _range, isBidirectionalRange, std,_range,primitives)
|
||||||
|
@ -148,7 +148,7 @@ Params:
|
||||||
range = an $(REF_ALTTEXT input _range, isInputRange, std,_range,primitives)
|
range = an $(REF_ALTTEXT input _range, isInputRange, std,_range,primitives)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
an input _range with the cached values of _range
|
An $(REF_ALTTEXT input _range, isInputRange, std,_range,primitives) with the cached values of _range
|
||||||
+/
|
+/
|
||||||
auto cache(Range)(Range range)
|
auto cache(Range)(Range range)
|
||||||
if (isInputRange!Range)
|
if (isInputRange!Range)
|
||||||
|
|
453
std/bitmanip.d
453
std/bitmanip.d
|
@ -52,8 +52,6 @@ Distributed under the Boost Software License, Version 1.0.
|
||||||
*/
|
*/
|
||||||
module std.bitmanip;
|
module std.bitmanip;
|
||||||
|
|
||||||
//debug = bitarray; // uncomment to turn on debugging printf's
|
|
||||||
|
|
||||||
import std.range.primitives;
|
import std.range.primitives;
|
||||||
public import std.system : Endian;
|
public import std.system : Endian;
|
||||||
import std.traits;
|
import std.traits;
|
||||||
|
@ -248,13 +246,11 @@ private template createTaggedReference(T, ulong a, string name, Ts...)
|
||||||
Allows creating bit fields inside $(D_PARAM struct)s and $(D_PARAM
|
Allows creating bit fields inside $(D_PARAM struct)s and $(D_PARAM
|
||||||
class)es.
|
class)es.
|
||||||
|
|
||||||
The sum of all bit lengths in one $(D_PARAM bitfield) instantiation
|
|
||||||
must be exactly 8, 16, 32, or 64. If padding is needed, just allocate
|
|
||||||
one bitfield with an empty name.
|
|
||||||
|
|
||||||
The type of a bit field can be any integral type or enumerated
|
The type of a bit field can be any integral type or enumerated
|
||||||
type. The most efficient type to store in bitfields is $(D_PARAM
|
type. The most efficient type to store in bitfields is $(D_PARAM
|
||||||
bool), followed by unsigned types, followed by signed types.
|
bool), followed by unsigned types, followed by signed types.
|
||||||
|
|
||||||
|
See_Also: $(REF BitFlags, std,typecons)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template bitfields(T...)
|
template bitfields(T...)
|
||||||
|
@ -262,6 +258,63 @@ template bitfields(T...)
|
||||||
enum { bitfields = createStorageAndFields!T.result }
|
enum { bitfields = createStorageAndFields!T.result }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a bitfield pack of eight bits, which fit in
|
||||||
|
one $(D_PARAM ubyte). The bitfields are allocated starting from the
|
||||||
|
least significant bit, i.e. x occupies the two least significant bits
|
||||||
|
of the bitfields storage.
|
||||||
|
*/
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
mixin(bitfields!(
|
||||||
|
uint, "x", 2,
|
||||||
|
int, "y", 3,
|
||||||
|
uint, "z", 2,
|
||||||
|
bool, "flag", 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
A obj;
|
||||||
|
obj.x = 2;
|
||||||
|
obj.z = obj.x;
|
||||||
|
|
||||||
|
assert(obj.x == 2);
|
||||||
|
assert(obj.y == 0);
|
||||||
|
assert(obj.z == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The sum of all bit lengths in one $(D_PARAM bitfield) instantiation
|
||||||
|
must be exactly 8, 16, 32, or 64. If padding is needed, just allocate
|
||||||
|
one bitfield with an empty name.
|
||||||
|
*/
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
mixin(bitfields!(
|
||||||
|
bool, "flag1", 1,
|
||||||
|
bool, "flag2", 1,
|
||||||
|
uint, "", 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// enums can be used too
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
enum ABC { A, B, C }
|
||||||
|
struct EnumTest
|
||||||
|
{
|
||||||
|
mixin(bitfields!(
|
||||||
|
ABC, "x", 2,
|
||||||
|
bool, "y", 1,
|
||||||
|
ubyte, "z", 5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creates a bitfield pack of eight bits, which fit in
|
Creates a bitfield pack of eight bits, which fit in
|
||||||
one `ubyte`. The bitfields are allocated starting from the
|
one `ubyte`. The bitfields are allocated starting from the
|
||||||
|
@ -827,9 +880,9 @@ struct DoubleRep
|
||||||
assert(rep.sign);
|
assert(rep.sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reading
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
// test reading
|
|
||||||
DoubleRep x;
|
DoubleRep x;
|
||||||
x.value = 1.0;
|
x.value = 1.0;
|
||||||
assert(x.fraction == 0 && x.exponent == 1023 && !x.sign);
|
assert(x.fraction == 0 && x.exponent == 1023 && !x.sign);
|
||||||
|
@ -837,22 +890,16 @@ struct DoubleRep
|
||||||
assert(x.fraction == 0 && x.exponent == 1022 && x.sign);
|
assert(x.fraction == 0 && x.exponent == 1022 && x.sign);
|
||||||
x.value = 0.5;
|
x.value = 0.5;
|
||||||
assert(x.fraction == 0 && x.exponent == 1022 && !x.sign);
|
assert(x.fraction == 0 && x.exponent == 1022 && !x.sign);
|
||||||
|
}
|
||||||
|
|
||||||
// test writing
|
/// Writing
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
DoubleRep x;
|
||||||
x.fraction = 1125899906842624;
|
x.fraction = 1125899906842624;
|
||||||
x.exponent = 1025;
|
x.exponent = 1025;
|
||||||
x.sign = true;
|
x.sign = true;
|
||||||
assert(x.value == -5.0);
|
assert(x.value == -5.0);
|
||||||
|
|
||||||
// test enums
|
|
||||||
enum ABC { A, B, C }
|
|
||||||
struct EnumTest
|
|
||||||
{
|
|
||||||
mixin(bitfields!(
|
|
||||||
ABC, "x", 2,
|
|
||||||
bool, "y", 1,
|
|
||||||
ubyte, "z", 5));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@safe unittest
|
@safe unittest
|
||||||
|
@ -1121,11 +1168,10 @@ public:
|
||||||
return cast(bool) bt(_ptr, i);
|
return cast(bool) bt(_ptr, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opIndex.unittest\n");
|
static void fun(const BitArray arr)
|
||||||
|
|
||||||
void Fun(const BitArray arr)
|
|
||||||
{
|
{
|
||||||
auto x = arr[0];
|
auto x = arr[0];
|
||||||
assert(x == 1);
|
assert(x == 1);
|
||||||
|
@ -1133,7 +1179,7 @@ public:
|
||||||
BitArray a;
|
BitArray a;
|
||||||
a.length = 3;
|
a.length = 3;
|
||||||
a[0] = 1;
|
a[0] = 1;
|
||||||
Fun(a);
|
fun(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************
|
/**********************************************
|
||||||
|
@ -1303,6 +1349,7 @@ public:
|
||||||
bt(_ptr, i) ? btr(_ptr, i) : bts(_ptr, i);
|
bt(_ptr, i) ? btr(_ptr, i) : bts(_ptr, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
auto ax = BitArray([1, 0, 0, 1]);
|
auto ax = BitArray([1, 0, 0, 1]);
|
||||||
|
@ -1328,6 +1375,7 @@ public:
|
||||||
return bitCount;
|
return bitCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
auto a = BitArray([0, 1, 1, 0, 0, 1, 1]);
|
auto a = BitArray([0, 1, 1, 0, 0, 1, 1]);
|
||||||
|
@ -1352,23 +1400,19 @@ public:
|
||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
BitArray a;
|
BitArray a;
|
||||||
BitArray b;
|
BitArray b;
|
||||||
int i;
|
|
||||||
|
|
||||||
debug(bitarray) printf("BitArray.dup.unittest\n");
|
|
||||||
|
|
||||||
a.length = 3;
|
a.length = 3;
|
||||||
a[0] = 1; a[1] = 0; a[2] = 1;
|
a[0] = 1; a[1] = 0; a[2] = 1;
|
||||||
b = a.dup;
|
b = a.dup;
|
||||||
assert(b.length == 3);
|
assert(b.length == 3);
|
||||||
for (i = 0; i < 3; i++)
|
foreach (i; 0 .. 3)
|
||||||
{ debug(bitarray) printf("b[%d] = %d\n", i, b[i]);
|
|
||||||
assert(b[i] == (((i ^ 1) & 1) ? true : false));
|
assert(b[i] == (((i ^ 1) & 1) ? true : false));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************
|
/**********************************************
|
||||||
* Support for `foreach` loops for `BitArray`.
|
* Support for `foreach` loops for `BitArray`.
|
||||||
|
@ -1434,11 +1478,10 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opApply unittest\n");
|
bool[] ba = [1,0,1];
|
||||||
|
|
||||||
static bool[] ba = [1,0,1];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
|
|
||||||
|
@ -1495,21 +1538,17 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.reverse.unittest\n");
|
|
||||||
|
|
||||||
BitArray b;
|
BitArray b;
|
||||||
static bool[5] data = [1,0,1,1,0];
|
bool[5] data = [1,0,1,1,0];
|
||||||
int i;
|
|
||||||
|
|
||||||
b = BitArray(data);
|
b = BitArray(data);
|
||||||
b.reverse;
|
b.reverse;
|
||||||
for (i = 0; i < data.length; i++)
|
foreach (i; 0 .. data.length)
|
||||||
{
|
|
||||||
assert(b[i] == data[4 - i]);
|
assert(b[i] == data[4 - i]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************
|
/**********************************************
|
||||||
|
@ -1559,16 +1598,15 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.sort.unittest\n");
|
size_t x = 0b1100011000;
|
||||||
|
auto ba = BitArray(10, &x);
|
||||||
__gshared size_t x = 0b1100011000;
|
|
||||||
__gshared ba = BitArray(10, &x);
|
|
||||||
ba.sort;
|
ba.sort;
|
||||||
for (size_t i = 0; i < 6; i++)
|
foreach (i; 0 .. 6)
|
||||||
assert(ba[i] == false);
|
assert(ba[i] == false);
|
||||||
for (size_t i = 6; i < 10; i++)
|
foreach (i; 6 .. 10)
|
||||||
assert(ba[i] == true);
|
assert(ba[i] == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1593,17 +1631,16 @@ public:
|
||||||
return (p1[i] & endMask) == (p2[i] & endMask);
|
return (p1[i] & endMask) == (p2[i] & endMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opEquals unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
bool[] bb = [1,0,1];
|
||||||
static bool[] ba = [1,0,1,0,1];
|
bool[] bc = [1,0,1,0,1,0,1];
|
||||||
static bool[] bb = [1,0,1];
|
bool[] bd = [1,0,1,1,1];
|
||||||
static bool[] bc = [1,0,1,0,1,0,1];
|
bool[] be = [1,0,1,0,1];
|
||||||
static bool[] bd = [1,0,1,1,1];
|
bool[] bf = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
|
||||||
static bool[] be = [1,0,1,0,1];
|
bool[] bg = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1];
|
||||||
static bool[] bf = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
|
|
||||||
static bool[] bg = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -1659,17 +1696,16 @@ public:
|
||||||
return (this.length > a2.length) - (this.length < a2.length);
|
return (this.length > a2.length) - (this.length < a2.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opCmp unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
bool[] bb = [1,0,1];
|
||||||
static bool[] ba = [1,0,1,0,1];
|
bool[] bc = [1,0,1,0,1,0,1];
|
||||||
static bool[] bb = [1,0,1];
|
bool[] bd = [1,0,1,1,1];
|
||||||
static bool[] bc = [1,0,1,0,1,0,1];
|
bool[] be = [1,0,1,0,1];
|
||||||
static bool[] bd = [1,0,1,1,1];
|
bool[] bf = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1];
|
||||||
static bool[] be = [1,0,1,0,1];
|
bool[] bg = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0];
|
||||||
static bool[] bf = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1];
|
|
||||||
static bool[] bg = [1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -1690,7 +1726,10 @@ public:
|
||||||
assert(a >= e);
|
assert(a >= e);
|
||||||
assert(f < g);
|
assert(f < g);
|
||||||
assert(g <= g);
|
assert(g <= g);
|
||||||
|
}
|
||||||
|
|
||||||
|
@system unittest
|
||||||
|
{
|
||||||
bool[] v;
|
bool[] v;
|
||||||
foreach (i; 1 .. 256)
|
foreach (i; 1 .. 256)
|
||||||
{
|
{
|
||||||
|
@ -1757,16 +1796,17 @@ public:
|
||||||
return _ptr[0 .. dim];
|
return _ptr[0 .. dim];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opCast unittest\n");
|
import std.array : array;
|
||||||
|
import std.range : repeat, take;
|
||||||
|
|
||||||
static bool[] ba = [1,0,1,0,1];
|
// bit array with 300 elements
|
||||||
|
auto a = BitArray(true.repeat.take(300).array);
|
||||||
auto a = BitArray(ba);
|
size_t[] v = cast(size_t[]) a;
|
||||||
void[] v = cast(void[]) a;
|
const blockSize = size_t.sizeof * 8;
|
||||||
|
assert(v.length == (a.length + blockSize - 1) / blockSize);
|
||||||
assert(v.length == a.dim * size_t.sizeof);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
|
@ -1789,11 +1829,10 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opCom unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
|
||||||
static bool[] ba = [1,0,1,0,1];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
BitArray b = ~a;
|
BitArray b = ~a;
|
||||||
|
@ -1835,10 +1874,9 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opAnd unittest\n");
|
|
||||||
|
|
||||||
static bool[] ba = [1,0,1,0,1];
|
static bool[] ba = [1,0,1,0,1];
|
||||||
static bool[] bb = [1,0,1,1,0];
|
static bool[] bb = [1,0,1,1,0];
|
||||||
|
|
||||||
|
@ -1854,12 +1892,11 @@ public:
|
||||||
assert(c[4] == 0);
|
assert(c[4] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opOr unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
bool[] bb = [1,0,1,1,0];
|
||||||
static bool[] ba = [1,0,1,0,1];
|
|
||||||
static bool[] bb = [1,0,1,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -1873,12 +1910,11 @@ public:
|
||||||
assert(c[4] == 1);
|
assert(c[4] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opXor unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
bool[] bb = [1,0,1,1,0];
|
||||||
static bool[] ba = [1,0,1,0,1];
|
|
||||||
static bool[] bb = [1,0,1,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -1892,12 +1928,11 @@ public:
|
||||||
assert(c[4] == 1);
|
assert(c[4] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opSub unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
bool[] bb = [1,0,1,1,0];
|
||||||
static bool[] ba = [1,0,1,0,1];
|
|
||||||
static bool[] bb = [1,0,1,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -1944,10 +1979,11 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
static bool[] ba = [1,0,1,0,1,1,0,1,0,1];
|
bool[] ba = [1,0,1,0,1,1,0,1,0,1];
|
||||||
static bool[] bb = [1,0,1,1,0];
|
bool[] bb = [1,0,1,1,0];
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
BitArray c = a;
|
BitArray c = a;
|
||||||
|
@ -1960,12 +1996,11 @@ public:
|
||||||
assert(a[9] == 1);
|
assert(a[9] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opAndAssign unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
bool[] bb = [1,0,1,1,0];
|
||||||
static bool[] ba = [1,0,1,0,1];
|
|
||||||
static bool[] bb = [1,0,1,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -1978,12 +2013,11 @@ public:
|
||||||
assert(a[4] == 0);
|
assert(a[4] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opOrAssign unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
bool[] bb = [1,0,1,1,0];
|
||||||
static bool[] ba = [1,0,1,0,1];
|
|
||||||
static bool[] bb = [1,0,1,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -1996,12 +2030,11 @@ public:
|
||||||
assert(a[4] == 1);
|
assert(a[4] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opXorAssign unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
bool[] bb = [1,0,1,1,0];
|
||||||
static bool[] ba = [1,0,1,0,1];
|
|
||||||
static bool[] bb = [1,0,1,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -2014,12 +2047,11 @@ public:
|
||||||
assert(a[4] == 1);
|
assert(a[4] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opSubAssign unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
bool[] bb = [1,0,1,1,0];
|
||||||
static bool[] ba = [1,0,1,0,1];
|
|
||||||
static bool[] bb = [1,0,1,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -2047,11 +2079,10 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opCatAssign unittest\n");
|
bool[] ba = [1,0,1,0,1];
|
||||||
|
|
||||||
static bool[] ba = [1,0,1,0,1];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
BitArray b;
|
BitArray b;
|
||||||
|
@ -2080,12 +2111,11 @@ public:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opCatAssign unittest\n");
|
bool[] ba = [1,0];
|
||||||
|
bool[] bb = [0,1,0];
|
||||||
static bool[] ba = [1,0];
|
|
||||||
static bool[] bb = [0,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -2137,12 +2167,11 @@ public:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
debug(bitarray) printf("BitArray.opCat unittest\n");
|
bool[] ba = [1,0];
|
||||||
|
bool[] bb = [0,1,0];
|
||||||
static bool[] ba = [1,0];
|
|
||||||
static bool[] bb = [0,1,0];
|
|
||||||
|
|
||||||
auto a = BitArray(ba);
|
auto a = BitArray(ba);
|
||||||
auto b = BitArray(bb);
|
auto b = BitArray(bb);
|
||||||
|
@ -2371,6 +2400,7 @@ public:
|
||||||
assert(c.bitsSet.equal(iota(0, 2 * r - 10)));
|
assert(c.bitsSet.equal(iota(0, 2 * r - 10)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
import std.format : format;
|
import std.format : format;
|
||||||
|
@ -2502,7 +2532,6 @@ public:
|
||||||
{
|
{
|
||||||
import std.format : format;
|
import std.format : format;
|
||||||
|
|
||||||
debug(bitarray) printf("BitArray.toString unittest\n");
|
|
||||||
auto b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
|
auto b = BitArray([0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1]);
|
||||||
|
|
||||||
auto s1 = format("%s", b);
|
auto s1 = format("%s", b);
|
||||||
|
@ -2547,7 +2576,6 @@ public:
|
||||||
import std.algorithm.comparison : equal;
|
import std.algorithm.comparison : equal;
|
||||||
import std.range : iota;
|
import std.range : iota;
|
||||||
|
|
||||||
debug(bitarray) printf("BitArray.bitsSet unittest\n");
|
|
||||||
BitArray b;
|
BitArray b;
|
||||||
enum wordBits = size_t.sizeof * 8;
|
enum wordBits = size_t.sizeof * 8;
|
||||||
b = BitArray([size_t.max], 0);
|
b = BitArray([size_t.max], 0);
|
||||||
|
@ -2651,6 +2679,7 @@ public:
|
||||||
assert(format("%b", b) == "1_00001111_00001111");
|
assert(format("%b", b) == "1_00001111_00001111");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
import std.format : format;
|
import std.format : format;
|
||||||
|
@ -3319,6 +3348,17 @@ if (canSwapEndianness!T &&
|
||||||
assert(index == 7);
|
assert(index == 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.algorithm.iteration : filter;
|
||||||
|
ubyte[] buffer = [1, 5, 22, 9, 44, 255, 7];
|
||||||
|
auto range = filter!"true"(buffer);
|
||||||
|
assert(range.peek!uint() == 17110537);
|
||||||
|
assert(range.peek!ushort() == 261);
|
||||||
|
assert(range.peek!ubyte() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -3520,17 +3560,6 @@ if (canSwapEndianness!T &&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
import std.algorithm.iteration : filter;
|
|
||||||
ubyte[] buffer = [1, 5, 22, 9, 44, 255, 7];
|
|
||||||
auto range = filter!"true"(buffer);
|
|
||||||
assert(range.peek!uint() == 17110537);
|
|
||||||
assert(range.peek!ushort() == 261);
|
|
||||||
assert(range.peek!ubyte() == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
|
Takes a range of `ubyte`s and converts the first `T.sizeof` bytes to
|
||||||
`T`. The value returned is converted from the given endianness to the
|
`T`. The value returned is converted from the given endianness to the
|
||||||
|
@ -3757,23 +3786,6 @@ if (canSwapEndianness!T && isInputRange!R && is(ElementType!R : const ubyte))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
import std.algorithm.iteration : filter;
|
|
||||||
ubyte[] buffer = [1, 5, 22, 9, 44, 255, 8];
|
|
||||||
auto range = filter!"true"(buffer);
|
|
||||||
assert(walkLength(range) == 7);
|
|
||||||
|
|
||||||
assert(range.read!ushort() == 261);
|
|
||||||
assert(walkLength(range) == 5);
|
|
||||||
|
|
||||||
assert(range.read!uint() == 369700095);
|
|
||||||
assert(walkLength(range) == 1);
|
|
||||||
|
|
||||||
assert(range.read!ubyte() == 8);
|
|
||||||
assert(range.empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
// issue 17247
|
// issue 17247
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
|
@ -3846,7 +3858,6 @@ if (canSwapEndianness!T &&
|
||||||
///
|
///
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
{
|
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
buffer.write!uint(29110231u, 0);
|
buffer.write!uint(29110231u, 0);
|
||||||
assert(buffer == [1, 188, 47, 215, 0, 0, 0, 0]);
|
assert(buffer == [1, 188, 47, 215, 0, 0, 0, 0]);
|
||||||
|
@ -3856,9 +3867,11 @@ if (canSwapEndianness!T &&
|
||||||
|
|
||||||
buffer.write!ubyte(42, 0);
|
buffer.write!ubyte(42, 0);
|
||||||
assert(buffer == [42, 159, 47, 215, 0, 0, 0, 0]);
|
assert(buffer == [42, 159, 47, 215, 0, 0, 0, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
///
|
||||||
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
buffer.write!uint(142700095u, 2);
|
buffer.write!uint(142700095u, 2);
|
||||||
assert(buffer == [0, 0, 8, 129, 110, 63, 0, 0, 0]);
|
assert(buffer == [0, 0, 8, 129, 110, 63, 0, 0, 0]);
|
||||||
|
@ -3868,9 +3881,11 @@ if (canSwapEndianness!T &&
|
||||||
|
|
||||||
buffer.write!ubyte(132, 2);
|
buffer.write!ubyte(132, 2);
|
||||||
assert(buffer == [0, 0, 132, 127, 110, 63, 0, 0, 0]);
|
assert(buffer == [0, 0, 132, 127, 110, 63, 0, 0, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
///
|
||||||
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
buffer.write!ushort(261, &index);
|
buffer.write!ushort(261, &index);
|
||||||
|
@ -3884,15 +3899,12 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!ubyte(8, &index);
|
buffer.write!ubyte(8, &index);
|
||||||
assert(buffer == [1, 5, 22, 9, 44, 255, 8, 0]);
|
assert(buffer == [1, 5, 22, 9, 44, 255, 8, 0]);
|
||||||
assert(index == 7);
|
assert(index == 7);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// bool
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
{
|
|
||||||
//bool
|
|
||||||
ubyte[] buffer = [0, 0];
|
ubyte[] buffer = [0, 0];
|
||||||
|
|
||||||
buffer.write!bool(false, 0);
|
buffer.write!bool(false, 0);
|
||||||
assert(buffer == [0, 0]);
|
assert(buffer == [0, 0]);
|
||||||
|
|
||||||
|
@ -3913,10 +3925,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!bool(true, &index);
|
buffer.write!bool(true, &index);
|
||||||
assert(buffer == [0, 1]);
|
assert(buffer == [0, 1]);
|
||||||
assert(index == 2);
|
assert(index == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// char(8-bit)
|
||||||
//char (8bit)
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0];
|
ubyte[] buffer = [0, 0, 0];
|
||||||
|
|
||||||
buffer.write!char('a', 0);
|
buffer.write!char('a', 0);
|
||||||
|
@ -3937,10 +3950,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!char('c', &index);
|
buffer.write!char('c', &index);
|
||||||
assert(buffer == [97, 98, 99]);
|
assert(buffer == [97, 98, 99]);
|
||||||
assert(index == 3);
|
assert(index == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// wchar (16bit - 2x ubyte)
|
||||||
//wchar (16bit - 2x ubyte)
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0];
|
||||||
|
|
||||||
buffer.write!wchar('ą', 0);
|
buffer.write!wchar('ą', 0);
|
||||||
|
@ -3957,10 +3971,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!wchar('ą', &index);
|
buffer.write!wchar('ą', &index);
|
||||||
assert(buffer == [1, 7, 1, 5]);
|
assert(buffer == [1, 7, 1, 5]);
|
||||||
assert(index == 4);
|
assert(index == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// dchar (32bit - 4x ubyte)
|
||||||
//dchar (32bit - 4x ubyte)
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
|
||||||
buffer.write!dchar('ą', 0);
|
buffer.write!dchar('ą', 0);
|
||||||
|
@ -3977,10 +3992,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!dchar('ą', &index);
|
buffer.write!dchar('ą', &index);
|
||||||
assert(buffer == [0, 0, 1, 7, 0, 0, 1, 5]);
|
assert(buffer == [0, 0, 1, 7, 0, 0, 1, 5]);
|
||||||
assert(index == 8);
|
assert(index == 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// float (32bit - 4x ubyte)
|
||||||
//float (32bit - 4x ubyte)
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
|
||||||
buffer.write!float(32.0f, 0);
|
buffer.write!float(32.0f, 0);
|
||||||
|
@ -3997,10 +4013,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!float(32.0f, &index);
|
buffer.write!float(32.0f, &index);
|
||||||
assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
|
assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
|
||||||
assert(index == 8);
|
assert(index == 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// double (64bit - 8x ubyte)
|
||||||
//double (64bit - 8x ubyte)
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
|
||||||
buffer.write!double(32.0, 0);
|
buffer.write!double(32.0, 0);
|
||||||
|
@ -4017,10 +4034,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!double(32.0, &index);
|
buffer.write!double(32.0, &index);
|
||||||
assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
|
assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
|
||||||
assert(index == 16);
|
assert(index == 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// enum
|
||||||
//enum
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
|
||||||
enum Foo
|
enum Foo
|
||||||
|
@ -4051,10 +4069,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!Foo(Foo.two, &index);
|
buffer.write!Foo(Foo.two, &index);
|
||||||
assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 20]);
|
assert(buffer == [0, 0, 0, 30, 0, 0, 0, 10, 0, 0, 0, 20]);
|
||||||
assert(index == 12);
|
assert(index == 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// enum - bool
|
||||||
//enum - bool
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0];
|
ubyte[] buffer = [0, 0];
|
||||||
|
|
||||||
enum Bool: bool
|
enum Bool: bool
|
||||||
|
@ -4077,10 +4096,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!Bool(Bool.bfalse, &index);
|
buffer.write!Bool(Bool.bfalse, &index);
|
||||||
assert(buffer == [0, 0]);
|
assert(buffer == [0, 0]);
|
||||||
assert(index == 2);
|
assert(index == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// enum - float
|
||||||
//enum - float
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
|
||||||
enum Float: float
|
enum Float: float
|
||||||
|
@ -4103,10 +4123,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!Float(Float.one, &index);
|
buffer.write!Float(Float.one, &index);
|
||||||
assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
|
assert(buffer == [65, 200, 0, 0, 66, 0, 0, 0]);
|
||||||
assert(index == 8);
|
assert(index == 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// enum - double
|
||||||
//enum - double
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
|
||||||
enum Double: double
|
enum Double: double
|
||||||
|
@ -4129,10 +4150,11 @@ if (canSwapEndianness!T &&
|
||||||
buffer.write!Double(Double.one, &index);
|
buffer.write!Double(Double.one, &index);
|
||||||
assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
|
assert(buffer == [64, 57, 0, 0, 0, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
|
||||||
assert(index == 16);
|
assert(index == 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// enum - real
|
||||||
//enum - real
|
@system unittest
|
||||||
|
{
|
||||||
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
ubyte[] buffer = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
|
||||||
enum Real: real
|
enum Real: real
|
||||||
|
@ -4142,7 +4164,6 @@ if (canSwapEndianness!T &&
|
||||||
}
|
}
|
||||||
|
|
||||||
static assert(!__traits(compiles, buffer.write!Real(Real.one)));
|
static assert(!__traits(compiles, buffer.write!Real(Real.one)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4184,11 +4205,10 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte))
|
||||||
assert(buffer.data == [1, 5, 22, 9, 44, 255, 8]);
|
assert(buffer.data == [1, 5, 22, 9, 44, 255, 8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// bool
|
||||||
@safe unittest
|
@safe unittest
|
||||||
{
|
{
|
||||||
import std.array;
|
import std.array : appender;
|
||||||
{
|
|
||||||
//bool
|
|
||||||
auto buffer = appender!(const ubyte[])();
|
auto buffer = appender!(const ubyte[])();
|
||||||
|
|
||||||
buffer.append!bool(true);
|
buffer.append!bool(true);
|
||||||
|
@ -4196,10 +4216,12 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte))
|
||||||
|
|
||||||
buffer.append!bool(false);
|
buffer.append!bool(false);
|
||||||
assert(buffer.data == [1, 0]);
|
assert(buffer.data == [1, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// char wchar dchar
|
||||||
//char wchar dchar
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.array : appender;
|
||||||
auto buffer = appender!(const ubyte[])();
|
auto buffer = appender!(const ubyte[])();
|
||||||
|
|
||||||
buffer.append!char('a');
|
buffer.append!char('a');
|
||||||
|
@ -4213,10 +4235,12 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte))
|
||||||
|
|
||||||
buffer.append!dchar('ą');
|
buffer.append!dchar('ą');
|
||||||
assert(buffer.data == [97, 98, 1, 5, 0, 0, 1, 5]);
|
assert(buffer.data == [97, 98, 1, 5, 0, 0, 1, 5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// float double
|
||||||
//float double
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.array : appender;
|
||||||
auto buffer = appender!(const ubyte[])();
|
auto buffer = appender!(const ubyte[])();
|
||||||
|
|
||||||
buffer.append!float(32.0f);
|
buffer.append!float(32.0f);
|
||||||
|
@ -4224,10 +4248,12 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte))
|
||||||
|
|
||||||
buffer.append!double(32.0);
|
buffer.append!double(32.0);
|
||||||
assert(buffer.data == [66, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
|
assert(buffer.data == [66, 0, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// enum
|
||||||
//enum
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.array : appender;
|
||||||
auto buffer = appender!(const ubyte[])();
|
auto buffer = appender!(const ubyte[])();
|
||||||
|
|
||||||
enum Foo
|
enum Foo
|
||||||
|
@ -4245,10 +4271,12 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte))
|
||||||
|
|
||||||
buffer.append!Foo(Foo.three);
|
buffer.append!Foo(Foo.three);
|
||||||
assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
|
assert(buffer.data == [0, 0, 0, 10, 0, 0, 0, 20, 0, 0, 0, 30]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// enum - bool
|
||||||
//enum - bool
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.array : appender;
|
||||||
auto buffer = appender!(const ubyte[])();
|
auto buffer = appender!(const ubyte[])();
|
||||||
|
|
||||||
enum Bool: bool
|
enum Bool: bool
|
||||||
|
@ -4265,10 +4293,12 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte))
|
||||||
|
|
||||||
buffer.append!Bool(Bool.btrue);
|
buffer.append!Bool(Bool.btrue);
|
||||||
assert(buffer.data == [1, 0, 1]);
|
assert(buffer.data == [1, 0, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// enum - float
|
||||||
//enum - float
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.array : appender;
|
||||||
auto buffer = appender!(const ubyte[])();
|
auto buffer = appender!(const ubyte[])();
|
||||||
|
|
||||||
enum Float: float
|
enum Float: float
|
||||||
|
@ -4282,10 +4312,12 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte))
|
||||||
|
|
||||||
buffer.append!Float(Float.two);
|
buffer.append!Float(Float.two);
|
||||||
assert(buffer.data == [66, 0, 0, 0, 65, 200, 0, 0]);
|
assert(buffer.data == [66, 0, 0, 0, 65, 200, 0, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// enum - double
|
||||||
//enum - double
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.array : appender;
|
||||||
auto buffer = appender!(const ubyte[])();
|
auto buffer = appender!(const ubyte[])();
|
||||||
|
|
||||||
enum Double: double
|
enum Double: double
|
||||||
|
@ -4299,10 +4331,12 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte))
|
||||||
|
|
||||||
buffer.append!Double(Double.two);
|
buffer.append!Double(Double.two);
|
||||||
assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
|
assert(buffer.data == [64, 64, 0, 0, 0, 0, 0, 0, 64, 57, 0, 0, 0, 0, 0, 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
/// enum - real
|
||||||
//enum - real
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.array : appender;
|
||||||
auto buffer = appender!(const ubyte[])();
|
auto buffer = appender!(const ubyte[])();
|
||||||
|
|
||||||
enum Real: real
|
enum Real: real
|
||||||
|
@ -4312,7 +4346,6 @@ if (canSwapEndianness!T && isOutputRange!(R, ubyte))
|
||||||
}
|
}
|
||||||
|
|
||||||
static assert(!__traits(compiles, buffer.append!Real(Real.one)));
|
static assert(!__traits(compiles, buffer.append!Real(Real.one)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@system unittest
|
@system unittest
|
||||||
|
|
|
@ -907,3 +907,214 @@ struct CharMatcher {
|
||||||
return trie[ch];
|
return trie[ch];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal non-resizeble array, switches between inline storage and CoW
|
||||||
|
// POD-only
|
||||||
|
struct SmallFixedArray(T, uint SMALL=3)
|
||||||
|
if (!hasElaborateDestructor!T)
|
||||||
|
{
|
||||||
|
import core.stdc.stdlib : malloc, free;
|
||||||
|
static struct Payload
|
||||||
|
{
|
||||||
|
size_t refcount;
|
||||||
|
T[0] placeholder;
|
||||||
|
inout(T)* ptr() inout { return placeholder.ptr; }
|
||||||
|
}
|
||||||
|
static assert(Payload.sizeof == size_t.sizeof);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
Payload* big;
|
||||||
|
T[SMALL] small;
|
||||||
|
}
|
||||||
|
size_t _sizeMask;
|
||||||
|
enum BIG_MASK = size_t(1)<<(8*size_t.sizeof-1);
|
||||||
|
enum SIZE_MASK = ~BIG_MASK;
|
||||||
|
|
||||||
|
@property bool isBig() const { return (_sizeMask & BIG_MASK) != 0; }
|
||||||
|
@property size_t length() const { return _sizeMask & SIZE_MASK; }
|
||||||
|
|
||||||
|
this(size_t size)
|
||||||
|
{
|
||||||
|
if (size <= SMALL)
|
||||||
|
{
|
||||||
|
small[] = T.init;
|
||||||
|
_sizeMask = size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
big = cast(Payload*) enforce(malloc(Payload.sizeof + T.sizeof*size), "Failed to malloc storage");
|
||||||
|
big.refcount = 1;
|
||||||
|
_sizeMask = size | BIG_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private @trusted @property inout(T)[] internalSlice() inout
|
||||||
|
{
|
||||||
|
return isBig ? big.ptr[0 .. length] : small[0 .. length];
|
||||||
|
}
|
||||||
|
|
||||||
|
this(this)
|
||||||
|
{
|
||||||
|
if (isBig)
|
||||||
|
{
|
||||||
|
big.refcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool opEquals(SmallFixedArray a)
|
||||||
|
{
|
||||||
|
return internalSlice[] == a.internalSlice[];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t toHash()
|
||||||
|
{
|
||||||
|
return hashOf(internalSlice[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
T opIndex(size_t idx) inout
|
||||||
|
{
|
||||||
|
return internalSlice[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
// accesses big to test self-referencing so not @safe
|
||||||
|
@trusted ref opAssign(SmallFixedArray arr)
|
||||||
|
{
|
||||||
|
if (isBig)
|
||||||
|
{
|
||||||
|
if (arr.isBig)
|
||||||
|
{
|
||||||
|
if (big is arr.big) return this; // self-assign
|
||||||
|
else
|
||||||
|
{
|
||||||
|
abandonRef();
|
||||||
|
_sizeMask = arr._sizeMask;
|
||||||
|
big = arr.big;
|
||||||
|
big.refcount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
abandonRef();
|
||||||
|
_sizeMask = arr._sizeMask;
|
||||||
|
small = arr.small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (arr.isBig)
|
||||||
|
{
|
||||||
|
_sizeMask = arr._sizeMask;
|
||||||
|
big = arr.big;
|
||||||
|
big.refcount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sizeMask = arr._sizeMask;
|
||||||
|
small = arr.small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutate(scope void delegate(T[]) filler)
|
||||||
|
{
|
||||||
|
if (isBig && big.refcount != 1) // copy on write
|
||||||
|
{
|
||||||
|
auto oldSizeMask = _sizeMask;
|
||||||
|
auto newbig = cast(Payload*) enforce(malloc(Payload.sizeof + T.sizeof*length), "Failed to malloc storage");
|
||||||
|
newbig.refcount = 1;
|
||||||
|
abandonRef();
|
||||||
|
big = newbig;
|
||||||
|
_sizeMask = oldSizeMask;
|
||||||
|
}
|
||||||
|
filler(internalSlice);
|
||||||
|
}
|
||||||
|
|
||||||
|
~this()
|
||||||
|
{
|
||||||
|
if (isBig)
|
||||||
|
{
|
||||||
|
abandonRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@trusted private void abandonRef()
|
||||||
|
{
|
||||||
|
assert(isBig);
|
||||||
|
if (--big.refcount == 0)
|
||||||
|
{
|
||||||
|
free(big);
|
||||||
|
_sizeMask = 0;
|
||||||
|
assert(!isBig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@system unittest
|
||||||
|
{
|
||||||
|
alias SA = SmallFixedArray!(int, 2);
|
||||||
|
SA create(int[] data)
|
||||||
|
{
|
||||||
|
SA a = SA(data.length);
|
||||||
|
a.mutate((slice) { slice[] = data[]; });
|
||||||
|
assert(a.internalSlice == data);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SA a;
|
||||||
|
a = SA(1);
|
||||||
|
assert(a.length == 1);
|
||||||
|
a = SA.init;
|
||||||
|
assert(a.length == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SA a, b, c, d;
|
||||||
|
assert(a.length == 0);
|
||||||
|
assert(a.internalSlice == b.internalSlice);
|
||||||
|
a = create([1]);
|
||||||
|
assert(a.internalSlice == [1]);
|
||||||
|
b = create([2, 3]);
|
||||||
|
assert(b.internalSlice == [2, 3]);
|
||||||
|
c = create([3, 4, 5]);
|
||||||
|
d = create([5, 6, 7, 8]);
|
||||||
|
assert(c.isBig);
|
||||||
|
a = c;
|
||||||
|
assert(a.isBig);
|
||||||
|
assert(a.big is c.big);
|
||||||
|
assert(a.big.refcount == 2);
|
||||||
|
assert(a.internalSlice == [3, 4, 5]);
|
||||||
|
assert(c.internalSlice == [3, 4, 5]);
|
||||||
|
a = b;
|
||||||
|
assert(!a.isBig);
|
||||||
|
assert(a.internalSlice == [2, 3]);
|
||||||
|
assert(c.big.refcount == 1);
|
||||||
|
a = c;
|
||||||
|
assert(c.big.refcount == 2);
|
||||||
|
|
||||||
|
// mutate copies on write if ref-count is not 1
|
||||||
|
a.mutate((slice){ slice[] = 1; });
|
||||||
|
assert(a.internalSlice == [1, 1, 1]);
|
||||||
|
assert(c.internalSlice == [3, 4, 5]);
|
||||||
|
assert(a.isBig && c.isBig);
|
||||||
|
assert(a.big.refcount == 1);
|
||||||
|
assert(c.big.refcount == 1);
|
||||||
|
|
||||||
|
auto e = d;
|
||||||
|
assert(e.big.refcount == 2);
|
||||||
|
auto f = d;
|
||||||
|
f = a;
|
||||||
|
assert(f.isBig);
|
||||||
|
assert(f.internalSlice == [1, 1, 1]);
|
||||||
|
assert(f.big.refcount == 2); // a & f
|
||||||
|
assert(e.big.refcount == 2); // d & e
|
||||||
|
a = c;
|
||||||
|
assert(f.big.refcount == 1); // f
|
||||||
|
assert(e.big.refcount == 2); // d & e
|
||||||
|
a = a;
|
||||||
|
a = a;
|
||||||
|
a = a;
|
||||||
|
assert(a.big.refcount == 2); // a & c
|
||||||
|
}
|
||||||
|
}
|
|
@ -689,3 +689,13 @@ version(none) // TODO: revist once we have proper benchmark framework
|
||||||
assert(c);
|
assert(c);
|
||||||
assert(c.whichPattern == 2);
|
assert(c.whichPattern == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bugzilla 18692
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
auto rx = regex("()()()");
|
||||||
|
auto ma = "".matchFirst(rx);
|
||||||
|
auto ma2 = ma;
|
||||||
|
ma = ma2;
|
||||||
|
assert(ma[1] == "");
|
||||||
|
}
|
|
@ -484,26 +484,20 @@ if (isSomeString!R)
|
||||||
{//@trusted because of union inside
|
{//@trusted because of union inside
|
||||||
alias DataIndex = size_t;
|
alias DataIndex = size_t;
|
||||||
alias String = R;
|
alias String = R;
|
||||||
|
alias Store = SmallFixedArray!(Group!DataIndex, 3);
|
||||||
private:
|
private:
|
||||||
import std.conv : text;
|
import std.conv : text;
|
||||||
enum smallString = 3;
|
Store matches;
|
||||||
enum SMALL_MASK = 0x8000_0000, REF_MASK= 0x1FFF_FFFF;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
Group!DataIndex[] big_matches;
|
|
||||||
Group!DataIndex[smallString] small_matches;
|
|
||||||
}
|
|
||||||
const(NamedGroup)[] _names;
|
const(NamedGroup)[] _names;
|
||||||
R _input;
|
R _input;
|
||||||
int _nMatch;
|
int _nMatch;
|
||||||
uint _f, _b;
|
uint _f, _b;
|
||||||
uint _refcount; // ref count or SMALL MASK + num groups
|
|
||||||
|
|
||||||
this(R input, uint n, const(NamedGroup)[] named)
|
this(R input, uint n, const(NamedGroup)[] named)
|
||||||
{
|
{
|
||||||
_input = input;
|
_input = input;
|
||||||
_names = named;
|
_names = named;
|
||||||
newMatches(n);
|
matches = Store(n);
|
||||||
_b = n;
|
_b = n;
|
||||||
_f = 0;
|
_f = 0;
|
||||||
}
|
}
|
||||||
|
@ -513,60 +507,12 @@ private:
|
||||||
_input = rmatch._input;
|
_input = rmatch._input;
|
||||||
_names = rmatch._engine.pattern.dict;
|
_names = rmatch._engine.pattern.dict;
|
||||||
immutable n = rmatch._engine.pattern.ngroup;
|
immutable n = rmatch._engine.pattern.ngroup;
|
||||||
newMatches(n);
|
matches = Store(n);
|
||||||
_b = n;
|
_b = n;
|
||||||
_f = 0;
|
_f = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property inout(Group!DataIndex[]) matches() inout
|
|
||||||
{
|
|
||||||
return (_refcount & SMALL_MASK) ? small_matches[0 .. _refcount & 0xFF] : big_matches;
|
|
||||||
}
|
|
||||||
|
|
||||||
void newMatches(uint n)
|
|
||||||
{
|
|
||||||
import core.stdc.stdlib : calloc;
|
|
||||||
import std.exception : enforce;
|
|
||||||
if (n > smallString)
|
|
||||||
{
|
|
||||||
auto p = cast(Group!DataIndex*) enforce(
|
|
||||||
calloc(Group!DataIndex.sizeof,n),
|
|
||||||
"Failed to allocate Captures struct"
|
|
||||||
);
|
|
||||||
big_matches = p[0 .. n];
|
|
||||||
_refcount = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_refcount = SMALL_MASK | n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool unique()
|
|
||||||
{
|
|
||||||
return (_refcount & SMALL_MASK) || _refcount == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
this(this)
|
|
||||||
{
|
|
||||||
if (!(_refcount & SMALL_MASK))
|
|
||||||
{
|
|
||||||
_refcount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
import core.stdc.stdlib : free;
|
|
||||||
if (!(_refcount & SMALL_MASK))
|
|
||||||
{
|
|
||||||
if (--_refcount == 0)
|
|
||||||
{
|
|
||||||
free(big_matches.ptr);
|
|
||||||
big_matches = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
///Slice of input prior to the match.
|
///Slice of input prior to the match.
|
||||||
@property R pre()
|
@property R pre()
|
||||||
{
|
{
|
||||||
|
@ -681,18 +627,6 @@ public:
|
||||||
|
|
||||||
///A hook for compatibility with original std.regex.
|
///A hook for compatibility with original std.regex.
|
||||||
@property ref captures(){ return this; }
|
@property ref captures(){ return this; }
|
||||||
|
|
||||||
typeof(this) opAssign()(auto ref Captures rhs)
|
|
||||||
{
|
|
||||||
if (rhs._refcount & SMALL_MASK)
|
|
||||||
small_matches[0 .. rhs._refcount & 0xFF] = rhs.small_matches[0 .. rhs._refcount & 0xFF];
|
|
||||||
else
|
|
||||||
big_matches = rhs.big_matches;
|
|
||||||
assert(&this.tupleof[0] is &big_matches);
|
|
||||||
assert(&this.tupleof[1] is &small_matches);
|
|
||||||
this.tupleof[2 .. $] = rhs.tupleof[2 .. $];
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -750,7 +684,7 @@ private:
|
||||||
_engine = _factory.create(prog, input);
|
_engine = _factory.create(prog, input);
|
||||||
assert(_engine.refCount == 1);
|
assert(_engine.refCount == 1);
|
||||||
_captures = Captures!R(this);
|
_captures = Captures!R(this);
|
||||||
_captures._nMatch = _engine.match(_captures.matches);
|
_captures.matches.mutate((slice) { _captures._nMatch = _engine.match(slice); });
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -811,12 +745,7 @@ public:
|
||||||
_engine = _factory.dup(old, _input);
|
_engine = _factory.dup(old, _input);
|
||||||
_factory.decRef(old);
|
_factory.decRef(old);
|
||||||
}
|
}
|
||||||
if (!_captures.unique)
|
_captures.matches.mutate((slice) { _captures._nMatch = _engine.match(slice); });
|
||||||
{
|
|
||||||
// has external references - allocate new space
|
|
||||||
_captures.newMatches(_engine.pattern.ngroup);
|
|
||||||
}
|
|
||||||
_captures._nMatch = _engine.match(_captures.matches);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///ditto
|
///ditto
|
||||||
|
@ -858,7 +787,7 @@ private @trusted auto matchOnce(RegEx, R)(R input, const auto ref RegEx prog)
|
||||||
cacheKey = key;
|
cacheKey = key;
|
||||||
}
|
}
|
||||||
auto captures = Captures!R(input, prog.ngroup, prog.dict);
|
auto captures = Captures!R(input, prog.ngroup, prog.dict);
|
||||||
captures._nMatch = engine.match(captures.matches);
|
captures.matches.mutate((slice){ captures._nMatch = engine.match(slice); });
|
||||||
return captures;
|
return captures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue