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