/**
 * HashTab container for internal usage.
 *
 * Copyright: Copyright Martin Nowak 2013.
 * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
 * Authors:   Martin Nowak
 */
module rt.util.container.hashtab;

import rt.util.container.array;
static import common = rt.util.container.common;

struct HashTab(Key, Value)
{
    static struct Node
    {
        Key _key;
        Value _value;
        Node* _next;
    }

    @disable this(this);

    ~this()
    {
        reset();
    }

    void reset()
    {
        foreach (p; _buckets)
        {
            while (p !is null)
            {
                auto pn = p._next;
                common.destroy(*p);
                common.free(p);
                p = pn;
            }
        }
        _buckets.reset();
        _length = 0;
    }

    @property size_t length() const
    {
        return _length;
    }

    @property bool empty() const
    {
        return !_length;
    }

    void remove(in Key key)
    in { assert(key in this); }
    body
    {
        ensureNotInOpApply();

        immutable hash = hashOf(key) & mask;
        auto pp = &_buckets[hash];
        while (*pp)
        {
            auto p = *pp;
            if (p._key == key)
            {
                *pp = p._next;
                common.destroy(*p);
                common.free(p);
                if (--_length < _buckets.length && _length >= 4)
                    shrink();
                return;
            }
            else
            {
                pp = &p._next;
            }
        }
        assert(0);
    }

    ref inout(Value) opIndex(Key key) inout
    {
        return *opIn_r(key);
    }

    void opIndexAssign(Value value, Key key)
    {
        *get(key) = value;
    }

    inout(Value)* opIn_r(in Key key) inout
    {
        if (_buckets.length)
        {
            immutable hash = hashOf(key) & mask;
            for (inout(Node)* p = _buckets[hash]; p !is null; p = p._next)
            {
                if (p._key == key)
                    return &p._value;
            }
        }
        return null;
    }

    int opApply(scope int delegate(ref Key, ref Value) dg)
    {
        immutable save = _inOpApply;
        _inOpApply = true;
        scope (exit) _inOpApply = save;
        foreach (p; _buckets)
        {
            while (p !is null)
            {
                if (auto res = dg(p._key, p._value))
                    return res;
                p = p._next;
            }
        }
        return 0;
    }

private:

    Value* get(Key key)
    {
        if (auto p = opIn_r(key))
            return p;

        ensureNotInOpApply();

        if (!_buckets.length)
            _buckets.length = 4;

        immutable hash = hashOf(key) & mask;
        auto p = cast(Node*)common.xmalloc(Node.sizeof);
        common.initialize(*p);
        p._key = key;
        p._next = _buckets[hash];
        _buckets[hash] = p;
        if (++_length >= 2 * _buckets.length)
            grow();
        return &p._value;
    }

    static hash_t hashOf(in ref Key key) @trusted
    {
        static if (is(Key U : U[]))
            return .hashOf(key, 0);
        else
            return .hashOf((&key)[0 .. 1], 0);
    }

    @property hash_t mask() const
    {
        return _buckets.length - 1;
    }

    void grow()
    in
    {
        assert(_buckets.length);
    }
    body
    {
        immutable ocnt = _buckets.length;
        immutable nmask = 2 * ocnt - 1;
        _buckets.length = 2 * ocnt;
        for (size_t i = 0; i < ocnt; ++i)
        {
            auto pp = &_buckets[i];
            while (*pp)
            {
                auto p = *pp;

                immutable nidx = hashOf(p._key) & nmask;
                if (nidx != i)
                {
                    *pp = p._next;
                    p._next = _buckets[nidx];
                    _buckets[nidx] = p;
                }
                else
                {
                    pp = &p._next;
                }
            }
        }
    }

    void shrink()
    in
    {
        assert(_buckets.length >= 2);
    }
    body
    {
        immutable ocnt = _buckets.length;
        immutable ncnt = ocnt >> 1;
        immutable nmask = ncnt - 1;

        for (size_t i = ncnt; i < ocnt; ++i)
        {
            if (auto tail = _buckets[i])
            {
                immutable nidx = i & nmask;
                auto pp = &_buckets[nidx];
                while (*pp)
                    pp = &(*pp)._next;
                *pp = tail;
                _buckets[i] = null;
            }
        }
        _buckets.length = ncnt;
    }

    void ensureNotInOpApply()
    {
        if (_inOpApply)
            assert(0, "Invalid HashTab manipulation during opApply iteration.");
    }

    Array!(Node*) _buckets;
    size_t _length;
    bool _inOpApply;
}

unittest
{
    HashTab!(int, int) tab;

    foreach (i; 0 .. 100)
        tab[i] = 100 - i;

    foreach (i; 0 .. 100)
        assert(tab[i] == 100 - i);

    foreach (k, v; tab)
        assert(v == 100 - k);

    foreach (i; 0 .. 50)
        tab.remove(2 * i);

    assert(tab.length == 50);

    foreach (i; 0 .. 50)
        assert(tab[2 * i + 1] == 100 - 2 * i - 1);

    assert(tab.length == 50);

    tab.reset();
    assert(tab.empty);
    tab[0] = 0;
    assert(!tab.empty);
    destroy(tab);
    assert(tab.empty);

    // not copyable
    static assert(!__traits(compiles, { HashTab!(int, int) tab2 = tab; }));
    HashTab!(int, int) tab2;
    static assert(!__traits(compiles, tab = tab2));
    static void foo(HashTab!(int, int) copy) {}
    static assert(!__traits(compiles, foo(tab)));
}

unittest
{
    HashTab!(string, size_t) tab;

    tab["foo"] = 0;
    assert(tab["foo"] == 0);
    ++tab["foo"];
    assert(tab["foo"] == 1);
    tab["foo"]++;
    assert(tab["foo"] == 2);

    auto s = "fo";
    s ~= "o";
    assert(tab[s] == 2);
    assert(tab.length == 1);
    tab[s] -= 2;
    assert(tab[s] == 0);
    tab["foo"] = 12;
    assert(tab[s] == 12);

    tab.remove("foo");
    assert(tab.empty);
}

unittest
{
    alias RC = common.RC!();
    HashTab!(size_t, RC) tab;

    size_t cnt;
    assert(cnt == 0);
    tab[0] = RC(&cnt);
    assert(cnt == 1);
    tab[1] = tab[0];
    assert(cnt == 2);
    tab.remove(0);
    assert(cnt == 1);
    tab.remove(1);
    assert(cnt == 0);
}

unittest
{
    import core.exception;

    HashTab!(uint, uint) tab;
    foreach (i; 0 .. 5)
        tab[i] = i;
    bool thrown;
    foreach (k, v; tab)
    {
        try
        {
            if (k == 3) tab.remove(k);
        }
        catch (AssertError e)
        {
            thrown = true;
        }
    }
    assert(thrown);
    assert(tab[3] == 3);
}
