001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *   Granite Data Services is free software; you can redistribute it and/or
008 *   modify it under the terms of the GNU Lesser General Public
009 *   License as published by the Free Software Foundation; either
010 *   version 2.1 of the License, or (at your option) any later version.
011 *
012 *   Granite Data Services is distributed in the hope that it will be useful,
013 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
014 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
015 *   General Public License for more details.
016 *
017 *   You should have received a copy of the GNU Lesser General Public
018 *   License along with this library; if not, write to the Free Software
019 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 *   USA, or see <http://www.gnu.org/licenses/>.
021 */
022package org.granite.messaging.jmf.codec.std.impl;
023
024import java.io.IOException;
025import java.io.OutputStream;
026import java.lang.reflect.Array;
027
028import org.granite.messaging.jmf.CodecRegistry;
029import org.granite.messaging.jmf.DumpContext;
030import org.granite.messaging.jmf.InputContext;
031import org.granite.messaging.jmf.JMFEncodingException;
032import org.granite.messaging.jmf.OutputContext;
033import org.granite.messaging.jmf.codec.std.PrimitiveArrayCodec;
034import org.granite.messaging.jmf.codec.std.impl.util.FloatUtil;
035import org.granite.messaging.jmf.codec.std.impl.util.IntegerUtil;
036import org.granite.messaging.jmf.codec.std.impl.util.LongUtil;
037import org.granite.messaging.jmf.codec.std.impl.util.DoubleUtil;
038
039/**
040 * @author Franck WOLFF
041 */
042public class PrimitiveArrayCodecImpl extends AbstractArrayCodec implements PrimitiveArrayCodec {
043        
044        protected static final boolean[] BOOLEAN_0 = new boolean[0];
045        protected static final char[] CHARACTER_0 = new char[0];
046        protected static final byte[] BYTE_0 = new byte[0];
047        protected static final short[] SHORT_0 = new short[0];
048        protected static final int[] INTEGER_0 = new int[0];
049        protected static final long[] LONG_0 = new long[0];
050        protected static final float[] FLOAT_0 = new float[0];
051        protected static final double[] DOUBLE_0 = new double[0];
052        
053        public int getObjectType() {
054                return JMF_PRIMITIVE_ARRAY;
055        }
056
057        public boolean canEncode(Object v) {
058                return v.getClass().isArray() && getComponentType(v).isPrimitive();
059        }
060
061        public void encode(OutputContext ctx, Object v) throws IOException {
062                int indexOfStoredObject = ctx.indexOfObject(v);
063                if (indexOfStoredObject != -1) {
064                        int count = IntegerUtil.significantIntegerBytesCount0(indexOfStoredObject);
065
066                        // Write the index to a stored array:
067                        // [parameterized type{1}, index{1,4}]
068                        ctx.getOutputStream().write(0x80 | (count << 4) | JMF_PRIMITIVE_ARRAY);
069                        IntegerUtil.encodeInteger(ctx, indexOfStoredObject, count);
070                }
071                else {
072                        ctx.addToObjects(v);
073                        
074                        ArrayStructure structure = new ArrayStructure(v);
075                        int jmfComponentType = primitiveClassToJmfType(structure.componentType);
076                        int length = Array.getLength(v);
077                        int count = IntegerUtil.significantIntegerBytesCount0(length);
078
079                        final OutputStream os = ctx.getOutputStream();
080                        
081                        if (structure.dimensions == 0) {
082                                // Write the length and component type of the array:
083                                // [parameterized type{1}, length{1,4}, jmf component type{1}]
084                                os.write((count << 4) | JMF_PRIMITIVE_ARRAY);
085                                IntegerUtil.encodeInteger(ctx, length, count);
086                                os.write(jmfComponentType);
087                                
088                                writePrimitiveArrayContent0(ctx, v, jmfComponentType);
089                        }
090                        else {
091                                // Write the length, component type and dimensions of the array:
092                                // [parameterized type{1}, length{1,4}, jmf component type{1}, dimensions{1}]
093                                os.write(0x40 | (count << 4) | JMF_PRIMITIVE_ARRAY);
094                                IntegerUtil.encodeInteger(ctx, length, count);
095                                os.write(jmfComponentType);
096                                os.write(structure.dimensions);
097                                
098                                writePrimitiveArrayContent(ctx, v, jmfComponentType, structure.dimensions);
099                        }
100                }
101        }
102        
103        protected void writePrimitiveArrayContent(OutputContext ctx, Object v, int jmfComponentType, int dimensions) throws IOException {
104                final int length = Array.getLength(v);
105                if (length == 0)
106                        return;
107                
108                dimensions--;
109                final boolean writePrimitiveArray0 = (dimensions == 0);
110                final OutputStream os = ctx.getOutputStream();
111
112                for (int index = 0; index < length; index++) {
113                        Object component = Array.get(v, index);
114                        if (component == null)
115                                os.write(JMF_NULL);
116                        else {
117                                int indexOfStoredObject = ctx.indexOfObject(component);
118                                if (indexOfStoredObject != -1) {
119                                        int count = IntegerUtil.significantIntegerBytesCount0(indexOfStoredObject);
120                                        // Write the index to a stored array:
121                                        // [parameterized type{1}, index{1,4}]
122                                        ctx.getOutputStream().write(0x80 | (count << 4) | JMF_PRIMITIVE_ARRAY);
123                                        IntegerUtil.encodeInteger(ctx, indexOfStoredObject, count);
124                                }
125                                else {
126                                        ctx.addToObjects(component);
127                                        
128                                        int componentLength = Array.getLength(component);
129                                        int count = IntegerUtil.significantIntegerBytesCount0(componentLength);
130
131                                        // Write the length of the array:
132                                        // [parameterized type{1}, length{1,4}]
133                                        os.write((count << 4) | JMF_PRIMITIVE_ARRAY);
134                                        IntegerUtil.encodeInteger(ctx, componentLength, count);
135                                        
136                                        if (writePrimitiveArray0)
137                                                writePrimitiveArrayContent0(ctx, component, jmfComponentType);
138                                        else
139                                                writePrimitiveArrayContent(ctx, component, jmfComponentType, dimensions);
140                                }
141                        }
142                }
143        }
144        
145        protected void writePrimitiveArrayContent0(OutputContext ctx, Object v, int jmfComponentType) throws IOException {
146                switch (jmfComponentType) {
147                        case JMF_BOOLEAN:
148                                writeBooleanArrayContent0(ctx, (boolean[])v);
149                                break;
150                        case JMF_CHARACTER:
151                                writeCharacterArrayContent0(ctx, (char[])v);
152                                break;
153                        case JMF_BYTE:
154                                writeByteArrayContent0(ctx, (byte[])v);
155                                break;
156                        case JMF_SHORT:
157                                writeShortArrayContent0(ctx, (short[])v);
158                                break;
159                        case JMF_INTEGER:
160                                writeIntegerArrayContent0(ctx, (int[])v);
161                                break;
162                        case JMF_LONG:
163                                writeLongArrayContent0(ctx, (long[])v);
164                                break;
165                        case JMF_FLOAT:
166                                writeFloatArrayContent0(ctx, (float[])v);
167                                break;
168                        case JMF_DOUBLE:
169                                writeDoubleArrayContent0(ctx, (double[])v);
170                                break;
171                        default:
172                                throw new JMFEncodingException("Unsupported primitive type: " + jmfComponentType);
173                }
174        }
175        
176        protected void writeBooleanArrayContent0(OutputContext ctx, boolean[] v) throws IOException {
177                if (v.length == 0)
178                        return;
179
180                final OutputStream os = ctx.getOutputStream();
181
182                byte[] bytes = new byte[lengthOfBooleanArray(v.length)];
183                int i = 0, j = 0;
184                for (boolean b : v) {
185                        if (b)
186                                bytes[i] |= 0x80 >>> j;
187                        j++;
188                        if (j >= 8) {
189                                j = 0;
190                                i++;
191                        }
192                }
193                os.write(bytes);
194        }
195        
196        protected void writeCharacterArrayContent0(OutputContext ctx, char[] v) throws IOException {
197                if (v.length == 0)
198                        return;
199
200                final OutputStream os = ctx.getOutputStream();
201
202                for (char c : v) {
203                        os.write(c >>> 8);
204                        os.write(c);
205                }
206        }
207        
208        protected void writeByteArrayContent0(OutputContext ctx, byte[] v) throws IOException {
209                if (v.length == 0)
210                        return;
211
212                ctx.getOutputStream().write(v);
213        }
214        
215        protected void writeShortArrayContent0(OutputContext ctx, short[] v) throws IOException {
216                if (v.length == 0)
217                        return;
218
219                final OutputStream os = ctx.getOutputStream();
220                
221                for (short s : v) {
222                        os.write(s >>> 8);
223                        os.write(s);
224                }
225        }
226        
227        protected void writeIntegerArrayContent0(OutputContext ctx, int[] v) throws IOException {
228                if (v.length == 0)
229                        return;
230
231                for (int i : v)
232                        IntegerUtil.encodeVariableInteger(ctx, i);
233        }
234        
235        protected void writeLongArrayContent0(OutputContext ctx, long[] v) throws IOException {
236                if (v.length == 0)
237                        return;
238
239                for (long l : v)
240                        LongUtil.encodeVariableLong(ctx, l);
241        }
242        
243        protected void writeFloatArrayContent0(OutputContext ctx, float[] v) throws IOException {
244                if (v.length == 0)
245                        return;
246
247                for (float f : v)
248                        FloatUtil.encodeFloat(ctx, f);
249        }
250        
251        protected void writeDoubleArrayContent0(OutputContext ctx, double[] v) throws IOException {
252                if (v.length == 0)
253                        return;
254
255                for (double d : v)
256                        DoubleUtil.encodeVariableDouble(ctx, d);
257        }
258        
259        public Object decode(InputContext ctx, int parameterizedJmfType) throws IOException, ClassNotFoundException {
260                Object v = null;
261                
262                // Read the index (stored array) or length of the array:
263                // [index or length{1,4}]
264                int indexOrLength = IntegerUtil.decodeInteger(ctx, (parameterizedJmfType >>> 4) & 0x03);
265                if ((parameterizedJmfType & 0x80) != 0)
266                        v = ctx.getObject(indexOrLength);
267                else {
268                        // Read the component type and, if the 0x40 flag is set, the dimensions of the array:
269                        // [component type{1}, dimensions{0,1}]
270                        int jmfComponentType = ctx.safeRead();
271                        int dimensions = ((parameterizedJmfType & 0x40) == 0 ? 0 : ctx.safeRead());
272                        
273                        Class<?> componentType = jmfTypeToPrimitiveClass(jmfComponentType);
274                        if (dimensions == 0)
275                                v = readPrimitiveArray0(ctx, componentType, jmfComponentType, indexOrLength);
276                        else
277                                v = readPrimitiveArray(ctx, componentType, jmfComponentType, indexOrLength, dimensions);
278                }
279                
280                return v;
281        }
282        
283        protected Object readPrimitiveArray(InputContext ctx, Class<?> componentType, int jmfComponentType, int length, int dimensions) throws IOException {
284                Object v = newArray(componentType, length, dimensions);
285                ctx.addToObjects(v);
286                
287                dimensions--;
288
289                final boolean readPrimitiveArray0 = (dimensions == 0);
290                for (int index = 0; index < length; index++) {
291                        // Read the type of the element (must be JMF_NULL or JMF_PRIMITIVE_ARRAY):
292                        // [array element type{1}]
293                        int eltParameterizedJmfType = ctx.safeRead();
294                        
295                        if (eltParameterizedJmfType == JMF_NULL)
296                                Array.set(v, index, null);
297                        else {
298                                // Read the length of the element (sub array):
299                                // [length{1, 4}]
300                                int eltIndexOrLength = IntegerUtil.decodeInteger(ctx, (eltParameterizedJmfType >>> 4) & 0x03);
301                                if ((eltParameterizedJmfType & 0x80) != 0)
302                                        Array.set(v, index, ctx.getObject(eltIndexOrLength));
303                                else if (readPrimitiveArray0)
304                                        Array.set(v, index, readPrimitiveArray0(ctx, componentType, jmfComponentType, eltIndexOrLength));
305                                else
306                                        Array.set(v, index, readPrimitiveArray(ctx, componentType, jmfComponentType, eltIndexOrLength, dimensions));
307                        }
308                }
309                
310                return v;
311        }
312        
313        protected Object readPrimitiveArray0(InputContext ctx, Class<?> componentType, int jmfComponentType, int length) throws IOException {
314                Object v = null;
315                
316                switch (jmfComponentType) {
317                        case JMF_BOOLEAN:
318                                v = readBooleanArray0(ctx, length);
319                                break;
320                        case JMF_CHARACTER:
321                                v = readCharacterArray0(ctx, length);
322                                break;
323                        case JMF_BYTE:
324                                v = readByteArray0(ctx, length);
325                                break;
326                        case JMF_SHORT:
327                                v = readShortArray0(ctx, length);
328                                break;
329                        case JMF_INTEGER:
330                                v = readIntegerArray0(ctx, length);
331                                break;
332                        case JMF_LONG:
333                                v = readLongArray0(ctx, length);
334                                break;
335                        case JMF_FLOAT:
336                                v = readFloatArray0(ctx, length);
337                                break;
338                        case JMF_DOUBLE:
339                                v = readDoubleArray0(ctx, length);
340                                break;
341                        default:
342                                throw new JMFEncodingException("Unsupported primitive type: " + jmfComponentType);
343                }
344                
345                ctx.addToObjects(v);
346                
347                return v;
348        }
349        
350        protected boolean[] readBooleanArray0(InputContext ctx, int length) throws IOException {
351                if (length == 0)
352                        return BOOLEAN_0;
353                
354                boolean[] a = new boolean[length];
355                int nb = lengthOfBooleanArray(length);
356                for (int i = 0; i < nb; i++) {
357                        int b = ctx.safeRead();
358                        for (int j = 0; j < 8; j++) {
359                                int index = (i * 8) + j;
360                                if (index >= length)
361                                        break;
362                                a[index] = ((b & (0x80 >>> j)) != 0);
363                        }
364                }
365                return a;
366        }
367        
368        protected char[] readCharacterArray0(InputContext ctx, int length) throws IOException {
369                if (length == 0)
370                        return CHARACTER_0;
371                
372                char[] a = new char[length];
373                for (int i = 0; i < length; i++)
374                        a[i] = (char)((ctx.safeRead() << 8) | ctx.safeRead());
375                return a;
376        }
377        
378        protected byte[] readByteArray0(InputContext ctx, int length) throws IOException {
379                if (length == 0)
380                        return BYTE_0;
381                
382                byte[] a = new byte[length];
383                ctx.safeReadFully(a);
384                return a;
385        }
386        
387        protected short[] readShortArray0(InputContext ctx, int length) throws IOException {
388                if (length == 0)
389                        return SHORT_0;
390                
391                short[] a = new short[length];
392                for (int i = 0; i < length; i++)
393                        a[i] = (short)((ctx.safeRead() << 8) | ctx.safeRead());
394                return a;
395        }
396        
397        protected int[] readIntegerArray0(InputContext ctx, int length) throws IOException {
398                if (length == 0)
399                        return INTEGER_0;
400
401                int[] a = new int[length];
402                for (int i = 0; i < length; i++)
403                        a[i] = IntegerUtil.decodeVariableInteger(ctx);
404                return a;
405        }
406        
407        protected long[] readLongArray0(InputContext ctx, int length) throws IOException {
408                if (length == 0)
409                        return LONG_0;
410
411                long[] a = new long[length];
412                for (int i = 0; i < length; i++)
413                        a[i] = LongUtil.decodeVariableLong(ctx);
414                return a;
415        }
416        
417        protected float[] readFloatArray0(InputContext ctx, int length) throws IOException {
418                if (length == 0)
419                        return FLOAT_0;
420
421                float[] a = new float[length];
422                for (int i = 0; i < length; i++)
423                        a[i] = FloatUtil.decodeFloat(ctx);
424                return a;
425        }
426        
427        protected double[] readDoubleArray0(InputContext ctx, int length) throws IOException {
428                if (length == 0)
429                        return DOUBLE_0;
430                
431                double[] a = new double[length];
432                for (int i = 0; i < length; i++)
433                        a[i] = DoubleUtil.decodeVariableDouble(ctx);
434                return a;
435        }
436
437        public void dump(DumpContext ctx, int parameterizedJmfType) throws IOException {
438                final CodecRegistry codecRegistry = ctx.getSharedContext().getCodecRegistry();
439
440                int jmfType = codecRegistry.extractJmfType(parameterizedJmfType);
441                
442                if (jmfType != JMF_PRIMITIVE_ARRAY)
443                        throw newBadTypeJMFEncodingException(jmfType, parameterizedJmfType);
444                
445                // Read the index (stored array) or length of the array:
446                // [index or length{1,4}]
447                int indexOrLength = IntegerUtil.decodeInteger(ctx, (parameterizedJmfType >>> 4) & 0x03);
448                if ((parameterizedJmfType & 0x80) != 0)
449                        ctx.indentPrintLn("<" + ctx.getObject(indexOrLength) + "@" + indexOrLength + ">");
450                else {
451                        // Read the component type and, if the 0x40 flag is set, the dimensions of the array:
452                        // [component type{1}, dimensions{0,1}]
453                        int jmfComponentType = ctx.safeRead();
454                        int dimensions = ((parameterizedJmfType & 0x40) == 0 ? 0 : ctx.safeRead());
455                        
456                        Class<?> componentType = jmfTypeToPrimitiveClass(jmfComponentType);
457                        if (dimensions == 0)
458                                dumpPrimitiveArray0(ctx, componentType, jmfComponentType, indexOrLength);
459                        else
460                                dumpPrimitiveArray(ctx, componentType, jmfComponentType, indexOrLength, dimensions);
461                }
462        }
463        
464        protected void dumpPrimitiveArray(DumpContext ctx, Class<?> componentType, int jmfComponentType, int length, int dimensions) throws IOException {
465                final CodecRegistry codecRegistry = ctx.getSharedContext().getCodecRegistry();
466
467                String v = newDumpPrimitiveArray(jmfComponentType, length, dimensions);
468                int indexOfStoredObject = ctx.addToObjects(v);
469                ctx.indentPrintLn(v + "@" + indexOfStoredObject + ": {");
470                ctx.incrIndent(1);
471                
472                dimensions--;
473
474                final boolean dumpPrimitiveArray0 = (dimensions == 0);
475                for (int index = 0; index < length; index++) {
476                        // Read the type of the element (must be JMF_NULL or JMF_PRIMITIVE_ARRAY):
477                        // [array element type{1}]
478                        int parameterizedJmfType = ctx.safeRead();
479                        int jmfType = codecRegistry.extractJmfType(parameterizedJmfType);
480                        
481                        if (jmfType == JMF_NULL)
482                                ctx.indentPrintLn("null");
483                        else if (jmfType == JMF_PRIMITIVE_ARRAY) {
484                                // Read the length of the sub array:
485                                // [length{1, 4}]
486                                int subLengthOrIndex = IntegerUtil.decodeInteger(ctx, (parameterizedJmfType >>> 4) & 0x03);
487                                if ((parameterizedJmfType & 0x80) != 0)
488                                        ctx.indentPrintLn("<" + ctx.getObject(subLengthOrIndex) + "@" + subLengthOrIndex + ">");
489                                else if (dumpPrimitiveArray0)
490                                        dumpPrimitiveArray0(ctx, componentType, jmfComponentType, subLengthOrIndex);
491                                else
492                                        dumpPrimitiveArray(ctx, componentType, jmfComponentType, subLengthOrIndex, dimensions);
493                        }
494                        else
495                                newBadTypeJMFEncodingException(jmfType, parameterizedJmfType);
496                }
497                
498                ctx.incrIndent(-1);
499                ctx.indentPrintLn("}");
500        }
501        
502        protected void dumpPrimitiveArray0(DumpContext ctx, Class<?> componentType, int jmfComponentType, int length) throws IOException {
503                String v = newDumpPrimitiveArray(jmfComponentType, length, 0);
504                int indexOfStoredObject = ctx.addToObjects(v);
505                ctx.indentPrint(v + "@" + indexOfStoredObject + ": {");
506                
507                switch (jmfComponentType) {
508                        case JMF_BOOLEAN:
509                                dumpBooleanArray0(ctx, length);
510                                break;
511                        case JMF_CHARACTER:
512                                dumpCharacterArray0(ctx, length);
513                                break;
514                        case JMF_BYTE:
515                                dumpByteArray0(ctx, length);
516                                break;
517                        case JMF_SHORT:
518                                dumpShortArray0(ctx, length);
519                                break;
520                        case JMF_INTEGER:
521                                dumpIntegerArray0(ctx, length);
522                                break;
523                        case JMF_LONG:
524                                dumpLongArray0(ctx, length);
525                                break;
526                        case JMF_FLOAT:
527                                dumpFloatArray0(ctx, length);
528                                break;
529                        case JMF_DOUBLE:
530                                dumpDoubleArray0(ctx, length);
531                                break;
532                        default:
533                                throw new JMFEncodingException("Unsupported primitive type: " + jmfComponentType);
534                }
535
536                ctx.noIndentPrintLn("}");
537        }
538        
539        protected String newDumpPrimitiveArray(int jmfComponentType, int length, int dimensions) throws IOException {
540                StringBuilder sb = new StringBuilder();
541                
542                switch (jmfComponentType) {
543                        case JMF_BOOLEAN: sb.append("boolean"); break;
544                        case JMF_CHARACTER: sb.append("char"); break;
545                        case JMF_BYTE: sb.append("byte"); break;
546                        case JMF_SHORT: sb.append("short"); break;
547                        case JMF_INTEGER: sb.append("int"); break;
548                        case JMF_LONG: sb.append("long"); break;
549                        case JMF_FLOAT: sb.append("float"); break;
550                        case JMF_DOUBLE: sb.append("double"); break;
551                        default: throw new JMFEncodingException("Unsupported primitive type: " + jmfComponentType);
552                }
553                
554                sb.append('[').append(length).append(']');
555                
556                for (int i = 0; i < dimensions; i++)
557                        sb.append("[]");
558                
559                return sb.toString();
560        }
561        
562        protected void dumpBooleanArray0(DumpContext ctx, int length) throws IOException {
563                if (length == 0)
564                        return;
565
566                int nb = lengthOfBooleanArray(length);
567                for (int i = 0; i < nb; i++) {
568                        int b = ctx.safeRead();
569                        for (int j = 0; j < 8; j++) {
570                                int index = (i * 8) + j;
571                                if (index >= length)
572                                        break;
573                                if (index > 0)
574                                        ctx.print(", ");
575                                ctx.print(String.valueOf(((b & (0x80 >>> j)) != 0)));
576                        }
577                }
578        }
579        
580        protected void dumpCharacterArray0(DumpContext ctx, int length) throws IOException {
581                for (int i = 0; i < length; i++) {
582                        if (i > 0)
583                                ctx.print(", ");
584                        ctx.print(String.valueOf((char)((ctx.safeRead() << 8) | ctx.safeRead())));
585                }
586        }
587        
588        protected void dumpByteArray0(DumpContext ctx, int length) throws IOException {
589                for (int i = 0; i < length; i++) {
590                        if (i > 0)
591                                ctx.print(", ");
592                        ctx.print(String.valueOf((byte)ctx.safeRead()));
593                }
594        }
595        
596        protected void dumpShortArray0(DumpContext ctx, int length) throws IOException {
597                for (int i = 0; i < length; i++) {
598                        if (i > 0)
599                                ctx.print(", ");
600                        ctx.print(String.valueOf((short)(ctx.safeRead() << 8) | ctx.safeRead()));
601                }
602        }
603        
604        protected void dumpIntegerArray0(DumpContext ctx, int length) throws IOException {
605                for (int i = 0; i < length; i++) {
606                        if (i > 0)
607                                ctx.print(", ");
608                        ctx.print(String.valueOf(IntegerUtil.decodeVariableInteger(ctx)));
609                }
610        }
611        
612        protected void dumpLongArray0(DumpContext ctx, int length) throws IOException {
613                for (int i = 0; i < length; i++) {
614                        if (i > 0)
615                                ctx.print(", ");
616                        ctx.print(String.valueOf(LongUtil.decodeVariableLong(ctx)));
617                }
618        }
619        
620        protected void dumpFloatArray0(DumpContext ctx, int length) throws IOException {
621                for (int i = 0; i < length; i++) {
622                        if (i > 0)
623                                ctx.print(", ");
624                        ctx.print(String.valueOf(FloatUtil.decodeFloat(ctx)));
625                }
626        }
627        
628        protected void dumpDoubleArray0(DumpContext ctx, int length) throws IOException {
629                for (int i = 0; i < length; i++) {
630                        if (i > 0)
631                                ctx.print(", ");
632                        ctx.print(String.valueOf(DoubleUtil.decodeVariableDouble(ctx)));
633                }
634        }
635        
636        protected int lengthOfBooleanArray(int nb) {
637                return (nb / 8) + (nb % 8 != 0 ? 1 : 0);
638        }
639        
640        protected int primitiveClassToJmfType(Class<?> primitiveClass) throws JMFEncodingException {
641                if (primitiveClass == byte.class)
642                        return JMF_BYTE;
643                if (primitiveClass == int.class)
644                        return JMF_INTEGER;
645                if (primitiveClass == char.class)
646                        return JMF_CHARACTER;
647                if (primitiveClass == double.class)
648                        return JMF_DOUBLE;
649                if (primitiveClass == long.class)
650                        return JMF_LONG;
651                if (primitiveClass == boolean.class)
652                        return JMF_BOOLEAN;
653                if (primitiveClass == float.class)
654                        return JMF_FLOAT;
655                if (primitiveClass == short.class)
656                        return JMF_SHORT;
657                throw new JMFEncodingException("Not a primitive class: " + primitiveClass);
658        }
659        
660        protected Class<?> jmfTypeToPrimitiveClass(int jmfType) throws JMFEncodingException {
661                switch (jmfType) {
662                case JMF_BOOLEAN:
663                        return boolean.class;
664                case JMF_BYTE:
665                        return byte.class;
666                case JMF_CHARACTER:
667                        return char.class;
668                case JMF_SHORT:
669                        return short.class;
670                case JMF_INTEGER:
671                        return int.class;
672                case JMF_LONG:
673                        return long.class;
674                case JMF_FLOAT:
675                        return float.class;
676                case JMF_DOUBLE:
677                        return double.class;
678                }
679                throw new JMFEncodingException("Not a primitive JMF type: " + jmfType);
680        }
681}