diff --git a/source/tanya/format/conv.d b/source/tanya/format/conv.d index 82bcada..77b84e3 100644 --- a/source/tanya/format/conv.d +++ b/source/tanya/format/conv.d @@ -8,7 +8,7 @@ * Copyright: Eugene Wissner 2017. * 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) + * Authors: Jeff Roberts, $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/format/conv.d, * tanya/format/conv.d) */ @@ -611,13 +611,13 @@ private @nogc unittest defaultAllocator.dispose(exception); } -package char[] number2String(T)(const T number, char[] buffer) +// Returns the last part of buffer with converted number. +package char[] number2String(T)(const T number, out char[20] buffer) { // abs the integer. ulong n64 = number < 0 ? -cast(long) number : number; - char[20] rightAligned; - char* start = rightAligned.ptr + rightAligned.sizeof; + char* start = buffer.ptr + buffer.sizeof; while (true) { @@ -644,8 +644,7 @@ package char[] number2String(T)(const T number, char[] buffer) // Ignore the leading zero if it was the last part of the integer. if (n64 == 0) { - if ((start[0] == '0') - && (start != (rightAligned.ptr + rightAligned.sizeof))) + if ((start[0] == '0') && (start != (buffer.ptr + buffer.sizeof))) { ++start; } @@ -659,34 +658,25 @@ package char[] number2String(T)(const T number, char[] buffer) } } - // Get the length that we copied. - auto l = cast(uint) ((rightAligned.ptr + rightAligned.sizeof) - start); + // Get the length that we have copied. + uint l = cast(uint) ((buffer.ptr + buffer.sizeof) - start); if (l == 0) { *--start = '0'; l = 1; } - - // Write the string. - char* bp = buffer.ptr; - - // Set the sign. - if (number < 0) + else if (number < 0) // Set the sign. { - *bp++ = '-'; + *--start = '-'; + ++l; } - // Copy the string into the target buffer. - int i = l; - copy(start[0 .. l], bp[0 .. l]); - bp += l; - - return buffer[0 .. bp - buffer.ptr]; + return buffer[$ - l .. $]; } -private @nogc unittest +private pure nothrow @system @nogc unittest { - char[21] buf; + char[20] buf; assert(number2String(80, buf) == "80"); assert(number2String(-80, buf) == "-80"); diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d index c79ecea..98fb9bc 100644 --- a/source/tanya/math/mp.d +++ b/source/tanya/math/mp.d @@ -17,9 +17,10 @@ module tanya.math.mp; import std.algorithm; import std.ascii; import std.range; -import std.traits; import tanya.container.array; import tanya.memory; +import tanya.meta.trait; +import tanya.meta.transform; /** * Algebraic sign. diff --git a/source/tanya/math/package.d b/source/tanya/math/package.d index a7a0a3b..24dc2b0 100644 --- a/source/tanya/math/package.d +++ b/source/tanya/math/package.d @@ -14,9 +14,9 @@ */ module tanya.math; -import std.traits; public import tanya.math.mp; public import tanya.math.random; +import tanya.meta.trait; version (unittest) { diff --git a/source/tanya/meta/metafunction.d b/source/tanya/meta/metafunction.d index 0466a12..37926a3 100644 --- a/source/tanya/meta/metafunction.d +++ b/source/tanya/meta/metafunction.d @@ -15,13 +15,9 @@ */ module tanya.meta.metafunction; +import tanya.meta.trait; import tanya.meta.transform; -version (unittest) -{ - import tanya.meta.trait; -} - /** * Tests whether $(D_INLINECODE Args[0]) is less than or equal to * $(D_INLINECODE Args[1]) according to $(D_PARAM cmp). diff --git a/source/tanya/meta/trait.d b/source/tanya/meta/trait.d index 7bb79e1..39acff0 100644 --- a/source/tanya/meta/trait.d +++ b/source/tanya/meta/trait.d @@ -1738,9 +1738,7 @@ pure nothrow @safe @nogc unittest } static assert(isInstanceOf!(S, S!int)); - static void func(T)() - { - } + static void func(T)(); static assert(isInstanceOf!(func, func!int)); template T(U) @@ -2055,3 +2053,269 @@ pure nothrow @safe @nogc unittest static assert(isAssignable!int); static assert(!isAssignable!(const int, int)); } + +/** + * Returns template parameters of $(D_PARAM T). + * + * Params: + * T = Template instance. + * + * Returns: Template parameters of $(D_PARAM T). + */ +alias TemplateArgsOf(alias T : Base!Args, alias Base, Args...) = Args; + +/// +pure nothrow @safe @nogc unittest +{ + template T(A, B) + { + } + static assert(is(TemplateArgsOf!(T!(int, uint)) == AliasSeq!(int, uint))); +} + +/** + * Returns a tuple with parameter types of a function. + * + * Params: + * F = A function. + * + * Returns: Tuple with parameter types of a function. + */ +template Parameters(F...) +if (isCallable!F) +{ + static if (is(FunctionTypeOf!F T == function)) + { + alias Parameters = T; + } + else + { + static assert(false, "Function has no parameters"); + } +} + +/// +pure nothrow @safe @nogc unittest +{ + int func(Object, uint[]); + static assert(is(Parameters!func == AliasSeq!(Object, uint[]))); +} + +/** + * Returns a string array with all parameter names of a function. + * + * If a parameter has no name, an empty string is placed into array. + * + * Params: + * F = A function. + * + * Returns: Function parameter names. + */ +template ParameterIdentifierTuple(F...) +if (isCallable!F) +{ + static if (is(FunctionTypeOf!F Params == __parameters)) + { + enum string[] Impl() + { + string[] tuple; + + foreach (k, P; Params) + { + static if (is(typeof(__traits(identifier, Params[k .. $])))) + { + tuple ~= __traits(identifier, Params[k .. $]); + } + else + { + tuple ~= ""; + } + } + + return tuple; + } + enum string[] ParameterIdentifierTuple = Impl(); + } + else + { + static assert(false, "Function has no parameters"); + } +} + +/// +pure nothrow @safe @nogc unittest +{ + int func(ref Object stuff, uint[] = null, scope uint k = 1); + alias P = ParameterIdentifierTuple!func; + static assert(P[0] == "stuff"); + static assert(P[1] == ""); + static assert(P[2] == "k"); +} + +/** + * Returns number of the arguments of the function $(D_PARAM F). + * + * For typesafe variadic functions variadic arguments count as one argument. + * For other variadic functions (D- and C-style) only non-variadic + * arguments count. + * + * Params: + * F = A function: + * + * Returns: Number of the arguments of $(D_PARAM F). + */ +template arity(F...) +if (isCallable!F) +{ + static if (is(FunctionTypeOf!F T == function)) + { + enum size_t arity = T.length; + } + else + { + static assert(false, "Function has no parameters"); + } +} + +/// +pure nothrow @safe @nogc unittest +{ + int func1(Object stuff = null, uint[] = null, uint k = 1); + static assert(arity!func1 == 3); + + int func2(); + static assert(arity!func2 == 0); + + int func3(int, ...); + static assert(arity!func3 == 1); + + int func4(int, int[]...); + static assert(arity!func4 == 2); +} + +/// Attributes can be attached to a function. +enum FunctionAttribute : uint +{ + none = 0x0000, + pure_ = 0x0001, + nothrow_ = 0x0002, + ref_ = 0x0004, + property = 0x0008, + trusted = 0x0010, + safe = 0x0020, + nogc = 0x0040, + system = 0x0080, + const_ = 0x0100, + immutable_ = 0x0200, + inout_ = 0x0400, + shared_ = 0x0800, + return_ = 0x1000, + scope_ = 0x2000, +} + +/** + * Retrieves the attributes of the function $(D_PARAM F). + * + * The attributes are returned as a bit-mask of + * $(D_PSYMBOL FunctionAttribute) values. + * + * Params: A function. + * + * Returns: Attributes of the function $(D_PARAM F). + * + * See_Also: $(D_PSYMBOL FunctionAttribute). + */ +template functionAttributes(F...) +if (isCallable!F) +{ + enum uint Impl() + { + uint attrs = FunctionAttribute.none; + foreach (a; __traits(getFunctionAttributes, F[0])) + { + static if (a == "const") + { + attrs |= FunctionAttribute.const_; + } + else static if (a == "immutable") + { + attrs |= FunctionAttribute.immutable_; + } + else static if (a == "inout") + { + attrs |= FunctionAttribute.inout_; + } + else static if (a == "@nogc") + { + attrs |= FunctionAttribute.nogc; + } + else static if (a == "nothrow") + { + attrs |= FunctionAttribute.nothrow_; + } + else static if (a == "@property") + { + attrs |= FunctionAttribute.property; + } + else static if (a == "pure") + { + attrs |= FunctionAttribute.pure_; + } + else static if (a == "ref") + { + attrs |= FunctionAttribute.ref_; + } + else static if (a == "return") + { + attrs |= FunctionAttribute.return_; + } + else static if (a == "@safe") + { + attrs |= FunctionAttribute.safe; + } + else static if (a == "scope") + { + attrs |= FunctionAttribute.scope_; + } + else static if (a == "shared") + { + attrs |= FunctionAttribute.shared_; + } + else static if (a == "system") + { + attrs |= FunctionAttribute.system; + } + else static if (a == "@trusted") + { + attrs |= FunctionAttribute.trusted; + } + } + return attrs; + } + enum uint functionAttributes = Impl(); +} + +/// +pure nothrow @safe @nogc unittest +{ + @property ref int func1() pure nothrow @safe @nogc shared scope; + static assert((functionAttributes!func1 & FunctionAttribute.pure_) + == FunctionAttribute.pure_); + static assert((functionAttributes!func1 & FunctionAttribute.nothrow_) + == FunctionAttribute.nothrow_); + static assert((functionAttributes!func1 & FunctionAttribute.safe) + == FunctionAttribute.safe); + static assert((functionAttributes!func1 & FunctionAttribute.nogc) + == FunctionAttribute.nogc); + static assert((functionAttributes!func1 & FunctionAttribute.shared_) + == FunctionAttribute.shared_); + static assert((functionAttributes!func1 & FunctionAttribute.ref_) + == FunctionAttribute.ref_); + static assert((functionAttributes!func1 & FunctionAttribute.property) + == FunctionAttribute.property); + static assert((functionAttributes!func1 & FunctionAttribute.scope_) + == FunctionAttribute.scope_); + static assert((functionAttributes!func1 & FunctionAttribute.system) == 0); + static assert((functionAttributes!func1 & FunctionAttribute.trusted) == 0); + static assert((functionAttributes!func1 & FunctionAttribute.return_) == 0); +} diff --git a/source/tanya/meta/transform.d b/source/tanya/meta/transform.d index 82a5fc9..3499a13 100644 --- a/source/tanya/meta/transform.d +++ b/source/tanya/meta/transform.d @@ -617,3 +617,211 @@ pure nothrow @safe @nogc unittest } static assert(isSame!(TemplateOf!(T!int), T)); } + +/** + * Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T). + * + * Params: + * T = A type. + * + * Returns: $(D_INLINECODE inout(T)). + */ +alias InoutOf(T) = inout(T); + +/// +pure nothrow @safe @nogc unittest +{ + static assert(is(InoutOf!int == inout int)); +} + +/** + * Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T). + * + * Params: + * T = A type. + * + * Returns: $(D_INLINECODE inout(T)). + */ +alias ConstOf(T) = const(T); + +/// +pure nothrow @safe @nogc unittest +{ + static assert(is(ConstOf!int == const int)); +} + +/** + * Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T). + * + * Params: + * T = A type. + * + * Returns: $(D_INLINECODE inout(T)). + */ +alias SharedOf(T) = shared(T); + +/// +pure nothrow @safe @nogc unittest +{ + static assert(is(SharedOf!int == shared int)); +} + +/** + * Adds $(D_KEYWORD inout) qualifier to the type $(D_PARAM T). + * + * Params: + * T = A type. + * + * Returns: $(D_INLINECODE inout(T)). + */ +alias SharedInoutOf(T) = shared(inout T); + +/// +pure nothrow @safe @nogc unittest +{ + static assert(is(SharedInoutOf!int == shared inout int)); +} + +/** + * Adds $(D_KEYWORD shared const) qualifier to the type $(D_PARAM T). + * + * Params: + * T = A type. + * + * Returns: $(D_INLINECODE shared(const T)). + */ +alias SharedConstOf(T) = shared(const T); + +/// +pure nothrow @safe @nogc unittest +{ + static assert(is(SharedConstOf!int == shared const int)); +} + +/** + * Adds $(D_KEYWORD immutable) qualifier to the type $(D_PARAM T). + * + * Params: + * T = A type. + * + * Returns: $(D_INLINECODE immutable(T)). + */ +alias ImmutableOf(T) = immutable(T); + +/// +pure nothrow @safe @nogc unittest +{ + static assert(is(ImmutableOf!int == immutable int)); +} + +/** + * Adds $(D_KEYWORD inout const) qualifier to the type $(D_PARAM T). + * + * Params: + * T = A type. + * + * Returns: $(D_INLINECODE inout(const T)). + */ +alias InoutConstOf(T) = inout(const T); + +/// +pure nothrow @safe @nogc unittest +{ + static assert(is(InoutConstOf!int == inout const int)); +} + +/** + * Adds $(D_KEYWORD shared inout const) qualifier to the type $(D_PARAM T). + * + * Params: + * T = A type. + * + * Returns: $(D_INLINECODE shared(inout const T)). + */ +alias SharedInoutConstOf(T) = shared(inout const T); + +/// +pure nothrow @safe @nogc unittest +{ + static assert(is(SharedInoutConstOf!int == shared inout const int)); +} + +/** + * Returns a template with one argument which applies all qualifiers of + * $(D_PARAM T) on its argument if instantiated. + * + * Params: + * T = A type. + * + * Returns: $(D_INLINECODE shared(inout const T)). + */ +template QualifierOf(T) +{ + static if (is(T U == const U)) + { + alias QualifierOf = ConstOf; + } + else static if (is(T U == immutable U)) + { + alias QualifierOf = ImmutableOf; + } + else static if (is(T U == inout U)) + { + alias QualifierOf = InoutOf; + } + else static if (is(T U == inout const U)) + { + alias QualifierOf = InoutConstOf; + } + else static if (is(T U == shared U)) + { + alias QualifierOf = SharedOf; + } + else static if (is(T U == shared const U)) + { + alias QualifierOf = SharedConstOf; + } + else static if (is(T U == shared inout U)) + { + alias QualifierOf = SharedInoutOf; + } + else static if (is(T U == shared inout const U)) + { + alias QualifierOf = SharedInoutConstOf; + } + else + { + alias QualifierOf(T) = T; + } +} + +/// +pure nothrow @safe @nogc unittest +{ + alias MutableOf = QualifierOf!int; + static assert(is(MutableOf!uint == uint)); + + alias ConstOf = QualifierOf!(const int); + static assert(is(ConstOf!uint == const uint)); + + alias InoutOf = QualifierOf!(inout int); + static assert(is(InoutOf!uint == inout uint)); + + alias InoutConstOf = QualifierOf!(inout const int); + static assert(is(InoutConstOf!uint == inout const uint)); + + alias ImmutableOf = QualifierOf!(immutable int); + static assert(is(ImmutableOf!uint == immutable uint)); + + alias SharedOf = QualifierOf!(shared int); + static assert(is(SharedOf!uint == shared uint)); + + alias SharedConstOf = QualifierOf!(shared const int); + static assert(is(SharedConstOf!uint == shared const uint)); + + alias SharedInoutOf = QualifierOf!(shared inout int); + static assert(is(SharedInoutOf!uint == shared inout uint)); + + alias SharedInoutConstOf = QualifierOf!(shared inout const int); + static assert(is(SharedInoutConstOf!uint == shared inout const uint)); +} diff --git a/source/tanya/net/inet.d b/source/tanya/net/inet.d index 96b87f7..f88eb11 100644 --- a/source/tanya/net/inet.d +++ b/source/tanya/net/inet.d @@ -16,21 +16,8 @@ module tanya.net.inet; import std.math; import std.range.primitives; -import std.traits; - -version (unittest) -{ - version (Windows) - { - import core.sys.windows.winsock2; - version = PlattformUnittest; - } - else version (Posix) - { - import core.sys.posix.arpa.inet; - version = PlattformUnittest; - } -} +import tanya.meta.trait; +import tanya.meta.transform; /** * Represents an unsigned integer as an $(D_KEYWORD ubyte) range. @@ -212,79 +199,6 @@ private unittest static assert(!is(NetworkOrder!1)); } -// Tests against the system's htonl, htons. -version (PlattformUnittest) -{ - private unittest - { - for (uint counter; counter <= 8 * uint.sizeof; ++counter) - { - const value = pow(2, counter) - 1; - const inNetworkOrder = htonl(value); - const p = cast(ubyte*) &inNetworkOrder; - auto networkOrder = NetworkOrder!4(value); - - assert(networkOrder.length == 4); - assert(!networkOrder.empty); - assert(networkOrder.front == *p); - assert(networkOrder.back == *(p + 3)); - - networkOrder.popBack(); - assert(networkOrder.length == 3); - assert(networkOrder.front == *p); - assert(networkOrder.back == *(p + 2)); - - networkOrder.popFront(); - assert(networkOrder.length == 2); - assert(networkOrder.front == *(p + 1)); - assert(networkOrder.back == *(p + 2)); - - networkOrder.popFront(); - assert(networkOrder.length == 1); - assert(networkOrder.front == *(p + 2)); - assert(networkOrder.back == *(p + 2)); - - networkOrder.popBack(); - assert(networkOrder.length == 0); - assert(networkOrder.empty); - } - - for (ushort counter; counter <= 8 * ushort.sizeof; ++counter) - { - const value = cast(ushort) (pow(2, counter) - 1); - const inNetworkOrder = htons(value); - const p = cast(ubyte*) &inNetworkOrder; - - auto networkOrder = NetworkOrder!2(value); - - assert(networkOrder.length == 2); - assert(!networkOrder.empty); - assert(networkOrder.front == *p); - assert(networkOrder.back == *(p + 1)); - - networkOrder.popBack(); - assert(networkOrder.length == 1); - assert(networkOrder.front == *p); - assert(networkOrder.back == *p); - - networkOrder.popBack(); - assert(networkOrder.length == 0); - assert(networkOrder.empty); - - networkOrder = NetworkOrder!2(value); - - networkOrder.popFront(); - assert(networkOrder.length == 1); - assert(networkOrder.front == *(p + 1)); - assert(networkOrder.back == *(p + 1)); - - networkOrder.popFront(); - assert(networkOrder.length == 0); - assert(networkOrder.empty); - } - } -} - /** * Converts the $(D_KEYWORD ubyte) input range $(D_PARAM range) to * $(D_PARAM T). @@ -330,29 +244,3 @@ pure nothrow @safe @nogc unittest auto networkOrder = NetworkOrder!4(value); assert(networkOrder.toHostOrder() == value); } - -// Tests against the system's htonl, htons. -version (PlattformUnittest) -{ - private unittest - { - for (uint counter; counter <= 8 * uint.sizeof; ++counter) - { - const value = pow(2, counter) - 1; - const inNetworkOrder = htonl(value); - const p = cast(ubyte*) &inNetworkOrder; - auto networkOrder = NetworkOrder!4(value); - - assert(p[0 .. uint.sizeof].toHostOrder() == value); - } - for (ushort counter; counter <= 8 * ushort.sizeof; ++counter) - { - const value = cast(ushort) (pow(2, counter) - 1); - const inNetworkOrder = htons(value); - const p = cast(ubyte*) &inNetworkOrder; - auto networkOrder = NetworkOrder!2(value); - - assert(p[0 .. ushort.sizeof].toHostOrder() == value); - } - } -} diff --git a/source/tanya/typecons.d b/source/tanya/typecons.d index d9d41fb..66ee8c9 100644 --- a/source/tanya/typecons.d +++ b/source/tanya/typecons.d @@ -17,7 +17,7 @@ */ module tanya.typecons; -import std.meta; +import tanya.meta.metafunction; /** * $(D_PSYMBOL Pair) can store two heterogeneous objects.