Scicos src: comment out Structs in var2vec
[scilab.git] / scilab / modules / scicos / src / cpp / var2vec.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2015 - Scilab Enterprises - Paul Bignier
4 *
5 *  This file must be used under the terms of the CeCILL.
6 *  This source file is licensed as described in the file COPYING, which
7 *  you should have received as part of this distribution.  The terms
8 *  are also available at
9 *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10 *
11 */
12
13 #include <vector>
14 #include <string>
15 #include <cwchar>
16 #include <cstring>
17
18 #include "var2vec.hxx"
19
20 #include "types.hxx"
21 #include "internal.hxx"
22 #include "double.hxx"
23 #include "int.hxx"
24 #include "bool.hxx"
25 #include "string.hxx"
26 #include "list.hxx"
27 #include "tlist.hxx"
28 #include "mlist.hxx"
29 //#include "struct.hxx"
30
31 extern "C"
32 {
33 #include "charEncoding.h"
34 #include "Scierror.h"
35 #include "localization.h"
36 }
37
38 static const std::string var2vecName = "var2vec";
39
40 static void computeDims(types::GenericType* input, int &iDims, int* &pDims, int &iElements, int &totalSize)
41 {
42     iDims = input->getDims();
43     pDims = input->getDimsArray();
44     iElements = 1;
45     for (int i = 0; i < iDims; ++i)
46     {
47         iElements *= pDims[i];
48     }
49
50     // Type + number of dimensions + dimensions
51     totalSize = 2 + iDims;
52 }
53
54 /**
55  * Calculate the length increment depending on the ::value_type of 'V' and the type of the Scilab type 'T'
56  *
57  * @param V variable that must have a 'value_type' field
58  * @param T Scilab type
59  * @param v the instance of the Scilab type
60  * @return the number of V elements used to store the data
61  */
62 template<typename V, typename T>
63 size_t required_length(const V /*it*/, T* v)
64 {
65     const size_t sizeof_ret_value = sizeof(typename V::value_type);
66     if (sizeof(typename T::type) >= sizeof_ret_value)
67     {
68         return v->getSize() * sizeof(typename T::type) / sizeof_ret_value;
69     }
70     else
71     {
72         // Increase the size to contain enough space, manage the size_t rounding issue
73         return (v->getSize() * sizeof(typename T::type) + (sizeof_ret_value - 1)) / sizeof_ret_value;
74     }
75 }
76
77 template <typename T>
78 void encode(T* input, std::vector<double> &ret)
79 {
80     int iDims, iElements, totalSize;
81     int* pDims;
82     computeDims(input, iDims, pDims, iElements, totalSize);
83
84     const int nDoubleNeeded = static_cast<int>(required_length(ret, input));
85     totalSize += nDoubleNeeded;
86
87     // Allocation for type + number of dimensions + each dimension + each element
88     ret.reserve(ret.size() + totalSize);
89
90     ret.push_back(((types::InternalType*) input)->getType());
91     ret.push_back(iDims);
92     for (int i = 0; i < iDims; ++i)
93     {
94         ret.push_back(pDims[i]);
95     }
96
97     // Using contiguity of the memory, we save the input into 'ret'
98     // Use a buffer to fill the entirety of 'ret'
99     size_t size = ret.size();
100     ret.resize(size + nDoubleNeeded);
101     double* data = ret.data() + size;
102     memcpy(data, input->get(), iElements * sizeof(typename T::type));
103 }
104
105 static void encode(types::Double* input, std::vector<double> &ret)
106 {
107     int iDims, iElements, totalSize;
108     int* pDims;
109     computeDims(input, iDims, pDims, iElements, totalSize);
110
111     const int isComplex = (input->isComplex()) ? 1 : 0;
112     totalSize++; // Add the complex boolean
113     totalSize += (isComplex + 1) * iElements; // Size of the required data buffer
114
115     // Allocation for type + number of dimensions + each dimension + complex boolean + each element (doubled if complex)
116     ret.reserve(ret.size() + totalSize);
117
118     ret.push_back(types::InternalType::ScilabDouble);
119     ret.push_back(iDims);
120     for (int i = 0; i < iDims; ++i)
121     {
122         ret.push_back(pDims[i]);
123     }
124     ret.push_back(isComplex);
125
126     size_t size = ret.size();
127     ret.resize(size + iElements * (isComplex + 1));
128     double* data = ret.data() + size;
129     memcpy(data, input->getReal(), iElements * sizeof(double));
130
131     if (isComplex == 1)
132     {
133         memcpy(data + iElements, input->getImg(), iElements * sizeof(double));
134     }
135
136     // An empty matrix input will return [12; 2; 0; 0; 0]
137 }
138
139 static void encode(types::String* input, std::vector<double> &ret)
140 {
141     int iDims, iElements, totalSize;
142     int* pDims;
143     computeDims(input, iDims, pDims, iElements, totalSize);
144
145     totalSize += iElements;
146
147     // Reserve space for the string offsets and contents
148     char** utf8 = new char*[iElements];
149     size_t* pLengths = new size_t[iElements];
150     int* offsets = new int[iElements];
151     int offset_cur = 0, offset_acc = 0;
152     for (int i = 0; i < iElements; ++i)
153     {
154         char* str = wide_string_to_UTF8(input->get(i));
155         utf8[i] = str;
156         // Adding the '\0' byte to the length
157         const size_t len = strlen(str) + 1;
158         pLengths[i] = len;
159
160         offset_cur = static_cast<int>((len * sizeof(char) + sizeof(double) - 1) / sizeof(double));
161         totalSize += offset_cur;
162         offset_acc += offset_cur;
163         offsets[i] = offset_acc;
164     }
165
166     // Allocation for type + number of dimensions + each dimension + each element length + each element
167     ret.reserve(ret.size() + totalSize);
168
169     ret.push_back(types::InternalType::ScilabString);
170     ret.push_back(iDims);
171     for (int i = 0; i < iDims; ++i)
172     {
173         ret.push_back(pDims[i]);
174     }
175     for (int i = 0; i < iElements; ++i)
176     {
177         ret.push_back(offsets[i]);
178     }
179
180     size_t size = ret.size();
181     ret.resize(size + offsets[iElements - 1]);
182     double* data = ret.data() + size;
183
184     size_t len = pLengths[0];
185     memcpy(data, utf8[0], len * sizeof(char));
186     data += offsets[0];
187     for (int i = 1; i < iElements; ++i)
188     {
189         size_t len = pLengths[i];
190         memcpy(data, utf8[i], len * sizeof(char));
191         data += offsets[i] - offsets[i - 1];
192     }
193
194     // Free all the strings, after being copied
195     for (int i = 0; i < iElements; ++i)
196     {
197         FREE(utf8[i]);
198     }
199     delete[] utf8;
200     delete[] offsets;
201     delete[] pLengths;
202 }
203
204 static void encode(types::List* input, std::vector<double> &ret)
205 {
206     const int iElements = input->getSize();
207
208     ret.push_back(input->getType());
209     ret.push_back(iElements);
210     for (int i = 0; i < iElements; ++i)
211     {
212         // Recursively call var2vec on each element and extract the obtained results
213         var2vec(input->get(i), ret);
214     }
215
216     // An empty list input will return [22; 0], a tlist [23; 0] and an mlist [24; 0]
217 }
218
219 // Structs are not used yet
220 //static void encode(types::Struct* input, std::vector<double> &ret)
221 //{
222 //    const bool isEmpty = input->getSize() == 0;
223
224 //    types::String* fields = nullptr;
225 //    int iElements = 0;
226 //    if (!isEmpty)
227 //    {
228 //        fields = input->getFieldNames();
229 //        iElements = fields->getSize();
230 //    }
231
232 //    ret.push_back(input->getType());
233 //    ret.push_back(iElements);
234 //    if (!isEmpty)
235 //    {
236 //        // Call var2vec on the struct's fields to extract a header
237 //        var2vec(fields, ret);
238
239 //        // Now extract the fields' content, assuming this is not a multidimensional struct
240 //        types::SingleStruct* content = input->get(0);
241 //        for (int i = 0; i < iElements; ++i)
242 //        {
243 //            var2vec(content->get(fields->get(i)), ret);
244 //        }
245
246
247 //        fields->killMe();
248 //    }
249
250 //    // An empty struct input will return [26; 0]
251 //}
252
253 bool var2vec(types::InternalType* in, std::vector<double> &out)
254 {
255     switch (in->getType())
256     {
257             // Reuse scicos model encoding for 'model.opar' and 'model.odstate' fields
258         case types::InternalType::ScilabDouble :
259             encode(in->getAs<types::Double>(), out);
260             break;
261
262         case types::InternalType::ScilabInt8   :
263             encode(in->getAs<types::Int8>(), out);
264             break;
265         case types::InternalType::ScilabUInt8  :
266             encode(in->getAs<types::UInt8>(), out);
267             break;
268         case types::InternalType::ScilabInt16  :
269             encode(in->getAs<types::Int16>(), out);
270             break;
271         case types::InternalType::ScilabUInt16 :
272             encode(in->getAs<types::UInt16>(), out);
273             break;
274         case types::InternalType::ScilabInt32  :
275             encode(in->getAs<types::Int32>(), out);
276             break;
277         case types::InternalType::ScilabUInt32 :
278             encode(in->getAs<types::UInt32>(), out);
279             break;
280         case types::InternalType::ScilabInt64  :
281             encode(in->getAs<types::Int64>(), out);
282             break;
283         case types::InternalType::ScilabUInt64 :
284             encode(in->getAs<types::UInt64>(), out);
285             break;
286         case types::InternalType::ScilabBool   :
287             encode(in->getAs<types::Bool>(), out);
288             break;
289
290         case types::InternalType::ScilabString :
291             encode(in->getAs<types::String>(), out);
292             break;
293
294         case types::InternalType::ScilabList   :
295             encode(in->getAs<types::List>(), out);
296             break;
297         case types::InternalType::ScilabTList  :
298             encode(in->getAs<types::List>(), out);
299             break;
300         case types::InternalType::ScilabMList  :
301             encode(in->getAs<types::List>(), out);
302             break;
303             //case types::InternalType::ScilabStruct :
304             //    encode(in->getAs<types::Struct>(), out);
305             //    break;
306
307         default :
308             //Scierror(999, _("%s: Wrong type for input argument #%d: %s, %s, %s, %s, %s or %s type.\n"), var2vecName.c_str(), 1, "Double", "Integer", "Boolean", "String", "List", "Struct");
309             Scierror(999, _("%s: Wrong type for input argument #%d: %s, %s, %s, %s or %s type.\n"), var2vecName.c_str(), 1, "Double", "Integer", "Boolean", "String", "List");
310             return false;
311     }
312
313     return true;
314 }