core.internal.hash
Written in the D programming language. This module provides functions to uniform calculating hash values for different types
Copyright
Copyright Igor Stepanov 2013-2013.
alias smallBytesHash
Types 1
private aliassmallBytesHash = fnv
Functions 29
fn
size_t hashOf(T)(auto ref T val, size_t seed = 0) if (is(T == enum) && !__traits(isScalar, T))fn
size_t hashOf(T)(scope const auto ref T val, size_t seed = 0) if (!is(T == enum) && __traits(isStaticArray, T) && canBitwiseHash!T)fn
size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && __traits(isStaticArray, T) && !canBitwiseHash!T)fn
size_t hashOf(T)(scope const T val, size_t seed = 0) if (is(T == S[], S) && (__traits(isScalar, S) || canBitwiseHash!S))fn
size_t hashOf(T)(T val, size_t seed = 0) if (is(T == S[], S) && !(__traits(isScalar, S) || canBitwiseHash!S))private fn
F coalesceFloat(F)(const F val) if (__traits(isFloating, val) && !is(F == __vector) && !is(F : creal))fn
size_t hashOf(T)(scope const T val) if (__traits(isScalar, T) && !is(T == __vector)) @trusted @nogc nothrow purefn
size_t hashOf(T)(scope const T val, size_t seed) if (__traits(isScalar, T) && !is(T == __vector)) @trusted @nogc nothrow purefn
size_t hashOf(T)(scope const T val, size_t seed = 0) if (is(T == __vector)) @safe @nogc nothrow purefn
size_t hashOf(T)(scope const T val) if (!is(T == enum) && is(T : typeof(null))) @trusted @nogc nothrow purefn
size_t hashOf(T)(scope const T val, size_t seed) if (!is(T == enum) && is(T : typeof(null))) @trusted @nogc nothrow purefn
size_t hashOf(T)(scope const auto ref T val, size_t seed = 0) if (!is(T == enum) && (is(T == struct) || is(T == union))
&& !is(T == const) && !is(T == immutable)
&& canBitwiseHash!T)fn
size_t hashOf(T)(auto ref T val) if (!is(T == enum) && (is(T == struct) || is(T == union))
&& !canBitwiseHash!T)fn
size_t hashOf(T)(auto ref T val, size_t seed) if (!is(T == enum) && (is(T == struct) || is(T == union))
&& !canBitwiseHash!T)fn
size_t hashOf(T)(scope auto ref T val, size_t seed = 0) if (!is(T == enum) && (is(T == struct) || is(T == union))
&& (is(T == const) || is(T == immutable))
&& canBitwiseHash!T && !canBitwiseHash!(Unconst!T))fn
size_t hashOf(T)(scope const T val, size_t seed = 0) if (!is(T == enum) && is(T == delegate)) @trusted @nogc nothrow purefn
size_t hashOf(T)(scope const T val) if (!is(T == enum) && (is(T == interface) || is(T == class))
&& canBitwiseHash!T) @nogc nothrow pure @trustedfn
size_t hashOf(T)(scope const T val, size_t seed) if (!is(T == enum) && (is(T == interface) || is(T == class))
&& canBitwiseHash!T) @nogc nothrow pure @trustedfn
size_t hashOf(T)(T val) if (!is(T == enum) && (is(T == interface) || is(T == class))
&& !canBitwiseHash!T)fn
size_t hashOf(T)(T val, size_t seed) if (!is(T == enum) && (is(T == interface) || is(T == class))
&& !canBitwiseHash!T)fn
size_t hashOf(T)(T aa) if (!is(T == enum) && __traits(isAssociativeArray, T))fn
size_t hashOf(T)(T aa, size_t seed) if (!is(T == enum) && __traits(isAssociativeArray, T))private fn
size_t _bytesHash(bool dataKnownToBeAligned)(scope const(ubyte)[] bytes, size_t seed) @nogc nothrow pure @trustedprivate fn
size_t _bytesHashAligned(scope const(ubyte)[] bytes, size_t seed) @nogc nothrow pure @trustedprivate fn
size_t _bytesHashUnaligned(scope const(ubyte)[] bytes, size_t seed) @nogc nothrow pure @trustedprivate fn
size_t bytesHash(bool dataKnownToBeAligned)(scope const(ubyte)[] bytes, size_t seed) @nogc nothrow pure @trustedVariables 3
private enumvar
floatCoalesceZeroes = trueprivate enumvar
floatCoalesceNaNs = trueprivate enumvar
_hashOfStruct = q{
enum bool isChained = is(typeof(seed) : size_t);
static if (!isChained) enum size_t seed = 0;
static if (hasCallableToHash!(typeof(val))) //CTFE depends on toHash()
{
static if (!__traits(isSame, typeof(val), __traits(parent, val.toHash))
&& is(typeof(val is null)))
{
static if (isChained)
return hashOf(__traits(getMember, val, __traits(getAliasThis, typeof(val))), seed);
else
return hashOf(__traits(getMember, val, __traits(getAliasThis, typeof(val))));
}
else
{
static if (isChained)
return hashOf(cast(size_t) val.toHash(), seed);
else
return val.toHash();
}
}
else
{
import core.internal.convert : toUbyte;
static if (__traits(hasMember, T, "toHash") && is(typeof(T.toHash) == function))
{
// TODO: in the future maybe this should be changed to a static
// assert(0), because if there's a `toHash` the programmer probably
// expected it to be called and a compilation failure here will
// expose a bug in his code.
// In the future we also might want to disallow non-const toHash
// altogether.
pragma(msg, "Warning: struct "~__traits(identifier, T)
~" has method toHash, however it cannot be called with "
~typeof(val).stringof~" this.");
static if (__traits(compiles, __traits(getLocation, T.toHash)))
{
enum file = __traits(getLocation, T.toHash)[0];
enum line = __traits(getLocation, T.toHash)[1].stringof;
pragma(msg, " ",__traits(identifier, T),".toHash defined here: ",file,"(",line,")");
}
}
static if (T.tupleof.length == 0)
{
return seed;
}
else static if ((is(T == struct) && !canBitwiseHash!T) || T.tupleof.length == 1)
{
static if (isChained) size_t h = seed;
static foreach (i, F; typeof(val.tupleof))
{
static if (__traits(isStaticArray, F))
{
static if (i == 0 && !isChained) size_t h = 0;
static if (F.sizeof > 0 && canBitwiseHash!F)
// May use smallBytesHash instead of bytesHash.
h = bytesHashWithExactSizeAndAlignment!F(toUbyte(val.tupleof[i]), h);
else
// We can avoid the "double hashing" the top-level version uses
// for consistency with TypeInfo.getHash.
foreach (ref e; val.tupleof[i])
h = hashOf(e, h);
}
else static if (is(F == struct) || is(F == union))
{
static if (hasCallableToHash!F)
{
static if (!__traits(isSame, F, __traits(parent, val.tupleof[i].toHash))
&& is(typeof(val.tupleof[i] is null)))
{
static if (i == 0 && !isChained)
size_t h = hashOf(__traits(getMember, val.tupleof[i], __traits(getAliasThis, F)));
else
h = hashOf(__traits(getMember, val.tupleof[i], __traits(getAliasThis, F)), h);
}
else
{
static if (i == 0 && !isChained)
size_t h = val.tupleof[i].toHash();
else
h = hashOf(cast(size_t) val.tupleof[i].toHash(), h);
}
}
else static if (F.tupleof.length == 1)
{
// Handle the single member case separately to avoid unnecessarily using bytesHash.
static if (i == 0 && !isChained)
size_t h = hashOf(val.tupleof[i].tupleof[0]);
else
h = hashOf(val.tupleof[i].tupleof[0], h);
}
else static if (canBitwiseHash!F)
{
// May use smallBytesHash instead of bytesHash.
static if (i == 0 && !isChained) size_t h = 0;
h = bytesHashWithExactSizeAndAlignment!F(toUbyte(val.tupleof[i]), h);
}
else
{
// Nothing special happening.
static if (i == 0 && !isChained)
size_t h = hashOf(val.tupleof[i]);
else
h = hashOf(val.tupleof[i], h);
}
}
else
{
// Nothing special happening.
static if (i == 0 && !isChained)
size_t h = hashOf(val.tupleof[i]);
else
h = hashOf(val.tupleof[i], h);
}
}
return h;
}
else static if (is(typeof(toUbyte(val)) == const(ubyte)[]))//CTFE ready for structs without reference fields
{
// Not using bytesHashWithExactSizeAndAlignment here because
// the result may differ from typeid(T).hashOf(&val).
return bytesHashAlignedBy!T(toUbyte(val), seed);
}
else // CTFE unsupported
{
assert(!__ctfe, "unable to compute hash of "~T.stringof~" at compile time");
const(ubyte)[] bytes = (() @trusted => (cast(const(ubyte)*)&val)[0 .. T.sizeof])();
// Not using bytesHashWithExactSizeAndAlignment here because
// the result may differ from typeid(T).hashOf(&val).
return bytesHashAlignedBy!T(bytes, seed);
}
}
}Templates 4
tmplisCppClassWithoutHash(T)
tmplcanBitwiseHash(T)
tmplbytesHashAlignedBy(AlignType)
tmplbytesHashWithExactSizeAndAlignment(SizeAndAlignType)