]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.common/src/org/simantics/db/common/utils/ValueType.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / utils / ValueType.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.common.utils;
13
14 public abstract class ValueType {
15
16     private ValueType() {
17     }    
18
19     public abstract int     getConstantSize(); // returns -1 if not constant size
20     public abstract void    serialize(ByteBuffer buffer, Object obj);
21     public abstract void    unsafeSerialize(ByteBuffer buffer, Object obj);
22     public abstract Object  deserialize(ByteBuffer buffer);
23
24     public boolean supportsNativeArray() {
25         return false;
26     }
27     public void serializeNativeArray(ByteBuffer buffer, Object obj, int length) {
28         // TODO Throw exception
29     }
30
31     public Object deserializeNativeArray(ByteBuffer buffer, int length) {
32         // TODO Throw exception
33         return null;
34     }
35
36     public byte[] serialize(Object obj) {
37         int constantSize = getConstantSize();
38         ByteBuffer buffer = new ByteBuffer(constantSize >= 0 ? constantSize : 0);
39         serialize(buffer, obj);
40         return buffer.content();
41     }
42
43     public Object deserialize(byte[] bytes) {
44         return deserialize(new ByteBuffer(bytes));
45     }    
46
47     public static class BooleanType extends ValueType {
48         public BooleanType() {}       
49
50         @Override
51         public int getConstantSize() {
52             return 1;
53         }        
54         @Override
55         public void serialize(ByteBuffer buffer, Object obj) {
56             buffer.needs(1);
57             buffer.putByte( (Boolean)obj == true ? (byte)1 : (byte)0 );
58
59         }
60         @Override
61         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
62             buffer.putByte( (Boolean)obj == true ? (byte)1 : (byte)0 );            
63         }
64         @Override
65         public Object deserialize(ByteBuffer buffer) {
66             return buffer.getByte() != 0;
67         }
68     }
69
70     public static class ByteType extends ValueType {
71         public ByteType() {}       
72
73         @Override
74         public int getConstantSize() {
75             return 1;
76         }        
77         @Override
78         public void serialize(ByteBuffer buffer, Object obj) {
79             buffer.needs(1);
80             buffer.putByte((Byte)obj);
81
82         }
83         @Override
84         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
85             buffer.putByte((Byte)obj);            
86         }
87         @Override
88         public Object deserialize(ByteBuffer buffer) {
89             return buffer.getByte();
90         }
91     }
92
93     public static class IntegerType extends ValueType {
94         public IntegerType() {}       
95
96         @Override
97         public int getConstantSize() {
98             return 4;
99         }        
100         @Override
101         public void serialize(ByteBuffer buffer, Object obj) {
102             buffer.needs(4);
103             buffer.putInt((Integer)obj);
104
105         }
106         @Override
107         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
108             buffer.putInt((Integer)obj);            
109         }
110         @Override
111         public Object deserialize(ByteBuffer buffer) {
112             return buffer.getInt();
113         }
114     }
115
116     public static class LongType extends ValueType {
117         public LongType() {}       
118
119         @Override
120         public int getConstantSize() {
121             return 8;
122         }        
123         @Override
124         public void serialize(ByteBuffer buffer, Object obj) {
125             buffer.needs(8);
126             buffer.putLong((Long)obj);
127
128         }
129         @Override
130         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
131             buffer.putLong((Long)obj);            
132         }
133         @Override
134         public Object deserialize(ByteBuffer buffer) {
135             return buffer.getLong();
136         }
137     }
138     
139     public static class FloatType extends ValueType {
140         public FloatType() {}       
141
142         @Override
143         public int getConstantSize() {
144             return 4;
145         }        
146         @Override
147         public void serialize(ByteBuffer buffer, Object obj) {
148             buffer.needs(4);
149             buffer.putFloat((Float)obj);
150
151         }
152         @Override
153         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
154             buffer.putFloat((Float)obj);            
155         }
156         @Override
157         public Object deserialize(ByteBuffer buffer) {
158             return buffer.getFloat();
159         }
160     }
161
162     public static class DoubleType extends ValueType {
163         public DoubleType() {}       
164
165         @Override
166         public int getConstantSize() {
167             return 8;
168         }        
169         @Override
170         public void serialize(ByteBuffer buffer, Object obj) {
171             buffer.needs(8);
172             buffer.putDouble((Double)obj);
173
174         }
175         @Override
176         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
177             buffer.putDouble((Double)obj);            
178         }
179         @Override
180         public Object deserialize(ByteBuffer buffer) {
181             return buffer.getDouble();
182         }
183         public boolean supportsNativeArray() {
184             return true;
185         }
186         public void serializeNativeArray(ByteBuffer buffer, Object obj, int length) {
187             double[] array = (double[])obj;
188             if(length < 0)
189                 buffer.putInt(array.length);
190             else
191                 ; // TODO check
192             for(double d : array)
193                 buffer.putDouble(d);
194         }
195
196         public Object deserializeNativeArray(ByteBuffer buffer, int length) {
197             double[] ret = new double[length];
198             for(int i=0;i<length;++i)
199                 ret[i] = buffer.getDouble();
200             return ret;
201         }
202     }
203
204     public static class StringType extends ValueType {
205         public StringType() {}       
206
207         @Override
208         public int getConstantSize() {
209             return -1;
210         }        
211         @Override
212         public void serialize(ByteBuffer buffer, Object obj) {
213             buffer.putString((String)obj);
214
215         }
216         @Override
217         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
218             // TODO Throw exception
219         }
220         @Override
221         public Object deserialize(ByteBuffer buffer) {
222             return buffer.getString();
223         }
224     }
225
226     public static class ProductType extends ValueType {
227         public final ValueType[] baseTypes;
228         private int constantSize;
229
230         public ProductType(ValueType[] baseTypes) {
231             this.baseTypes = baseTypes;
232             constantSize = 0;
233             for(ValueType b : baseTypes) {
234                 int temp = b.getConstantSize();
235                 if(temp==-1) {
236                     constantSize = -1;
237                     break;
238                 }
239                 constantSize += temp;
240             }
241         }
242
243         @Override
244         public int getConstantSize() {
245             return constantSize;
246         }        
247         @Override
248         public void serialize(ByteBuffer buffer, Object obj) {
249             if(constantSize >= 0) {
250                 buffer.needs(constantSize);
251                 unsafeSerialize(buffer, obj);
252             }
253             else {
254                 Object[] subobjects = (Object[])obj;
255                 // FIXME Catch cast exception
256                 // FIXME Check length
257                 for(int i=0;i<baseTypes.length;++i)
258                     baseTypes[i].serialize(buffer, subobjects[i]);
259             }
260         }
261         @Override
262         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
263             Object[] subobjects = (Object[])obj;
264             // FIXME Catch cast exception
265             // FIXME Check length
266             for(int i=0;i<baseTypes.length;++i)
267                 baseTypes[i].unsafeSerialize(buffer, subobjects[i]);
268         }
269         @Override
270         public Object deserialize(ByteBuffer buffer) {
271             Object[] ret = new Object[baseTypes.length];
272             for(int i=0;i<baseTypes.length;++i)
273                 ret[i] = baseTypes[i].deserialize(buffer);
274             return ret;
275         }
276     }
277
278     public static class Construction {
279         int constructor;
280         Object value;
281     }
282
283     public static class SumType extends ValueType {
284         public final ValueType[] baseTypes;
285         private int constantSize;
286
287         public SumType(ValueType[] baseTypes) {
288             this.baseTypes = baseTypes;
289             constantSize = -2;
290             for(ValueType b : baseTypes) {
291                 int temp = b.getConstantSize();
292                 if(temp != constantSize) {
293                     if(constantSize==-2 && temp >= 0)
294                         constantSize = temp;                        
295                     else {
296                         constantSize = -1;
297                         break;
298                     }
299                 }
300             }
301             if(constantSize >= 0)
302                 constantSize += 4;
303         }
304
305         @Override
306         public int getConstantSize() {
307             return constantSize;
308         }        
309         @Override
310         public void serialize(ByteBuffer buffer, Object obj) {
311             if(constantSize >= 0) {
312                 buffer.needs(constantSize);
313                 unsafeSerialize(buffer, obj);
314             }
315             else {
316                 Construction construction = (Construction)obj;
317                 // FIXME validate construction.constructor
318                 buffer.needs(4);
319                 buffer.putInt(construction.constructor);
320                 baseTypes[construction.constructor].serialize(buffer, construction.value);
321             }
322         }
323         @Override
324         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
325             Construction construction = (Construction)obj;
326             // FIXME validate construction.constructor
327             buffer.putInt(construction.constructor);
328             baseTypes[construction.constructor].unsafeSerialize(buffer, construction.value);
329         }
330         @Override
331         public Object deserialize(ByteBuffer buffer) {
332             Construction ret = new Construction();
333             ret.constructor = buffer.getInt();
334             // FIXME validate construction.constructor
335             ret.value = baseTypes[ret.constructor].deserialize(buffer);
336             return ret;
337         }
338     }
339
340     public static class VariableLengthArrayType extends ValueType {
341         public final ValueType baseType;
342         private int baseTypeConstantSize;
343         private boolean supportsNativeArray;
344
345         public VariableLengthArrayType(ValueType baseType) {
346             this.baseType = baseType;
347             baseTypeConstantSize = baseType.getConstantSize();
348             supportsNativeArray = baseType.supportsNativeArray();
349         }
350
351         @Override
352         public int getConstantSize() {
353             return -1;
354         }        
355
356         @Override
357         public void serialize(ByteBuffer buffer, Object obj) {
358             if(baseTypeConstantSize >= 0) {
359                 if(obj instanceof Object[]) {
360                     Object[] subobjects = (Object[])obj;              
361                     buffer.needs(4 + subobjects.length * baseTypeConstantSize);
362                     buffer.putInt(subobjects.length);
363                     for(Object subobj : subobjects)
364                         baseType.unsafeSerialize(buffer, subobj);
365                 }
366                 else if(supportsNativeArray) 
367                     baseType.serializeNativeArray(buffer, obj, -1);
368                 else
369                     ; // TODO exc
370
371             }
372             else {
373                 Object[] subobjects = (Object[])obj;              
374                 buffer.needs(4);
375                 buffer.putInt(subobjects.length);
376                 for(Object subobj : subobjects)
377                     baseType.serialize(buffer, subobj);
378             }
379         }
380         @Override
381         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
382             // TODO Throw exception
383         }
384         @Override
385         public Object deserialize(ByteBuffer buffer) {
386             int length = buffer.getInt();
387             if(supportsNativeArray) 
388                 return baseType.deserializeNativeArray(buffer, length);
389             else {
390                 Object[] ret = new Object[length];
391                 for(int i=0;i<length;++i)
392                     ret[i] = baseType.deserialize(buffer);
393                 return ret;
394             }
395         }
396     }
397
398     public static class FixedLengthArrayType extends ValueType {
399         public final ValueType baseType;
400         public final int dimension;
401         private int constantSize;
402         private boolean supportsNativeArray;
403
404         public FixedLengthArrayType(ValueType baseType, int dimension) {
405             this.baseType = baseType;
406             this.dimension = dimension;
407             constantSize = baseType.getConstantSize();
408             if(constantSize >= 0) {
409                 constantSize *= dimension;
410                 supportsNativeArray = baseType.supportsNativeArray();
411             }
412         }
413
414         @Override
415         public int getConstantSize() {
416             return constantSize;
417         }        
418
419         @Override
420         public void serialize(ByteBuffer buffer, Object obj) {
421             if(constantSize >= 0) {
422                 buffer.needs(constantSize);
423                 unsafeSerialize(buffer, obj);
424             }
425             else {
426                 Object[] subobjects = (Object[])obj;              
427                 // FIXME checks
428                 for(Object subobj : subobjects)
429                     baseType.serialize(buffer, subobj);
430             }
431         }
432         @Override
433         public void  unsafeSerialize(ByteBuffer buffer, Object obj) {
434             if(supportsNativeArray)
435                 baseType.serializeNativeArray(buffer, obj, dimension);
436             else {
437                 Object[] subobjects = (Object[])obj;              
438                 // FIXME checks
439                 for(Object subobj : subobjects)
440                     baseType.unsafeSerialize(buffer, subobj);
441             }
442         }
443         @Override
444         public Object deserialize(ByteBuffer buffer) {
445             if(supportsNativeArray) 
446                 return baseType.deserializeNativeArray(buffer, dimension);
447             else {
448                 Object[] ret = new Object[dimension];
449                 for(int i=0;i<dimension;++i)
450                     ret[i] = baseType.deserialize(buffer);
451                 return ret;
452             }
453         }
454     }    
455
456     static final private class ByteBuffer {
457         public byte[] bytes;
458         public int    offset;
459
460         public ByteBuffer(int capacity) {
461             this.bytes = new byte[capacity];
462             this.offset = 0;
463         }
464
465         public ByteBuffer(byte[] bytes) {
466             this.bytes = bytes;
467             this.offset = 0;
468         }
469
470         public void needs(int size) {
471             if(offset + size > bytes.length) {
472                 // FIXME bytes = Arrays.copyOf(bytes, newSize);
473                 byte[] newBytes = new byte[offset*2 + size];
474                 for(int i=0;i<bytes.length;++i)
475                     newBytes[i] = bytes[i];
476                 bytes = newBytes;
477             }
478         }
479
480         public byte[] content() {
481             if(offset == bytes.length)
482                 return bytes;
483             // FIXME bytes = Arrays.copyOf(bytes, offset);
484             byte[] newBytes = new byte[offset];
485             for(int i=0;i<offset;++i)
486                 newBytes[i] = bytes[i];
487             return newBytes;
488         }
489
490         public void putByte(byte v) {
491             bytes[offset] = v;
492             offset += 1;
493         }
494         public void putShort(short v) {
495             bytes[offset] = (byte) v;
496             bytes[offset+1] = (byte) (v >>> 8);
497             offset += 2;
498         }
499         public void putInt(int v) {
500             bytes[offset] = (byte) v;
501             bytes[offset+1] = (byte) (v >>> 8);
502             bytes[offset+2] = (byte) (v >>> 16);
503             bytes[offset+3] = (byte) (v >>> 24);
504             offset += 4;
505         }
506         public void putLong(long v) {
507             bytes[offset] = (byte) v;
508             bytes[offset+1] = (byte) (v >>> 8);
509             bytes[offset+2] = (byte) (v >>> 16);
510             bytes[offset+3] = (byte) (v >>> 24);
511             bytes[offset+4] = (byte) (v >>> 32);
512             bytes[offset+5] = (byte) (v >>> 40);
513             bytes[offset+6] = (byte) (v >>> 48);
514             bytes[offset+7] = (byte) (v >>> 56);
515             offset += 8;
516         }
517         public void putFloat(float _v) {
518             int v = Float.floatToIntBits(_v);
519             bytes[offset] = (byte) v;
520             bytes[offset+1] = (byte) (v >>> 8);
521             bytes[offset+2] = (byte) (v >>> 16);
522             bytes[offset+3] = (byte) (v >>> 24);
523             offset += 4;
524         }
525         public void putDouble(double _v) {
526             long v = Double.doubleToLongBits(_v);
527             bytes[offset] = (byte) v;
528             bytes[offset+1] = (byte) (v >>> 8);
529             bytes[offset+2] = (byte) (v >>> 16);
530             bytes[offset+3] = (byte) (v >>> 24);
531             bytes[offset+4] = (byte) (v >>> 32);
532             bytes[offset+5] = (byte) (v >>> 40);
533             bytes[offset+6] = (byte) (v >>> 48);
534             bytes[offset+7] = (byte) (v >>> 56);
535             offset += 8;
536         }
537         public void putString(String str) {
538
539             // UTF-16 -> modified UTF-8
540
541             int length = 4;
542             for(int i=0;i<str.length();++i) {
543                 char c = str.charAt(i);
544                 if(c < 0x80)
545                     length += 1;
546                 else if(c < 0x800)
547                     length += 2;
548                 else 
549                     length += 3;
550             }
551             needs(length);
552             putInt(str.length());
553             for(int i=0;i<str.length();++i) {
554                 char c = str.charAt(i);
555                 if(c < 0x80) {
556                     bytes[offset] = (byte)c;
557                     offset += 1;
558                 }
559                 else if(c < 0x800) {
560                     bytes[offset]   = (byte)(0xc0 + (c >>> 6));
561                     bytes[offset+1] = (byte)(0x80 + (c & 0x3f));
562                     offset += 2;
563                 }
564                 else {
565                     // FIXME handle range D800 - DFFF
566                     bytes[offset]   = (byte)(0xe0 + (c >>> 12));
567                     bytes[offset+1] = (byte)(0x80 + ((c >>> 6) & 0x3f));
568                     bytes[offset+2] = (byte)(0x80 + (c & 0x3f));
569                     offset += 3;
570                 }
571             }
572         }
573         public byte getByte() {
574             ++offset;
575             return bytes[offset-1];
576         }
577         public short getShort() {
578             int v = bytes[offset] & 0xFF;
579             v += (bytes[offset+1] & 0xFF) << 8;
580             offset += 2;
581             return (short)v;
582         }
583         public int getInt() {
584             int v = bytes[offset] & 0xFF;
585             v += (bytes[offset+1] & 0xFF) << 8;
586             v += (bytes[offset+2] & 0xFF) << 16;
587             v += (bytes[offset+3] & 0xFF) << 24;
588             offset += 4;
589             return v;
590         }
591         public long getLong() {
592             long v = bytes[offset] & 0xFFL;
593             v += (bytes[offset+1] & 0xFFL) << 8;
594             v += (bytes[offset+2] & 0xFFL) << 16;
595             v += (bytes[offset+3] & 0xFFL) << 24;
596             v += (bytes[offset+4] & 0xFFL) << 32;
597             v += (bytes[offset+5] & 0xFFL) << 40;
598             v += (bytes[offset+6] & 0xFFL) << 48;
599             v += (bytes[offset+7] & 0xFFL) << 56;
600             offset += 8;
601             return v;
602         }
603         public float getFloat() {
604             int v = bytes[offset] & 0xFF;
605             v += (bytes[offset+1] & 0xFF) << 8;
606             v += (bytes[offset+2] & 0xFF) << 16;
607             v += (bytes[offset+3] & 0xFF) << 24;
608             offset += 4;
609             return Float.intBitsToFloat(v);
610         }
611         public double getDouble() {
612             long v = bytes[offset] & 0xFFL;
613             v += (bytes[offset+1] & 0xFFL) << 8;
614             v += (bytes[offset+2] & 0xFFL) << 16;
615             v += (bytes[offset+3] & 0xFFL) << 24;
616             v += (bytes[offset+4] & 0xFFL) << 32;
617             v += (bytes[offset+5] & 0xFFL) << 40;
618             v += (bytes[offset+6] & 0xFFL) << 48;
619             v += (bytes[offset+7] & 0xFFL) << 56;
620             offset += 8;
621             return Double.longBitsToDouble(v);
622         }
623         public String getString() {
624             int length = getInt();
625             char[] chars = new char[length];
626             for(int i=0;i<length;++i) {
627                 int b0 = (int)bytes[offset];
628                 int c;
629                 if(b0 >= 0) {
630                     c = b0;
631                     offset += 1;
632                 }
633                 else if(b0 < 0xe0-256) {
634                     c = ((b0 & 0x1f) << 6) +
635                         (bytes[offset+1] & 0x3f);
636                     offset += 2;
637                 }
638                 else if(b0 < 0xf0-256) {
639                     c = ((b0 & 0x0f) << 12) +
640                         ((bytes[offset+1] & 0x3f) << 6) +
641                         (bytes[offset+2] & 0x3f);
642                     offset += 3;
643                 }
644                 else
645                     c = 0; // FIXME
646                 chars[i] = (char)c;
647             }
648             return new String(chars);
649         }
650         
651     }
652     
653 }