HashValueTable.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package avt.lang.table;

public final class HashValueTable(Object)
{
    private long fldLength;
    private HashValueEntry[] fldTable;

    public () {
        fldTable = new HashValueEntry[0x0f];
    }

    public void append(long2 hash, Object value) {
        if(value == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "value" }));
        }
        HashValueEntry[] table = fldTable;
        long length = fldLength;
        int capacity = table.length;
        int index = Entry.getIndex(hash, capacity);
        if(length++ >= capacity && length <= Int.MAX_VALUE)
        {
            rehash();
            index = Entry.getIndex(hash, (table = fldTable).length);
        }
        table[index] = new HashValueEntry(hash, value, table[index]);
        fldLength = length;
    }

    public boolean removeWeakValue(RemoveWeakValueState state) {
        for(HashValueEntry[] table = fldTable, int index = Array.indexOfNon(null, table, state == null ? 0 : state.index, 0); index >= 0; index = Array.indexOfNon(null, table, index + 1, 0))
        {
            for(HashValueEntry prev = null, HashValueEntry entry = table[index]; entry != null; entry = (prev = entry).next) if(entry.isWeakValue())
            {
                if(state != null)
                {
                    state.index = index;
                }
                if(prev != null)
                {
                    prev.next = entry.next;
                } else
                {
                    table[index] = entry.next;
                }
                fldLength--;
                return true;
            }
        }
        return false;
    }

    public boolean remove(long2 hash, Object value) {
        if(value != null)
        {
            HashValueEntry[] table = fldTable;
            int index = Entry.getIndex(hash, table.length);
            for(HashValueEntry prev = null, HashValueEntry entry = table[index]; entry != null; entry = (prev = entry).next) if(entry.hash == hash && entry.value == value)
            {
                if(prev != null)
                {
                    prev.next = entry.next;
                } else
                {
                    table[index] = entry.next;
                }
                fldLength--;
                return true;
            }
        }
        return false;
    }

    public boolean change(long2 hash, Object value, Object newValue) {
        if(value != null) for(HashValueEntry[] table = fldTable, HashValueEntry entry = table[Entry.getIndex(hash, table.length)]; entry != null; entry = entry.next)
        {
            if(hash == entry.hash && value == entry.value)
            {
                entry.value = newValue;
                return true;
            }
        }
        return false;
    }

    public boolean contains(long2 hash, Object value) {
        if(value != null) for(HashValueEntry[] table = fldTable, HashValueEntry entry = table[Entry.getIndex(hash, table.length)]; entry != null; entry = entry.next)
        {
            if(hash == entry.hash && value.equals(entry.value)) return true;
        }
        return false;
    }

    public Object get(long2 hash, Object value) {
        if(value == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "value" }));
        }
        for(HashValueEntry[] table = fldTable, HashValueEntry entry = table[Entry.getIndex(hash, table.length)]; entry != null; entry = entry.next)
        {
            Object eval = entry.value;
            if(hash == entry.hash && value.equals(eval)) return eval;
        }
        return null;
    }

    public Enumeration enumerate() {
        HashValueEntry[] table = fldTable;
        int index = Array.indexOfNon(null, table, 0, 0);
        return index < 0 ? null : new HashValueEnumeration(table, index, table[index]);
    }

    public long length { read = fldLength }

    private void rehash() {
        HashValueEntry[] oldTable = fldTable;
        int oldCapacity = oldTable.length;
        int newCapacity = oldCapacity << 1 | 1;
        if(newCapacity < 0) newCapacity = Int.MAX_VALUE;
        HashValueEntry[] newTable = fldTable = new HashValueEntry[newCapacity];
        for(int oldIndex = oldCapacity; oldIndex-- > 0; ) for(HashValueEntry oldEntry = oldTable[oldIndex]; oldEntry != null; )
        {
            int newIndex = Entry.getIndex(oldEntry.hash, newCapacity);
            HashValueEntry newEntry = oldEntry;
            oldEntry = oldEntry.next;
            newEntry.next = newTable[newIndex];
            newTable[newIndex] = newEntry;
        }
    }
}

class HashValueEntry(Entry)
{
    private HashValueEntry fldNext;

    (long2 hash, Object value, HashValueEntry next): super(hash, value) {
        fldNext = next;
    }

    public HashValueEntry next { read = fldNext, write = fldNext }
}

class HashValueEnumeration(Enumeration)
{
    private int fldIndex;
    private HashValueEntry fldEntry;
    private final HashValueEntry[] fldTable;

    (HashValueEntry[] table, int index, HashValueEntry entry): super(entry.hash, null, entry.value) {
        fldIndex = index;
        fldEntry = entry;
        fldTable = table;
    }

    public boolean findNext() {
        HashValueEntry entry = fldEntry;
        label0: if(entry != null)
        {
            if((entry = entry.next) == null)
            {
                int index = fldIndex;
                HashValueEntry[] table = fldTable;
                if((index = Array.indexOfNon(null, table, index + 1, 0)) < 0)
                {
                    fldEntry = null;
                    break label0;
                }
                entry = table[fldIndex = index];
            }
            fldEntry = entry;
            setProperties(entry.hash, null, entry.value);
            return true;
        }
        return false;
    }
}