1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.collections4.trie.analyzer;
18
19 import org.apache.commons.collections4.trie.KeyAnalyzer;
20
21
22
23
24
25
26
27
28 public class StringKeyAnalyzer extends KeyAnalyzer<String> {
29
30 private static final long serialVersionUID = -7032449491269434877L;
31
32
33 public static final StringKeyAnalyzer INSTANCE = new StringKeyAnalyzer();
34
35
36 public static final int LENGTH = Character.SIZE;
37
38
39 private static final int MSB = 0x8000;
40
41
42 private static int mask(final int bit) {
43 return MSB >>> bit;
44 }
45
46
47
48
49
50
51 @Deprecated
52 public StringKeyAnalyzer() {
53
54 }
55
56 @Override
57 public int bitIndex(final String key, final int offsetInBits, final int lengthInBits,
58 final String other, final int otherOffsetInBits, final int otherLengthInBits) {
59
60 boolean allNull = true;
61
62 if (offsetInBits % LENGTH != 0 || otherOffsetInBits % LENGTH != 0
63 || lengthInBits % LENGTH != 0 || otherLengthInBits % LENGTH != 0) {
64 throw new IllegalArgumentException("The offsets and lengths must be at Character boundaries");
65 }
66
67 final int beginIndex1 = offsetInBits / LENGTH;
68 final int beginIndex2 = otherOffsetInBits / LENGTH;
69
70 final int endIndex1 = beginIndex1 + lengthInBits / LENGTH;
71 final int endIndex2 = beginIndex2 + otherLengthInBits / LENGTH;
72
73 final int length = Math.max(endIndex1, endIndex2);
74
75
76
77
78 char k = 0;
79 char f = 0;
80 for (int i = 0; i < length; i++) {
81 final int index1 = beginIndex1 + i;
82 final int index2 = beginIndex2 + i;
83
84 if (index1 >= endIndex1) {
85 k = 0;
86 } else {
87 k = key.charAt(index1);
88 }
89
90 if (other == null || index2 >= endIndex2) {
91 f = 0;
92 } else {
93 f = other.charAt(index2);
94 }
95
96 if (k != f) {
97 final int x = k ^ f;
98 return i * LENGTH + Integer.numberOfLeadingZeros(x) - LENGTH;
99 }
100
101 if (k != 0) {
102 allNull = false;
103 }
104 }
105
106
107 if (allNull) {
108 return NULL_BIT_KEY;
109 }
110
111
112 return EQUAL_BIT_KEY;
113 }
114
115 @Override
116 public int bitsPerElement() {
117 return LENGTH;
118 }
119
120 @Override
121 public boolean isBitSet(final String key, final int bitIndex, final int lengthInBits) {
122 if (key == null || bitIndex >= lengthInBits) {
123 return false;
124 }
125
126 final int index = bitIndex / LENGTH;
127 final int bit = bitIndex % LENGTH;
128
129 return (key.charAt(index) & mask(bit)) != 0;
130 }
131
132 @Override
133 public boolean isPrefix(final String prefix, final int offsetInBits,
134 final int lengthInBits, final String key) {
135 if (offsetInBits % LENGTH != 0 || lengthInBits % LENGTH != 0) {
136 throw new IllegalArgumentException(
137 "Cannot determine prefix outside of Character boundaries");
138 }
139
140 final String s1 = prefix.substring(offsetInBits / LENGTH, lengthInBits / LENGTH);
141 return key.startsWith(s1);
142 }
143
144 @Override
145 public int lengthInBits(final String key) {
146 return key != null ? key.length() * LENGTH : 0;
147 }
148 }