a8af5f63101c4648e400f5588613db30dda9b24a
[scilab.git] / scilab / modules / matio / src / c / GetCharVariable.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  * Copyright (C) 2010 - DIGITEO - Vincent COUVERT 
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 #include <string.h>
15 #include "GetMatlabVariable.h"
16 #include "api_scilab.h"
17 #include "sci_types.h"
18 #include "freeArrayOfString.h"
19 #ifdef _MSC_VER
20 #include "strdup_windows.h"
21 #endif
22 #include "MALLOC.h"
23 #include "localization.h"
24
25 matvar_t *GetCharVariable(int iVar, const char *name, int * parent, int item_position)
26 {
27     char * dataAdr = NULL;
28     int rank = 0, i = 0, j = 0;
29     int *dims = NULL;
30     matvar_t *createdVar = NULL;
31     int* piLen = NULL;
32     char** pstData = NULL;
33     char* pstMatData = NULL;
34     int * piAddr = NULL;
35     int * item_addr = NULL;
36     int var_type;
37     int saveDim = 0; /* Used to save old dimension before restoring it */
38     SciErr sciErr;
39
40     if (parent==NULL)
41     {
42         sciErr = getVarAddressFromPosition(pvApiCtx, iVar, &piAddr);
43         if(sciErr.iErr)
44         {
45             printError(&sciErr, 0);
46             return NULL;
47         }
48         sciErr = getVarType(pvApiCtx, piAddr, &var_type);
49         if(sciErr.iErr)
50         {
51             printError(&sciErr, 0);
52             return NULL;
53         }
54     }
55     else
56     {
57         sciErr = getListItemAddress(pvApiCtx, parent, item_position, &item_addr);
58         if(sciErr.iErr)
59         {
60             printError(&sciErr, 0);
61             return NULL;
62         }
63         sciErr = getVarType(pvApiCtx, item_addr, &var_type);
64         if(sciErr.iErr)
65         {
66             printError(&sciErr, 0);
67             return NULL;
68         }
69     }
70
71     if(var_type == sci_strings) /* 2-D array */
72     {
73         rank = 2;
74         if ((dims = (int*)MALLOC(sizeof(int) * rank)) == NULL)
75         {
76             Scierror(999, _("%s: No more memory.\n"), "GetCharVariable");
77             return NULL;
78         }
79
80         if (parent==NULL)
81         {
82             // First call to retrieve dimensions
83             sciErr = getMatrixOfString(pvApiCtx, piAddr, &dims[0], &dims[1], NULL, NULL);
84             if(sciErr.iErr)
85             {
86                 printError(&sciErr, 0);
87                 return 0;
88             }
89             piLen = (int *)MALLOC(dims[0] * dims[1] * sizeof(int));
90             // Second call to retrieve length of each string
91             sciErr = getMatrixOfString(pvApiCtx, piAddr, &dims[0], &dims[1], piLen, NULL);
92             if(sciErr.iErr)
93             {
94                 printError(&sciErr, 0);
95                 return 0;
96             }
97             pstData = (char**)MALLOC(sizeof(char*) * dims[0] * dims[1]);
98             for(i = 0 ; i < dims[0] * dims[1] ; i++)
99             {
100                 pstData[i] = (char*)MALLOC(sizeof(char) * (piLen[i] + 1)); //+ 1 for null termination
101             }
102             // Third call to retrieve data
103             sciErr = getMatrixOfString(pvApiCtx, piAddr, &dims[0], &dims[1], piLen, pstData);
104             if(sciErr.iErr)
105             {
106                 printError(&sciErr, 0);
107                 return 0;
108             }
109             dataAdr = strdup(pstData[0]);
110         }
111         else
112         {
113             // First call to retrieve dimensions
114             sciErr  = getMatrixOfStringInList(pvApiCtx, parent, item_position, &dims[0], &dims[1], NULL, NULL);
115             if(sciErr.iErr)
116             {
117                 printError(&sciErr, 0);
118                 return NULL;
119             }
120             piLen = (int *)MALLOC(dims[0] * dims[1] * sizeof(int));
121             // Second call to retrieve length of each string
122             sciErr = getMatrixOfStringInList(pvApiCtx, parent, item_position, &dims[0], &dims[1], piLen, NULL);
123             if(sciErr.iErr)
124             {
125                 printError(&sciErr, 0);
126                 return NULL;
127             }
128             pstData = (char**)MALLOC(sizeof(char*) * dims[0] * dims[1]);
129             for(i = 0 ; i < dims[0] * dims[1] ; i++)
130             {
131                 pstData[i] = (char*)MALLOC(sizeof(char) * (piLen[i] + 1)); //+ 1 for null termination
132             }
133             // Third call to retrieve data
134             sciErr = getMatrixOfStringInList(pvApiCtx, parent, item_position, &dims[0], &dims[1], piLen, pstData);
135             if(sciErr.iErr)
136             {
137                 printError(&sciErr, 0);
138                 return NULL;
139             }
140             dataAdr = strdup(pstData[0]);
141         }
142
143         if (dims[0] == 0) /* Empty character string */
144         {
145             createdVar = Mat_VarCreate(name, MAT_C_CHAR, MAT_T_UINT8, rank, dims, pstData[0], 0);
146         }
147         else if (dims[0]*dims[1] == 1) /* Scalar character string */
148         {
149             saveDim = dims[1];
150             dims[1] = piLen[0];
151             createdVar = Mat_VarCreate(name, MAT_C_CHAR, MAT_T_UINT8, rank, dims, pstData[0], 0);
152             dims[1] = saveDim;
153         }
154         else /* More than one character string -> save as a Cell */
155         {
156             if (dims[0] == 1)
157             {
158                 /* TODO: Should be saved as a cell */
159                 Scierror(999, _("%s: Row array of strings saving is not implemented.\n"), "GetCharVariable");
160                 freeArrayOfString(pstData, dims[0]*dims[1]);
161                 FREE(dims);
162                 FREE(dataAdr);
163                 FREE(piLen);
164                 return NULL;
165             }
166             else if (dims[1] == 1)
167             {
168                 /* Check that all strings have the same length */
169                 for (i = 0 ; i < dims[0] ; i++)
170                 {
171                     if (piLen[0] != piLen[i])
172                     {
173                         /* TODO: Should be saved as a cell */
174                         Scierror(999, _("%s: Column array of strings with different lengths saving is not implemented.\n"), "GetCharVariable");
175                         freeArrayOfString(pstData, dims[0]*dims[1]);
176                         FREE(dims);
177                         FREE(dataAdr);
178                         FREE(piLen);
179                         return NULL;
180                     }
181                 }
182
183                 /* Reorder characters */
184                 pstMatData = (char*)MALLOC(sizeof(char) * dims[0] * piLen[0]);
185                 for (i = 0 ; i < dims[0] ; i++)
186                 {
187                     for (j = 0 ; j < piLen[0] ; j++)
188                     {
189                         pstMatData[i+j*dims[0]] = pstData[i][j];
190                     }
191                 }
192
193                 /* Save the variable */
194                 saveDim = dims[1];
195                 dims[1] = piLen[0];
196                 createdVar = Mat_VarCreate(name, MAT_C_CHAR, MAT_T_UINT8, rank, dims, pstMatData, 0);
197                 dims[1] = saveDim;
198
199                 freeArrayOfString(pstData, dims[0]*dims[1]); /* FREE now because dimensions are changed just below */
200                 FREE(pstMatData);
201                 FREE(dims);
202                 FREE(dataAdr);
203                 FREE(piLen);
204             }
205             else
206             {
207                 /* TODO: Should be saved as a cell */
208                 Scierror(999, _("%s: 2D array of strings saving is not implemented.\n"), "GetCharVariable");
209                 freeArrayOfString(pstData, dims[0]*dims[1]);
210                 FREE(dims);
211                 FREE(dataAdr);
212                 FREE(piLen);
213                 return NULL;
214             }
215         }
216     }
217     else
218     {
219         Scierror(999, _("%s: Wrong type for first input argument: String matrix expected.\n"), "GetCharVariable");
220         freeArrayOfString(pstData, dims[0]*dims[1]);
221         FREE(dims);
222         FREE(dataAdr);
223         FREE(piLen);
224         return NULL;
225     }
226
227     return createdVar;
228 }