CovertyFix-CID:1366841,CID:1366842 Resource Leak
[scilab.git] / scilab / modules / api_scilab / src / cpp / api_stack_boolean_sparse.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Antoine ELIAS
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
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.
13  *
14  * Please note that piece of code will be rewrited for the Scilab 6 family
15  * However, the API (profile of the functions in the header files) will be
16  * still available and supported in Scilab 6.
17  */
18
19 #include "sparse.hxx"
20 #include "context.hxx"
21 #include "gatewaystruct.hxx"
22
23 extern "C"
24 {
25 #include <string.h>
26 #include "sci_malloc.h"
27 #include "api_scilab.h"
28 #include "call_scilab.h"
29 #include "core_math.h"
30 #include "api_internal_common.h"
31 #include "api_stack_boolean_sparse.h"
32 #include "api_internal_boolean_sparse.h"
33 #include "localization.h"
34 }
35
36 SciErr getBooleanSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos)
37 {
38     SciErr sciErr = sciErrInit();
39     int iType = 0;
40
41     if (_piAddress == NULL)
42     {
43         addErrorMessage(&sciErr, API_ERROR_INVALID_POINTER, _("%s: Invalid argument address"), "getBooleanSparseMatrix");
44         return sciErr;
45     }
46
47     sciErr =  getVarType(_pvCtx, _piAddress, &iType);
48     if (sciErr.iErr || iType != sci_boolean_sparse)
49     {
50         addErrorMessage(&sciErr, API_ERROR_GET_BOOLEAN_SPARSE, _("%s: Unable to get argument #%d"), "getBooleanSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
51         return sciErr;
52     }
53
54     sciErr = getVarDimension(_pvCtx, _piAddress, _piRows, _piCols);
55     if (sciErr.iErr)
56     {
57         addErrorMessage(&sciErr, API_ERROR_GET_BOOLEAN_SPARSE, _("%s: Unable to get argument #%d"), "getBooleanSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
58         return sciErr;
59     }
60
61     types::SparseBool* pSpBool = ((types::InternalType*)_piAddress)->getAs<types::SparseBool>();
62     *_piNbItem = (int)pSpBool->nbTrue();
63
64     if (_piNbItemRow == NULL)
65     {
66         return sciErr;
67     }
68
69     //WARNING: leak memory, caller must free pointer
70     int* piNbItemRows = (int*)MALLOC(sizeof(int) **_piRows);
71     *_piNbItemRow = pSpBool->getNbItemByRow(piNbItemRows);
72
73     if (_piColPos == NULL)
74     {
75         return sciErr;
76     }
77
78     //WARNING: leak memory, caller must free pointer
79     int* piColPos = (int*)MALLOC(sizeof(int) **_piNbItem);
80     *_piColPos = pSpBool->getColPos(piColPos);
81
82     return sciErr;
83 }
84
85 SciErr allocBooleanSparseMatrix(void* _pvCtx, int _iVar, int _iRows, int _iCols, int _iNbItem, int** _piNbItemRow, int** _piColPos)
86 {
87     SciErr sciErr = sciErrInit();
88     // We cant rewrite this function in Scilab 6
89     // because sparses are not stored like scilab 5.
90     // We cant return pointer to _piNbItemRow and
91     // _piColPos and let user fill it.
92     return sciErr;
93 }
94
95 SciErr fillBooleanSparseMatrix(void* _pvCtx, int* _piAddress, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos)
96 {
97     SciErr sciErr = sciErrInit();
98
99     if (_piAddress == NULL)
100     {
101         addErrorMessage(&sciErr, API_ERROR_INVALID_POINTER, _("%s: Invalid argument address"), "fillBooleanSparseMatrix");
102         return sciErr;
103     }
104
105     types::SparseBool* pSparse = (types::SparseBool*)_piAddress;
106
107     for (int i = 0; i < _iRows; i++)
108     {
109         for (int j = 0; j < _piNbItemRow[i]; j++)
110         {
111             int iIndex = (*_piColPos++ - 1) * _iRows + i;
112             pSparse->set(iIndex, true);
113         }
114     }
115
116     return sciErr;
117 }
118
119 SciErr createBooleanSparseMatrix(void* _pvCtx, int _iVar, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos)
120 {
121     SciErr sciErr = sciErrInit();
122
123     if (_iRows == 0 && _iCols == 0)
124     {
125         double dblReal = 0;
126         sciErr = createMatrixOfDouble(_pvCtx, _iVar, 0, 0, &dblReal);
127         if (sciErr.iErr)
128         {
129             addErrorMessage(&sciErr, API_ERROR_CREATE_EMPTY_MATRIX, _("%s: Unable to create variable in Scilab memory"), "createEmptyMatrix");
130         }
131         return sciErr;
132     }
133
134     types::GatewayStruct* pStr = (types::GatewayStruct*)_pvCtx;
135     types::InternalType** out = pStr->m_pOut;
136
137     types::SparseBool* pSparse = new types::SparseBool(_iRows, _iCols);
138     if (pSparse == NULL)
139     {
140         addErrorMessage(&sciErr, API_ERROR_CREATE_BOOLEAN_SPARSE, _("%s: Unable to create variable in Scilab memory"), "createBooleanSparseMatrix");
141         return sciErr;
142     }
143
144     int rhs = _iVar - *getNbInputArgument(_pvCtx);
145     out[rhs - 1] = pSparse;
146
147     sciErr = fillBooleanSparseMatrix(_pvCtx, (int*)pSparse, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos);
148     return sciErr;
149 }
150
151 SciErr createNamedBooleanSparseMatrix(void* _pvCtx, const char* _pstName, int _iRows, int _iCols, int _iNbItem, const int* _piNbItemRow, const int* _piColPos)
152 {
153     SciErr sciErr = sciErrInit();
154
155     // check variable name
156     if (checkNamedVarFormat(_pvCtx, _pstName) == 0)
157     {
158         addErrorMessage(&sciErr, API_ERROR_CREATE_EMPTY_MATRIX, _("%s: Invalid variable name: %s."), "createNamedMatrixOfBoolean", _pstName);
159         return sciErr;
160     }
161
162     //return named empty matrix
163     if (_iRows == 0 && _iCols == 0)
164     {
165         double dblReal = 0;
166         sciErr = createNamedMatrixOfDouble(_pvCtx, _pstName, 0, 0, &dblReal);
167         if (sciErr.iErr)
168         {
169             addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_EMPTY_MATRIX, _("%s: Unable to create variable in Scilab memory"), "createNamedEmptyMatrix");
170         }
171         return sciErr;
172     }
173
174     if (!checkNamedVarFormat(_pvCtx, _pstName))
175     {
176         addErrorMessage(&sciErr, API_ERROR_INVALID_NAME, _("%s: Invalid variable name: %s."), "createNamedBooleanSparseMatrix", _pstName);
177         return sciErr;
178     }
179
180     types::SparseBool* pSparse = new types::SparseBool(_iRows, _iCols);
181     if (pSparse == NULL)
182     {
183         addErrorMessage(&sciErr, API_ERROR_CREATE_NAMED_BOOLEAN_SPARSE, _("%s: Unable to create %s named \"%s\""), "createNamedBooleanSparseMatrix", _("boolean sparse matrix"), _pstName);
184         return sciErr;
185     }
186
187     sciErr = fillBooleanSparseMatrix(_pvCtx, (int*)pSparse, _iRows, _iCols, _iNbItem, _piNbItemRow, _piColPos);
188
189     wchar_t* pwstName = to_wide_string(_pstName);
190     symbol::Context* ctx = symbol::Context::getInstance();
191     symbol::Symbol sym = symbol::Symbol(pwstName);
192     FREE(pwstName);
193     if (ctx->isprotected(sym) == false)
194     {
195         ctx->put(sym, pSparse);
196     }
197     else
198     {
199         delete pSparse;
200         addErrorMessage(&sciErr, API_ERROR_REDEFINE_PERMANENT_VAR, _("Redefining permanent variable.\n"));
201     }
202     return sciErr;
203 }
204
205 SciErr readNamedBooleanSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int* _piNbItemRow, int* _piColPos)
206 {
207     SciErr sciErr       = sciErrInit();
208     struct Attr
209     {
210     public:
211         int *piAddr;
212         int *piNbItemRow;
213         int *piColPos;
214         Attr() : piAddr(NULL), piNbItemRow(NULL), piColPos(NULL) {}
215         ~Attr()
216         {
217             if (piNbItemRow)
218             {
219                 FREE(piNbItemRow);
220             }
221             if (piColPos)
222             {
223                 FREE(piColPos);
224             }
225             if (piAddr)
226             {
227                 FREE(piAddr);
228             }
229         }
230     };
231     struct Attr attr;
232     sciErr = getVarAddressFromName(_pvCtx, _pstName, &attr.piAddr);
233     if (sciErr.iErr)
234     {
235         addErrorMessage(&sciErr, API_ERROR_READ_NAMED_BOOLEAN_SPARSE, _("%s: Unable to get variable \"%s\""), "readNamedBooleanSparseMatrix", _pstName);
236         return sciErr;
237     }
238
239     sciErr = getBooleanSparseMatrix(_pvCtx, attr.piAddr, _piRows, _piCols, _piNbItem, &attr.piNbItemRow, &attr.piColPos);
240     if (sciErr.iErr)
241     {
242         addErrorMessage(&sciErr, API_ERROR_READ_NAMED_BOOLEAN_SPARSE, _("API_ERROR_READ_NAMED_BOOLEAN_SPARSE"));
243         return sciErr;
244     }
245
246     if (_piNbItemRow == NULL)
247     {
248         return sciErr;
249     }
250
251     memcpy(_piNbItemRow, attr.piNbItemRow, *_piRows * sizeof(int));
252
253     if (_piColPos == NULL)
254     {
255         return sciErr;
256     }
257
258     memcpy(_piColPos, attr.piColPos, *_piNbItem * sizeof(int));
259     return sciErr;
260 }
261 /*--------------------------------------------------------------------------*/
262 int isBooleanSparseType(void* _pvCtx, int* _piAddress)
263 {
264     return checkVarType(_pvCtx, _piAddress, sci_boolean_sparse);
265 }
266 /*--------------------------------------------------------------------------*/
267 int isNamedBooleanSparseType(void* _pvCtx, const char* _pstName)
268 {
269     return checkNamedVarType(_pvCtx, _pstName, sci_boolean_sparse);
270 }
271 /*--------------------------------------------------------------------------*/
272 int getAllocatedBooleanSparseMatrix(void* _pvCtx, int* _piAddress, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos)
273 {
274     SciErr sciErr = sciErrInit();
275     int* piNbItemRow    = NULL;
276     int* piColPos                       = NULL;
277
278     sciErr = getBooleanSparseMatrix(_pvCtx, _piAddress, _piRows, _piCols, _piNbItem, &piNbItemRow, &piColPos);
279     if (sciErr.iErr)
280     {
281         addErrorMessage(&sciErr, API_ERROR_GET_ALLOC_BOOLEAN_SPARSE, _("%s: Unable to get argument #%d"), "getAllocatedBooleanSparseMatrix", getRhsFromAddress(_pvCtx, _piAddress));
282         printError(&sciErr, 0);
283         FREE(piNbItemRow);
284         FREE(piColPos);
285         return sciErr.iErr;
286     }
287
288     *_piNbItemRow               = (int*)MALLOC(sizeof(int) **_piRows);
289     memcpy(*_piNbItemRow, piNbItemRow, sizeof(int) **_piRows);
290
291     *_piColPos                  = (int*)MALLOC(sizeof(int) **_piNbItem);
292     memcpy(*_piColPos, piColPos, sizeof(int) **_piNbItem);
293
294     FREE(piNbItemRow);
295     FREE(piColPos);
296     return 0;
297 }
298 /*--------------------------------------------------------------------------*/
299 int getNamedAllocatedBooleanSparseMatrix(void* _pvCtx, const char* _pstName, int* _piRows, int* _piCols, int* _piNbItem, int** _piNbItemRow, int** _piColPos)
300 {
301     SciErr sciErr = sciErrInit();
302     sciErr = readNamedBooleanSparseMatrix(_pvCtx, _pstName, _piRows, _piCols, _piNbItem, NULL, NULL);
303     if (sciErr.iErr)
304     {
305         addErrorMessage(&sciErr, API_ERROR_GET_NAMED_ALLOC_BOOLEAN_SPARSE, _("%s: Unable to get argument \"%s\""), "getNamedAllocatedBooleanSparseMatrix", _pstName);
306         printError(&sciErr, 0);
307         return sciErr.iErr;
308     }
309
310     *_piNbItemRow               = (int*)MALLOC(sizeof(int) **_piRows);
311     *_piColPos                  = (int*)MALLOC(sizeof(int) **_piNbItem);
312
313     sciErr = readNamedBooleanSparseMatrix(_pvCtx, _pstName, _piRows, _piCols, _piNbItem, *_piNbItemRow, *_piColPos);
314     if (sciErr.iErr)
315     {
316         addErrorMessage(&sciErr, API_ERROR_GET_NAMED_ALLOC_BOOLEAN_SPARSE, _("%s: Unable to get argument \"%s\""), "getNamedAllocatedBooleanSparseMatrix", _pstName);
317         printError(&sciErr, 0);
318         return sciErr.iErr;
319     }
320
321     return 0;
322 }
323 /*--------------------------------------------------------------------------*/
324 void freeAllocatedBooleanSparse(int* _piNbItemRow, int* _piColPos)
325 {
326     FREE(_piNbItemRow);
327     FREE(_piColPos);
328 }