File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\mvstore\type\ObjectType.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.mvstore.type;
8
9 import java.math.BigDecimal;
10 import java.math.BigInteger;
11 import java.nio.ByteBuffer;
12 import java.util.UUID;
13 import org.h2.mvstore.DataUtils;
14 import org.h2.util.Utils;
15
16 /**
17 * A data type implementation for the most common data types, including
18 * serializable objects.
19 */
20 public class ObjectType implements DataType {
21
22 // TODO maybe support InputStream, Reader
23 // TODO maybe support ResultSet, Date, Time, Timestamp
24 // TODO maybe support boolean[], short[],...
25
26 /**
27 * The type constants are also used as tag values.
28 */
29 static final int TYPE_BOOLEAN = 1;
30 static final int TYPE_BYTE = 2;
31 static final int TYPE_SHORT = 3;
32 static final int TYPE_INTEGER = 4;
33 static final int TYPE_LONG = 5;
34 static final int TYPE_BIG_INTEGER = 6;
35 static final int TYPE_FLOAT = 7;
36 static final int TYPE_DOUBLE = 8;
37 static final int TYPE_BIG_DECIMAL = 9;
38 static final int TYPE_CHARACTER = 10;
39 static final int TYPE_STRING = 11;
40 static final int TYPE_UUID = 12;
41 static final int TYPE_BYTE_ARRAY = 13;
42 static final int TYPE_INT_ARRAY = 14;
43 static final int TYPE_LONG_ARRAY = 15;
44 static final int TYPE_CHAR_ARRAY = 16;
45 static final int TYPE_SERIALIZED_OBJECT = 17;
46
47 /**
48 * For very common values (e.g. 0 and 1) we save space by encoding the value
49 * in the tag. e.g. TAG_BOOLEAN_TRUE and TAG_FLOAT_0.
50 */
51 static final int TAG_BOOLEAN_TRUE = 32;
52 static final int TAG_INTEGER_NEGATIVE = 33;
53 static final int TAG_INTEGER_FIXED = 34;
54 static final int TAG_LONG_NEGATIVE = 35;
55 static final int TAG_LONG_FIXED = 36;
56 static final int TAG_BIG_INTEGER_0 = 37;
57 static final int TAG_BIG_INTEGER_1 = 38;
58 static final int TAG_BIG_INTEGER_SMALL = 39;
59 static final int TAG_FLOAT_0 = 40;
60 static final int TAG_FLOAT_1 = 41;
61 static final int TAG_FLOAT_FIXED = 42;
62 static final int TAG_DOUBLE_0 = 43;
63 static final int TAG_DOUBLE_1 = 44;
64 static final int TAG_DOUBLE_FIXED = 45;
65 static final int TAG_BIG_DECIMAL_0 = 46;
66 static final int TAG_BIG_DECIMAL_1 = 47;
67 static final int TAG_BIG_DECIMAL_SMALL = 48;
68 static final int TAG_BIG_DECIMAL_SMALL_SCALED = 49;
69
70 /**
71 * For small-values/small-arrays, we encode the value/array-length in the
72 * tag.
73 */
74 static final int TAG_INTEGER_0_15 = 64;
75 static final int TAG_LONG_0_7 = 80;
76 static final int TAG_STRING_0_15 = 88;
77 static final int TAG_BYTE_ARRAY_0_15 = 104;
78
79 /**
80 * Constants for floating point synchronization.
81 */
82 static final int FLOAT_ZERO_BITS = Float.floatToIntBits(0.0f);
83 static final int FLOAT_ONE_BITS = Float.floatToIntBits(1.0f);
84 static final long DOUBLE_ZERO_BITS = Double.doubleToLongBits(0.0d);
85 static final long DOUBLE_ONE_BITS = Double.doubleToLongBits(1.0d);
86
87 private AutoDetectDataType last = new StringType(this);
88
89 @Override
90 public int compare(Object a, Object b) {
91 return last.compare(a, b);
92 }
93
94 @Override
95 public int getMaxLength(Object obj) {
96 return last.getMaxLength(obj);
97 }
98
99 @Override
100 public int getMemory(Object obj) {
101 return last.getMemory(obj);
102 }
103
104 @Override
105 public void write(ByteBuffer buff, Object obj) {
106 last.write(buff, obj);
107 }
108
109 private AutoDetectDataType newType(int typeId) {
110 switch (typeId) {
111 case TYPE_BOOLEAN:
112 return new BooleanType(this);
113 case TYPE_BYTE:
114 return new ByteType(this);
115 case TYPE_SHORT:
116 return new ShortType(this);
117 case TYPE_CHARACTER:
118 return new CharacterType(this);
119 case TYPE_INTEGER:
120 return new IntegerType(this);
121 case TYPE_LONG:
122 return new LongType(this);
123 case TYPE_FLOAT:
124 return new FloatType(this);
125 case TYPE_DOUBLE:
126 return new DoubleType(this);
127 case TYPE_BIG_INTEGER:
128 return new BigIntegerType(this);
129 case TYPE_BIG_DECIMAL:
130 return new BigDecimalType(this);
131 case TYPE_BYTE_ARRAY:
132 return new ByteArrayType(this);
133 case TYPE_CHAR_ARRAY:
134 return new CharArrayType(this);
135 case TYPE_INT_ARRAY:
136 return new IntArrayType(this);
137 case TYPE_LONG_ARRAY:
138 return new LongArrayType(this);
139 case TYPE_STRING:
140 return new StringType(this);
141 case TYPE_UUID:
142 return new UUIDType(this);
143 case TYPE_SERIALIZED_OBJECT:
144 return new SerializedObjectType(this);
145 }
146 throw new RuntimeException("Unsupported type: " + typeId);
147 }
148
149 @Override
150 public Object read(ByteBuffer buff) {
151 int tag = buff.get();
152 int typeId;
153 if (tag <= TYPE_SERIALIZED_OBJECT) {
154 typeId = tag;
155 } else {
156 switch(tag) {
157 case TAG_BOOLEAN_TRUE:
158 typeId = TYPE_BOOLEAN;
159 break;
160 case TAG_INTEGER_NEGATIVE:
161 case TAG_INTEGER_FIXED:
162 typeId = TYPE_INTEGER;
163 break;
164 case TAG_LONG_NEGATIVE:
165 case TAG_LONG_FIXED:
166 typeId = TYPE_LONG;
167 break;
168 case TAG_BIG_INTEGER_0:
169 case TAG_BIG_INTEGER_1:
170 case TAG_BIG_INTEGER_SMALL:
171 typeId = TYPE_BIG_INTEGER;
172 break;
173 case TAG_FLOAT_0:
174 case TAG_FLOAT_1:
175 case TAG_FLOAT_FIXED:
176 typeId = TYPE_FLOAT;
177 break;
178 case TAG_DOUBLE_0:
179 case TAG_DOUBLE_1:
180 case TAG_DOUBLE_FIXED:
181 typeId = TYPE_DOUBLE;
182 break;
183 case TAG_BIG_DECIMAL_0:
184 case TAG_BIG_DECIMAL_1:
185 case TAG_BIG_DECIMAL_SMALL:
186 case TAG_BIG_DECIMAL_SMALL_SCALED:
187 typeId = TYPE_BIG_DECIMAL;
188 break;
189 default:
190 if (tag >= TAG_INTEGER_0_15 && tag <= TAG_INTEGER_0_15 + 15) {
191 typeId = TYPE_INTEGER;
192 } else if (tag >= TAG_STRING_0_15 && tag <= TAG_STRING_0_15 + 15) {
193 typeId = TYPE_STRING;
194 } else if (tag >= TAG_LONG_0_7 && tag <= TAG_LONG_0_7 + 7) {
195 typeId = TYPE_LONG;
196 } else if (tag >= TAG_BYTE_ARRAY_0_15 && tag <= TAG_BYTE_ARRAY_0_15 + 15) {
197 typeId = TYPE_BYTE_ARRAY;
198 } else {
199 throw new RuntimeException("Unknown tag: " + tag);
200 }
201 }
202 }
203 if (typeId != last.typeId) {
204 last = newType(typeId);
205 }
206 return last.read(buff, tag);
207 }
208
209 @Override
210 public String asString() {
211 return "o";
212 }
213
214 private static int getTypeId(Object obj) {
215 if (obj instanceof Integer) {
216 return TYPE_INTEGER;
217 } else if (obj instanceof String) {
218 return TYPE_STRING;
219 } else if (obj instanceof Long) {
220 return TYPE_LONG;
221 } else if (obj instanceof BigDecimal) {
222 if (obj.getClass() == BigDecimal.class) {
223 return TYPE_BIG_DECIMAL;
224 }
225 } else if (obj instanceof byte[]) {
226 return TYPE_BYTE_ARRAY;
227 } else if (obj instanceof Double) {
228 return TYPE_DOUBLE;
229 } else if (obj instanceof Float) {
230 return TYPE_FLOAT;
231 } else if (obj instanceof Boolean) {
232 return TYPE_BOOLEAN;
233 } else if (obj instanceof UUID) {
234 return TYPE_UUID;
235 } else if (obj instanceof Byte) {
236 return TYPE_BYTE;
237 } else if (obj instanceof int[]) {
238 return TYPE_INT_ARRAY;
239 } else if (obj instanceof long[]) {
240 return TYPE_LONG_ARRAY;
241 } else if (obj instanceof char[]) {
242 return TYPE_CHAR_ARRAY;
243 } else if (obj instanceof Short) {
244 return TYPE_SHORT;
245 } else if (obj instanceof BigInteger) {
246 if (obj.getClass() == BigInteger.class) {
247 return TYPE_BIG_INTEGER;
248 }
249 } else if (obj instanceof Character) {
250 return TYPE_CHARACTER;
251 }
252 if (obj == null) {
253 throw new NullPointerException();
254 }
255 return TYPE_SERIALIZED_OBJECT;
256 }
257
258 /**
259 * Switch the last remembered type to match the type of the given object.
260 *
261 * @param obj the object
262 * @return the auto-detected type used
263 */
264 AutoDetectDataType switchType(Object obj) {
265 int typeId = getTypeId(obj);
266 AutoDetectDataType l = last;
267 if (typeId != l.typeId) {
268 l = last = newType(typeId);
269 }
270 return l;
271 }
272
273 /**
274 * Compare the contents of two arrays.
275 *
276 * @param data1 the first array (must not be null)
277 * @param data2 the second array (must not be null)
278 * @return the result of the comparison (-1, 1 or 0)
279 */
280 public static int compareNotNull(char[] data1, char[] data2) {
281 if (data1 == data2) {
282 return 0;
283 }
284 int len = Math.min(data1.length, data2.length);
285 for (int i = 0; i < len; i++) {
286 char x = data1[i];
287 char x2 = data2[i];
288 if (x != x2) {
289 return x > x2 ? 1 : -1;
290 }
291 }
292 return Integer.signum(data1.length - data2.length);
293 }
294
295 /**
296 * Compare the contents of two arrays.
297 *
298 * @param data1 the first array (must not be null)
299 * @param data2 the second array (must not be null)
300 * @return the result of the comparison (-1, 1 or 0)
301 */
302 public static int compareNotNull(int[] data1, int[] data2) {
303 if (data1 == data2) {
304 return 0;
305 }
306 int len = Math.min(data1.length, data2.length);
307 for (int i = 0; i < len; i++) {
308 int x = data1[i];
309 int x2 = data2[i];
310 if (x != x2) {
311 return x > x2 ? 1 : -1;
312 }
313 }
314 return Integer.signum(data1.length - data2.length);
315 }
316
317 /**
318 * Compare the contents of two arrays.
319 *
320 * @param data1 the first array (must not be null)
321 * @param data2 the second array (must not be null)
322 * @return the result of the comparison (-1, 1 or 0)
323 */
324 public static int compareNotNull(long[] data1, long[] data2) {
325 if (data1 == data2) {
326 return 0;
327 }
328 int len = Math.min(data1.length, data2.length);
329 for (int i = 0; i < len; i++) {
330 long x = data1[i];
331 long x2 = data2[i];
332 if (x != x2) {
333 return x > x2 ? 1 : -1;
334 }
335 }
336 return Integer.signum(data1.length - data2.length);
337 }
338
339 /**
340 * The base class for auto-detect data types.
341 */
342 abstract class AutoDetectDataType implements DataType {
343
344 protected final ObjectType base;
345 protected final int typeId;
346
347 AutoDetectDataType(ObjectType base, int typeId) {
348 this.base = base;
349 this.typeId = typeId;
350 }
351
352 @Override
353 public int getMemory(Object o) {
354 return getType(o).getMemory(o);
355 }
356
357 @Override
358 public int compare(Object aObj, Object bObj) {
359 AutoDetectDataType aType = getType(aObj);
360 AutoDetectDataType bType = getType(bObj);
361 if (aType == bType) {
362 return aType.compare(aObj, bObj);
363 }
364 int typeDiff = aType.typeId - bType.typeId;
365 return Integer.signum(typeDiff);
366 }
367
368 @Override
369 public int getMaxLength(Object o) {
370 return getType(o).getMaxLength(o);
371 }
372
373 @Override
374 public void write(ByteBuffer buff, Object o) {
375 getType(o).write(buff, o);
376 }
377
378 @Override
379 public final Object read(ByteBuffer buff) {
380 throw new RuntimeException();
381 }
382
383 /**
384 * Get the type for the given object.
385 *
386 * @param o the object
387 * @return the type
388 */
389 AutoDetectDataType getType(Object o) {
390 return base.switchType(o);
391 }
392
393 /**
394 * Read an object from the buffer.
395 *
396 * @param buff the buffer
397 * @param tag the first byte of the object (usually the type)
398 * @return the read object
399 */
400 abstract Object read(ByteBuffer buff, int tag);
401
402 @Override
403 public String asString() {
404 return "o" + typeId;
405 }
406
407 }
408
409 /**
410 * The type for boolean true and false.
411 */
412 class BooleanType extends AutoDetectDataType {
413
414 BooleanType(ObjectType base) {
415 super(base, TYPE_BOOLEAN);
416 }
417
418 @Override
419 public int compare(Object aObj, Object bObj) {
420 if (aObj instanceof Boolean && bObj instanceof Boolean) {
421 Boolean a = (Boolean) aObj;
422 Boolean b = (Boolean) bObj;
423 return a.compareTo(b);
424 }
425 return super.compare(aObj, bObj);
426 }
427
428 @Override
429 public int getMemory(Object obj) {
430 return obj instanceof Boolean ? 0 : super.getMemory(obj);
431 }
432
433 @Override
434 public int getMaxLength(Object obj) {
435 return obj instanceof Boolean ? 1 : super.getMaxLength(obj);
436 }
437
438 @Override
439 public void write(ByteBuffer buff, Object obj) {
440 if (obj instanceof Boolean) {
441 int tag = ((Boolean) obj) ? TAG_BOOLEAN_TRUE : TYPE_BOOLEAN;
442 buff.put((byte) tag);
443 } else {
444 super.write(buff, obj);
445 }
446 }
447
448 @Override
449 public Object read(ByteBuffer buff, int tag) {
450 return tag == TYPE_BOOLEAN ? Boolean.FALSE : Boolean.TRUE;
451 }
452
453 }
454
455 /**
456 * The type for byte objects.
457 */
458 class ByteType extends AutoDetectDataType {
459
460 ByteType(ObjectType base) {
461 super(base, TYPE_BYTE);
462 }
463
464 @Override
465 public int compare(Object aObj, Object bObj) {
466 if (aObj instanceof Byte && bObj instanceof Byte) {
467 Byte a = (Byte) aObj;
468 Byte b = (Byte) bObj;
469 return a.compareTo(b);
470 }
471 return super.compare(aObj, bObj);
472 }
473
474 @Override
475 public int getMemory(Object obj) {
476 return obj instanceof Byte ? 0 : super.getMemory(obj);
477 }
478
479 @Override
480 public int getMaxLength(Object obj) {
481 return obj instanceof Byte ? 2 : super.getMaxLength(obj);
482 }
483
484 @Override
485 public void write(ByteBuffer buff, Object obj) {
486 if (obj instanceof Byte) {
487 buff.put((byte) TYPE_BYTE);
488 buff.put(((Byte) obj).byteValue());
489 } else {
490 super.write(buff, obj);
491 }
492 }
493
494 public Object read(ByteBuffer buff, int tag) {
495 return Byte.valueOf(buff.get());
496 }
497
498 }
499
500 /**
501 * The type for character objects.
502 */
503 class CharacterType extends AutoDetectDataType {
504
505 CharacterType(ObjectType base) {
506 super(base, TYPE_CHARACTER);
507 }
508
509 @Override
510 public int compare(Object aObj, Object bObj) {
511 if (aObj instanceof Character && bObj instanceof Character) {
512 Character a = (Character) aObj;
513 Character b = (Character) bObj;
514 return a.compareTo(b);
515 }
516 return super.compare(aObj, bObj);
517 }
518
519 @Override
520 public int getMemory(Object obj) {
521 return obj instanceof Character ? 24 : super.getMemory(obj);
522 }
523
524 @Override
525 public int getMaxLength(Object obj) {
526 return obj instanceof Character ? 3 : super.getMaxLength(obj);
527 }
528
529 @Override
530 public void write(ByteBuffer buff, Object obj) {
531 if (obj instanceof Character) {
532 buff.put((byte) TYPE_CHARACTER);
533 buff.putChar(((Character) obj).charValue());
534 } else {
535 super.write(buff, obj);
536 }
537 }
538
539 @Override
540 public Object read(ByteBuffer buff, int tag) {
541 return Character.valueOf(buff.getChar());
542 }
543
544 }
545
546 /**
547 * The type for short objects.
548 */
549 class ShortType extends AutoDetectDataType {
550
551 ShortType(ObjectType base) {
552 super(base, TYPE_SHORT);
553 }
554
555 @Override
556 public int compare(Object aObj, Object bObj) {
557 if (aObj instanceof Short && bObj instanceof Short) {
558 Short a = (Short) aObj;
559 Short b = (Short) bObj;
560 return a.compareTo(b);
561 }
562 return super.compare(aObj, bObj);
563 }
564
565 @Override
566 public int getMemory(Object obj) {
567 return obj instanceof Short ? 24 : super.getMemory(obj);
568 }
569
570 @Override
571 public int getMaxLength(Object obj) {
572 return obj instanceof Short ? 3 : super.getMaxLength(obj);
573 }
574
575 @Override
576 public void write(ByteBuffer buff, Object obj) {
577 if (obj instanceof Short) {
578 buff.put((byte) TYPE_SHORT);
579 buff.putShort(((Short) obj).shortValue());
580 } else {
581 super.write(buff, obj);
582 }
583 }
584
585 @Override
586 public Object read(ByteBuffer buff, int tag) {
587 return Short.valueOf(buff.getShort());
588 }
589
590 }
591
592 /**
593 * The type for integer objects.
594 */
595 class IntegerType extends AutoDetectDataType {
596
597 IntegerType(ObjectType base) {
598 super(base, TYPE_INTEGER);
599 }
600
601 @Override
602 public int compare(Object aObj, Object bObj) {
603 if (aObj instanceof Integer && bObj instanceof Integer) {
604 Integer a = (Integer) aObj;
605 Integer b = (Integer) bObj;
606 return a.compareTo(b);
607 }
608 return super.compare(aObj, bObj);
609 }
610
611 @Override
612 public int getMemory(Object obj) {
613 return obj instanceof Integer ? 24 : super.getMemory(obj);
614 }
615
616 @Override
617 public int getMaxLength(Object obj) {
618 return obj instanceof Integer ?
619 1 + DataUtils.MAX_VAR_INT_LEN :
620 super.getMaxLength(obj);
621 }
622
623 @Override
624 public void write(ByteBuffer buff, Object obj) {
625 if (obj instanceof Integer) {
626 int x = (Integer) obj;
627 if (x < 0) {
628 // -Integer.MIN_VALUE is smaller than 0
629 if (-x < 0 || -x > DataUtils.COMPRESSED_VAR_INT_MAX) {
630 buff.put((byte) TAG_INTEGER_FIXED);
631 buff.putInt(x);
632 } else {
633 buff.put((byte) TAG_INTEGER_NEGATIVE);
634 DataUtils.writeVarInt(buff, -x);
635 }
636 } else if (x <= 15) {
637 buff.put((byte) (TAG_INTEGER_0_15 + x));
638 } else if (x <= DataUtils.COMPRESSED_VAR_INT_MAX) {
639 buff.put((byte) TYPE_INTEGER);
640 DataUtils.writeVarInt(buff, x);
641 } else {
642 buff.put((byte) TAG_INTEGER_FIXED);
643 buff.putInt(x);
644 }
645 } else {
646 super.write(buff, obj);
647 }
648 }
649
650 @Override
651 public Object read(ByteBuffer buff, int tag) {
652 switch (tag) {
653 case TYPE_INTEGER:
654 return DataUtils.readVarInt(buff);
655 case TAG_INTEGER_NEGATIVE:
656 return -DataUtils.readVarInt(buff);
657 case TAG_INTEGER_FIXED:
658 return buff.getInt();
659 }
660 return tag - TAG_INTEGER_0_15;
661 }
662
663 }
664
665 /**
666 * The type for long objects.
667 */
668 public class LongType extends AutoDetectDataType {
669
670 LongType(ObjectType base) {
671 super(base, TYPE_LONG);
672 }
673
674 @Override
675 public int compare(Object aObj, Object bObj) {
676 if (aObj instanceof Long && bObj instanceof Long) {
677 Long a = (Long) aObj;
678 Long b = (Long) bObj;
679 return a.compareTo(b);
680 }
681 return super.compare(aObj, bObj);
682 }
683
684 @Override
685 public int getMemory(Object obj) {
686 return obj instanceof Long ? 30 : super.getMemory(obj);
687 }
688
689 @Override
690 public int getMaxLength(Object obj) {
691 return obj instanceof Long ?
692 1 + DataUtils.MAX_VAR_LONG_LEN :
693 super.getMaxLength(obj);
694 }
695
696 @Override
697 public void write(ByteBuffer buff, Object obj) {
698 if (obj instanceof Long) {
699 long x = (Long) obj;
700 if (x < 0) {
701 // -Long.MIN_VALUE is smaller than 0
702 if (-x < 0 || -x > DataUtils.COMPRESSED_VAR_LONG_MAX) {
703 buff.put((byte) TAG_LONG_FIXED);
704 buff.putLong(x);
705 } else {
706 buff.put((byte) TAG_LONG_NEGATIVE);
707 DataUtils.writeVarLong(buff, -x);
708 }
709 } else if (x <= 7) {
710 buff.put((byte) (TAG_LONG_0_7 + x));
711 } else if (x <= DataUtils.COMPRESSED_VAR_LONG_MAX) {
712 buff.put((byte) TYPE_LONG);
713 DataUtils.writeVarLong(buff, x);
714 } else {
715 buff.put((byte) TAG_LONG_FIXED);
716 buff.putLong(x);
717 }
718 } else {
719 super.write(buff, obj);
720 }
721 }
722
723 @Override
724 public Object read(ByteBuffer buff, int tag) {
725 switch (tag) {
726 case TYPE_LONG:
727 return DataUtils.readVarLong(buff);
728 case TAG_LONG_NEGATIVE:
729 return -DataUtils.readVarLong(buff);
730 case TAG_LONG_FIXED:
731 return buff.getLong();
732 }
733 return Long.valueOf(tag - TAG_LONG_0_7);
734 }
735
736 }
737
738 /**
739 * The type for float objects.
740 */
741 class FloatType extends AutoDetectDataType {
742
743 FloatType(ObjectType base) {
744 super(base, TYPE_FLOAT);
745 }
746
747 @Override
748 public int compare(Object aObj, Object bObj) {
749 if (aObj instanceof Float && bObj instanceof Float) {
750 Float a = (Float) aObj;
751 Float b = (Float) bObj;
752 return a.compareTo(b);
753 }
754 return super.compare(aObj, bObj);
755 }
756
757 @Override
758 public int getMemory(Object obj) {
759 return obj instanceof Float ? 24 : super.getMemory(obj);
760 }
761
762 @Override
763 public int getMaxLength(Object obj) {
764 return obj instanceof Float ?
765 1 + DataUtils.MAX_VAR_INT_LEN :
766 super.getMaxLength(obj);
767 }
768
769 @Override
770 public void write(ByteBuffer buff, Object obj) {
771 if (obj instanceof Float) {
772 float x = (Float) obj;
773 int f = Float.floatToIntBits(x);
774 if (f == ObjectType.FLOAT_ZERO_BITS) {
775 buff.put((byte) TAG_FLOAT_0);
776 } else if (f == ObjectType.FLOAT_ONE_BITS) {
777 buff.put((byte) TAG_FLOAT_1);
778 } else {
779 int value = Integer.reverse(f);
780 if (value >= 0 && value <= DataUtils.COMPRESSED_VAR_INT_MAX) {
781 buff.put((byte) TYPE_FLOAT);
782 DataUtils.writeVarInt(buff, value);
783 } else {
784 buff.put((byte) TAG_FLOAT_FIXED);
785 buff.putFloat(x);
786 }
787 }
788 } else {
789 super.write(buff, obj);
790 }
791 }
792
793 @Override
794 public Object read(ByteBuffer buff, int tag) {
795 switch (tag) {
796 case TAG_FLOAT_0:
797 return 0f;
798 case TAG_FLOAT_1:
799 return 1f;
800 case TAG_FLOAT_FIXED:
801 return buff.getFloat();
802 }
803 return Float.intBitsToFloat(Integer.reverse(DataUtils.readVarInt(buff)));
804 }
805
806 }
807
808 /**
809 * The type for double objects.
810 */
811 class DoubleType extends AutoDetectDataType {
812
813 DoubleType(ObjectType base) {
814 super(base, TYPE_DOUBLE);
815 }
816
817 @Override
818 public int compare(Object aObj, Object bObj) {
819 if (aObj instanceof Double && bObj instanceof Double) {
820 Double a = (Double) aObj;
821 Double b = (Double) bObj;
822 return a.compareTo(b);
823 }
824 return super.compare(aObj, bObj);
825 }
826
827 @Override
828 public int getMemory(Object obj) {
829 return obj instanceof Double ? 30 : super.getMemory(obj);
830 }
831
832 @Override
833 public int getMaxLength(Object obj) {
834 return obj instanceof Double ?
835 1 + DataUtils.MAX_VAR_LONG_LEN :
836 super.getMaxLength(obj);
837 }
838
839 @Override
840 public void write(ByteBuffer buff, Object obj) {
841 if (obj instanceof Double) {
842 double x = (Double) obj;
843 long d = Double.doubleToLongBits(x);
844 if (d == ObjectType.DOUBLE_ZERO_BITS) {
845 buff.put((byte) TAG_DOUBLE_0);
846 } else if (d == ObjectType.DOUBLE_ONE_BITS) {
847 buff.put((byte) TAG_DOUBLE_1);
848 } else {
849 long value = Long.reverse(d);
850 if (value >= 0 && value <= DataUtils.COMPRESSED_VAR_LONG_MAX) {
851 buff.put((byte) TYPE_DOUBLE);
852 DataUtils.writeVarLong(buff, value);
853 } else {
854 buff.put((byte) TAG_DOUBLE_FIXED);
855 buff.putDouble(x);
856 }
857 }
858 } else {
859 super.write(buff, obj);
860 }
861 }
862
863 @Override
864 public Object read(ByteBuffer buff, int tag) {
865 switch (tag) {
866 case TAG_DOUBLE_0:
867 return 0d;
868 case TAG_DOUBLE_1:
869 return 1d;
870 case TAG_DOUBLE_FIXED:
871 return buff.getDouble();
872 }
873 return Double.longBitsToDouble(Long.reverse(DataUtils.readVarLong(buff)));
874 }
875
876 }
877
878 /**
879 * The type for BigInteger objects.
880 */
881 class BigIntegerType extends AutoDetectDataType {
882
883 BigIntegerType(ObjectType base) {
884 super(base, TYPE_BIG_INTEGER);
885 }
886
887 @Override
888 public int compare(Object aObj, Object bObj) {
889 if (aObj instanceof BigInteger && bObj instanceof BigInteger) {
890 BigInteger a = (BigInteger) aObj;
891 BigInteger b = (BigInteger) bObj;
892 return a.compareTo(b);
893 }
894 return super.compare(aObj, bObj);
895 }
896
897 @Override
898 public int getMemory(Object obj) {
899 return obj instanceof BigInteger ? 100 : super.getMemory(obj);
900 }
901
902 @Override
903 public int getMaxLength(Object obj) {
904 if (!(obj instanceof BigInteger)) {
905 return super.getMaxLength(obj);
906 }
907 BigInteger x = (BigInteger) obj;
908 if (BigInteger.ZERO.equals(x) || BigInteger.ONE.equals(x)) {
909 return 1;
910 }
911 int bits = x.bitLength();
912 if (bits <= 63) {
913 return 1 + DataUtils.MAX_VAR_LONG_LEN;
914 }
915 byte[] bytes = x.toByteArray();
916 return 1 + DataUtils.MAX_VAR_INT_LEN + bytes.length;
917 }
918
919 @Override
920 public void write(ByteBuffer buff, Object obj) {
921 if (obj instanceof BigInteger) {
922 BigInteger x = (BigInteger) obj;
923 if (BigInteger.ZERO.equals(x)) {
924 buff.put((byte) TAG_BIG_INTEGER_0);
925 } else if (BigInteger.ONE.equals(x)) {
926 buff.put((byte) TAG_BIG_INTEGER_1);
927 } else {
928 int bits = x.bitLength();
929 if (bits <= 63) {
930 buff.put((byte) TAG_BIG_INTEGER_SMALL);
931 DataUtils.writeVarLong(buff, x.longValue());
932 } else {
933 buff.put((byte) TYPE_BIG_INTEGER);
934 byte[] bytes = x.toByteArray();
935 DataUtils.writeVarInt(buff, bytes.length);
936 buff.put(bytes);
937 }
938 }
939 } else {
940 super.write(buff, obj);
941 }
942 }
943
944 @Override
945 public Object read(ByteBuffer buff, int tag) {
946 switch (tag) {
947 case TAG_BIG_INTEGER_0:
948 return BigInteger.ZERO;
949 case TAG_BIG_INTEGER_1:
950 return BigInteger.ONE;
951 case TAG_BIG_INTEGER_SMALL:
952 return BigInteger.valueOf(DataUtils.readVarLong(buff));
953 }
954 int len = DataUtils.readVarInt(buff);
955 byte[] bytes = Utils.newBytes(len);
956 buff.get(bytes);
957 return new BigInteger(bytes);
958 }
959
960 }
961
962 /**
963 * The type for BigDecimal objects.
964 */
965 class BigDecimalType extends AutoDetectDataType {
966
967 BigDecimalType(ObjectType base) {
968 super(base, TYPE_BIG_DECIMAL);
969 }
970
971 @Override
972 public int compare(Object aObj, Object bObj) {
973 if (aObj instanceof BigDecimal && bObj instanceof BigDecimal) {
974 BigDecimal a = (BigDecimal) aObj;
975 BigDecimal b = (BigDecimal) bObj;
976 return a.compareTo(b);
977 }
978 return super.compare(aObj, bObj);
979 }
980
981 @Override
982 public int getMemory(Object obj) {
983 return obj instanceof BigDecimal ? 150 : super.getMemory(obj);
984 }
985
986 @Override
987 public int getMaxLength(Object obj) {
988 if (!(obj instanceof BigDecimal)) {
989 return super.getMaxLength(obj);
990 }
991 BigDecimal x = (BigDecimal) obj;
992 if (BigDecimal.ZERO.equals(x) || BigDecimal.ONE.equals(x)) {
993 return 1;
994 }
995 int scale = x.scale();
996 BigInteger b = x.unscaledValue();
997 int bits = b.bitLength();
998 if (bits <= 63) {
999 if (scale == 0) {
1000 return 1 + DataUtils.MAX_VAR_LONG_LEN;
1001 }
1002 return 1 + DataUtils.MAX_VAR_INT_LEN +
1003 DataUtils.MAX_VAR_LONG_LEN;
1004 }
1005 byte[] bytes = b.toByteArray();
1006 return 1 + DataUtils.MAX_VAR_INT_LEN +
1007 DataUtils.MAX_VAR_INT_LEN + bytes.length;
1008 }
1009
1010 @Override
1011 public void write(ByteBuffer buff, Object obj) {
1012 if (obj instanceof BigDecimal) {
1013 BigDecimal x = (BigDecimal) obj;
1014 if (BigDecimal.ZERO.equals(x)) {
1015 buff.put((byte) TAG_BIG_DECIMAL_0);
1016 } else if (BigDecimal.ONE.equals(x)) {
1017 buff.put((byte) TAG_BIG_DECIMAL_1);
1018 } else {
1019 int scale = x.scale();
1020 BigInteger b = x.unscaledValue();
1021 int bits = b.bitLength();
1022 if (bits < 64) {
1023 if (scale == 0) {
1024 buff.put((byte) TAG_BIG_DECIMAL_SMALL);
1025 } else {
1026 buff.put((byte) TAG_BIG_DECIMAL_SMALL_SCALED);
1027 DataUtils.writeVarInt(buff, scale);
1028 }
1029 DataUtils.writeVarLong(buff, b.longValue());
1030 } else {
1031 buff.put((byte) TYPE_BIG_DECIMAL);
1032 DataUtils.writeVarInt(buff, scale);
1033 byte[] bytes = b.toByteArray();
1034 DataUtils.writeVarInt(buff, bytes.length);
1035 buff.put(bytes);
1036 }
1037 }
1038 } else {
1039 super.write(buff, obj);
1040 }
1041 }
1042
1043 @Override
1044 public Object read(ByteBuffer buff, int tag) {
1045 switch (tag) {
1046 case TAG_BIG_DECIMAL_0:
1047 return BigDecimal.ZERO;
1048 case TAG_BIG_DECIMAL_1:
1049 return BigDecimal.ONE;
1050 case TAG_BIG_DECIMAL_SMALL:
1051 return BigDecimal.valueOf(DataUtils.readVarLong(buff));
1052 case TAG_BIG_DECIMAL_SMALL_SCALED:
1053 int scale = DataUtils.readVarInt(buff);
1054 return BigDecimal.valueOf(DataUtils.readVarLong(buff), scale);
1055 }
1056 int scale = DataUtils.readVarInt(buff);
1057 int len = DataUtils.readVarInt(buff);
1058 byte[] bytes = Utils.newBytes(len);
1059 buff.get(bytes);
1060 BigInteger b = new BigInteger(bytes);
1061 return new BigDecimal(b, scale);
1062 }
1063
1064 }
1065
1066 /**
1067 * The type for string objects.
1068 */
1069 class StringType extends AutoDetectDataType {
1070
1071 StringType(ObjectType base) {
1072 super(base, TYPE_STRING);
1073 }
1074
1075 @Override
1076 public int getMemory(Object obj) {
1077 if (!(obj instanceof String)) {
1078 return super.getMemory(obj);
1079 }
1080 return 24 + 2 * obj.toString().length();
1081 }
1082
1083 @Override
1084 public int compare(Object aObj, Object bObj) {
1085 if (aObj instanceof String && bObj instanceof String) {
1086 return aObj.toString().compareTo(bObj.toString());
1087 }
1088 return super.compare(aObj, bObj);
1089 }
1090
1091 @Override
1092 public int getMaxLength(Object obj) {
1093 if (!(obj instanceof String)) {
1094 return super.getMaxLength(obj);
1095 }
1096 return 1 + DataUtils.MAX_VAR_INT_LEN + 3 * obj.toString().length();
1097 }
1098
1099 @Override
1100 public void write(ByteBuffer buff, Object obj) {
1101 if (!(obj instanceof String)) {
1102 super.write(buff, obj);
1103 return;
1104 }
1105 String s = (String) obj;
1106 int len = s.length();
1107 if (len <= 15) {
1108 buff.put((byte) (TAG_STRING_0_15 + len));
1109 } else {
1110 buff.put((byte) TYPE_STRING);
1111 DataUtils.writeVarInt(buff, len);
1112 }
1113 DataUtils.writeStringData(buff, s, len);
1114 }
1115
1116 @Override
1117 public Object read(ByteBuffer buff, int tag) {
1118 int len;
1119 if (tag == TYPE_STRING) {
1120 len = DataUtils.readVarInt(buff);
1121 } else {
1122 len = tag - TAG_STRING_0_15;
1123 }
1124 return DataUtils.readString(buff, len);
1125 }
1126
1127 }
1128
1129 /**
1130 * The type for UUID objects.
1131 */
1132 class UUIDType extends AutoDetectDataType {
1133
1134 UUIDType(ObjectType base) {
1135 super(base, TYPE_UUID);
1136 }
1137
1138 @Override
1139 public int getMemory(Object obj) {
1140 return obj instanceof UUID ? 40 : super.getMemory(obj);
1141 }
1142
1143 @Override
1144 public int compare(Object aObj, Object bObj) {
1145 if (aObj instanceof UUID && bObj instanceof UUID) {
1146 UUID a = (UUID) aObj;
1147 UUID b = (UUID) bObj;
1148 return a.compareTo(b);
1149 }
1150 return super.compare(aObj, bObj);
1151 }
1152
1153 @Override
1154 public int getMaxLength(Object obj) {
1155 if (!(obj instanceof UUID)) {
1156 return super.getMaxLength(obj);
1157 }
1158 return 17;
1159 }
1160
1161 @Override
1162 public void write(ByteBuffer buff, Object obj) {
1163 if (!(obj instanceof UUID)) {
1164 super.write(buff, obj);
1165 return;
1166 }
1167 buff.put((byte) TYPE_UUID);
1168 UUID a = (UUID) obj;
1169 buff.putLong(a.getMostSignificantBits());
1170 buff.putLong(a.getLeastSignificantBits());
1171 }
1172
1173 @Override
1174 public Object read(ByteBuffer buff, int tag) {
1175 long a = buff.getLong(), b = buff.getLong();
1176 return new UUID(a, b);
1177 }
1178
1179 }
1180
1181 /**
1182 * The type for byte arrays.
1183 */
1184 class ByteArrayType extends AutoDetectDataType {
1185
1186 ByteArrayType(ObjectType base) {
1187 super(base, TYPE_BYTE_ARRAY);
1188 }
1189
1190 @Override
1191 public int getMemory(Object obj) {
1192 if (!(obj instanceof byte[])) {
1193 return super.getMemory(obj);
1194 }
1195 return 24 + ((byte[]) obj).length;
1196 }
1197
1198 @Override
1199 public int compare(Object aObj, Object bObj) {
1200 if (aObj instanceof byte[] && bObj instanceof byte[]) {
1201 byte[] a = (byte[]) aObj;
1202 byte[] b = (byte[]) bObj;
1203 return Utils.compareNotNull(a, b);
1204 }
1205 return super.compare(aObj, bObj);
1206 }
1207
1208 @Override
1209 public int getMaxLength(Object obj) {
1210 if (!(obj instanceof byte[])) {
1211 return super.getMaxLength(obj);
1212 }
1213 return 1 + DataUtils.MAX_VAR_INT_LEN + ((byte[]) obj).length;
1214 }
1215
1216 @Override
1217 public void write(ByteBuffer buff, Object obj) {
1218 if (obj instanceof byte[]) {
1219 byte[] data = (byte[]) obj;
1220 int len = data.length;
1221 if (len <= 15) {
1222 buff.put((byte) (TAG_BYTE_ARRAY_0_15 + len));
1223 } else {
1224 buff.put((byte) TYPE_BYTE_ARRAY);
1225 DataUtils.writeVarInt(buff, data.length);
1226 }
1227 buff.put(data);
1228 } else {
1229 super.write(buff, obj);
1230 }
1231 }
1232
1233 @Override
1234 public Object read(ByteBuffer buff, int tag) {
1235 int len;
1236 if (tag == TYPE_BYTE_ARRAY) {
1237 len = DataUtils.readVarInt(buff);
1238 } else {
1239 len = tag - TAG_BYTE_ARRAY_0_15;
1240 }
1241 byte[] data = new byte[len];
1242 buff.get(data);
1243 return data;
1244 }
1245
1246 }
1247
1248 /**
1249 * The type for char arrays.
1250 */
1251 class CharArrayType extends AutoDetectDataType {
1252
1253 CharArrayType(ObjectType base) {
1254 super(base, TYPE_CHAR_ARRAY);
1255 }
1256
1257 @Override
1258 public int getMemory(Object obj) {
1259 if (!(obj instanceof char[])) {
1260 return super.getMemory(obj);
1261 }
1262 return 24 + 2 * ((char[]) obj).length;
1263 }
1264
1265 @Override
1266 public int compare(Object aObj, Object bObj) {
1267 if (aObj instanceof char[] && bObj instanceof char[]) {
1268 char[] a = (char[]) aObj;
1269 char[] b = (char[]) bObj;
1270 return compareNotNull(a, b);
1271 }
1272 return super.compare(aObj, bObj);
1273 }
1274
1275 @Override
1276 public int getMaxLength(Object obj) {
1277 if (!(obj instanceof char[])) {
1278 return super.getMaxLength(obj);
1279 }
1280 return 1 + DataUtils.MAX_VAR_INT_LEN + 2 * ((char[]) obj).length;
1281 }
1282
1283 @Override
1284 public void write(ByteBuffer buff, Object obj) {
1285 if (obj instanceof char[]) {
1286 buff.put((byte) TYPE_CHAR_ARRAY);
1287 char[] data = (char[]) obj;
1288 int len = data.length;
1289 DataUtils.writeVarInt(buff, len);
1290 buff.asCharBuffer().put(data);
1291 buff.position(buff.position() + len + len);
1292 } else {
1293 super.write(buff, obj);
1294 }
1295 }
1296
1297 @Override
1298 public Object read(ByteBuffer buff, int tag) {
1299 int len = DataUtils.readVarInt(buff);
1300 char[] data = new char[len];
1301 buff.asCharBuffer().get(data);
1302 buff.position(buff.position() + len + len);
1303 return data;
1304 }
1305
1306 }
1307
1308 /**
1309 * The type for char arrays.
1310 */
1311 class IntArrayType extends AutoDetectDataType {
1312
1313 IntArrayType(ObjectType base) {
1314 super(base, TYPE_INT_ARRAY);
1315 }
1316
1317 @Override
1318 public int getMemory(Object obj) {
1319 if (!(obj instanceof int[])) {
1320 return super.getMemory(obj);
1321 }
1322 return 24 + 4 * ((int[]) obj).length;
1323 }
1324
1325 @Override
1326 public int compare(Object aObj, Object bObj) {
1327 if (aObj instanceof int[] && bObj instanceof int[]) {
1328 int[] a = (int[]) aObj;
1329 int[] b = (int[]) bObj;
1330 return compareNotNull(a, b);
1331 }
1332 return super.compare(aObj, bObj);
1333 }
1334
1335 @Override
1336 public int getMaxLength(Object obj) {
1337 if (!(obj instanceof int[])) {
1338 return super.getMaxLength(obj);
1339 }
1340 return 1 + DataUtils.MAX_VAR_INT_LEN + 4 * ((int[]) obj).length;
1341 }
1342
1343 @Override
1344 public void write(ByteBuffer buff, Object obj) {
1345 if (obj instanceof int[]) {
1346 buff.put((byte) TYPE_INT_ARRAY);
1347 int[] data = (int[]) obj;
1348 int len = data.length;
1349 DataUtils.writeVarInt(buff, len);
1350 buff.asIntBuffer().put(data);
1351 buff.position(buff.position() + 4 * len);
1352 } else {
1353 super.write(buff, obj);
1354 }
1355 }
1356
1357 @Override
1358 public Object read(ByteBuffer buff, int tag) {
1359 int len = DataUtils.readVarInt(buff);
1360 int[] data = new int[len];
1361 buff.asIntBuffer().get(data);
1362 buff.position(buff.position() + 4 * len);
1363 return data;
1364 }
1365
1366 }
1367
1368 /**
1369 * The type for char arrays.
1370 */
1371 class LongArrayType extends AutoDetectDataType {
1372
1373 LongArrayType(ObjectType base) {
1374 super(base, TYPE_LONG_ARRAY);
1375 }
1376
1377 @Override
1378 public int getMemory(Object obj) {
1379 if (!(obj instanceof long[])) {
1380 return super.getMemory(obj);
1381 }
1382 return 24 + 8 * ((long[]) obj).length;
1383 }
1384
1385 @Override
1386 public int compare(Object aObj, Object bObj) {
1387 if (aObj instanceof long[] && bObj instanceof long[]) {
1388 long[] a = (long[]) aObj;
1389 long[] b = (long[]) bObj;
1390 return compareNotNull(a, b);
1391 }
1392 return super.compare(aObj, bObj);
1393 }
1394
1395 @Override
1396 public int getMaxLength(Object obj) {
1397 if (!(obj instanceof long[])) {
1398 return super.getMaxLength(obj);
1399 }
1400 return 1 + DataUtils.MAX_VAR_INT_LEN + 8 * ((long[]) obj).length;
1401 }
1402
1403 @Override
1404 public void write(ByteBuffer buff, Object obj) {
1405 if (obj instanceof long[]) {
1406 buff.put((byte) TYPE_LONG_ARRAY);
1407 long[] data = (long[]) obj;
1408 int len = data.length;
1409 DataUtils.writeVarInt(buff, len);
1410 buff.asLongBuffer().put(data);
1411 buff.position(buff.position() + 8 * len);
1412 } else {
1413 super.write(buff, obj);
1414 }
1415 }
1416
1417 @Override
1418 public Object read(ByteBuffer buff, int tag) {
1419 int len = DataUtils.readVarInt(buff);
1420 long[] data = new long[len];
1421 buff.asLongBuffer().get(data);
1422 buff.position(buff.position() + 8 * len);
1423 return data;
1424 }
1425
1426 }
1427
1428 /**
1429 * The type for serialized objects.
1430 */
1431 class SerializedObjectType extends AutoDetectDataType {
1432
1433 SerializedObjectType(ObjectType base) {
1434 super(base, TYPE_SERIALIZED_OBJECT);
1435 }
1436
1437 @SuppressWarnings("unchecked")
1438 @Override
1439 public int compare(Object aObj, Object bObj) {
1440 if (aObj == bObj) {
1441 return 0;
1442 }
1443 DataType ta = getType(aObj);
1444 DataType tb = getType(bObj);
1445 if (ta != this && ta == tb) {
1446 return ta.compare(aObj, bObj);
1447 }
1448 // TODO ensure comparable type (both may be comparable but not
1449 // with each other)
1450 if (aObj instanceof Comparable) {
1451 if (aObj.getClass().isAssignableFrom(bObj.getClass())) {
1452 return ((Comparable<Object>) aObj).compareTo(bObj);
1453 }
1454 }
1455 if (bObj instanceof Comparable) {
1456 if (bObj.getClass().isAssignableFrom(aObj.getClass())) {
1457 return -((Comparable<Object>) bObj).compareTo(aObj);
1458 }
1459 }
1460 byte[] a = Utils.serialize(aObj);
1461 byte[] b = Utils.serialize(bObj);
1462 return Utils.compareNotNull(a, b);
1463 }
1464
1465 @Override
1466 public int getMemory(Object obj) {
1467 DataType t = getType(obj);
1468 if (t == this) {
1469 return 1000;
1470 }
1471 return t.getMemory(obj);
1472 }
1473
1474 @Override
1475 public int getMaxLength(Object obj) {
1476 DataType t = getType(obj);
1477 if (t == this) {
1478 byte[] data = Utils.serialize(obj);
1479 return 1 + DataUtils.MAX_VAR_INT_LEN + data.length;
1480 }
1481 return t.getMaxLength(obj);
1482 }
1483
1484 @Override
1485 public void write(ByteBuffer buff, Object obj) {
1486 DataType t = getType(obj);
1487 if (t == this) {
1488 buff.put((byte) TYPE_SERIALIZED_OBJECT);
1489 byte[] data = Utils.serialize(obj);
1490 DataUtils.writeVarInt(buff, data.length);
1491 buff.put(data);
1492 } else {
1493 t.write(buff, obj);
1494 }
1495 }
1496
1497 @Override
1498 public Object read(ByteBuffer buff, int tag) {
1499 int len = DataUtils.readVarInt(buff);
1500 byte[] data = new byte[len];
1501 buff.get(data);
1502 return Utils.deserialize(data);
1503 }
1504
1505 }
1506
1507 }
1508