1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.mavibot.btree.serializer;
21
22
23 import java.io.IOException;
24 import java.io.UnsupportedEncodingException;
25 import java.nio.ByteBuffer;
26 import java.util.Comparator;
27
28 import org.apache.directory.mavibot.btree.comparator.StringComparator;
29 import org.apache.directory.mavibot.btree.util.Strings;
30
31
32
33
34
35
36
37 public class StringSerializer extends AbstractElementSerializer<String>
38 {
39 public static final StringSerializer INSTANCE = new StringSerializer();
40
41
42
43
44 public StringSerializer()
45 {
46 super( new StringComparator() );
47 }
48
49
50
51
52
53 public StringSerializer( Comparator comparator )
54 {
55 super( comparator );
56 }
57
58
59
60
61
62
63
64 public static String deserialize( byte[] in )
65 {
66 return deserialize( in, 0 );
67 }
68
69
70
71
72
73
74
75 public static String deserialize( byte[] in, int start )
76 {
77 int length = IntSerializer.deserialize( in, start );
78
79 if ( length == 0xFFFFFFFF )
80 {
81 return null;
82 }
83
84 if ( in.length < length + 4 + start )
85 {
86 throw new RuntimeException( "Cannot extract a String from a buffer with not enough bytes" );
87 }
88
89 return Strings.utf8ToString( in, start + 4, length );
90 }
91
92
93
94
95
96
97
98
99
100
101 public static byte[] serialize( byte[] buffer, int start, String element )
102 {
103 int len = -1;
104
105 if ( element != null )
106 {
107 len = element.length();
108 }
109
110 switch ( len )
111 {
112 case 0:
113 buffer[start] = 0x00;
114 buffer[start + 1] = 0x00;
115 buffer[start + 2] = 0x00;
116 buffer[start + 3] = 0x00;
117
118 break;
119
120 case -1:
121 buffer[start] = ( byte ) 0xFF;
122 buffer[start + 1] = ( byte ) 0xFF;
123 buffer[start + 2] = ( byte ) 0xFF;
124 buffer[start + 3] = ( byte ) 0xFF;
125
126 break;
127
128 default:
129 try
130 {
131 byte[] strBytes = element.getBytes( "UTF-8" );
132
133 buffer = new byte[strBytes.length + 4];
134
135 System.arraycopy( strBytes, 0, buffer, 4, strBytes.length );
136
137 buffer[start] = ( byte ) ( strBytes.length >>> 24 );
138 buffer[start + 1] = ( byte ) ( strBytes.length >>> 16 );
139 buffer[start + 2] = ( byte ) ( strBytes.length >>> 8 );
140 buffer[start + 3] = ( byte ) ( strBytes.length );
141 }
142 catch ( UnsupportedEncodingException uee )
143 {
144
145 throw new RuntimeException( uee );
146 }
147 }
148
149 return buffer;
150 }
151
152
153
154
155
156 public byte[] serialize( String element )
157 {
158 int len = -1;
159
160 if ( element != null )
161 {
162 len = element.length();
163 }
164
165 byte[] bytes = null;
166
167 switch ( len )
168 {
169 case 0:
170 bytes = new byte[4];
171
172 bytes[0] = 0x00;
173 bytes[1] = 0x00;
174 bytes[2] = 0x00;
175 bytes[3] = 0x00;
176
177 break;
178
179 case -1:
180 bytes = new byte[4];
181
182 bytes[0] = ( byte ) 0xFF;
183 bytes[1] = ( byte ) 0xFF;
184 bytes[2] = ( byte ) 0xFF;
185 bytes[3] = ( byte ) 0xFF;
186
187 break;
188
189 default:
190 char[] chars = element.toCharArray();
191 byte[] tmpBytes = new byte[chars.length * 2];
192
193 int pos = 0;
194 len = 0;
195
196 for ( char c : chars )
197 {
198 if ( ( c & 0xFF80 ) == 0 )
199 {
200 tmpBytes[pos++] = ( byte ) c;
201 }
202 else if ( ( c & 0xF800 ) == 0 )
203 {
204 tmpBytes[pos++] = ( byte ) ( ( byte ) 0x00C0 | ( byte ) ( ( c & 0x07C0 ) >> 6 ) );
205 tmpBytes[pos++] = ( byte ) ( ( byte ) 0x80 | ( byte ) ( c & 0x003F ) );
206 }
207 else
208 {
209 tmpBytes[pos++] = ( byte ) ( ( byte ) 0x80 | ( byte ) ( c & 0x001F ) );
210 tmpBytes[pos++] = ( byte ) ( ( byte ) 0x80 | ( byte ) ( c & 0x07C0 ) );
211 tmpBytes[pos++] = ( byte ) ( ( byte ) 0xE0 | ( byte ) ( c & 0x7800 ) );
212 }
213 }
214
215 bytes = new byte[pos + 4];
216
217 bytes[0] = ( byte ) ( pos >>> 24 );
218 bytes[1] = ( byte ) ( pos >>> 16 );
219 bytes[2] = ( byte ) ( pos >>> 8 );
220 bytes[3] = ( byte ) ( pos );
221
222 System.arraycopy( tmpBytes, 0, bytes, 4, pos );
223 }
224
225 return bytes;
226 }
227
228
229
230
231
232
233 public String deserialize( BufferHandler bufferHandler ) throws IOException
234 {
235 byte[] in = bufferHandler.read( 4 );
236
237 int len = IntSerializer.deserialize( in );
238
239 switch ( len )
240 {
241 case 0:
242 return "";
243
244 case -1:
245 return null;
246
247 default:
248 in = bufferHandler.read( len );
249
250 return Strings.utf8ToString( in );
251 }
252 }
253
254
255
256
257
258 public String deserialize( ByteBuffer buffer ) throws IOException
259 {
260 int len = buffer.getInt();
261
262 switch ( len )
263 {
264 case 0:
265 return "";
266
267 case -1:
268 return null;
269
270 default:
271 byte[] bytes = new byte[len];
272
273 buffer.get( bytes );
274 char[] chars = new char[len];
275 int clen = 0;
276
277 for ( int i = 0; i < len; i++ )
278 {
279 byte b = bytes[i];
280
281 if ( b >= 0 )
282 {
283 chars[clen++] = ( char ) b;
284 }
285 else
286 {
287 if ( ( b & 0xE0 ) == 0 )
288 {
289
290 i++;
291 byte b2 = bytes[i];
292 i++;
293 byte b3 = bytes[i];
294 chars[clen++] = ( char ) ( ( ( b & 0x000F ) << 12 ) | ( ( b2 & 0x003F ) << 6 ) | ( ( b3 & 0x003F ) ) );
295 }
296 else
297 {
298
299 i++;
300 byte b2 = bytes[i];
301 chars[clen++] = ( char ) ( ( ( b & 0x001F ) << 6 ) | ( b2 & 0x003F ) );
302 }
303 }
304 }
305
306 return new String( chars, 0, clen );
307 }
308 }
309
310
311
312
313
314 @Override
315 public int compare( String type1, String type2 )
316 {
317 if ( type1 == type2 )
318 {
319 return 0;
320 }
321
322 if ( type1 == null )
323 {
324 if ( type2 == null )
325 {
326 return 0;
327 }
328 else
329 {
330 return -1;
331 }
332 }
333 else
334 {
335 if ( type2 == null )
336 {
337 return 1;
338 }
339 else
340 {
341 return type1.compareTo( type2 );
342 }
343 }
344 }
345 }