-registering same system multiple times only replace pointer for callback

-added export attributes (required by windows to make DLL library, not work at now due to DMD bugs)
-interface D files to import
This commit is contained in:
Mergul 2018-09-18 13:28:04 +02:00
parent cb0f56b0fb
commit d0fcdba6cd
20 changed files with 1322 additions and 105 deletions

328
import/ecs/hash_map.di Normal file
View file

@ -0,0 +1,328 @@
// D import file generated from 'source\ecs\hash_map.d'
module ecs.hash_map;
import std.traits;
import ecs.vector;
import ecs.traits;
enum doNotInline = "version(DigitalMars)pragma(inline,false);version(LDC)pragma(LDC_never_inline);";
private enum HASH_EMPTY = 0;
private enum HASH_DELETED = 1;
private enum HASH_FILLED_MARK = ulong(1) << 8 * (ulong).sizeof - 1;
export ulong defaultHashFunc(T)(auto ref T t)
{
static if (isIntegral!T)
{
return hashInt(t);
}
else
{
return hashInt(t.hashOf);
}
}
export nothrow @nogc @safe ulong hashInt(ulong x);
struct HashMap(KeyPar, ValuePar, alias hashFunc = defaultHashFunc)
{
alias Key = KeyPar;
alias Value = ValuePar;
enum rehashFactor = 0.75;
enum size_t getIndexEmptyValue = size_t.max;
static struct KeyVal
{
Key key;
Value value;
}
static struct Bucket
{
ulong hash;
KeyVal keyValue;
}
Vector!Bucket elements;
size_t length;
size_t markerdDeleted;
export void clear()
{
elements.clear();
length = 0;
markerdDeleted = 0;
}
export void reset()
{
elements.reset();
length = 0;
markerdDeleted = 0;
}
export bool isIn(ref Key el)
{
return getIndex(el) != getIndexEmptyValue;
}
export bool isIn(Key el)
{
return getIndex(el) != getIndexEmptyValue;
}
export Value* getPtr()(auto ref Key k)
{
size_t index = getIndex(k);
if (index == getIndexEmptyValue)
{
return null;
}
else
{
return &elements[index].keyValue.value;
}
}
export ref Value get()(auto ref Key k)
{
size_t index = getIndex(k);
assert(index != getIndexEmptyValue);
return elements[index].keyValue.value;
}
deprecated("Use get with second parameter.") export auto ref Value getDefault()(auto ref Key k, auto ref Value defaultValue)
{
return get(k, defaultValue);
}
export auto ref Value get()(auto ref Key k, auto ref Value defaultValue)
{
size_t index = getIndex(k);
if (index == getIndexEmptyValue)
{
return defaultValue;
}
else
{
return elements[index].keyValue.value;
}
}
export ref Value getInsertDefault()(auto ref Key k, auto ref Value defaultValue)
{
size_t index = getIndex(k);
if (index == getIndexEmptyValue)
{
add(k, defaultValue);
}
index = getIndex(k);
assert(index != getIndexEmptyValue);
return elements[index].keyValue.value;
}
export bool tryRemove(Key el)
{
size_t index = getIndex(el);
if (index == getIndexEmptyValue)
{
return false;
}
length--;
elements[index].hash = HASH_DELETED;
markerdDeleted++;
return true;
}
export void remove(Key el)
{
bool ok = tryRemove(el);
assert(ok);
}
export ref Value opIndex()(auto ref Key key)
{
return get(key);
}
export void opIndexAssign()(auto ref Value value, auto ref Key key)
{
add(key, value);
}
export void add()(auto ref Key key, auto ref Value value)
{
size_t index = getIndex(key);
if (index != getIndexEmptyValue)
{
elements[index].keyValue.value = value;
return ;
}
if (getLoadFactor(length + 1) > rehashFactor || getLoadFactor(length + markerdDeleted) > rehashFactor)
{
rehash();
}
length++;
immutable ulong hash = hashFunc(key) | HASH_FILLED_MARK;
immutable size_t rotateMask = elements.length - 1;
index = hash & rotateMask;
while (true)
{
Bucket* gr = &elements[index];
if ((gr.hash & HASH_FILLED_MARK) == 0)
{
if (gr.hash == HASH_DELETED)
{
markerdDeleted--;
}
gr.hash = hash;
gr.keyValue.key = key;
gr.keyValue.value = value;
return ;
}
index++;
index = index & rotateMask;
}
}
export size_t getIndex(Key el)
{
return getIndex(el);
}
export size_t getIndex(ref Key el)
{
mixin(doNotInline);
immutable size_t groupsLength = elements.length;
if (groupsLength == 0)
{
return getIndexEmptyValue;
}
immutable ulong hash = hashFunc(el) | HASH_FILLED_MARK;
immutable size_t rotateMask = groupsLength - 1;
size_t index = hash & rotateMask;
while (true)
{
Bucket* gr = &elements[index];
if (gr.hash == hash && (gr.keyValue.key == el))
{
return index;
}
if (gr.hash == HASH_EMPTY)
{
return getIndexEmptyValue;
}
index++;
index = index & rotateMask;
}
}
export float getLoadFactor(size_t forElementsNum)
{
if (elements.length == 0)
{
return 1;
}
return cast(float)forElementsNum / elements.length;
}
export void rehash()
{
mixin(doNotInline);
Vector!KeyVal allElements;
allElements.reserve(elements.length);
foreach (ref Bucket el; elements)
{
if ((el.hash & HASH_FILLED_MARK) == 0)
{
el.hash = HASH_EMPTY;
continue;
}
el.hash = HASH_EMPTY;
allElements ~= el.keyValue;
}
if (getLoadFactor(length + 1) > rehashFactor)
{
elements.length = (elements.length ? elements.length : 4) << 1;
}
foreach (i, ref el; allElements)
{
add(el.key, el.value);
}
length = allElements.length;
markerdDeleted = 0;
}
export int opApply(DG)(scope DG dg)
{
int result;
foreach (ref Bucket gr; elements)
{
if ((gr.hash & HASH_FILLED_MARK) == 0)
{
continue;
}
static if (isForeachDelegateWithTypes!(DG, Key))
{
result = dg(gr.keyValue.key);
}
else
{
static if (isForeachDelegateWithTypes!(DG, Value))
{
result = dg(gr.keyValue.value);
}
else
{
static if (isForeachDelegateWithTypes!(DG, Key, Value))
{
result = dg(gr.keyValue.key, gr.keyValue.value);
}
else
{
static assert(0);
}
}
}
if (result)
break;
}
return result;
}
export int byKey(scope int delegate(Key k) dg)
{
int result;
foreach (ref Key k; this)
{
result = dg(k);
if (result)
break;
}
return result;
}
export int byValue(scope int delegate(ref Value k) dg)
{
int result;
foreach (ref Value v; this)
{
result = dg(v);
if (result)
break;
}
return result;
}
export int byKeyValue(scope int delegate(ref Key k, ref Value v) dg)
{
int result;
foreach (ref Key k, ref Value v; this)
{
result = dg(k, v);
if (result)
break;
}
return result;
}
import std.format : FormatSpec, formatValue;
export void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt)
{
formatValue(sink, '[', fmt);
foreach (ref k, ref v; &byKeyValue)
{
formatValue(sink, k, fmt);
formatValue(sink, ':', fmt);
formatValue(sink, v, fmt);
formatValue(sink, ", ", fmt);
}
formatValue(sink, ']', fmt);
}
}
static void dumpHashMapToJson(T)(ref T map, string path = "HashMapDump.json")
{
Vector!char data;
import std.file;
import mutils.serializer.json;
JSONSerializer.instance.serialize!(Load.no)(map, data);
std.file.write(path, data[]);
}
static void printHashMap(T)(ref T map)
{
import std.stdio;
writeln(T.stringof, " dump:\x0a");
foreach (k, v; &map.byKeyValue)
{
writefln("%20s : %20s", k, v);
}
}