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