/** * Encode the double data * * @param var the data to encode * @param vec the resulting buffer */ private void encode(ScilabDouble var, VectorOfDouble vec) { // Header encodeHeader(var, vec, ScilabTypeEnum.sci_matrix); // specific flag for managing the complex case if (var.isReal()) { vec.add(0f); } else { vec.add(1f); } // push the data for (int i = 0; i < var.getHeight(); i++) { for (int j = 0; j < var.getWidth(); j++) { vec.add(var.getRealElement(i, j)); } } // push the complex data if (!var.isReal()) { for (int i = 0; i < var.getHeight(); i++) { for (int j = 0; j < var.getWidth(); j++) { vec.add(var.getImaginaryElement(i, j)); } } } }
private void decodeString( int height, int width, VectorOfDouble vec, StoreFunction<Integer, Integer, String> store) { // reconstruct the offset int[][] offset = new int[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { offset[i][j] = (int) vec.get(position++); } } Charset utf8 = Charset.forName("UTF-8"); int accumulatedOffset = 0; // reconstruct each String object for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { final int nbOfDouble = offset[i][j] - accumulatedOffset; ByteBuffer view = vec.asByteBuffer(position, nbOfDouble); byte[] bytes = new byte[nbOfDouble * Double.BYTES]; view.get(bytes); // to avoid mis-decoding we have to pass the len of bytes int strlen = 0; while (bytes[strlen] != 0) { strlen++; } store.apply(i, j, new String(bytes, 0, strlen, utf8)); accumulatedOffset += nbOfDouble; position += nbOfDouble; } } }
private void encode(ScilabBoolean var, VectorOfDouble vec) { // header encodeHeader(var, vec, ScilabTypeEnum.sci_boolean); // put all the boolean as int accordingly to Scilab 6 implementation final int requiredBytes = Integer.BYTES * var.getHeight() * var.getWidth(); final int doubleLen = (requiredBytes + Double.BYTES - 1) / Double.BYTES; int index = vec.size(); vec.resize(index + doubleLen); ByteBuffer buffer = vec.asByteBuffer(index, doubleLen); for (int i = 0; i < var.getHeight(); i++) { for (int j = 0; j < var.getWidth(); j++) { buffer.putInt(var.getData()[i][j] ? 1 : 0); } } }
private ScilabType decode(VectorOfDouble vec, ScilabDouble var) { double[][] realPart = var.getRealPart(); for (int i = 0; i < var.getHeight(); i++) { for (int j = 0; j < var.getWidth(); j++) { realPart[i][j] = vec.get(position++); } } if (!var.isReal()) { double[][] imaginaryPart = var.getImaginaryPart(); for (int i = 0; i < var.getHeight(); i++) { for (int j = 0; j < var.getWidth(); j++) { imaginaryPart[i][j] = vec.get(position++); } } } return var; }
private void encode(ScilabString var, VectorOfDouble vec) { // header encodeHeader(var, vec, ScilabTypeEnum.sci_strings); // add the offset table which contains the offset of each UTF-8 encoded strings int offsetTableStart = vec.size(); vec.resize(offsetTableStart + var.getHeight() * var.getWidth()); int offsetTableAccumulated = 0; // encode the strings as UTF-8 and store the associated offset Charset utf8 = Charset.forName("UTF-8"); for (int i = 0; i < var.getHeight(); i++) { for (int j = 0; j < var.getWidth(); j++) { String str = var.getData()[i][j]; byte[] bytes = str.getBytes(utf8); // append the terminal '\0' final int requiredBytes = bytes.length + 1; final int doubleLen = (requiredBytes + Double.BYTES - 1) / Double.BYTES; // set the offset offsetTableAccumulated += doubleLen; vec.set(offsetTableStart++, offsetTableAccumulated); // push the data through a temporary byte buffer int index = vec.size(); vec.resize(index + doubleLen); vec.asByteBuffer(index, doubleLen).put(bytes).put((byte) 0); } } }
private ScilabType decode(VectorOfDouble vec, ScilabBoolean var) { final boolean[][] data = var.getData(); final int doubleLen = (Integer.BYTES * var.getHeight() * var.getWidth()) / Double.BYTES + 1; ByteBuffer view = vec.asByteBuffer(position, doubleLen); for (int i = 0; i < var.getHeight(); i++) { for (int j = 0; j < var.getWidth(); j++) { data[i][j] = view.getInt() != 0; } } position += doubleLen; return var; }
/** * Helper method to add an header of the detected type * * @param var the scilab matrix type to encode * @param vec the raw encoded data container * @param as the type to encode * @param detected the detected type */ @SuppressWarnings({"unchecked", "fallthrough"}) private void encodeHeader(Object var, VectorOfDouble vec, final ScilabTypeEnum as) { ScilabType matrix = null; ArrayList<ScilabType> list = null; // defensive programming switch (as) { case sci_boolean: case sci_ints: case sci_matrix: case sci_strings: matrix = (ScilabType) var; break; case sci_list: case sci_mlist: case sci_tlist: list = (ArrayList<ScilabType>) var; break; default: throw new IllegalArgumentException(); } vec.add(as.swigValue()); if (matrix instanceof ScilabInteger) { vec.add(((ScilabInteger) matrix).getPrec().swigValue()); } if (matrix != null) { vec.add(2); vec.add(matrix.getHeight()); vec.add(matrix.getWidth()); } else if (list != null) { vec.add(list.size()); } else { throw new IllegalArgumentException(); } }
/** * Utility to display a vec on debug * * @param vec the vector to convert * @return a representative string */ public static String toString(VectorOfDouble vec) { int len = vec.size(); double[] copy = new double[len]; DoubleBuffer.wrap(copy).put(vec.asByteBuffer(0, len).asDoubleBuffer()); return Arrays.toString(copy); }
private void decodeToJava(VectorOfDouble vec, ArrayList<Object> arguments) { int nativeScilabType = (int) vec.get(position++); // specific integer sub-type int precision = 0; // for data[][]-based type int height = 0; int width = 0; // for ArrayList-based type int listLen = 0; final ScilabTypeEnum type = ScilabTypeEnum.swigToEnum(nativeScilabType); switch (type) { case sci_ints: // special case for integer precision precision = (int) vec.get(position++); case sci_matrix: case sci_boolean: case sci_strings: position++; // n-Dims not managed height = (int) vec.get(position++); width = (int) vec.get(position++); break; case sci_list: case sci_mlist: case sci_tlist: listLen = (int) vec.get(position++); break; default: throw new IllegalArgumentException(); } // special case for complex double matrix boolean isComplex = false; if (type == ScilabTypeEnum.sci_matrix) { isComplex = vec.get(position++) != 0; } // allocate the right type with the decoded properties switch (type) { case sci_matrix: for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { arguments.add(vec.get(position++)); } } if (isComplex) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { arguments.add(vec.get(position++)); } } } break; case sci_boolean: { final int doubleLen = (Integer.BYTES * height * width) / Double.BYTES + 1; ByteBuffer view = vec.asByteBuffer(position, doubleLen); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { arguments.add(view.getInt() != 0); } } position += doubleLen; } break; case sci_ints: switch (ScilabIntegerTypeEnum.swigToEnum(precision)) { case sci_int8: case sci_uint8: { final int sizeof = Byte.BYTES; final int doubleLen = (sizeof * height * width) / Double.BYTES + 1; ByteBuffer view = vec.asByteBuffer(position, doubleLen); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { arguments.add(view.get()); } } } break; case sci_int16: case sci_uint16: { final int sizeof = Short.BYTES; final int doubleLen = (sizeof * height * width) / Double.BYTES + 1; ByteBuffer view = vec.asByteBuffer(position, doubleLen); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { arguments.add(view.getShort()); } } } break; case sci_int32: case sci_uint32: { final int sizeof = Integer.BYTES; final int doubleLen = (sizeof * height * width) / Double.BYTES + 1; ByteBuffer view = vec.asByteBuffer(position, doubleLen); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { arguments.add(view.getInt()); } } } break; case sci_int64: case sci_uint64: { final int sizeof = Long.BYTES; final int doubleLen = (sizeof * height * width) / Double.BYTES + 1; ByteBuffer view = vec.asByteBuffer(position, doubleLen); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { arguments.add(view.getLong()); } } } break; } break; case sci_strings: decodeString(height, width, vec, (i, j, v) -> arguments.add(v)); break; case sci_list: case sci_mlist: case sci_tlist: { for (int i = 0; i < listLen; i++) { decodeToJava(vec, arguments); } } break; default: throw new IllegalArgumentException(); } }
@SuppressWarnings("fallthrough") private ScilabType decodeHeader(VectorOfDouble vec) { int nativeScilabType = (int) vec.get(position++); // specific integer sub-type int precision = 0; // for data[][]-based type int height = 0; int width = 0; // for ArrayList-based type int listLen = 0; final ScilabTypeEnum type = ScilabTypeEnum.swigToEnum(nativeScilabType); switch (type) { case sci_ints: // special case for integer precision precision = (int) vec.get(position++); case sci_matrix: case sci_boolean: case sci_strings: position++; // n-Dims not managed height = (int) vec.get(position++); width = (int) vec.get(position++); break; case sci_list: case sci_mlist: case sci_tlist: listLen = (int) vec.get(position++); break; default: throw new IllegalArgumentException(); } // special case for complex double matrix double[][] imagData = null; if (type == ScilabTypeEnum.sci_matrix) { boolean isComplex = vec.get(position++) != 0; if (isComplex) { imagData = new double[height][width]; } } // allocate the right type with the decoded properties switch (type) { case sci_matrix: if (height * width == 0) { return new ScilabDouble(); } else { return new ScilabDouble(new double[height][width], imagData); } case sci_boolean: if (height * width == 0) { return new ScilabBoolean(); } else { return new ScilabBoolean(new boolean[height][width]); } case sci_ints: if (height * width == 0) { return new ScilabInteger(); } else { switch (ScilabIntegerTypeEnum.swigToEnum(precision)) { case sci_int8: return new ScilabInteger(new byte[height][width], false); case sci_int16: return new ScilabInteger(new short[height][width], false); case sci_int32: return new ScilabInteger(new int[height][width], false); case sci_int64: return new ScilabInteger(new long[height][width], false); case sci_uint8: return new ScilabInteger(new byte[height][width], true); case sci_uint16: return new ScilabInteger(new short[height][width], true); case sci_uint32: return new ScilabInteger(new int[height][width], true); case sci_uint64: return new ScilabInteger(new long[height][width], true); } } case sci_strings: if (height * width == 0) { return new ScilabString(); } else { return new ScilabString(new String[height][width]); } case sci_list: return new ScilabList(Collections.nCopies(listLen, null)); case sci_mlist: return new ScilabMList(new String[listLen - 1], Collections.nCopies(listLen - 1, null)); case sci_tlist: return new ScilabTList(new String[listLen - 1], Collections.nCopies(listLen - 1, null)); default: throw new IllegalArgumentException(); } }
private ScilabType decode(VectorOfDouble vec, ScilabInteger var) { final int sizeof; long[][] longData = null; short[][] shortData = null; int[][] intData = null; byte[][] byteData = null; switch (var.getPrec()) { case sci_int64: case sci_uint64: sizeof = Long.BYTES; longData = var.getDataAsLong(); break; case sci_int32: case sci_uint32: sizeof = Integer.BYTES; intData = var.getDataAsInt(); break; case sci_int16: case sci_uint16: sizeof = Short.BYTES; shortData = var.getDataAsShort(); break; case sci_int8: case sci_uint8: sizeof = Byte.BYTES; byteData = var.getDataAsByte(); break; default: throw new IllegalArgumentException(); } final int doubleLen = (sizeof * var.getHeight() * var.getWidth()) / Double.BYTES + 1; ByteBuffer view = vec.asByteBuffer(position, doubleLen); for (int i = 0; i < var.getHeight(); i++) { for (int j = 0; j < var.getWidth(); j++) { switch (var.getPrec()) { case sci_int64: case sci_uint64: longData[i][j] = view.getLong(); break; case sci_int32: case sci_uint32: intData[i][j] = view.getInt(); break; case sci_int16: case sci_uint16: shortData[i][j] = view.getShort(); break; case sci_int8: case sci_uint8: byteData[i][j] = view.get(); break; } } } position += doubleLen; return var; }
private void encode(ScilabInteger var, VectorOfDouble vec) { // pre-processing: retrieve the raw data per type int sizeof; long[][] longData = null; short[][] shortData = null; int[][] intData = null; byte[][] byteData = null; switch (var.getPrec()) { case sci_int64: case sci_uint64: sizeof = Long.BYTES; longData = var.getDataAsLong(); break; case sci_int32: case sci_uint32: sizeof = Integer.BYTES; intData = var.getDataAsInt(); break; case sci_int16: case sci_uint16: sizeof = Short.BYTES; shortData = var.getDataAsShort(); break; case sci_int8: case sci_uint8: sizeof = Byte.BYTES; byteData = var.getDataAsByte(); break; default: throw new IllegalArgumentException(); } // Header encodeHeader(var, vec, ScilabTypeEnum.sci_ints); // push the data on a pre-allocated space final int requiredBytes = sizeof * var.getHeight() * var.getWidth(); final int doubleLen = (requiredBytes + Double.BYTES - 1) / Double.BYTES; final int index = vec.size(); vec.resize(index + doubleLen); ByteBuffer view = vec.asByteBuffer(index, doubleLen); for (int i = 0; i < var.getHeight(); i++) { for (int j = 0; j < var.getWidth(); j++) { switch (var.getPrec()) { case sci_int64: case sci_uint64: view.putLong(longData[i][j]); break; case sci_int32: case sci_uint32: view.putInt(intData[i][j]); break; case sci_int16: case sci_uint16: view.putShort(shortData[i][j]); break; case sci_int8: case sci_uint8: view.put(byteData[i][j]); break; } } } }