Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #760 from MartinNowak/dup
Browse files Browse the repository at this point in the history
implement dup and idup library functions
  • Loading branch information
WalterBright committed Apr 11, 2014
2 parents ebb53ee + a403169 commit a6cbeef
Show file tree
Hide file tree
Showing 11 changed files with 438 additions and 163 deletions.
3 changes: 2 additions & 1 deletion mak/COPY
Expand Up @@ -13,8 +13,9 @@ COPY=\
$(IMPDIR)\core\time.d \
$(IMPDIR)\core\vararg.d \
\
$(IMPDIR)\core\internal\hash.d \
$(IMPDIR)\core\internal\convert.d \
$(IMPDIR)\core\internal\hash.d \
$(IMPDIR)\core\internal\traits.d \
\
$(IMPDIR)\core\stdc\complex.d \
$(IMPDIR)\core\stdc\config.d \
Expand Down
3 changes: 2 additions & 1 deletion mak/MANIFEST
Expand Up @@ -33,8 +33,9 @@ MANIFEST=\
src\core\time.d \
src\core\vararg.d \
\
src\core\internal\hash.d \
src\core\internal\convert.d \
src\core\internal\hash.d \
src\core\internal\traits.d \
\
src\core\stdc\complex.d \
src\core\stdc\config.d \
Expand Down
3 changes: 2 additions & 1 deletion mak/SRCS
Expand Up @@ -14,8 +14,9 @@ SRCS=\
src\core\time.d \
src\core\vararg.d \
\
src\core\internal\hash.d \
src\core\internal\convert.d \
src\core\internal\hash.d \
src\core\internal\traits.d \
\
src\core\stdc\config.d \
src\core\stdc\ctype.d \
Expand Down
10 changes: 1 addition & 9 deletions src/core/internal/convert.d
Expand Up @@ -8,6 +8,7 @@
* Source: $(DRUNTIMESRC core/internal/_convert.d)
*/
module core.internal.convert;
import core.internal.traits : Unqual;

@trusted pure nothrow
const(ubyte)[] toUbyte(T)(ref T val) if(is(Unqual!T == float) || is(Unqual!T == double) || is(Unqual!T == real) ||
Expand Down Expand Up @@ -478,15 +479,6 @@ template floatFormat(T) if(is(T:real) || is(T:ireal))
static assert(0);

}
private template Unqual(T)
{
static if (is(T U == shared(const U))) alias U Unqual;
else static if (is(T U == const U )) alias U Unqual;
else static if (is(T U == immutable U )) alias U Unqual;
else static if (is(T U == inout U )) alias U Unqual;
else static if (is(T U == shared U )) alias U Unqual;
else alias T Unqual;
}

// all toUbyte functions must be evaluable at compile time
@trusted pure nothrow
Expand Down
54 changes: 54 additions & 0 deletions src/core/internal/traits.d
@@ -0,0 +1,54 @@
/**
* Contains traits for runtime internal usage.
*
* Copyright: Copyright Digital Mars 2014 -.
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
* Authors: Martin Nowak
* Source: $(DRUNTIMESRC core/internal/_traits.d)
*/
module core.internal.traits;

/// taken from std.typetuple.TypeTuple
template TypeTuple(TList...)
{
alias TypeTuple = TList;
}

T trustedCast(T, U)(auto ref U u) @trusted pure nothrow
{
return cast(T)u;
}

template Unconst(T)
{
static if (is(T U == immutable U)) alias Unconst = U;
else static if (is(T U == inout const U)) alias Unconst = U;
else static if (is(T U == inout U)) alias Unconst = U;
else static if (is(T U == const U)) alias Unconst = U;
else alias Unconst = T;
}

/// taken from std.traits.Unqual
template Unqual(T)
{
version (none) // Error: recursive alias declaration @@@BUG1308@@@
{
static if (is(T U == const U)) alias Unqual = Unqual!U;
else static if (is(T U == immutable U)) alias Unqual = Unqual!U;
else static if (is(T U == inout U)) alias Unqual = Unqual!U;
else static if (is(T U == shared U)) alias Unqual = Unqual!U;
else alias Unqual = T;
}
else // workaround
{
static if (is(T U == immutable U)) alias Unqual = U;
else static if (is(T U == shared inout const U)) alias Unqual = U;
else static if (is(T U == shared inout U)) alias Unqual = U;
else static if (is(T U == shared const U)) alias Unqual = U;
else static if (is(T U == shared U)) alias Unqual = U;
else static if (is(T U == inout const U)) alias Unqual = U;
else static if (is(T U == inout U)) alias Unqual = U;
else static if (is(T U == const U)) alias Unqual = U;
else alias Unqual = T;
}
}
33 changes: 1 addition & 32 deletions src/core/time.d
Expand Up @@ -78,6 +78,7 @@ module core.time;
import core.exception;
import core.stdc.time;
import core.stdc.stdio;
import core.internal.traits : _Unqual = Unqual;

