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