001 package com.thaiopensource.relaxng.impl;
002
003
004 final class PatternInterner {
005 private static final int INIT_SIZE = 256;
006 private static final float LOAD_FACTOR = 0.3f;
007 private Pattern[] table;
008 private int used;
009 private int usedLimit;
010
011 PatternInterner() {
012 table = null;
013 used = 0;
014 usedLimit = 0;
015 }
016
017 PatternInterner(PatternInterner parent) {
018 table = parent.table;
019 if (table != null)
020 table = (Pattern[])table.clone();
021 used = parent.used;
022 usedLimit = parent.usedLimit;
023 }
024
025 Pattern intern(Pattern p) {
026 int h;
027
028 if (table == null) {
029 table = new Pattern[INIT_SIZE];
030 usedLimit = (int)(INIT_SIZE * LOAD_FACTOR);
031 h = firstIndex(p);
032 }
033 else {
034 for (h = firstIndex(p); table[h] != null; h = nextIndex(h)) {
035 if (p.samePattern(table[h]))
036 return table[h];
037 }
038 }
039 if (used >= usedLimit) {
040 // rehash
041 Pattern[] oldTable = table;
042 table = new Pattern[table.length << 1];
043 for (int i = oldTable.length; i > 0;) {
044 --i;
045 if (oldTable[i] != null) {
046 int j;
047 for (j = firstIndex(oldTable[i]); table[j] != null; j = nextIndex(j))
048 ;
049 table[j] = oldTable[i];
050 }
051 }
052 for (h = firstIndex(p); table[h] != null; h = nextIndex(h))
053 ;
054 usedLimit = (int)(table.length * LOAD_FACTOR);
055 }
056 used++;
057 table[h] = p;
058 return p;
059 }
060
061 private int firstIndex(Pattern p) {
062 return p.patternHashCode() & (table.length - 1);
063 }
064
065 private int nextIndex(int i) {
066 return i == 0 ? table.length - 1 : i - 1;
067 }
068 }