org.robovm.compiler.hash.HashTableGenerator Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2012 RoboVM AB
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.robovm.compiler.hash;
import java.util.LinkedList;
import java.util.List;
import org.robovm.compiler.llvm.Constant;
import org.robovm.compiler.llvm.IntegerConstant;
import org.robovm.compiler.llvm.IntegerType;
import org.robovm.compiler.llvm.StructureConstant;
import org.robovm.compiler.llvm.StructureConstantBuilder;
import org.robovm.compiler.llvm.Type;
/**
* Generates static hash tables in the form of a {@link StructureConstant} using
* a {@link HashFunction}.
*/
public class HashTableGenerator {
private static final IntegerType INDEX_TYPE = Type.I32;
private final HashFunction function;
private List>[] table;
private int tableSize;
private int count = 0;
private double loadFactor;
public HashTableGenerator(HashFunction function) {
this(function, 4, 0.75);
}
public HashTableGenerator(HashFunction function, int tableSize) {
this(function, tableSize, 0.75);
}
public HashTableGenerator(HashFunction function, int tableSize, double loadFactor) {
this.function = function;
this.tableSize = tableSize;
this.loadFactor = loadFactor;
allocateTable();
}
@SuppressWarnings("unchecked")
private void allocateTable() {
this.table = new List[1 << tableSize];
}
public void put(K k, V v) {
int h = function.hash(k);
putNoRehash(new Entry(h, k, v));
if (count > loadFactor * table.length) {
rehash();
}
}
private void rehash() {
List>[] oldTable = table;
tableSize++;
count = 0;
allocateTable();
for (int i = 0; i < oldTable.length; i++) {
if (oldTable[i] != null) {
for (Entry entry : oldTable[i]) {
putNoRehash(entry);
}
}
}
}
private void putNoRehash(Entry entry) {
int idx = entry.h & ((1 << tableSize) - 1);
if (table[idx] == null) {
table[idx] = new LinkedList>();
}
for (Entry e : table[idx]) {
if (e.h == entry.h && (e.k.equals(entry.k))) {
e.v = entry.v;
return;
}
}
table[idx].add(entry);
count++;
}
public StructureConstant generate() {
StructureConstantBuilder builder = new StructureConstantBuilder();
int start = 0;
builder.add(new IntegerConstant(count));
builder.add(new IntegerConstant(table.length, INDEX_TYPE));
builder.add(new IntegerConstant(start, INDEX_TYPE));
for (int i = 1; i <= table.length; i++) {
if (table[i - 1] == null) {
builder.add(new IntegerConstant(start, INDEX_TYPE));
} else {
start += table[i - 1].size();
builder.add(new IntegerConstant(start, INDEX_TYPE));
}
}
for (int i = 0; i < table.length; i++) {
if (table[i] != null) {
for (Entry entry : table[i]) {
builder.add(entry.v);
}
}
}
return builder.build();
}
private static class Entry {
int h;
K k;
V v;
Entry(int h, K k, V v) {
this.h = h;
this.k = k;
this.v = v;
}
@Override
public int hashCode() {
return h;
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
Entry e = (Entry) obj;
return this.h == e.h
&& (this.k == e.k || this.k.equals(e.k))
&& (this.v == e.v || this.v.equals(e.v));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy