hdf5: fix memory leaks
[scilab.git] / scilab / modules / hdf5 / src / cpp / listvar_in_hdf5_v1.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2012 - DIGITEO - Antoine ELIAS
4 *
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution.  The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10 *
11 */
12
13 #include <hdf5.h>
14 extern "C"
15 {
16 #include <string.h>
17 #include "gw_hdf5.h"
18 #include "MALLOC.h"
19 #include "Scierror.h"
20 #include "localization.h"
21 #include "sciprint.h"
22 #include "api_scilab.h"
23 #include "../../../call_scilab/includes/call_scilab.h"
24 #include "h5_fileManagement.h"
25 #include "h5_readDataFromFile_v1.h"
26 #include "expandPathVariable.h"
27 #include "freeArrayOfString.h"
28 }
29
30 #include <vector>
31
32 typedef struct __VAR_INFO_V1__
33 {
34     char pstInfo[128];
35     char varName[128];
36     int iType;
37     int iSize;
38     int iDims;
39     int piDims[2];
40
41     __VAR_INFO_V1__() : iType(0), iSize(0), iDims(0) {}
42 } VarInfo_v1;
43
44 static bool read_data_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
45 static bool read_double_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
46 static bool read_string_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
47 static bool read_boolean_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
48 static bool read_integer_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
49 static bool read_sparse_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
50 static bool read_boolean_sparse_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
51 static bool read_poly_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
52 static bool read_list_v1(int _iDatasetId, int _iVarType, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
53 static bool read_void_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
54 static bool read_undefined_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo);
55
56 static void generateInfo_v1(VarInfo_v1* _pInfo, const char* _pstType);
57
58 int sci_listvar_in_hdf5_v1(char *fname, unsigned long fname_len)
59 {
60     SciErr sciErr;
61     int *piAddr     = NULL;
62     char* pstFile   = NULL;
63     int iFile       = 0;
64     int iNbItem     = 0;
65     VarInfo_v1* pInfo  = NULL;
66
67     CheckRhs(1, 1);
68     CheckLhs(1, 4);
69
70     sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr);
71     if (sciErr.iErr)
72     {
73         printError(&sciErr, 0);
74         return 1;
75     }
76
77     if (getAllocatedSingleString(pvApiCtx, piAddr, &pstFile))
78     {
79         if (pstFile)
80         {
81             FREE(pstFile);
82         }
83
84         Scierror(999, _("%s: Wrong size for input argument #%d: A string expected.\n"), fname, 1);
85         return 1;
86     }
87
88     char* pstFileName = expandPathVariable(pstFile);
89     iFile = openHDF5File(pstFileName, 0);
90     if (iFile < 0)
91     {
92         FREE(pstFileName);
93         Scierror(999, _("%s: Unable to open file: %s\n"), fname, pstFile);
94         FREE(pstFile);
95         return 1;
96     }
97     FREE(pstFileName);
98     FREE(pstFile);
99
100     iNbItem = getVariableNames_v1(iFile, NULL);
101     if (iNbItem != 0)
102     {
103         char** pstVarNameList = (char**)MALLOC(sizeof(char*) * iNbItem);
104         bool b;
105         pInfo = (VarInfo_v1*)MALLOC(iNbItem * sizeof(VarInfo_v1));
106
107         if (Lhs == 1)
108         {
109             sciprint("Name                     Type           Size            Bytes\n");
110             sciprint("---------------------------------------------------------------\n");
111         }
112
113         iNbItem = getVariableNames_v1(iFile, pstVarNameList);
114         for (int i = 0; i < iNbItem; i++)
115         {
116             int iDataSetId = getDataSetIdFromName_v1(iFile, pstVarNameList[i]);
117             if (iDataSetId == 0)
118             {
119                 break;
120             }
121
122             strncpy(pInfo[i].varName, pstVarNameList[i], sizeof(pInfo[i].varName));
123             b = read_data_v1(iDataSetId, 0, NULL, &pInfo[i]) == false;
124             closeDataSet_v1(iDataSetId);
125
126             if (b)
127             {
128                 break;
129             }
130
131             if (Lhs == 1)
132             {
133                 sciprint("%s\n", pInfo[i].pstInfo);
134             }
135         }
136
137         freeArrayOfString(pstVarNameList, iNbItem);
138     }
139     else
140     {
141         //no variable returms [] for each Lhs
142         for (int i = 0 ; i < Lhs ; i++)
143         {
144             createEmptyMatrix(pvApiCtx, Rhs + i + 1);
145             LhsVar(i + 1) = Rhs + i + 1;
146         }
147
148         PutLhsVar();
149         return 0;
150     }
151
152     closeHDF5File(iFile);
153
154     //1st Lhs
155     char** pstVarName = (char**)MALLOC(sizeof(char*) * iNbItem);
156     for (int i = 0 ; i < iNbItem ; i++)
157     {
158         pstVarName[i] = pInfo[i].varName;
159     }
160
161     sciErr = createMatrixOfString(pvApiCtx, Rhs + 1, iNbItem, 1, pstVarName);
162     FREE(pstVarName);
163     if (sciErr.iErr)
164     {
165         FREE(pInfo);
166         printError(&sciErr, 0);
167         return 1;
168     }
169
170     LhsVar(1) = Rhs + 1;
171
172     if (Lhs > 1)
173     {
174         //2nd Lhs
175         double* pdblType;
176         sciErr = allocMatrixOfDouble(pvApiCtx, Rhs + 2, iNbItem, 1, &pdblType);
177         if (sciErr.iErr)
178         {
179             FREE(pInfo);
180             printError(&sciErr, 0);
181             return 1;
182         }
183
184         for (int i = 0 ; i < iNbItem ; i++)
185         {
186             pdblType[i] = pInfo[i].iType;
187         }
188
189         LhsVar(2) = Rhs + 2;
190
191         if (Lhs > 2)
192         {
193             //3rd Lhs
194             int* pList = NULL;
195             sciErr = createList(pvApiCtx, Rhs + 3, iNbItem, &pList);
196             for (int i = 0 ; i < iNbItem ; i++)
197             {
198                 double* pdblDims = NULL;
199                 allocMatrixOfDoubleInList(pvApiCtx, Rhs + 3, pList, i + 1, 1, pInfo[i].iDims, &pdblDims);
200                 for (int j = 0 ; j < pInfo[i].iDims ; j++)
201                 {
202                     pdblDims[j] = pInfo[i].piDims[j];
203                 }
204             }
205
206             LhsVar(3) = Rhs + 3;
207         }
208
209         if (Lhs > 3)
210         {
211             //4th Lhs
212             double* pdblSize;
213             sciErr = allocMatrixOfDouble(pvApiCtx, Rhs + 4, iNbItem, 1, &pdblSize);
214             for (int i = 0 ; i < iNbItem ; i++)
215             {
216                 pdblSize[i] = pInfo[i].iSize;
217             }
218
219             LhsVar(4) = Rhs + 4;
220         }
221
222     }
223
224     FREE(pInfo);
225     PutLhsVar();
226     return 0;
227 }
228
229 static bool read_data_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
230 {
231     bool bRet = false;
232
233     _pInfo->iType = getScilabTypeFromDataSet_v1(_iDatasetId);
234     switch (_pInfo->iType)
235     {
236         case sci_matrix:
237         {
238             bRet = read_double_v1(_iDatasetId, _iItemPos, _piAddress, _pInfo);
239             break;
240         }
241         case sci_strings:
242         {
243             bRet = read_string_v1(_iDatasetId, _iItemPos, _piAddress, _pInfo);
244             break;
245         }
246         case sci_list:
247         case sci_tlist:
248         case sci_mlist:
249         {
250             bRet = read_list_v1(_iDatasetId, _pInfo->iType, _iItemPos, _piAddress, _pInfo);
251             break;
252         }
253         case sci_boolean:
254         {
255             bRet = read_boolean_v1(_iDatasetId, _iItemPos, _piAddress, _pInfo);
256             break;
257         }
258         case sci_poly:
259         {
260             bRet = read_poly_v1(_iDatasetId, _iItemPos, _piAddress, _pInfo);
261             break;
262         }
263         case sci_ints:
264         {
265             bRet = read_integer_v1(_iDatasetId, _iItemPos, _piAddress, _pInfo);
266             break;
267         }
268         case sci_sparse:
269         {
270             bRet = read_sparse_v1(_iDatasetId, _iItemPos, _piAddress, _pInfo);
271             break;
272         }
273         case sci_boolean_sparse:
274         {
275             bRet = read_boolean_sparse_v1(_iDatasetId, _iItemPos, _piAddress, _pInfo);
276             break;
277         }
278         case sci_void:             //void item only on list variable
279         {
280             bRet = read_void_v1(_iDatasetId, _iItemPos, _piAddress, _pInfo);
281             break;
282         }
283         case sci_undefined:        //undefined item only on list variable
284         {
285             bRet = read_undefined_v1(_iDatasetId, _iItemPos, _piAddress, _pInfo);
286             break;
287         }
288         default:
289         {
290             Scierror(999, _("%s: Invalid HDF5 Scilab format.\n"), "listvar_in_hdf5");
291             break;
292         }
293     }
294
295     return bRet;
296 }
297
298 static bool read_double_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
299 {
300     int iRet = 0;
301     int iRows = 0;
302     int iCols = 0;
303     int iComplex = 0;
304
305     iRet = getDatasetDims_v1(_iDatasetId, &iRows, &iCols);
306     iComplex = isComplexData_v1(_iDatasetId);
307
308     _pInfo->iDims = 2;
309     _pInfo->piDims[0] = iRows;
310     _pInfo->piDims[1] = iCols;
311     _pInfo->iSize = (2 + (iRows * iCols * (iComplex + 1))) * 8;
312
313     generateInfo_v1(_pInfo, "constant");
314     return true;
315 }
316
317 static bool read_string_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
318 {
319     int iRet = 0;
320     int iRows = 0;
321     int iCols = 0;
322     char** pstData = NULL;
323
324     iRet = getDatasetDims_v1(_iDatasetId, &iRows, &iCols);
325
326     _pInfo->iDims = 2;
327     _pInfo->piDims[0] = iRows;
328     _pInfo->piDims[1] = iCols;
329
330     pstData = (char **)MALLOC(iRows * iCols * sizeof(char *));
331     memset(pstData, 0x00, iRows * iCols * sizeof(char *));
332     iRet = readStringMatrix_v1(_iDatasetId, iRows, iCols, pstData);
333
334     for (int i = 0 ; i < iRows * iCols ; i++)
335     {
336         _pInfo->iSize += (int)strlen(pstData[i]) * 4;
337         FREE(pstData[i]);
338     }
339
340     FREE(pstData);
341     //always full double size
342     _pInfo->iSize += (8 - (_pInfo->iSize % 8));
343     //header + offset
344     _pInfo->iSize += 16 + (1 + iRows * iCols) * 4;
345
346     generateInfo_v1(_pInfo, "string");
347     return true;
348 }
349
350 static bool read_boolean_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
351 {
352     int iRet = 0;
353     int iRows = 0;
354     int iCols = 0;
355
356     iRet = getDatasetDims_v1(_iDatasetId, &iRows, &iCols);
357
358     _pInfo->iDims = 2;
359     _pInfo->piDims[0] = iRows;
360     _pInfo->piDims[1] = iCols;
361     _pInfo->iSize = (3 + iRows * iCols) * 4;
362
363     generateInfo_v1(_pInfo, "boolean");
364     return true;
365 }
366
367 static bool read_integer_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
368 {
369     int iRet = 0;
370     int iRows = 0;
371     int iCols = 0;
372     int iPrec = 0;
373
374     iRet = getDatasetDims_v1(_iDatasetId, &iRows, &iCols);
375     iRet = getDatasetPrecision_v1(_iDatasetId, &iPrec);
376
377     _pInfo->iDims = 2;
378     _pInfo->piDims[0] = iRows;
379     _pInfo->piDims[1] = iCols;
380     _pInfo->iSize = 16 + iRows * iCols * (iPrec % 10);
381
382     generateInfo_v1(_pInfo, "integer");
383     return true;
384 }
385
386 static bool read_sparse_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
387 {
388     int iRet = 0;
389     int iRows = 0;
390     int iCols = 0;
391     int iNbItem = 0;
392     int iComplex = 0;
393
394     iRet = getSparseDimension_v1(_iDatasetId, &iRows, &iCols, &iNbItem);
395     if (iRet)
396     {
397         return false;
398     }
399
400     iComplex = isComplexData_v1(_iDatasetId);
401
402     _pInfo->iDims = 2;
403     _pInfo->piDims[0] = iRows;
404     _pInfo->piDims[1] = iCols;
405     _pInfo->iSize = 20 + iRows * 4 + iNbItem * 4 + (iNbItem * (iComplex + 1) * 8);
406
407     generateInfo_v1(_pInfo, "sparse");
408     return true;
409 }
410
411 static bool read_boolean_sparse_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
412 {
413     int iRet = 0;
414     int iRows = 0;
415     int iCols = 0;
416     int iNbItem = 0;
417     int iComplex = 0;
418
419     iRet = getSparseDimension_v1(_iDatasetId, &iRows, &iCols, &iNbItem);
420     if (iRet)
421     {
422         return false;
423     }
424
425     _pInfo->iDims = 2;
426     _pInfo->piDims[0] = iRows;
427     _pInfo->piDims[1] = iCols;
428     _pInfo->iSize = 20 + iRows * 4 + iNbItem * 4;
429
430     generateInfo_v1(_pInfo, "boolean sparse");
431     return true;
432 }
433
434 static bool read_poly_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
435 {
436     int iRet = 0;
437     int iRows = 0;
438     int iCols = 0;
439     int iComplex = 0;
440     char pstVarName[64] = { 0 };
441     double **pdblReal = NULL;
442     double **pdblImg = NULL;
443     int *piNbCoef = NULL;
444
445     iRet = getDatasetDims_v1(_iDatasetId, &iRows, &iCols);
446     if (iRet)
447     {
448         return false;
449     }
450
451     iComplex = isComplexData_v1(_iDatasetId);
452
453     _pInfo->iDims = 2;
454     _pInfo->piDims[0] = iRows;
455     _pInfo->piDims[1] = iCols;
456     _pInfo->iSize = 8 * 4 + (iRows * iCols + 1) * 4;
457
458     if (iComplex)
459     {
460         piNbCoef = (int *)MALLOC(iRows * iCols * sizeof(int));
461         pdblReal = (double **)MALLOC(iRows * iCols * sizeof(double *));
462         pdblImg = (double **)MALLOC(iRows * iCols * sizeof(double *));
463         iRet = readPolyComplexMatrix_v1(_iDatasetId, pstVarName, iRows, iCols, piNbCoef, pdblReal, pdblImg);
464     }
465     else
466     {
467         piNbCoef = (int *)MALLOC(iRows * iCols * sizeof(int));
468         pdblReal = (double **)MALLOC(iRows * iCols * sizeof(double *));
469         iRet = readPolyMatrix_v1(_iDatasetId, pstVarName, iRows, iCols, piNbCoef, pdblReal);
470     }
471
472     for (int i = 0 ; i < iRows * iCols ; i++)
473     {
474         _pInfo->iSize += piNbCoef[i] * 8 * (iComplex + 1);
475         FREE(pdblReal[i]);
476         if (iComplex)
477         {
478             FREE(pdblImg[i]);
479         }
480     }
481
482     FREE(piNbCoef);
483     FREE(pdblReal);
484     if (iComplex)
485     {
486         FREE(pdblImg);
487     }
488
489     generateInfo_v1(_pInfo, "polynomial");
490     return true;
491 }
492
493 static bool read_list_v1(int _iDatasetId, int _iVarType, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
494 {
495     int iRet = 0;
496     int iItems = 0;
497     int *piListAddr = NULL;
498     hobj_ref_t *piItemRef = NULL;
499
500     iRet = getListDims_v1(_iDatasetId, &iItems);
501     if (iRet)
502     {
503         return false;
504     }
505
506     if (iItems == 0)
507     {
508         //special case for empty list
509     }
510     else
511     {
512         iRet = getListItemReferences_v1(_iDatasetId, &piItemRef);
513         if (iRet)
514         {
515             return false;
516         }
517     }
518     //_pInfo = (VarInfo_v1*)MALLOC(sizeof(VarInfo));
519     _pInfo->iDims = 1;
520     _pInfo->piDims[0] = iItems;
521     _pInfo->iSize = (2 + iItems + 1) * 4;
522
523     for (int i = 0; i < iItems; i++)
524     {
525         int iItemDataset = 0;
526
527         iRet = getListItemDataset_v1(_iDatasetId, piItemRef, i, &iItemDataset);
528         if (iRet || iItemDataset == 0)
529         {
530             return false;
531         }
532         VarInfo_v1 info;
533         bool bRet = read_data_v1(iItemDataset, i + 1, piListAddr, &info);
534         if (bRet == false)
535         {
536             return false;
537         }
538
539         _pInfo->iSize += info.iSize;
540     }
541
542     if (_iVarType == sci_list)
543     {
544         generateInfo_v1(_pInfo, "list");
545     }
546     else if (_iVarType == sci_tlist)
547     {
548         generateInfo_v1(_pInfo, "tlist");
549     }
550     else if (_iVarType == sci_mlist)
551     {
552         generateInfo_v1(_pInfo, "mlist");
553     }
554
555     return true;
556 }
557
558 static bool read_void_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
559 {
560     _pInfo->iSize = 1;
561     return true;
562 }
563
564 static bool read_undefined_v1(int _iDatasetId, int _iItemPos, int *_piAddress, VarInfo_v1* _pInfo)
565 {
566     _pInfo->iSize = 1;
567     return true;
568 }
569
570 static void generateInfo_v1(VarInfo_v1* _pInfo, const char* _pstType)
571 {
572     char pstSize[17];
573
574     if (_pInfo->iDims == 2)
575     {
576         sprintf(pstSize, "%d by %d", _pInfo->piDims[0], _pInfo->piDims[1]);
577     }
578     else
579     {
580         sprintf(pstSize, "%d", _pInfo->piDims[0]);
581     }
582     sprintf(_pInfo->pstInfo, "%-*s%-*s%-*s%-*d", 25, _pInfo->varName, 15, _pstType, 16, pstSize, 10, _pInfo->iSize);
583 }
584