version(Windows)
{
Expand Down Expand Up @@ -3316,38 +3317,6 @@ string numToString(long value) @safe pure nothrow
}


/+ A copy of std.traits.Unqual. +/
private template _Unqual(T)
{
version (none) // Error: recursive alias declaration @@@BUG1308@@@
{
static if (is(T U == const U)) alias _Unqual!U _Unqual;
else static if (is(T U == immutable U)) alias _Unqual!U _Unqual;
else static if (is(T U == shared U)) alias _Unqual!U _Unqual;
else alias T _Unqual;
}
else // workaround
{
static if (is(T U == shared(const U))) alias U _Unqual;
else static if (is(T U == const U )) alias U _Unqual;
else static if (is(T U == immutable U )) alias U _Unqual;
else static if (is(T U == shared U )) alias U _Unqual;
else alias T _Unqual;
}
}

unittest
{
static assert(is(_Unqual!(int) == int));
static assert(is(_Unqual!(const int) == int));
static assert(is(_Unqual!(immutable int) == int));
static assert(is(_Unqual!(shared int) == int));
static assert(is(_Unqual!(shared(const int)) == int));
alias immutable(int[]) ImmIntArr;
static assert(is(_Unqual!(ImmIntArr) == immutable(int)[]));
}


/+ A copy of std.typecons.TypeTuple. +/
private template _TypeTuple(TList...)
{
Expand Down
92 changes: 92 additions & 0 deletions src/object.di
Expand Up @@ -628,3 +628,95 @@ version (unittest)
}
}
}

private extern (C) void[] _d_newarrayU(const TypeInfo ti, size_t length) pure nothrow;

/// Provide the .dup array property.
auto dup(T)(T[] a)
if (!is(const(T) : T))
{
import core.internal.traits : Unconst;
static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~
" to "~Unconst!T.stringof~" in dup.");

// wrap unsafe _dup in @trusted to preserve @safe postblit
static if (__traits(compiles, (T b) @safe { T a = b; }))
return _trustedDup!(T, Unconst!T)(a);
else
return _dup!(T, Unconst!T)(a);
}

/// ditto
// const overload to support implicit conversion to immutable (unique result, see DIP29)
T[] dup(T)(const(T)[] a)
if (is(const(T) : T))
{
// wrap unsafe _dup in @trusted to preserve @safe postblit
static if (__traits(compiles, (T b) @safe { T a = b; }))
return _trustedDup!(const(T), T)(a);
else
return _dup!(const(T), T)(a);
}

/// Provide the .idup array property.
immutable(T)[] idup(T)(T[] a)
{
static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~
" to immutable in idup.");

// wrap unsafe _dup in @trusted to preserve @safe postblit
static if (__traits(compiles, (T b) @safe { T a = b; }))
return _trustedDup!(T, immutable(T))(a);
else
return _dup!(T, immutable(T))(a);
}

private U[] _trustedDup(T, U)(T[] a) @trusted
{
return _dup!(T, U)(a);
}

private U[] _dup(T, U)(T[] a) // pure nothrow depends on postblit
{
if (__ctfe)
{
U[] res;
foreach (ref e; a)
res ~= e;
return res;
}

import core.stdc.string : memcpy;

auto arr = _d_newarrayU(typeid(T[]), a.length);
memcpy(cast(void*)arr.ptr, cast(void*)a.ptr, T.sizeof * a.length);
auto res = *cast(typeof(return)*)&arr;
_doPostblit(res);
return res;
}

private void _doPostblit(T)(T[] ary)
{
// infer static postblit type, run postblit if any
static if (is(T == struct))
{
import core.internal.traits : Unqual;

alias PostBlitT = typeof(function(void*){T a = T.init, b = a;});
// use typeid(Unqual!T) here to skip TypeInfo_Const/Shared/...
auto postBlit = cast(PostBlitT)typeid(Unqual!T).xpostblit;
if (postBlit !is null)
{
foreach (ref el; ary)
postBlit(cast(void*)&el);
}
}
else if ((&typeid(T).postblit).funcptr !is &TypeInfo.postblit)
{
alias PostBlitT = typeof(delegate(void*){T a = T.init, b = a;});
auto postBlit = cast(PostBlitT)&typeid(T).postblit;

foreach (ref el; ary)
postBlit(cast(void*)&el);
}
}

0 comments on commit a6cbeef

Please sign in to comment.