46df25fe332742d57217f30f1e85a37de08c558e
[scilab.git] / scilab / modules / matio / src / cpp / CreateMatlabTreeVariable.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2008 - INRIA - Vincent COUVERT
4  * Copyright (C) 2010 - DIGITEO - Yann COLLETTE
5  * Copyright (C) 2015 - Scilab Enterprises - Sylvain GENIN
6  *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15  *
16  */
17
18 #include "CreateMatlabTreeVariable.hxx"
19 #include "cell.hxx"
20 #include "struct.hxx"
21 #include "string.hxx"
22 #include "sparse.hxx"
23 #include "int.hxx"
24
25 extern "C"
26 {
27 #include "CreateMatlabVariable.h"
28 #include "api_scilab.h"
29 #include "Scierror.h"
30 }
31
32 types::InternalType* CreateMatlabTreeVariable(matvar_t *matVariable)
33 {
34     types::InternalType* pOut = NULL;
35     /* To be sure isComplex is 0 or 1 */
36     bool isComplex = (matVariable->isComplex != 0);
37     int* piDims = NULL;
38
39     int iRank = matVariable->rank;
40     if (iRank != 0)
41     {
42         if (iRank == 1)
43         {
44             iRank = 2;
45             piDims = (int *)MALLOC(iRank * sizeof(int));
46             piDims[0] = (int)matVariable->dims[0];
47             piDims[1] = 1;
48         }
49         else
50         {
51             piDims = (int *)MALLOC(iRank * sizeof(int));
52
53             for (int i = 0; i < iRank; ++i)
54             {
55                 piDims[i] = (int)matVariable->dims[i];
56             }
57         }
58     }
59
60     switch (matVariable->class_type)
61     {
62         case MAT_C_CELL: /* 1 */
63         {
64
65             if ((iRank == 2) && ((piDims[0] * piDims[1]) <= 0))
66             {
67                 pOut = new types::Cell();
68             }
69             else
70             {
71                 pOut = new types::Cell(iRank, piDims);
72
73                 matvar_t** allData = (matvar_t**)(matVariable->data);
74                 int iSize = pOut->getAs<types::Cell>()->getSize();
75                 types::InternalType** ppIT = new types::InternalType*[iSize];
76                 for (int i = 0; i < iSize; i++)
77                 {
78                     ppIT[i] = CreateMatlabTreeVariable(allData[i]);
79                 }
80
81                 pOut->getAs<types::Cell>()->set(ppIT);
82             }
83
84         }
85         break;
86         case MAT_C_STRUCT: /* 2 */
87         {
88             if (matVariable->data == NULL)
89             {
90                 pOut = new types::Struct();
91             }
92             else
93             {
94                 pOut = new types::Struct(iRank, piDims);
95                 int iSizeStruct = Mat_VarGetNumberOfFields(matVariable);
96
97                 matvar_t** allData = (matvar_t**)(matVariable->data);
98
99                 bool bSearchSizeStruck = false;
100                 for (int i = 0; (allData[i] != NULL) && (bSearchSizeStruck == false) && (i < iSizeStruct); i++)
101                 {
102                     for (int j = (i - 1); j >= 0; j--)
103                     {
104                         if (strcmp((char*)allData[i]->name, (char*)allData[j]->name) == 0)
105                         {
106                             bSearchSizeStruck = true;
107                             break;
108                         }
109                     }
110                     std::wstring wstField(to_wide_string((char*)allData[i]->name));
111                     pOut->getAs<types::Struct>()->addField(wstField);
112                 }
113
114                 for (int i = 0; i < pOut->getAs<types::Struct>()->getSize(); i++)
115                 {
116                     for (int j = 0; j < iSizeStruct; j++)
117                     {
118                         std::wstring wstField(to_wide_string((char*)allData[j]->name));
119                         pOut->getAs<types::Struct>()->get(i)->set(wstField, CreateMatlabTreeVariable(allData[i * iSizeStruct + j]));
120                     }
121                 }
122             }
123         }
124
125         break;
126         case MAT_C_CHAR: /* 4 */
127         {
128             char* pChar = (char*)MALLOC(sizeof(char) * (piDims[1] + 1));
129             pChar[0] = '\0';
130             strncat(pChar, (char*)matVariable->data, piDims[1]);
131             types::String* pString = new types::String(pChar);
132             pOut = pString;
133         }
134         break;
135         case MAT_C_SPARSE: /* 5 */
136         {
137             mat_sparse_t *sparseData = (mat_sparse_t*)matVariable->data;
138
139             types::Sparse* pSparse = new types::Sparse(piDims[0], piDims[1], isComplex);
140             int *colIndexes = NULL;
141             int *rowIndexes = NULL;
142
143             /* Computes column indexes from Matlab indexes */
144             if (sparseData->njc > 1)
145             {
146                 colIndexes = (int*)MALLOC(sizeof(int) *  (sparseData->njc - 1));
147                 if (colIndexes == NULL)
148                 {
149                     Scierror(999, _("%s: No more memory.\n"), "CreateMatlabTreeVariable");
150                     return NULL;
151                 }
152
153                 for (int K = 0; K < sparseData->njc - 1; K++)
154                 {
155                     colIndexes[K] = sparseData->jc[K + 1] - sparseData->jc[K];
156                 }
157             }
158
159             /* Computes row indexes from Matlab indexes */
160             rowIndexes = (int*)MALLOC(sizeof(int) * sparseData->nir);
161             if (rowIndexes == NULL)
162             {
163                 Scierror(999, _("%s: No more memory.\n"), "CreateMatlabTreeVariable");
164                 return NULL;
165             }
166
167             for (int K = 0; K < sparseData->nir; K++)
168             {
169                 rowIndexes[K] = sparseData->ir[K] + 1;
170             }
171
172
173             if (isComplex)
174             {
175
176                 mat_complex_split_t *mat5ComplexData = NULL;
177                 mat5ComplexData = (mat_complex_split_t*)sparseData->data;
178
179                 double* pReal = (double*)mat5ComplexData->Re;
180                 double* pIm = (double*)mat5ComplexData->Im;
181
182                 int i = 0;
183                 for (int j = 0; j < (sparseData->njc - 1); j++)
184                 {
185                     for (int k = 0; k < colIndexes[j]; k++)
186                     {
187                         std::complex<double> dbl(pReal[i], pIm[i]);
188                         pSparse->set((rowIndexes[i] - 1), j, dbl);
189                         i++;
190                     }
191                 }
192
193             }
194             else
195             {
196                 double* pReal = (double*)sparseData->data;
197                 int i = 0;
198                 for (int j = 0; j < (sparseData->njc - 1); j++)
199                 {
200                     for (int k = 0; k < colIndexes[j]; k++)
201                     {
202                         pSparse->set((rowIndexes[i] - 1), j, pReal[i]);
203                         i++;
204                     }
205                 }
206             }
207             pOut = pSparse;
208             FREE(rowIndexes);
209             FREE(colIndexes);
210         }
211         break;
212         case MAT_C_DOUBLE: /* 6 */
213         case MAT_C_SINGLE: /* 7 */
214         {
215             types::Double* pDbl = new types::Double(iRank, piDims, isComplex);
216             if (isComplex)
217             {
218                 mat_complex_split_t *mat5ComplexData = NULL;
219                 mat5ComplexData = (mat_complex_split_t*)matVariable->data;
220
221                 pDbl->set((double*)mat5ComplexData->Re);
222                 pDbl->setImg((double*)mat5ComplexData->Im);
223             }
224             else
225             {
226                 pDbl->set((double*)matVariable->data);
227             }
228
229             pOut = pDbl;
230         }
231         break;
232         case MAT_C_INT8: /* 8 */
233         {
234             types::Int8* pInt8 = new types::Int8(iRank, piDims);
235
236             pInt8->set((char*)matVariable->data);
237
238             pOut = pInt8;
239         }
240         break;
241         case MAT_C_UINT8: /* 9 */
242         {
243             types::UInt8* pUInt8 = new types::UInt8(iRank, piDims);
244
245             pUInt8->set((unsigned char*)matVariable->data);
246
247             pOut = pUInt8;
248         }
249         break;
250         case MAT_C_INT16: /* 10 */
251         {
252             types::Int16* pInt16 = new types::Int16(iRank, piDims);
253
254             pInt16->set((short*)matVariable->data);
255
256             pOut = pInt16;
257         }
258         break;
259         case MAT_C_UINT16: /* 11 */
260         {
261             types::UInt16* pUInt16 = new types::UInt16(iRank, piDims);
262
263             pUInt16->set((unsigned short*)matVariable->data);
264
265             pOut = pUInt16;
266         }
267         break;
268         case MAT_C_INT32: /* 12 */
269         {
270             types::Int32* pInt32 = new types::Int32(iRank, piDims);
271
272             pInt32->set((int*)matVariable->data);
273
274             pOut = pInt32;
275         }
276         break;
277         case MAT_C_UINT32: /* 13 */
278         {
279             types::UInt32* pUInt32 = new types::UInt32(iRank, piDims);
280
281             pUInt32->set((unsigned int*)matVariable->data);
282
283             pOut = pUInt32;
284         }
285         break;
286 #ifdef __SCILAB_INT64__
287         case MAT_C_INT64: /* 14 */
288         {
289             types::Int64* pInt64 = new types::Int64(iRank, piDims);
290
291             pInt64->set((long long*)matVariable->data);
292
293             pOut = pInt64;
294         }
295         break;
296         case MAT_C_UINT64: /* 15 */
297         {
298             types::UInt64* pUInt64 = new types::UInt64(iRank, piDims);
299
300             pUInt64->set((unsigned long long*)matVariable->data);
301
302             pOut = pUInt64;
303         }
304         break;
305 #else
306         case MAT_C_INT64: /* 14 */
307         case MAT_C_UINT64: /* 15 */
308 #endif
309         case MAT_C_OBJECT: /* 3 to be written */
310         case MAT_C_FUNCTION: /* 16 to be written */
311         default:
312             /* Empty matrix returned */
313             return types::Double::Empty();
314     }
315
316     if (iRank != 0)
317     {
318         FREE(piDims);
319     }
320
321     return pOut;
322 }