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