Xcos: fix opar integers encoding issues 94/21594/3
Clément DAVID [Mon, 5 Oct 2020 15:45:47 +0000 (17:45 +0200)]
Change-Id: I375d1c270a09a63ec5a6ca8225e8ea670ddf3380

scilab/CHANGES.md
scilab/modules/scicos/sci_gateway/cpp/sci_scicosim.cpp
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/ScilabTypeCoder.java
scilab/modules/xcos/tests/nonreg_tests/bug_7202.tst [new file with mode: 0644]

index 29c6df9..42a7644 100644 (file)
@@ -329,6 +329,7 @@ Bug Fixes
 * [#3188](https://bugzilla.scilab.org/3188): `part()` was slower than in Scilab 4.1.2.
 * [#4648](https://bugzilla.scilab.org/4648): Scilab missed more secure hashing functions (md5 is now broken)
 * [#5511](https://bugzilla.scilab.org/5511): printf_conversion page was poorly presented and had many issues: The described types of accepted value and printed result were often switched; nothing was told about the processing of complex numbers; special escaped sequences \n \r \t \\ were not described; possible numbering of placeholders was not described; in the pt_BR version, the itemized lists were wrongly unnested and characters typing placeholders (d,u,o,x,f,e,g..) were missing.
+* [#7202](https://bugzilla.scilab.org/7202): It was not possible to send string parameters via the opar structure of an xcos block to a block of type 4.
 * [#8059](https://bugzilla.scilab.org/8059): A local `.wgetrc` config file could make troubles in `atomsDownload`.
 * [#8100](https://bugzilla.scilab.org/8100): `cumsum()` on sparse documented.
 * [#8378](https://bugzilla.scilab.org/8378): Datatip `ContextMenu => Delete last datatip` was useless.
@@ -437,7 +438,7 @@ Bug Fixes
 * [#16571](https://bugzilla.scilab.org/16571): `mfile2sci` had several issues when converting the NOT ~ operator: 1) `~(1-1)` was converted into `~1-1` instead of `~(1-1)`  2) ~ applied to an integer expression yielded an error from `convert2double`  3) `~i` was converted into `~%i` instead of `~abs(%i)`.
 * [#16573](https://bugzilla.scilab.org/16573): `mfile2sci`: Some `axis` conversions were wrong or not reliable.
 * [#16586](https://bugzilla.scilab.org/16586): `mfile2sci`: The `prettyprintoutput` flag badly managed appended comments.
-* [#16596](https://bugzilla.scilab.org/16596): Concatenating encoded integers with sparse numeric data was not possible. 
+* [#16596](https://bugzilla.scilab.org/16596): Concatenating encoded integers with sparse numeric data was not possible.
 * [#16608](https://bugzilla.scilab.org/16608): `union` did not support input boolean, sparse boolean, nor sparse numerical matrices. The result of `union(complexA, complexB)` was wrongly conjugate.
 * [#16609](https://bugzilla.scilab.org/16609): `bitcmp` needed to be upgraded for Scilab 6.
 * [#16612](https://bugzilla.scilab.org/16612): Unlike the `.*.` operator, `kron()` was not defined for sparse numeric matrices.
index 12eaee8..5622d3a 100644 (file)
@@ -12,7 +12,7 @@
  * along with this program.
  *
  */
-
+#include <vector>
 #include <string>
 #include <cstdio>
 #include <cwchar>
@@ -1614,7 +1614,7 @@ types::Function::ReturnValue sci_scicosim(types::typed_list &in, int _iRetCount,
                     oztyp[j] = SCSUNKNOW_N;
                     oz[j] = il_state_oz->get(j);
                     ozsz[j] = 0; // rows
-                    ozsz[j + nopar] = 0; // cols
+                    ozsz[j + noz] = 0; // cols
                     break;
                 }
             }
@@ -1624,9 +1624,18 @@ types::Function::ReturnValue sci_scicosim(types::typed_list &in, int _iRetCount,
     /****************************
     * Set opar, oparsz, opartyp
     ****************************/
+    struct UTF8AllocatedStrings : std::vector<char*> {
+        ~UTF8AllocatedStrings() {
+            for (char* ptr : *this)
+            {
+                FREE(ptr);
+            }
+        };
+    };
     void** opar = nullptr;
     int* oparsz = nullptr;
     int* opartyp = nullptr;
+    UTF8AllocatedStrings oparStrings;
     if (nopar > 0)
     {
         // Allocation of 'opar'
@@ -1813,6 +1822,20 @@ types::Function::ReturnValue sci_scicosim(types::typed_list &in, int _iRetCount,
                     opar[j] = (SCSUINT32_COP *) oparUInt32->get();
                     break;
                 }
+                case types::InternalType::ScilabString :
+                {
+                    types::String* oparString = il_sim_opar->get(j)->getAs<types::String>();
+                    opartyp[j] = SCSINT8_N; // int8
+                    oparsz[j] = oparString->getSize();
+                    oparsz[j + nopar] = 1;
+                    for (int i = 0; i < oparString->getSize(); ++i)
+                    {
+                        // convert string as char* buffers, owned by oparStrings
+                        oparStrings.emplace_back(wide_string_to_UTF8(oparString->get(i)));
+                        opar[j] = oparStrings.back();
+                    }
+                    break;
+                }
                 default:
                 {
                     opartyp[j] = SCSUNKNOW_N;
index b7ef697..142d270 100644 (file)
@@ -384,7 +384,15 @@ public class ScilabTypeCoder {
         }
 
         ScilabType var = decodeHeader(vec);
-        decode(vec, var);
+        try
+        {
+            decode(vec, var);
+        } catch (IllegalArgumentException e)
+        {
+            e.printStackTrace();
+            LOG.log(Level.SEVERE, "Unable to decode {0}", toString(vec));
+        }
+            
 
         // System.err.println("vec2var:" + toString(vec) + ":" + var.toString());
         if (LOG.isLoggable(Level.FINE)) {
@@ -485,7 +493,7 @@ public class ScilabTypeCoder {
                 throw new IllegalArgumentException();
         }
 
-        final int doubleLen = (sizeof * var.getHeight() * var.getWidth()) / Double.BYTES + 1;
+        final int doubleLen = requiredLength(sizeof, var.getHeight(), var.getWidth());
         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
 
         for (int i = 0; i < var.getHeight(); i++) {
@@ -595,7 +603,7 @@ public class ScilabTypeCoder {
         int listLen = 0;
 
         final ScilabTypeEnum type = ScilabTypeEnum.swigToEnum(nativeScilabType);
-        switch (type) {
+        switch (type) { 
             case sci_ints:
                 // special case for integer precision
                 precision = (int) vec.get(position++);
@@ -697,6 +705,15 @@ public class ScilabTypeCoder {
         decodeToJava(vec, arguments);
         return String.format(format, arguments.toArray());
     }
+    
+    private int requiredLength(int sizeof, int height, int width)
+    {
+        if (sizeof == Double.BYTES) {
+            return height * width * sizeof / Double.BYTES;
+        } else {
+            return (height * width * sizeof + (Double.BYTES - 1)) / Double.BYTES;
+        }
+    }
 
     private void decodeToJava(VectorOfDouble vec, ArrayList<Object> arguments) {
         int nativeScilabType = (int) vec.get(position++);
@@ -761,7 +778,8 @@ public class ScilabTypeCoder {
                 }
                 break;
             case sci_boolean: {
-                final int doubleLen = (Integer.BYTES * height * width) / Double.BYTES + 1;
+                final int sizeof = Integer.BYTES;
+                final int doubleLen = requiredLength(sizeof, height, width);
                 ByteBuffer view = vec.asByteBuffer(position, doubleLen);
                 for (int i = 0; i < height; i++) {
                     for (int j = 0; j < width; j++) {
@@ -776,7 +794,7 @@ public class ScilabTypeCoder {
                     case sci_int8:
                     case sci_uint8: {
                         final int sizeof = Byte.BYTES;
-                        final int doubleLen = (sizeof * height * width) / Double.BYTES + 1;
+                        final int doubleLen = requiredLength(sizeof, height, width);
                         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
                         for (int i = 0; i < height; i++) {
                             for (int j = 0; j < width; j++) {
@@ -788,7 +806,7 @@ public class ScilabTypeCoder {
                     case sci_int16:
                     case sci_uint16: {
                         final int sizeof = Short.BYTES;
-                        final int doubleLen = (sizeof * height * width) / Double.BYTES + 1;
+                        final int doubleLen = requiredLength(sizeof, height, width);
                         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
                         for (int i = 0; i < height; i++) {
                             for (int j = 0; j < width; j++) {
@@ -800,7 +818,7 @@ public class ScilabTypeCoder {
                     case sci_int32:
                     case sci_uint32: {
                         final int sizeof = Integer.BYTES;
-                        final int doubleLen = (sizeof * height * width) / Double.BYTES + 1;
+                        final int doubleLen = requiredLength(sizeof, height, width);
                         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
                         for (int i = 0; i < height; i++) {
                             for (int j = 0; j < width; j++) {
@@ -812,7 +830,7 @@ public class ScilabTypeCoder {
                     case sci_int64:
                     case sci_uint64: {
                         final int sizeof = Long.BYTES;
-                        final int doubleLen = (sizeof * height * width) / Double.BYTES + 1;
+                        final int doubleLen = requiredLength(sizeof, height, width);
                         ByteBuffer view = vec.asByteBuffer(position, doubleLen);
                         for (int i = 0; i < height; i++) {
                             for (int j = 0; j < width; j++) {
diff --git a/scilab/modules/xcos/tests/nonreg_tests/bug_7202.tst b/scilab/modules/xcos/tests/nonreg_tests/bug_7202.tst
new file mode 100644 (file)
index 0000000..7c4cc8f
--- /dev/null
@@ -0,0 +1,51 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2020 - ESI Group - Clement DAVID
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- XCOS TEST -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 7202 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/7202
+//
+// <-- Short Description -->
+// It's not possible to send string parameters via the opar structure of an xcos
+// block.
+
+function [x,y,typ] = CUSTOM_7202(job,arg1,arg2)
+    x=[];
+    y=[];
+    typ=[];
+    select job
+    case "set" then
+        x=arg1;
+        x.model.opar(1) = "this is a string parameter"
+    case "define" then
+        model=scicos_model();
+        model.sim="trash";
+        model.dep_ut = [%t %f];
+        model.opar(1) = "this is a string parameter"
+        x=standard_define([2 3], model, "", []);
+    end
+endfunction
+
+scs_m = scicos_diagram();
+scs_m.props.tf = 1;
+scs_m.objs(1) = CUSTOM_7202("define");
+
+// check the simulation
+scicos_simulate(scs_m);
+
+// save, load and check
+fname = fullfile(TMPDIR, "sample.zcos");
+xcosDiagramToScilab(fname, scs_m);
+prev_scs_m = xcosDiagramToScilab(fname);
+
+assert_checkequal(scs_m.objs(1).model.opar(1), prev_scs_m.objs(1).model.opar(1));
+assert_checkequal(scs_m.objs(1).model.opar(1), "this is a string parameter");
+