1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.eos.trie;
17
18 import net.sf.eos.trie.PatriciaTrie.KeyAnalyzer;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class CharSequenceKeyAnalyzer implements KeyAnalyzer<CharSequence> {
53
54 private static final long serialVersionUID = -7032449491269434877L;
55
56 private static final int[] BITS = createIntBitMask(16);
57
58 public static final int[] createIntBitMask(int bitCount) {
59 int[] bits = new int[bitCount];
60 for(int i = 0; i < bitCount; i++) {
61 bits[i] = 1 << (bitCount - i - 1);
62 }
63 return bits;
64 }
65 public int length(CharSequence key) {
66 return (key != null ? key.length() * 16 : 0);
67 }
68
69 public int bitIndex(CharSequence key, int keyOff, int keyLength,
70 CharSequence found, int foundOff, int foundKeyLength) {
71 boolean allNull = true;
72
73 if(keyOff % 16 != 0 || foundOff % 16 != 0 ||
74 keyLength % 16 != 0 || foundKeyLength % 16 != 0)
75 throw new IllegalArgumentException("offsets & lengths must be at "
76 + "character boundaries");
77
78 int off1 = keyOff / 16;
79 int off2 = foundOff / 16;
80 int len1 = keyLength / 16 + off1;
81 int len2 = foundKeyLength / 16 + off2;
82 int length = Math.max(len1, len2);
83
84
85
86
87 char k = 0, f = 0;
88 for(int i = 0; i < length; i++) {
89 int kOff = i + off1;
90 int fOff = i + off2;
91
92 if(kOff >= len1)
93 k = 0;
94 else
95 k = key.charAt(kOff);
96
97 if(found == null || fOff >= len2)
98 f = 0;
99 else
100 f = found.charAt(fOff);
101
102 if(k != f) {
103 int x = k ^ f;
104 return i * 16 + (Integer.numberOfLeadingZeros(x) - 16);
105 }
106
107 if(k != 0)
108 allNull = false;
109
110 }
111
112 if (allNull) {
113 return KeyAnalyzer.NULL_BIT_KEY;
114 }
115
116 return KeyAnalyzer.EQUAL_BIT_KEY;
117 }
118
119 public boolean isBitSet(CharSequence key, int keyLength, int bitIndex) {
120 if (key == null || bitIndex >= keyLength) {
121 return false;
122 }
123
124 int index = bitIndex / BITS.length;
125 int bit = bitIndex - index * BITS.length;
126 return (key.charAt(index) & BITS[bit]) != 0;
127 }
128
129 public int compare(CharSequence o1, CharSequence o2) {
130 return o1.toString().compareTo(o2.toString());
131 }
132
133 public int bitsPerElement() {
134 return 16;
135 }
136
137 public boolean isPrefix(CharSequence prefix, int offset, int length, CharSequence key) {
138 if(offset % 16 != 0 || length % 16 != 0)
139 throw new IllegalArgumentException("Cannot determine prefix outside of character boundaries");
140 String s1 = prefix.subSequence(offset / 16, length / 16).toString();
141 String s2 = key.toString();
142 return s2.startsWith(s1);
143 }
144 }
145