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