2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2015 - Scilab Enterprises - Paul Bignier
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
22 #include "vec2var.hxx"
25 #include "internal.hxx"
33 //#include "struct.hxx"
37 #include "api_scilab.h"
40 #include "localization.h"
43 static const std::string vec2varName = "vec2var";
46 * Calculate the length increment depending on the type of the Scilab type
48 * @param T Scilab type
49 * @param v the instance on the Scilab type
50 * @return the number of double used to store the data
53 size_t required_length(T* v)
55 const size_t sizeof_double = sizeof(double);
56 if (sizeof(typename T::type) >= sizeof_double)
58 return v->getSize() * sizeof(typename T::type) / sizeof_double;
62 // Increase the size to contain enough space, manage the size_t rounding issue
63 return (v->getSize() * sizeof(typename T::type) + (sizeof_double - 1)) / sizeof_double;
68 int decode(const double* const tab, const int tabSize, const int iDims, const int offset, T* &res)
72 Scierror(999, _("%s: Wrong value for element #%d of input argument #%d: Integer matrix cannot be empty.\n"), vec2varName.c_str(), offset + 3, 1);
77 int* pDims = new int[iDims];
78 for (int i = 0; i < iDims; ++i)
80 pDims[i] = static_cast<int>(tab[i]);
81 iElements *= pDims[i];
84 res = new T(iDims, pDims);
87 const int numberOfDoubleNeeded = static_cast<int>(required_length(res));
88 if (tabSize < numberOfDoubleNeeded + 2 + iDims)
90 // Error case: the input doesn't have enough elements
91 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, numberOfDoubleNeeded + 2 + iDims + offset, 1);
96 //Use a buffer to prevent copying only parts of integers
97 double* buffer = new double[numberOfDoubleNeeded];
98 memcpy(buffer, tab + iDims, numberOfDoubleNeeded * sizeof(double));
99 memcpy(res->get(), buffer, iElements * sizeof(typename T::type));
102 assert(2 + iDims + numberOfDoubleNeeded > 0);
103 return 2 + iDims + numberOfDoubleNeeded;
107 int decode(const double* const tab, const int tabSize, const int iDims, const int offset, types::Double* &res)
110 int* pDims = new int[iDims];
111 for (int i = 0; i < iDims; ++i)
113 pDims[i] = static_cast<int>(tab[i]);
114 iElements *= pDims[i];
116 if (tabSize < iElements + 3 + iDims)
118 // Error case: the input doesn't have enough elements
120 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, iElements + 3 + iDims + offset, 1);
125 res = types::Double::Empty();
129 const bool isComplex = (tab[iDims] == 1);
131 res = new types::Double(iDims, pDims, isComplex);
134 res->set(tab + iDims + 1);
135 if (isComplex == true)
137 res->setImg(tab + iDims + 1 + iElements);
141 return 2 + iDims + 1 + iElements;
145 int decode(const double* const tab, const int tabSize, const int iDims, const int offset, types::String* &res)
149 Scierror(999, _("%s: Wrong value for element #%d of input argument #%d: String matrix cannot be empty.\n"), vec2varName.c_str(), offset + 2, 1);
154 int* pDims = new int[iDims];
155 for (int i = 0; i < iDims; ++i)
157 pDims[i] = static_cast<int>(tab[i]);
158 iElements *= pDims[i];
160 if (tabSize < iElements * 2 + 2 + iDims)
162 // Error case: the input doesn't have enough elements
164 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, iElements * 2 + 2 + iDims + offset, 1);
168 res = new types::String(iDims, pDims);
171 // Retrieving the first value pointer
172 double* strData = const_cast<double*>(tab + iDims + iElements);
174 res->set(0, (char*) & (*strData));
175 strData += static_cast<size_t>(tab[iDims]);
176 int stringOffset = static_cast<int>(tab[iDims]);
177 for (int i = 1; i < iElements; i++)
179 res->set(i, (char*) & (*strData));
181 // Increment the value pointer by the number of elements
182 const size_t numberOfElem = static_cast<size_t>(tab[iDims + i]) - static_cast<size_t>(tab[iDims + i - 1]);
183 strData += numberOfElem;
184 stringOffset += static_cast<int>(numberOfElem);
187 return 2 + iDims + iElements + stringOffset;
190 static bool readElement(const double* const input, const int iType, const int iDims, const int inputRows, int &offset, types::InternalType* &res)
198 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 5, 1);
202 types::Double* pDouble = nullptr;
203 const int resSize = decode<types::Double>(input + 2, inputRows, iDims, offset, pDouble);
215 switch (static_cast<int>(input[1]))
221 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 5, 1);
225 types::Int8* pInt8 = nullptr;
226 const int resSize = decode<types::Int8>(input + 3, inputRows, iDims, offset, pInt8);
232 offset += 1 + resSize;
239 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 5, 1);
243 types::UInt8* pUInt8 = nullptr;
244 const int resSize = decode<types::UInt8>(input + 3, inputRows, iDims, offset, pUInt8);
250 offset += 1 + resSize;
257 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 5, 1);
261 types::Int16* pInt16 = nullptr;
262 const int resSize = decode<types::Int16>(input + 3, inputRows, iDims, offset, pInt16);
268 offset += 1 + resSize;
275 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 5, 1);
279 types::UInt16* pUInt16 = nullptr;
280 const int resSize = decode<types::UInt16>(input + 3, inputRows, iDims, offset, pUInt16);
286 offset += 1 + resSize;
293 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 5, 1);
297 types::Int32* pInt32 = nullptr;
298 const int resSize = decode<types::Int32>(input + 3, inputRows, iDims, offset, pInt32);
304 offset += 1 + resSize;
311 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 5, 1);
315 types::UInt32* pUInt32 = nullptr;
316 const int resSize = decode<types::UInt32>(input + 3, inputRows, iDims, offset, pUInt32);
322 offset += 1 + resSize;
329 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 5, 1);
333 types::Int64* pInt64 = nullptr;
334 const int resSize = decode<types::Int64>(input + 3, inputRows, iDims, offset, pInt64);
340 offset += 1 + resSize;
347 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 5, 1);
351 types::UInt64* pUInt64 = nullptr;
352 const int resSize = decode<types::UInt64>(input + 3, inputRows, iDims, offset, pUInt64);
358 offset += 1 + resSize;
368 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 4, 1);
372 types::Bool* pBool = nullptr;
373 const int resSize = decode<types::Bool>(input + 2, inputRows, iDims, offset, pBool);
387 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 4, 1);
391 types::String* pString = nullptr;
392 const int resSize = decode<types::String>(input + 2, inputRows, iDims, offset, pString);
408 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 2, 1);
412 types::List* pList = nullptr;
413 if (iType == sci_list)
415 pList = new types::List();
417 else if (iType == sci_tlist)
419 pList = new types::TList();
423 pList = new types::MList();
433 // If reading a sublist, start off with a new offset
438 for (int i = 0; i < iDims; ++i)
440 if (inputRows < 2 + offset)
443 Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 2, 1);
446 // Extract the list elements infos and recursively call readElement
447 int elementType = static_cast<int>(*(input + offset));
449 if (elementType == sci_ints)
451 // Integers store their precision in *(input + offset + 1)
452 elementDims = static_cast<int>(*(input + offset + 2));
456 elementDims = static_cast<int>(*(input + offset + 1));
458 types::InternalType* element;
459 if (!readElement(input + offset, elementType, elementDims, inputRows - offset, offset, element))
465 pList->append(element);
466 if (element->isList())
471 offset += offsetSave;
476 // Structs are not used yet
477 //case types::InternalType::ScilabStruct :
479 // if (inputRows < 2)
481 // Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 2, 1);
487 // res = new types::Struct();
492 // int offsetSave = 0;
499 // // If reading a sublist, start off with a new offset
500 // offsetSave = offset;
503 // // Read the header...
504 // int elementType = static_cast<int>(*(input + offset));
505 // if (elementType != types::InternalType::ScilabString)
507 // Scierror(999, _("%s: Wrong value for input argument #%d: %d (String) expected.\n"), vec2varName.c_str(), 1, 11);
510 // int elementDims = static_cast<int>(*(input + offset + 1));
511 // types::InternalType* element;
512 // if (!readElement(input + offset, elementType, elementDims, inputRows - offset, offset, element))
517 // types::Struct* pStruct = new types::Struct(1, 1);
518 // types::String* header = element->getAs<types::String>();
519 // // ... and copy it in 'pStruct'
520 // for (int i = 0; i < header->getSize(); ++i)
522 // pStruct->get(0)->addField(header->get(i));
525 // for (int i = 1; i < iDims + 1; ++i)
527 // if (inputRows < 2 + offset)
530 // Scierror(999, _("%s: Wrong size for input argument #%d: At least %dx%d expected.\n"), vec2varName.c_str(), 1, offset + 2, 1);
533 // // Extract the fields content infos and recursively call readElement
534 // elementType = static_cast<int>(*(input + offset));
535 // elementDims = static_cast<int>(*(input + offset + 1));
536 // if (!readElement(input + offset, elementType, elementDims, inputRows - offset, offset, element))
541 // pStruct->get(0)->set(header->get(i - 1), element);
545 // offset += offsetSave;
551 Scierror(999, _("%s: Wrong value for element #%d of input argument #%d: Unknown type.\n"), vec2varName.c_str(), offset + 1, 1);
558 bool vec2var(const std::vector<double> in, types::InternalType* &out)
560 const int iType = static_cast<int>(in[0]);
562 if (iType == sci_ints)
564 // Integers store their precision in in[1]
565 iDims = static_cast<int>(in[2]);
569 iDims = static_cast<int>(in[1]);
573 if (!readElement(&in[0], iType, iDims, static_cast<int>(in.size()), offset, out))