Replace tuples with custom types
This commit is contained in:
parent
5453c646f6
commit
90797a48be
@ -5,7 +5,7 @@
|
|||||||
/*
|
/*
|
||||||
* Internal package used by containers that rely on entries/nodes.
|
* Internal package used by containers that rely on entries/nodes.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2016-2020.
|
* Copyright: Eugene Wissner 2016-2022.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -19,7 +19,6 @@ import tanya.memory.allocator;
|
|||||||
import tanya.memory.lifetime;
|
import tanya.memory.lifetime;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.meta.transform;
|
import tanya.meta.transform;
|
||||||
import tanya.typecons;
|
|
||||||
|
|
||||||
package struct SEntry(T)
|
package struct SEntry(T)
|
||||||
{
|
{
|
||||||
@ -54,7 +53,11 @@ package struct Bucket(K, V = void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alias KV = Tuple!(K, "key", V, "value");
|
package struct KV
|
||||||
|
{
|
||||||
|
package K key;
|
||||||
|
package V value;
|
||||||
|
}
|
||||||
KV kv;
|
KV kv;
|
||||||
}
|
}
|
||||||
BucketStatus status = BucketStatus.empty;
|
BucketStatus status = BucketStatus.empty;
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
*
|
*
|
||||||
* More advanced formatting is currently not implemented.
|
* More advanced formatting is currently not implemented.
|
||||||
*
|
*
|
||||||
* Copyright: Eugene Wissner 2017-2020.
|
* Copyright: Eugene Wissner 2017-2022.
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
||||||
* Mozilla Public License, v. 2.0).
|
* Mozilla Public License, v. 2.0).
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
||||||
@ -56,7 +56,6 @@ import tanya.meta.metafunction;
|
|||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
import tanya.meta.transform;
|
import tanya.meta.transform;
|
||||||
import tanya.range;
|
import tanya.range;
|
||||||
import tanya.typecons : Tuple;
|
|
||||||
|
|
||||||
// Returns the last part of buffer with converted number.
|
// Returns the last part of buffer with converted number.
|
||||||
package(tanya) char[] integral2String(T)(T number, return ref char[21] buffer)
|
package(tanya) char[] integral2String(T)(T number, return ref char[21] buffer)
|
||||||
@ -940,6 +939,12 @@ private struct uint128
|
|||||||
{
|
{
|
||||||
ulong[2] data;
|
ulong[2] data;
|
||||||
|
|
||||||
|
private struct DivMod
|
||||||
|
{
|
||||||
|
uint128 quotient;
|
||||||
|
uint128 remainder;
|
||||||
|
}
|
||||||
|
|
||||||
this(ulong upper, ulong lower) @nogc nothrow pure @safe
|
this(ulong upper, ulong lower) @nogc nothrow pure @safe
|
||||||
{
|
{
|
||||||
this.data[0] = upper;
|
this.data[0] = upper;
|
||||||
@ -1174,7 +1179,7 @@ private struct uint128
|
|||||||
return this.data[1];
|
return this.data[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple!(uint128, uint128) divMod(ulong rhs) const @nogc nothrow pure @safe
|
DivMod divMod(ulong rhs) const @nogc nothrow pure @safe
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
assert(rhs != uint128(), "Division by 0");
|
assert(rhs != uint128(), "Division by 0");
|
||||||
@ -1197,22 +1202,22 @@ private struct uint128
|
|||||||
typeof(return) result;
|
typeof(return) result;
|
||||||
for (ubyte x = this.bits; x > 0; --x)
|
for (ubyte x = this.bits; x > 0; --x)
|
||||||
{
|
{
|
||||||
result[0] = result[0] << 1;
|
result.quotient = result.quotient << 1;
|
||||||
result[1] = result[1] << 1;
|
result.remainder = result.remainder << 1;
|
||||||
|
|
||||||
if ((this >> (x - 1U)) & 1)
|
if ((this >> (x - 1U)) & 1)
|
||||||
{
|
{
|
||||||
++result[1];
|
++result.remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result[1] >= rhs)
|
if (result.remainder >= rhs)
|
||||||
{
|
{
|
||||||
if (result[1].data[1] < rhs)
|
if (result.remainder.data[1] < rhs)
|
||||||
{
|
{
|
||||||
--result[1].data[0];
|
--result.remainder.data[0];
|
||||||
}
|
}
|
||||||
result[1].data[1] -= rhs;
|
result.remainder.data[1] -= rhs;
|
||||||
++result[0];
|
++result.quotient;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -1220,12 +1225,12 @@ private struct uint128
|
|||||||
|
|
||||||
uint128 opBinary(string op : "/")(ulong rhs)
|
uint128 opBinary(string op : "/")(ulong rhs)
|
||||||
{
|
{
|
||||||
return divMod(rhs)[0];
|
return divMod(rhs).quotient;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint128 opBinary(string op : "%")(ulong rhs) const
|
uint128 opBinary(string op : "%")(ulong rhs) const
|
||||||
{
|
{
|
||||||
return divMod(rhs)[1];
|
return divMod(rhs).remainder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1302,12 +1307,12 @@ do
|
|||||||
enum ulong power19 = cast(ulong) 1e19;
|
enum ulong power19 = cast(ulong) 1e19;
|
||||||
|
|
||||||
auto qr = leftBoundary.divMod(power19);
|
auto qr = leftBoundary.divMod(power19);
|
||||||
auto low = cast(ulong) qr[1];
|
auto low = cast(ulong) qr.remainder;
|
||||||
const lowFactor = cast(ulong) (qr[0] % power19);
|
const lowFactor = cast(ulong) (qr.quotient % power19);
|
||||||
|
|
||||||
qr = rightBoundary.divMod(power19);
|
qr = rightBoundary.divMod(power19);
|
||||||
auto high = cast(ulong) qr[1];
|
auto high = cast(ulong) qr.remainder;
|
||||||
const highFactor = cast(ulong) (qr[0] % power19);
|
const highFactor = cast(ulong) (qr.quotient % power19);
|
||||||
size_t digitIndex;
|
size_t digitIndex;
|
||||||
|
|
||||||
if (lowFactor != highFactor)
|
if (lowFactor != highFactor)
|
||||||
|
@ -16,7 +16,6 @@ module tanya.math.random;
|
|||||||
|
|
||||||
import std.typecons;
|
import std.typecons;
|
||||||
import tanya.memory.allocator;
|
import tanya.memory.allocator;
|
||||||
import tanya.typecons;
|
|
||||||
|
|
||||||
/// Maximum amount gathered from the entropy sources.
|
/// Maximum amount gathered from the entropy sources.
|
||||||
enum maxGather = 128;
|
enum maxGather = 128;
|
||||||
|
@ -1,154 +0,0 @@
|
|||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type constructors.
|
|
||||||
*
|
|
||||||
* This module contains templates that allow to build new types from the
|
|
||||||
* available ones.
|
|
||||||
*
|
|
||||||
* Copyright: Eugene Wissner 2017-2020.
|
|
||||||
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
|
|
||||||
* Mozilla Public License, v. 2.0).
|
|
||||||
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
|
|
||||||
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/typecons.d,
|
|
||||||
* tanya/typecons.d)
|
|
||||||
*/
|
|
||||||
module tanya.typecons;
|
|
||||||
|
|
||||||
import tanya.format;
|
|
||||||
import tanya.memory.lifetime;
|
|
||||||
import tanya.meta.metafunction;
|
|
||||||
import tanya.meta.trait;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* $(D_PSYMBOL Tuple) can store two or more heterogeneous objects.
|
|
||||||
*
|
|
||||||
* The objects can by accessed by index as `obj[0]` and `obj[1]` or by optional
|
|
||||||
* names (e.g. `obj.first`).
|
|
||||||
*
|
|
||||||
* $(D_PARAM Specs) contains a list of object types and names. First
|
|
||||||
* comes the object type, then an optional string containing the name.
|
|
||||||
* If you want the object be accessible only by its index (`0` or `1`),
|
|
||||||
* just skip the name.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* Specs = Field types and names.
|
|
||||||
*
|
|
||||||
* See_Also: $(D_PSYMBOL tuple).
|
|
||||||
*/
|
|
||||||
template Tuple(Specs...)
|
|
||||||
{
|
|
||||||
template parseSpecs(size_t fieldCount, Specs...)
|
|
||||||
{
|
|
||||||
static if (Specs.length == 0)
|
|
||||||
{
|
|
||||||
alias parseSpecs = AliasSeq!();
|
|
||||||
}
|
|
||||||
else static if (is(Specs[0]) && fieldCount < 2)
|
|
||||||
{
|
|
||||||
static if (is(typeof(Specs[1]) == string))
|
|
||||||
{
|
|
||||||
alias parseSpecs
|
|
||||||
= AliasSeq!(Pack!(Specs[0], Specs[1]),
|
|
||||||
parseSpecs!(fieldCount + 1, Specs[2 .. $]));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alias parseSpecs
|
|
||||||
= AliasSeq!(Pack!(Specs[0]),
|
|
||||||
parseSpecs!(fieldCount + 1, Specs[1 .. $]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static assert(false, "Invalid argument: " ~ Specs[0].stringof);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
alias ChooseType(alias T) = T.Seq[0];
|
|
||||||
alias ParsedSpecs = parseSpecs!(0, Specs);
|
|
||||||
|
|
||||||
static assert(ParsedSpecs.length > 1, "Invalid argument count");
|
|
||||||
|
|
||||||
private string formatAliases(size_t n, Specs...)()
|
|
||||||
{
|
|
||||||
static if (Specs.length == 0)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string fieldAlias;
|
|
||||||
static if (Specs[0].length == 2)
|
|
||||||
{
|
|
||||||
char[21] buffer;
|
|
||||||
fieldAlias = "alias " ~ Specs[0][1] ~ " = expand["
|
|
||||||
~ integral2String(n, buffer).idup ~ "];";
|
|
||||||
}
|
|
||||||
return fieldAlias ~ formatAliases!(n + 1, Specs[1 .. $])();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Tuple
|
|
||||||
{
|
|
||||||
/// Field types.
|
|
||||||
alias Types = Map!(ChooseType, ParsedSpecs);
|
|
||||||
|
|
||||||
// Create field aliases.
|
|
||||||
mixin(formatAliases!(0, ParsedSpecs[0 .. $])());
|
|
||||||
|
|
||||||
/// Represents the values of the $(D_PSYMBOL Tuple) as a list of values.
|
|
||||||
Types expand;
|
|
||||||
|
|
||||||
alias expand this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
auto pair = Tuple!(int, "first", string, "second")(1, "second");
|
|
||||||
assert(pair.first == 1);
|
|
||||||
assert(pair[0] == 1);
|
|
||||||
assert(pair.second == "second");
|
|
||||||
assert(pair[1] == "second");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new $(D_PSYMBOL Tuple).
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* Names = Field names.
|
|
||||||
*
|
|
||||||
* See_Also: $(D_PSYMBOL Tuple).
|
|
||||||
*/
|
|
||||||
template tuple(Names...)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates a new $(D_PSYMBOL Tuple).
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* Args = Field types.
|
|
||||||
* args = Field values.
|
|
||||||
*
|
|
||||||
* Returns: Newly created $(D_PSYMBOL Tuple).
|
|
||||||
*/
|
|
||||||
auto tuple(Args...)(auto ref Args args)
|
|
||||||
if (Args.length >= Names.length && isTypeTuple!Args)
|
|
||||||
{
|
|
||||||
alias Zipped = ZipWith!(AliasSeq, Pack!Args, Pack!Names);
|
|
||||||
alias Nameless = Args[Names.length .. $];
|
|
||||||
|
|
||||||
return Tuple!(Zipped, Nameless)(forward!args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
auto t = tuple!("one", "two")(20, 5);
|
|
||||||
assert(t.one == 20);
|
|
||||||
assert(t.two == 5);
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
module tanya.tests.typecons;
|
|
||||||
|
|
||||||
import tanya.test.stub;
|
|
||||||
import tanya.typecons;
|
|
||||||
|
|
||||||
@nogc nothrow pure @safe unittest
|
|
||||||
{
|
|
||||||
static assert(is(Tuple!(int, int)));
|
|
||||||
static assert(!is(Tuple!(int, 5)));
|
|
||||||
|
|
||||||
static assert(is(Tuple!(int, "first", int)));
|
|
||||||
static assert(is(Tuple!(int, "first", int, "second")));
|
|
||||||
static assert(is(Tuple!(int, "first", int)));
|
|
||||||
|
|
||||||
static assert(is(Tuple!(int, int, "second")));
|
|
||||||
static assert(!is(Tuple!("first", int, "second", int)));
|
|
||||||
static assert(!is(Tuple!(int, int, int)));
|
|
||||||
|
|
||||||
static assert(!is(Tuple!(int, "first")));
|
|
||||||
|
|
||||||
static assert(!is(Tuple!(int, double, char)));
|
|
||||||
static assert(!is(Tuple!(int, "first", double, "second", char, "third")));
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user