* Port to matio 1.5.0 * Code cleaning * Prepare code for Scilab 6 (YaSp branch merge)
[scilab.git] / scilab / modules / matio / src / c / CreateStructVariable.c
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  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 #ifdef _MSC_VER
15 #include "strdup_Windows.h"
16 #endif
17
18 #include "CreateMatlabVariable.h"
19 #include "freeArrayOfString.h"
20 #include "api_scilab.h"
21 #include "MALLOC.h"
22 #include "localization.h"
23 #include "Scierror.h"
24 #include "sciprint.h"
25
26 int CreateStructVariable(void *pvApiCtx, int iVar, matvar_t *matVariable, int * parent, int item_position)
27 {
28     char **fieldNames = NULL;
29     int nbFields = 0;
30     int fieldIndex = 0;
31     int K = 0;
32     int prodDims = 0;
33     int valueIndex = 0;
34     matvar_t *fieldMatVar = NULL;
35     matvar_t ** allData = NULL;
36     int * cell_addr = NULL;
37     int * cell_entry_addr = NULL;
38     int type;
39     SciErr sciErr;
40     int *piDims = NULL;
41     int i = 0;
42
43     /* Fields of the struct */
44     nbFields = 2; /* "st" "dims" */
45     nbFields += Mat_VarGetNumberOfFields(matVariable);
46
47     fieldNames = (char**) MALLOC(sizeof(char*) * nbFields);
48     if (fieldNames == NULL)
49     {
50         Scierror(999, _("%s: No more memory.\n"), "CreateStructVariable");
51         return FALSE;
52     }
53
54     fieldNames[0] = strdup("st");
55     if (fieldNames[0] == NULL)
56     {
57         Scierror(999, _("%s: No more memory.\n"), "CreateStructVariable");
58         return FALSE;
59     }
60     fieldNames[1] = strdup("dims");
61     if (fieldNames[1] == NULL)
62     {
63         Scierror(999, _("%s: No more memory.\n"), "CreateStructVariable");
64         return FALSE;
65     }
66
67     for (fieldIndex = 1; fieldIndex < nbFields - 1; fieldIndex++)
68     {
69         fieldMatVar = Mat_VarGetStructField(matVariable, &fieldIndex, MAT_BY_INDEX, 0);
70         fieldNames[fieldIndex + 1] = strdup(fieldMatVar->name);
71         if (fieldNames[fieldIndex + 1] == NULL)
72         {
73             Scierror(999, _("%s: No more memory.\n"), "CreateStructVariable");
74             return FALSE;
75         }
76     }
77
78     /* Returned mlist initialization */
79     if (parent == NULL)
80     {
81         sciErr = createMList(pvApiCtx, iVar, nbFields, &cell_addr);
82         if (sciErr.iErr)
83         {
84             printError(&sciErr, 0);
85             return 0;
86         }
87     }
88     else
89     {
90         sciErr = createMListInList(pvApiCtx, iVar, parent, item_position, nbFields, &cell_addr);
91         if (sciErr.iErr)
92         {
93             printError(&sciErr, 0);
94             return 0;
95         }
96     }
97
98     /* FIRST LIST ENTRY: fieldnames */
99     sciErr = createMatrixOfStringInList(pvApiCtx, iVar, cell_addr, 1, 1, nbFields, fieldNames);
100     if (sciErr.iErr)
101     {
102         printError(&sciErr, 0);
103         return 0;
104     }
105
106     /* SECOND LIST ENTRY: Dimensions (int32 type) */
107     if (nbFields == 2) /* Empty struct must have size 0x0 in Scilab */
108     {
109         matVariable->dims[0] = 0;
110         matVariable->dims[1] = 0;
111     }
112
113     piDims = (int *) MALLOC(matVariable->rank * sizeof(int));
114     for (i = 0 ; i < matVariable->rank ; ++i)
115     {
116         piDims[i] = (int)matVariable->dims[i];
117     }
118
119     if (matVariable->rank == 2) /* Two dimensions */
120     {
121         sciErr = createMatrixOfInteger32InList(pvApiCtx, iVar, cell_addr, 2, 1, matVariable->rank, piDims);
122         if (sciErr.iErr)
123         {
124             printError(&sciErr, 0);
125             return 0;
126         }
127     }
128     else /* 3 or more dimensions -> Scilab HyperMatrix */
129     {
130         type = I_INT32;
131         CreateHyperMatrixVariable(pvApiCtx, iVar, MATRIX_OF_VARIABLE_SIZE_INTEGER_DATATYPE,
132                                   &type, &matVariable->rank, piDims, (double*)matVariable->data,
133                                   NULL, cell_addr, 2);
134     }
135
136     FREE(piDims);
137
138     /* ALL OTHER ENTRIES: Fields data */
139     prodDims = 1;
140     for (K = 0; K < matVariable->rank; K++)
141     {
142         prodDims *= (int)matVariable->dims[K];
143     }
144
145     allData = (matvar_t**) (matVariable->data);
146
147     if (prodDims == 1) /* Scalar struct */
148     {
149         for (fieldIndex = 0; fieldIndex < nbFields - 2; fieldIndex++)
150         {
151             /* Create list entry in the stack */
152             if (!CreateMatlabVariable(pvApiCtx, iVar, allData[fieldIndex], cell_addr, fieldIndex + 3)) /* Could not Create Variable */
153             {
154                 if (allData[fieldIndex]->class_type != 0) /* class is 0 for not initialized fields */
155                 {
156                     sciprint("Do not know how to read a variable of class %d.\n", allData[fieldIndex]->class_type);
157                 }
158             }
159         }
160     }
161     else
162     {
163         for (fieldIndex = 0; fieldIndex < nbFields - 2; fieldIndex++)
164         {
165             sciErr = createListInList(pvApiCtx, iVar, cell_addr, fieldIndex + 3, prodDims, &cell_entry_addr);
166             if (sciErr.iErr)
167             {
168                 printError(&sciErr, 0);
169                 return 0;
170             }
171
172             for (valueIndex = 0; valueIndex < prodDims; valueIndex++)
173             {
174                 /* Create list entry in the stack */
175                 if (!CreateMatlabVariable(pvApiCtx, iVar, allData[(fieldIndex) + (nbFields - 2)*valueIndex], cell_entry_addr, valueIndex + 1)) /* Could not Create Variable */
176                 {
177                     if (allData[(fieldIndex) + (nbFields - 2)*valueIndex]->class_type != 0) /* class is 0 for not initialized fields */
178                     {
179                         sciprint("Do not know how to read a variable of class %d.\n", allData[(fieldIndex) + (nbFields - 2)*valueIndex]->class_type);
180                     }
181                 }
182             }
183         }
184     }
185
186     freeArrayOfString(fieldNames, nbFields);
187
188     return TRUE;
189 }
190