01: package org.kohsuke.rngom.binary;
02:
03: final class PatternInterner {
04: private static final int INIT_SIZE = 256;
05: private static final float LOAD_FACTOR = 0.3f;
06: private Pattern[] table;
07: private int used;
08: private int usedLimit;
09:
10: PatternInterner() {
11: table = null;
12: used = 0;
13: usedLimit = 0;
14: }
15:
16: PatternInterner(PatternInterner parent) {
17: table = parent.table;
18: if (table != null)
19: table = (Pattern[]) table.clone();
20: used = parent.used;
21: usedLimit = parent.usedLimit;
22: }
23:
24: Pattern intern(Pattern p) {
25: int h;
26:
27: if (table == null) {
28: table = new Pattern[INIT_SIZE];
29: usedLimit = (int) (INIT_SIZE * LOAD_FACTOR);
30: h = firstIndex(p);
31: } else {
32: for (h = firstIndex(p); table[h] != null; h = nextIndex(h)) {
33: if (p.samePattern(table[h]))
34: return table[h];
35: }
36: }
37: if (used >= usedLimit) {
38: // rehash
39: Pattern[] oldTable = table;
40: table = new Pattern[table.length << 1];
41: for (int i = oldTable.length; i > 0;) {
42: --i;
43: if (oldTable[i] != null) {
44: int j;
45: for (j = firstIndex(oldTable[i]); table[j] != null; j = nextIndex(j))
46: ;
47: table[j] = oldTable[i];
48: }
49: }
50: for (h = firstIndex(p); table[h] != null; h = nextIndex(h))
51: ;
52: usedLimit = (int) (table.length * LOAD_FACTOR);
53: }
54: used++;
55: table[h] = p;
56: return p;
57: }
58:
59: private int firstIndex(Pattern p) {
60: return p.patternHashCode() & (table.length - 1);
61: }
62:
63: private int nextIndex(int i) {
64: return i == 0 ? table.length - 1 : i - 1;
65: }
66: }
|