Skip to content

Commit

Permalink
Stop Hpricot from using JRuby's IntHashMap - instead implement a subs…
Browse files Browse the repository at this point in the history
…et of it in FastXs
  • Loading branch information
olabini committed Jan 11, 2010
1 parent c97430d commit df45020
Showing 1 changed file with 94 additions and 1 deletion.
95 changes: 94 additions & 1 deletion ext/fast_xs/FastXsService.java
Expand Up @@ -10,7 +10,6 @@
import org.jruby.runtime.CallbackFactory;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.BasicLibraryService;
import org.jruby.util.collections.IntHashMap;

public class FastXsService implements BasicLibraryService {

Expand Down Expand Up @@ -477,6 +476,100 @@ static interface EntityMap {
int value(String name);
}

// Very limited IntHashMap - it only supports get() and put()
private static class IntHashMap {
private transient Entry table[];

private transient int count;


private int threshold;

private final float loadFactor;

private static class Entry {
final int hash;
final int key;
Object value;
Entry next;

protected Entry(int hash, int key, Object value, Entry next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
}

public IntHashMap() {
this.loadFactor = 0.75f;
table = new Entry[20];
threshold = (int) (20 * 0.75f);
}

public Object get(int key) {
Entry tab[] = table;
int hash = key;
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry e = tab[index]; e != null; e = e.next) {
if (e.hash == hash) {
return e.value;
}
}
return null;
}

protected void rehash() {
int oldCapacity = table.length;
Entry oldMap[] = table;

int newCapacity = oldCapacity * 2 + 1;
Entry newMap[] = new Entry[newCapacity];

threshold = (int) (newCapacity * loadFactor);
table = newMap;

for (int i = oldCapacity; i-- > 0;) {
for (Entry old = oldMap[i]; old != null;) {
Entry e = old;
old = old.next;

int index = (e.hash & 0x7FFFFFFF) % newCapacity;
e.next = newMap[index];
newMap[index] = e;
}
}
}

public Object put(int key, Object value) {
// Makes sure the key is not already in the hashtable.
Entry tab[] = table;
int hash = key;
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry e = tab[index]; e != null; e = e.next) {
if (e.hash == hash) {
Object old = e.value;
e.value = value;
return old;
}
}

if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();

tab = table;
index = (hash & 0x7FFFFFFF) % tab.length;
}

// Creates the new entry.
Entry e = new Entry(hash, key, value, tab[index]);
tab[index] = e;
count++;
return null;
}
}

static class PrimitiveEntityMap implements EntityMap {
private Map mapNameToValue = new HashMap();

Expand Down

0 comments on commit df45020

Please sign in to comment.