Typo fixes
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / io / ScilabTypeCoder.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2015 - Scilab Enterprises - Clement DAVID
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15 package org.scilab.modules.xcos.io;
16
17 import java.nio.ByteBuffer;
18 import java.nio.DoubleBuffer;
19 import java.nio.IntBuffer;
20 import java.nio.LongBuffer;
21 import java.nio.charset.Charset;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.IllegalFormatException;
26 import java.util.function.Consumer;
27 import org.scilab.modules.types.ScilabBoolean;
28 import org.scilab.modules.types.ScilabDouble;
29 import org.scilab.modules.types.ScilabInteger;
30 import org.scilab.modules.types.ScilabIntegerTypeEnum;
31 import org.scilab.modules.types.ScilabList;
32 import org.scilab.modules.types.ScilabMList;
33 import org.scilab.modules.types.ScilabString;
34 import org.scilab.modules.types.ScilabTList;
35 import org.scilab.modules.types.ScilabType;
36 import org.scilab.modules.types.ScilabTypeEnum;
37 import org.scilab.modules.xcos.VectorOfDouble;
38 import org.scilab.modules.xcos.VectorOfInt;
39 import org.scilab.modules.xcos.VectorOfScicosID;
40
41 import java.util.logging.Level;
42 import java.util.logging.Logger;
43
44 /**
45  * Encode and decode using a var2vec / vec2var compatible encoding.
46  *
47  * <p>
48  * This encoder is used to store arbitrary data to the model. Usually some
49  * properties are hard to map to both Java and C++ STL type system, using a
50  * shared encoding let us provide an implementation whatever the language is
51  * without sharing too low-level information.
52  */
53 public class ScilabTypeCoder {
54
55     private static final Logger LOG = Logger.getLogger("org.scilab.modules.xcos.io");
56
57     class JavaScilabType {
58
59         final ScilabTypeEnum type;
60         final ScilabIntegerTypeEnum intType;
61
62         public JavaScilabType(ScilabTypeEnum type, ScilabIntegerTypeEnum intType) {
63             this.type = type;
64             this.intType = intType;
65         }
66     }
67
68     /**
69      * current position in the vec buffer
70      */
71     int position = 0;
72
73     public ScilabTypeCoder() {
74     }
75
76     /*
77      * var2vec implementation
78      */
79     /**
80      * Encode any scilab type to a buffer
81      *
82      * @param var the Scilab value to encode
83      * @return the encoded buffer
84      */
85     public VectorOfDouble var2vec(ScilabType var) {
86         final ScilabType value;
87         if (var == null) {
88             value = new ScilabDouble();
89         } else {
90             value = var;
91         }
92
93         if (LOG.isLoggable(Level.FINER)) {
94             LOG.entering(ScilabTypeCoder.class.getCanonicalName(), "var2vec");
95         }
96
97         VectorOfDouble vec = new VectorOfDouble();
98         encode(value, vec);
99
100         // System.err.println("var2vec:" + var.toString() + ":" + toString(vec));
101         if (LOG.isLoggable(Level.FINE)) {
102             LOG.log(Level.FINE, "var2vec:{0}:{1}", new Object[] {var.toString(), toString(vec)});
103         }
104
105         if (LOG.isLoggable(Level.FINER)) {
106             LOG.exiting(ScilabTypeCoder.class.getCanonicalName(), "var2vec");
107         }
108
109         return vec;
110     }
111
112     @SuppressWarnings("unchecked")
113     private VectorOfDouble encode(ScilabType var, VectorOfDouble vec) {
114         switch (var.getType()) {
115             case sci_matrix:
116                 encode((ScilabDouble) var, vec);
117                 break;
118             case sci_ints:
119                 encode((ScilabInteger) var, vec);
120                 break;
121             case sci_boolean:
122                 encode((ScilabBoolean) var, vec);
123                 break;
124             case sci_strings:
125                 encode((ScilabString) var, vec);
126                 break;
127             case sci_list:
128                 encode((ArrayList<ScilabType>) var, vec, var.getType());
129                 break;
130             case sci_mlist:
131                 encode((ArrayList<ScilabType>) var, vec, var.getType());
132                 break;
133             case sci_tlist:
134                 encode((ArrayList<ScilabType>) var, vec, var.getType());
135                 break;
136             default:
137                 break;
138         }
139
140         return vec;
141     }
142
143     /**
144      * Encode the double data
145      *
146      * @param var the data to encode
147      * @param vec the resulting buffer
148      */
149     private void encode(ScilabDouble var, VectorOfDouble vec) {
150         // Header
151         encodeHeader(var, vec, ScilabTypeEnum.sci_matrix);
152
153         // specific flag for managing the complex case
154         if (var.isReal()) {
155             vec.add(0f);
156         } else {
157             vec.add(1f);
158         }
159
160         // push the data
161         for (int i = 0; i < var.getHeight(); i++) {
162             for (int j = 0; j < var.getWidth(); j++) {
163                 vec.add(var.getRealElement(i, j));
164             }
165         }
166
167         // push the complex data
168         if (!var.isReal()) {
169             for (int i = 0; i < var.getHeight(); i++) {
170                 for (int j = 0; j < var.getWidth(); j++) {
171                     vec.add(var.getImaginaryElement(i, j));
172                 }
173             }
174         }
175     }
176
177     private void encode(ScilabInteger var, VectorOfDouble vec) {
178         // pre-processing: retrieve the raw data per type
179         int sizeof;
180         long[][] longData = null;
181         short[][] shortData = null;
182         int[][] intData = null;
183         byte[][] byteData = null;
184         switch (var.getPrec()) {
185             case sci_int64:
186             case sci_uint64:
187                 sizeof = Long.BYTES;
188                 longData = var.getDataAsLong();
189                 break;
190             case sci_int32:
191             case sci_uint32:
192                 sizeof = Integer.BYTES;
193                 intData = var.getDataAsInt();
194                 break;
195             case sci_int16:
196             case sci_uint16:
197                 sizeof = Short.BYTES;
198                 shortData = var.getDataAsShort();
199                 break;
200             case sci_int8:
201             case sci_uint8:
202                 sizeof = Byte.BYTES;
203                 byteData = var.getDataAsByte();
204                 break;
205             default:
206                 throw new IllegalArgumentException();
207         }
208
209         // Header
210         encodeHeader(var, vec, ScilabTypeEnum.sci_ints);
211
212         // push the data on a pre-allocated space
213         final int requiredBytes = sizeof * var.getHeight() * var.getWidth();
214         final int doubleLen = (requiredBytes + Double.BYTES - 1) / Double.BYTES;
215         final int index = vec.size();
216         vec.resize(index + doubleLen);
217         ByteBuffer view = vec.asByteBuffer(index, doubleLen);
218
219         for (int i = 0; i < var.getHeight(); i++) {
220             for (int j = 0; j < var.getWidth(); j++) {
221                 switch (var.getPrec()) {
222                     case sci_int64:
223                     case sci_uint64:
224                         view.putLong(longData[i][j]);
225                         break;
226                     case sci_int32:
227                     case sci_uint32:
228                         view.putInt(intData[i][j]);
229                         break;
230                     case sci_int16:
231                     case sci_uint16:
232                         view.putShort(shortData[i][j]);
233                         break;
234                     case sci_int8:
235                     case sci_uint8:
236                         view.put(byteData[i][j]);
237                         break;
238                 }
239             }
240         }
241     }
242
243     private void encode(ScilabBoolean var, VectorOfDouble vec) {
244         // header
245         encodeHeader(var, vec, ScilabTypeEnum.sci_boolean);
246
247         // put all the boolean as int accordingly to Scilab 6 implementation
248         final int requiredBytes = Integer.BYTES * var.getHeight() * var.getWidth();
249         final int doubleLen = (requiredBytes + Double.BYTES - 1) / Double.BYTES;
250         int index = vec.size();
251         vec.resize(index + doubleLen);
252
253         ByteBuffer buffer = vec.asByteBuffer(index, doubleLen);
254
255         for (int i = 0; i < var.getHeight(); i++) {
256             for (int j = 0; j < var.getWidth(); j++) {
257                 buffer.putInt(var.getData()[i][j] ? 1 : 0);
258             }
259         }
260     }
261
262     private void encode(ScilabString var, VectorOfDouble vec) {
263         // header
264         encodeHeader(var, vec, ScilabTypeEnum.sci_strings);
265
266         // add the offset table which contains the offset of each UTF-8 encoded strings
267         int offsetTableStart = vec.size();
268         vec.resize(offsetTableStart + var.getHeight() * var.getWidth());
269         int offsetTableAccumulated = 0;
270
271         // encode the strings as UTF-8 and store the associated offset
272         Charset utf8 = Charset.forName("UTF-8");
273         for (int i = 0; i < var.getHeight(); i++) {
274             for (int j = 0; j < var.getWidth(); j++) {
275                 String str = var.getData()[i][j];
276                 byte[] bytes = str.getBytes(utf8);
277                 // append the terminal '\0'
278                 final int requiredBytes = bytes.length + 1;
279                 final int doubleLen = (requiredBytes + Double.BYTES - 1) / Double.BYTES;
280
281                 // set the offset
282                 offsetTableAccumulated += doubleLen;
283                 vec.set(offsetTableStart++, offsetTableAccumulated);
284
285                 // push the data through a temporary byte buffer
286                 int index = vec.size();
287                 vec.resize(index + doubleLen);
288                 vec.asByteBuffer(index, doubleLen).put(bytes).put((byte) 0);
289
290             }
291         }
292     }
293
294     private void encode(ArrayList<ScilabType> var, VectorOfDouble vec, ScilabTypeEnum as) {
295         // header
296         encodeHeader(var, vec, as);
297
298         // encode list content
299         for (ScilabType localVar : var) {
300             encode(localVar, vec);
301         }
302     }
303
304     /**
305      * Helper method to add an header of the detected type
306      *
307      * @param var the scilab matrix type to encode
308      * @param vec the raw encoded data container
309      * @param as the type to encode
310      * @param detected the detected type
311      */
312     @SuppressWarnings({"unchecked", "fallthrough"})
313     private void encodeHeader(Object var, VectorOfDouble vec, final ScilabTypeEnum as) {
314         ScilabType matrix = null;
315         ArrayList<ScilabType> list = null;
316
317         // defensive programming
318         switch (as) {
319             case sci_boolean:
320             case sci_ints:
321             case sci_matrix:
322             case sci_strings:
323                 matrix = (ScilabType) var;
324                 break;
325             case sci_list:
326             case sci_mlist:
327             case sci_tlist:
328                 list = (ArrayList<ScilabType>) var;
329                 break;
330             default:
331                 throw new IllegalArgumentException();
332         }
333
334         vec.add(as.swigValue());
335         if (matrix instanceof ScilabInteger) {
336             vec.add(((ScilabInteger) matrix).getPrec().swigValue());
337         }
338         if (matrix != null) {
339             vec.add(2);
340             vec.add(matrix.getHeight());
341             vec.add(matrix.getWidth());
342         } else if (list != null) {
343             vec.add(list.size());
344         } else {
345             throw new IllegalArgumentException();
346         }
347     }
348
349     /*
350      * vec2var implementation
351      */
352     /**
353      * Decode a scilab type from a buffer
354      *
355      * @param vec the buffer containing encoded scilab types
356      * @return the decoded scilab type
357      */
358     public ScilabType vec2var(VectorOfDouble vec) {
359         position = 0;
360
361         if (LOG.isLoggable(Level.FINER)) {
362             LOG.entering(ScilabTypeCoder.class.getName(), "vec2var", vec);
363         }
364
365         ScilabType var = decodeHeader(vec);
366         decode(vec, var);
367
368         // System.err.println("vec2var:" + toString(vec) + ":" + var.toString());
369         if (LOG.isLoggable(Level.FINE)) {
370             LOG.log(Level.FINE, "vec2var:{0}:{1}", new Object[] {toString(vec), var.toString()});
371         }
372
373         if (LOG.isLoggable(Level.FINER)) {
374             LOG.exiting(ScilabTypeCoder.class.getName(), "vec2var");
375         }
376
377         return var;
378     }
379
380     @FunctionalInterface
381     private static interface StoreFunction<R, C, V> {
382         public void apply(R r, C c, V v);
383     }
384
385     @SuppressWarnings("unchecked")
386     private ScilabType decode(VectorOfDouble vec, ScilabType var) {
387         switch (var.getType()) {
388             case sci_matrix:
389                 decode(vec, (ScilabDouble) var);
390                 break;
391             case sci_ints:
392                 decode(vec, (ScilabInteger) var);
393                 break;
394             case sci_boolean:
395                 decode(vec, (ScilabBoolean) var);
396                 break;
397             case sci_strings:
398                 decode(vec, (ScilabString) var);
399                 break;
400             case sci_list:
401                 decode(vec, (ArrayList<ScilabType>) var);
402                 break;
403             case sci_mlist:
404                 decode(vec, (ArrayList<ScilabType>) var);
405                 break;
406             case sci_tlist:
407                 decode(vec, (ArrayList<ScilabType>) var);
408                 break;
409             default:
410                 break;
411         }
412         return var;
413     }
414
415     private ScilabType decode(VectorOfDouble vec, ScilabDouble var) {
416         double[][] realPart = var.getRealPart();
417         for (int i = 0; i < var.getHeight(); i++) {
418             for (int j = 0; j < var.getWidth(); j++) {
419                 realPart[i][j] = vec.get(position++);
420             }
421         }
422
423         if (!var.isReal()) {
424             double[][] imaginaryPart = var.getImaginaryPart();
425
426             for (int i = 0; i < var.getHeight(); i++) {
427                 for (int j = 0; j < var.getWidth(); j++) {
428                     imaginaryPart[i][j] = vec.get(position++);
429                 }
430             }
431         }
432         return var;
433     }
434
435     private ScilabType decode(VectorOfDouble vec, ScilabInteger var) {
436         final int sizeof;
437         long[][] longData = null;
438         short[][] shortData = null;
439         int[][] intData = null;
440         byte[][] byteData = null;
441
442         switch (var.getPrec()) {
443             case sci_int64:
444             case sci_uint64:
445                 sizeof = Long.BYTES;
446                 longData = var.getDataAsLong();
447                 break;
448             case sci_int32:
449             case sci_uint32:
450                 sizeof = Integer.BYTES;
451                 intData = var.getDataAsInt();
452                 break;
453             case sci_int16:
454             case sci_uint16:
455                 sizeof = Short.BYTES;
456                 shortData = var.getDataAsShort();
457                 break;
458             case sci_int8:
459             case sci_uint8:
460                 sizeof = Byte.BYTES;
461                 byteData = var.getDataAsByte();
462                 break;
463             default:
464                 throw new IllegalArgumentException();
465         }
466
467         final int doubleLen = (sizeof * var.getHeight() * var.getWidth()) / Double.BYTES + 1;
468         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
469
470         for (int i = 0; i < var.getHeight(); i++) {
471             for (int j = 0; j < var.getWidth(); j++) {
472                 switch (var.getPrec()) {
473                     case sci_int64:
474                     case sci_uint64:
475                         longData[i][j] = view.getLong();
476                         break;
477                     case sci_int32:
478                     case sci_uint32:
479                         intData[i][j] = view.getInt();
480                         break;
481                     case sci_int16:
482                     case sci_uint16:
483                         shortData[i][j] = view.getShort();
484                         break;
485                     case sci_int8:
486                     case sci_uint8:
487                         byteData[i][j] = view.get();
488                         break;
489                 }
490             }
491         }
492         position += doubleLen;
493
494         return var;
495     }
496
497     private ScilabType decode(VectorOfDouble vec, ScilabBoolean var) {
498         final boolean[][] data = var.getData();
499
500         final int doubleLen = (Integer.BYTES * var.getHeight() * var.getWidth()) / Double.BYTES + 1;
501         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
502
503         for (int i = 0; i < var.getHeight(); i++) {
504             for (int j = 0; j < var.getWidth(); j++) {
505                 data[i][j] = view.getInt() != 0;
506             }
507         }
508         position += doubleLen;
509         return var;
510     }
511
512     private ScilabType decode(VectorOfDouble vec, ScilabString var) {
513         final String[][] data = var.getData();
514         decodeString(var.getHeight(), var.getWidth(), vec, (i, j, str) -> data[i][j] = str);
515         return var;
516     }
517
518     private void decodeString(int height, int width, VectorOfDouble vec, StoreFunction<Integer, Integer, String> store) {
519         // reconstruct the offset
520         int[][] offset = new int[height][width];
521         for (int i = 0; i < height; i++) {
522             for (int j = 0; j < width; j++) {
523                 offset[i][j] = (int) vec.get(position++);
524             }
525         }
526
527         Charset utf8 = Charset.forName("UTF-8");
528         int accumulatedOffset = 0;
529         // reconstruct each String object
530         for (int i = 0; i < height; i++) {
531             for (int j = 0; j < width; j++) {
532                 final int nbOfDouble = offset[i][j] - accumulatedOffset;
533                 ByteBuffer view = vec.asByteBuffer(position, nbOfDouble);
534                 byte[] bytes = new byte[nbOfDouble * Double.BYTES];
535
536                 view.get(bytes);
537
538                 // to avoid mis-decoding we have to pass the len of bytes
539                 int strlen = 0;
540                 while (bytes[strlen] != 0) {
541                     strlen++;
542                 }
543
544                 store.apply(i, j, new String(bytes, 0, strlen, utf8));
545
546                 accumulatedOffset += nbOfDouble;
547                 position += nbOfDouble;
548             }
549         }
550     }
551
552     private ScilabType decode(VectorOfDouble vec, ArrayList<ScilabType> var) {
553         for (int i = 0; i < var.size(); i++) {
554             ScilabType sub = decodeHeader(vec);
555             decode(vec, sub);
556
557             var.set(i, sub);
558         }
559         return (ScilabType) var;
560     }
561
562     @SuppressWarnings("fallthrough")
563     private ScilabType decodeHeader(VectorOfDouble vec) {
564         int nativeScilabType = (int) vec.get(position++);
565
566         // specific integer sub-type
567         int precision = 0;
568
569         // for data[][]-based type
570         int height = 0;
571         int width = 0;
572
573         // for ArrayList-based type
574         int listLen = 0;
575
576         final ScilabTypeEnum type = ScilabTypeEnum.swigToEnum(nativeScilabType);
577         switch (type) {
578             case sci_ints:
579                 // special case for integer precision
580                 precision = (int) vec.get(position++);
581             case sci_matrix:
582             case sci_boolean:
583             case sci_strings:
584                 position++; // n-Dims not managed
585                 height = (int) vec.get(position++);
586                 width = (int) vec.get(position++);
587                 break;
588             case sci_list:
589             case sci_mlist:
590             case sci_tlist:
591                 listLen = (int) vec.get(position++);
592                 break;
593             default:
594                 throw new IllegalArgumentException();
595         }
596
597         // special case for complex double matrix
598         double[][] imagData = null;
599         if (type == ScilabTypeEnum.sci_matrix) {
600             boolean isComplex = vec.get(position++) != 0;
601
602             if (isComplex) {
603                 imagData = new double[height][width];
604             }
605         }
606
607         // allocate the right type with the decoded properties
608         switch (type) {
609             case sci_matrix:
610                 if (height * width == 0) {
611                     return new ScilabDouble();
612                 } else {
613                     return new ScilabDouble(new double[height][width], imagData);
614                 }
615             case sci_boolean:
616                 if (height * width == 0) {
617                     return new ScilabBoolean();
618                 } else {
619                     return new ScilabBoolean(new boolean[height][width]);
620                 }
621             case sci_ints:
622                 if (height * width == 0) {
623                     return new ScilabInteger();
624                 } else {
625                     switch (ScilabIntegerTypeEnum.swigToEnum(precision)) {
626                         case sci_int8:
627                             return new ScilabInteger(new byte[height][width], false);
628                         case sci_int16:
629                             return new ScilabInteger(new short[height][width], false);
630                         case sci_int32:
631                             return new ScilabInteger(new int[height][width], false);
632                         case sci_int64:
633                             return new ScilabInteger(new long[height][width], false);
634                         case sci_uint8:
635                             return new ScilabInteger(new byte[height][width], true);
636                         case sci_uint16:
637                             return new ScilabInteger(new short[height][width], true);
638                         case sci_uint32:
639                             return new ScilabInteger(new int[height][width], true);
640                         case sci_uint64:
641                             return new ScilabInteger(new long[height][width], true);
642
643                     }
644                 }
645             case sci_strings:
646                 if (height * width == 0) {
647                     return new ScilabString();
648                 } else {
649                     return new ScilabString(new String[height][width]);
650                 }
651             case sci_list:
652                 return new ScilabList(Collections.nCopies(listLen, null));
653             case sci_mlist:
654                 return new ScilabMList(new String[listLen - 1], Collections.nCopies(listLen - 1, null));
655             case sci_tlist:
656                 return new ScilabTList(new String[listLen - 1], Collections.nCopies(listLen - 1, null));
657             default:
658                 throw new IllegalArgumentException();
659
660         }
661     }
662
663     /**
664      * Format the encoded value accordingly to the Java format string
665      *
666      * @param format a
667      * {@link String#format(java.lang.String, java.lang.Object...)} compatible
668      * argument
669      * @param vec the buffer containing encoded scilab types
670      * @throws IllegalFormatException when the underlying formatting failed
671      * @throws IllegalArgumentException when the vec argument is wrongly encoded
672      * @return A formatted string
673      */
674     public String format(String format, VectorOfDouble vec) throws IllegalFormatException, IllegalArgumentException {
675         ArrayList<Object> arguments = new ArrayList<>();
676         decodeToJava(vec, arguments);
677         return String.format(format, arguments.toArray());
678     }
679
680     private void decodeToJava(VectorOfDouble vec, ArrayList<Object> arguments) {
681         int nativeScilabType = (int) vec.get(position++);
682
683         // specific integer sub-type
684         int precision = 0;
685
686         // for data[][]-based type
687         int height = 0;
688         int width = 0;
689
690         // for ArrayList-based type
691         int listLen = 0;
692
693         final ScilabTypeEnum type = ScilabTypeEnum.swigToEnum(nativeScilabType);
694         switch (type) {
695             case sci_ints:
696                 // special case for integer precision
697                 precision = (int) vec.get(position++);
698             case sci_matrix:
699             case sci_boolean:
700             case sci_strings:
701                 position++; // n-Dims not managed
702                 height = (int) vec.get(position++);
703                 width = (int) vec.get(position++);
704                 break;
705             case sci_list:
706             case sci_mlist:
707             case sci_tlist:
708                 listLen = (int) vec.get(position++);
709                 break;
710             default:
711                 throw new IllegalArgumentException();
712         }
713
714         // special case for complex double matrix
715         boolean isComplex = false;
716         if (type == ScilabTypeEnum.sci_matrix) {
717             isComplex = vec.get(position++) != 0;
718         }
719
720         // allocate the right type with the decoded properties
721         switch (type) {
722             case sci_matrix:
723                 for (int i = 0; i < height; i++) {
724                     for (int j = 0; j < width; j++) {
725                         arguments.add(vec.get(position++));
726                     }
727                 }
728
729                 if (isComplex) {
730                     for (int i = 0; i < height; i++) {
731                         for (int j = 0; j < width; j++) {
732                             arguments.add(vec.get(position++));
733                         }
734                     }
735                 }
736                 break;
737             case sci_boolean: {
738                 final int doubleLen = (Integer.BYTES * height * width) / Double.BYTES + 1;
739                 ByteBuffer view = vec.asByteBuffer(position, doubleLen);
740                 for (int i = 0; i < height; i++) {
741                     for (int j = 0; j < width; j++) {
742                         arguments.add(view.getInt() != 0);
743                     }
744                 }
745                 position += doubleLen;
746             }
747             break;
748             case sci_ints:
749                 switch (ScilabIntegerTypeEnum.swigToEnum(precision)) {
750                     case sci_int8:
751                     case sci_uint8: {
752                         final int sizeof = Byte.BYTES;
753                         final int doubleLen = (sizeof * height * width) / Double.BYTES + 1;
754                         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
755                         for (int i = 0; i < height; i++) {
756                             for (int j = 0; j < width; j++) {
757                                 arguments.add(view.get());
758                             }
759                         }
760                     }
761                     break;
762                     case sci_int16:
763                     case sci_uint16: {
764                         final int sizeof = Short.BYTES;
765                         final int doubleLen = (sizeof * height * width) / Double.BYTES + 1;
766                         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
767                         for (int i = 0; i < height; i++) {
768                             for (int j = 0; j < width; j++) {
769                                 arguments.add(view.getShort());
770                             }
771                         }
772                     }
773                     break;
774                     case sci_int32:
775                     case sci_uint32: {
776                         final int sizeof = Integer.BYTES;
777                         final int doubleLen = (sizeof * height * width) / Double.BYTES + 1;
778                         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
779                         for (int i = 0; i < height; i++) {
780                             for (int j = 0; j < width; j++) {
781                                 arguments.add(view.getInt());
782                             }
783                         }
784                     }
785                     break;
786                     case sci_int64:
787                     case sci_uint64: {
788                         final int sizeof = Long.BYTES;
789                         final int doubleLen = (sizeof * height * width) / Double.BYTES + 1;
790                         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
791                         for (int i = 0; i < height; i++) {
792                             for (int j = 0; j < width; j++) {
793                                 arguments.add(view.getLong());
794                             }
795                         }
796                     }
797                     break;
798                 }
799                 break;
800             case sci_strings:
801                 decodeString(height, width, vec, (i, j, v) -> arguments.add(v));
802                 break;
803             case sci_list:
804             case sci_mlist:
805             case sci_tlist: {
806                 for (int i = 0; i < listLen; i++) {
807                     decodeToJava(vec, arguments);
808                 }
809             }
810             break;
811             default:
812                 throw new IllegalArgumentException();
813         }
814     }
815
816     /**
817      * Utility to display a vec on debug
818      *
819      * @param vec the vector to convert
820      * @return a representative string
821      */
822     public static String toString(VectorOfDouble vec) {
823         int len = vec.size();
824         double[] copy = new double[len];
825         DoubleBuffer.wrap(copy).put(vec.asByteBuffer(0, len).asDoubleBuffer());
826         return Arrays.toString(copy);
827     }
828
829     /**
830      * Utility to display a vec on debug
831      *
832      * @param vec the vector to convert
833      * @return a representative string
834      */
835     public static String toString(VectorOfScicosID vec) {
836         int len = vec.size();
837         long[] copy = new long[len];
838         LongBuffer.wrap(copy).put(vec.asByteBuffer(0, len).asLongBuffer());
839         return Arrays.toString(copy);
840     }
841
842     /**
843      * Utility to display a vec on debug
844      *
845      * @param vec the vector to convert
846      * @return a representative string
847      */
848     public static String toString(VectorOfInt vec) {
849         int len = vec.size();
850         int[] copy = new int[len];
851         IntBuffer.wrap(copy).put(vec.asByteBuffer(0, len).asIntBuffer());
852         return Arrays.toString(copy);
853     }
854 }