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