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