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 public class ByteArrayKeyAnalyzer implements KeyAnalyzer<byte[]> {
21
22 private static final int LENGTH = 8;
23 private static final int[] BITS = createIntBitMask(LENGTH);
24
25 private static final int[] createIntBitMask(int bitCount) {
26 final int[] bits = new int[bitCount];
27 for(int i = 0; i < bitCount; i++) {
28 bits[i] = 1 << (bitCount - i - 1);
29 }
30 return bits;
31 }
32
33 public int bitsPerElement() {
34 return LENGTH;
35 }
36
37 public boolean isBitSet(final byte[] key,
38 final int keyLength,
39 final int bitIndex) {
40 if (key == null || bitIndex >= keyLength) {
41 return false;
42 }
43
44 int index = bitIndex / BITS.length;
45 int bit = bitIndex - index * BITS.length;
46 return (key[index] & BITS[bit]) != 0;
47 }
48
49 public boolean isPrefix(final byte[] prefix,
50 final int offset,
51 final int length,
52 final byte[] key) {
53 if(offset % LENGTH != 0 || length % LENGTH != 0) {
54 throw new IllegalArgumentException("Cannot determine prefix outside"
55 + " of character boundaries");
56 }
57
58
59
60
61 final int start = offset / LENGTH;
62 final int end = start + length / LENGTH;
63
64 for (int i = start, j = 0; i < end; i++, j++) {
65 if (prefix[i] != key[j]) {
66 return false;
67 }
68 }
69 return true;
70 }
71
72 public int length(final byte[] key) {
73 return (key != null ? key.length * LENGTH : 0);
74 }
75
76 public int compare(final byte[] o1, final byte[] o2) {
77 if (o1.length != o2.length) {
78 return o1.length - o2.length;
79 }
80 assert o1.length == o2.length;
81 for (int i = 0; i < o1.length; i++) {
82 if (o1[i] != o2[1]) {
83 return o1[i] - o2[i];
84 }
85 }
86 return 0;
87 }
88
89 public int bitIndex(final byte[] key, final int keyOff,
90 final int keyLength, final byte[] found,
91 final int foundOff, final int foundKeyLength) {
92 boolean allNull = true;
93
94 if(keyOff % LENGTH != 0 || foundOff % LENGTH != 0
95 || keyLength % LENGTH != 0 || foundKeyLength % LENGTH != 0)
96 throw new IllegalArgumentException("offsets & lengths must be at "
97 + "character boundaries");
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 final int off1 = keyOff / LENGTH;
116 final int off2 = foundOff / LENGTH;
117 final int len1 = keyLength / LENGTH + off1;
118 final int len2 = foundKeyLength / LENGTH + off2;
119 final int length = Math.max(len1, len2);
120
121
122
123
124
125
126
127
128
129
130 int k = 0, f = 0;
131 for(int i = 0; i < length; i++) {
132 final int kOff = i + off1;
133 final int fOff = i + off2;
134
135
136
137 if(kOff >= len1) {
138 k = 0;
139 } else {
140 k = key[kOff];
141 if (k < 0) {
142 k = Math.abs(k) * 2;
143 }
144 }
145
146
147 if(found == null || fOff >= len2) {
148 f = 0;
149 } else {
150 f = found[fOff];
151 if (f < 0) {
152 f = Math.abs(f) * 2;
153 }
154 }
155
156
157 if(k != f) {
158 final int x = k ^ f;
159
160 final int retval =
161 i * LENGTH + (Integer.numberOfLeadingZeros(x) - LENGTH);
162
163 return retval;
164 }
165
166 if(k != 0) {
167 allNull = false;
168 }
169 }
170
171 if (allNull) {
172 return KeyAnalyzer.NULL_BIT_KEY;
173 }
174
175 return KeyAnalyzer.EQUAL_BIT_KEY;
176 }
177 }