bug_9339 updated
[scilab.git] / scilab / modules / hdf5 / sci_gateway / cpp / sci_hdf5_load_v3.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2015 - Scilab Enterprises - 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 #include <list>
13 #include <map>
14 #include <hdf5.h>
15 #include "hdf5_gw.hxx"
16 #include "context.hxx"
17 #include "string.hxx"
18 #include "double.hxx"
19 #include "struct.hxx"
20 #include "cell.hxx"
21 #include "int.hxx"
22 #include "list.hxx"
23 #include "tlist.hxx"
24 #include "mlist.hxx"
25 #include "polynom.hxx"
26 #include "sparse.hxx"
27 #include "graphichandle.hxx"
28 #include "macro.hxx"
29 #include "void.hxx"
30 #include "listundefined.hxx"
31 #include "context.hxx"
32 #include "handle_properties.hxx"
33 #include "deserializervisitor.hxx"
34 #include "execvisitor.hxx"
35
36 std::unordered_map<int, Links::PathList> Links::paths;
37
38 extern "C"
39 {
40 #include "sci_malloc.h"
41 #include "Scierror.h"
42 #include "localization.h"
43 #include "freeArrayOfString.h"
44 #include "os_string.h"
45 #include "deleteafile.h"
46 #include "expandPathVariable.h"
47 #include "h5_fileManagement.h"
48 #include "h5_writeDataToFile.h"
49 #include "h5_readDataFromFile.h"
50 #include "h5_attributeConstants.h"
51 #include "HandleManagement.h"
52
53 }
54 /*--------------------------------------------------------------------------*/
55 static bool import_variable(int file, std::string& name);
56 types::InternalType* import_data(int dataset);
57 static types::InternalType* import_double(int dataset);
58 static types::InternalType* import_string(int dataset);
59 static types::InternalType* import_boolean(int dataset);
60 static types::InternalType* import_int(int dataset);
61 static types::InternalType* import_list(int dataset, types::List* lst);
62 static types::InternalType* import_struct(int dataset);
63 static types::InternalType* import_poly(int dataset);
64 static types::InternalType* import_cell(int dataset);
65 static types::InternalType* import_handles(int dataset);
66 static types::InternalType* import_sparse(int dataset);
67 static types::InternalType* import_boolean_sparse(int dataset);
68 static types::InternalType* import_macro(int dataset);
69 static types::InternalType* import_usertype(int dataset);
70
71
72 /*--------------------------------------------------------------------------*/
73 static const std::string fname("load");
74 /*--------------------------------------------------------------------------*/
75 types::Function::ReturnValue sci_hdf5_load_v3(types::typed_list &in, int _iRetCount, types::typed_list &out)
76 {
77     std::string filename;
78     int rhs = static_cast<int>(in.size());
79
80     if (rhs < 1)
81     {
82         Scierror(999, _("%s: Wrong number of input argument(s): at least %d expected.\n"), fname.data(), 1);
83         return types::Function::Error;
84     }
85
86     if (in[0]->getId() != types::InternalType::IdScalarString)
87     {
88         Scierror(999, _("%s: Wrong size for input argument #%d: A string expected.\n"), fname.data(), 1);
89         return types::Function::Error;
90     }
91
92     wchar_t* wfilename = expandPathVariableW(in[0]->getAs<types::String>()->get()[0]);
93     char* cfilename = wide_string_to_UTF8(wfilename);
94     filename = cfilename;
95     FREE(wfilename);
96     FREE(cfilename);
97
98     int iFile = openHDF5File(filename.data(), 0);
99     if (iFile < 0)
100     {
101         Scierror(999, _("%s: Unable to open file: %s\n"), fname.data(), filename.data());
102         return types::Function::Error;
103     }
104
105     //manage version information
106     int iVersion = getSODFormatAttribute(iFile);
107     if (iVersion != SOD_FILE_VERSION)
108     {
109         //can't read file with version newer that me !
110         Scierror(999, _("%s: Wrong SOD file format version. Expected: %d Found: %d\n"), fname.data(), SOD_FILE_VERSION, iVersion);
111         return types::Function::Error;
112     }
113
114     if (rhs > 1)
115     {
116         for (int i = 1; i < rhs; ++i)
117         {
118             std::string var;
119             char* cvar = wide_string_to_UTF8(in[i]->getAs<types::String>()->get()[0]);
120             var = cvar;
121             FREE(cvar);
122
123             if (import_variable(iFile, var) == false)
124             {
125                 Scierror(999, _("%s: Unable to load \'%s\'.\n"), fname.data(), var.data());
126                 return types::Function::Error;
127             }
128         }
129     }
130     else
131     {
132         //restore all variables
133         int iNbItem = 0;
134         iNbItem = getVariableNames6(iFile, NULL);
135         if (iNbItem != 0)
136         {
137             std::vector<char*> vars(iNbItem);
138             iNbItem = getVariableNames6(iFile, vars.data());
139             for (auto &var : vars)
140             {
141                 std::string s(var);
142                 if (import_variable(iFile, s) == false)
143                 {
144                     Scierror(999, _("%s: Unable to load \'%s\'.\n"), fname.data(), var);
145                     return types::Function::Error;
146                 }
147             }
148         }
149     }
150
151     //close the file
152     closeHDF5File(iFile);
153
154     out.push_back(new types::Bool(1));
155     return types::Function::OK;
156 }
157
158 static bool import_variable(int file, std::string& name)
159 {
160     int dataset = getDataSetIdFromName(file, name.data());
161     if (dataset <= 0)
162     {
163         return false;
164     }
165
166     types::InternalType* data = import_data(dataset);
167     if (data != nullptr)
168     {
169         wchar_t* var = to_wide_string(name.data());
170         //update macro name
171         if (data->isMacro())
172         {
173             types::Macro* macro = data->getAs<types::Macro>();
174             macro->setName(var);
175             symbol::Context::getInstance()->addMacro(macro);
176         }
177         else
178         {
179             //add to context
180             symbol::Context::getInstance()->put(symbol::Symbol(var), data);
181         }
182         FREE(var);
183         return true;
184     }
185
186     return false;
187 }
188
189 types::InternalType* import_data(int dataset)
190 {
191     //get var type
192     char* ctype = getScilabTypeFromDataSet6(dataset);
193     std::string type(ctype);
194     FREE(ctype);
195
196     if (type == g_SCILAB_CLASS_DOUBLE)
197     {
198         return import_double(dataset);
199     }
200
201     if (type == g_SCILAB_CLASS_STRING)
202     {
203         return import_string(dataset);
204     }
205
206     if (type == g_SCILAB_CLASS_INT)
207     {
208         return import_int(dataset);
209     }
210
211     if (type == g_SCILAB_CLASS_BOOLEAN)
212     {
213         return import_boolean(dataset);
214     }
215
216     if (type == g_SCILAB_CLASS_LIST)
217     {
218         return import_list(dataset, new types::List());
219     }
220
221     if (type == g_SCILAB_CLASS_TLIST)
222     {
223         return import_list(dataset, new types::TList());
224     }
225
226     if (type == g_SCILAB_CLASS_MLIST)
227     {
228         return import_list(dataset, new types::MList());
229     }
230
231     if (type == g_SCILAB_CLASS_STRUCT)
232     {
233         return import_struct(dataset);
234     }
235
236     if (type == g_SCILAB_CLASS_POLY)
237     {
238         return import_poly(dataset);
239     }
240
241     if (type == g_SCILAB_CLASS_SPARSE)
242     {
243         return import_sparse(dataset);
244     }
245
246     if (type == g_SCILAB_CLASS_BSPARSE)
247     {
248         return import_boolean_sparse(dataset);
249     }
250
251     if (type == g_SCILAB_CLASS_CELL)
252     {
253         return import_cell(dataset);
254     }
255
256     if (type == g_SCILAB_CLASS_HANDLE)
257     {
258         return import_handles(dataset);
259     }
260
261     if (type == g_SCILAB_CLASS_MACRO)
262     {
263         return import_macro(dataset);
264     }
265
266     if (type == g_SCILAB_CLASS_VOID)
267     {
268         closeDataSet(dataset);
269         return new types::Void();
270     }
271
272     if (type == g_SCILAB_CLASS_UNDEFINED)
273     {
274         closeDataSet(dataset);
275         return new types::ListUndefined();
276     }
277
278     if (type == g_SCILAB_CLASS_USERTYPE)
279     {
280         return import_usertype(dataset);
281     }
282
283
284     return nullptr;
285 }
286
287 static types::InternalType* import_double(int dataset)
288 {
289     int complex = 0;
290     int dims = 0;
291     int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
292     if (ret < 0)
293     {
294         closeDataSet(dataset);
295         return nullptr;
296     }
297
298     std::vector<int> d(dims);
299     int size = getDatasetInfo(dataset, &complex, &dims, d.data());
300
301
302     if (dims == 0 || size == 0)
303     {
304         closeDataSet(dataset);
305         return types::Double::Empty();
306     }
307
308     types::Double* dbl = new types::Double(dims, d.data(), complex == 1);
309
310     double* real = dbl->get();
311     double* img = dbl->getImg();
312
313     if (complex)
314     {
315         readDoubleComplexMatrix(dataset, real, img);
316     }
317     else
318     {
319         readDoubleMatrix(dataset, real);
320     }
321     return dbl;
322 }
323
324 static types::InternalType* import_string(int dataset)
325 {
326     int complex = 0;
327     int dims = 0;
328     int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
329     if (ret < 0)
330     {
331         closeDataSet(dataset);
332         return nullptr;
333     }
334
335
336     std::vector<int> d(dims);
337     int size = getDatasetInfo(dataset, &complex, &dims, d.data());
338
339
340     if (dims == 0 || size == 0)
341     {
342         closeDataSet(dataset);
343         return types::Double::Empty();
344     }
345
346     std::vector<char*> s(size);
347     ret = readStringMatrix(dataset, s.data());
348
349     types::String* str = new types::String(dims, d.data());
350     wchar_t** pstr = str->get();
351
352     for (int i = 0; i < size; ++i)
353     {
354         pstr[i] = to_wide_string(s[i]);
355     }
356
357     freeStringMatrix(dataset, s.data());
358
359     return str;
360 }
361
362 static types::InternalType* import_boolean(int dataset)
363 {
364     int complex = 0;
365     int dims = 0;
366     int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
367     if (ret < 0)
368     {
369         closeDataSet(dataset);
370         return nullptr;
371     }
372
373     std::vector<int> d(dims);
374     int size = getDatasetInfo(dataset, &complex, &dims, d.data());
375
376
377     if (dims == 0 || size == 0)
378     {
379         closeDataSet(dataset);
380         return types::Double::Empty();
381     }
382
383     types::Bool* bools = new types::Bool(dims, d.data());
384
385     int* b = bools->get();
386     readBooleanMatrix(dataset, b);
387     return bools;
388 }
389
390 static types::InternalType* import_int(int dataset)
391 {
392     types::InternalType* pOut = nullptr;
393     int complex = 0;
394     int dims = 0;
395     int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
396     if (ret < 0)
397     {
398         closeDataSet(dataset);
399         return nullptr;
400     }
401
402     std::vector<int> d(dims);
403     int size = getDatasetInfo(dataset, &complex, &dims, d.data());
404
405
406     if (dims == 0 || size == 0)
407     {
408         closeDataSet(dataset);
409         return types::Double::Empty();
410     }
411
412     int prec = 0;
413     ret = getDatasetPrecision(dataset, &prec);
414     if (ret != 0)
415     {
416         closeDataSet(dataset);
417         return nullptr;
418     }
419
420     switch (prec)
421     {
422         case SCI_INT8:
423         {
424             types::Int8* pi = new types::Int8(dims, d.data());
425             ret = readInteger8Matrix(dataset, pi->get());
426             pOut = pi;
427             break;
428         }
429         case SCI_INT16:
430         {
431             types::Int16* pi = new types::Int16(dims, d.data());
432             ret = readInteger16Matrix(dataset, pi->get());
433             pOut = pi;
434             break;
435         }
436         case SCI_INT32:
437         {
438             types::Int32* pi = new types::Int32(dims, d.data());
439             ret = readInteger32Matrix(dataset, pi->get());
440             pOut = pi;
441             break;
442         }
443         case SCI_INT64:
444         {
445             types::Int64* pi = new types::Int64(dims, d.data());
446             ret = readInteger64Matrix(dataset, pi->get());
447             pOut = pi;
448             break;
449         }
450         case SCI_UINT8:
451         {
452             types::UInt8* pi = new types::UInt8(dims, d.data());
453             ret = readUnsignedInteger8Matrix(dataset, pi->get());
454             pOut = pi;
455             break;
456         }
457         case SCI_UINT16:
458         {
459             types::UInt16* pi = new types::UInt16(dims, d.data());
460             ret = readUnsignedInteger16Matrix(dataset, pi->get());
461             pOut = pi;
462             break;
463         }
464         case SCI_UINT32:
465         {
466             types::UInt32* pi = new types::UInt32(dims, d.data());
467             ret = readUnsignedInteger32Matrix(dataset, pi->get());
468             pOut = pi;
469             break;
470         }
471         case SCI_UINT64:
472         {
473             types::UInt64* pi = new types::UInt64(dims, d.data());
474             ret = readUnsignedInteger64Matrix(dataset, pi->get());
475             pOut = pi;
476             break;
477         }
478         default:
479             return nullptr;
480             break;
481     }
482
483     return pOut;
484 }
485
486 static types::InternalType* import_list(int dataset, types::List* lst)
487 {
488     int count = 0;
489     int ret  = getListDims6(dataset, &count);
490     if (ret)
491     {
492         closeList6(dataset);
493         delete lst;
494         return nullptr;
495     }
496
497     if (count == 0)
498     {
499         closeList6(dataset);
500         return lst;
501     }
502
503     //get children
504
505     for (int i = 0; i < count; ++i)
506     {
507         int data = getDataSetIdFromName(dataset, std::to_string(i).data());
508         if (data <= 0)
509         {
510             closeList6(dataset);
511             delete lst;
512             return nullptr;
513         }
514
515         types::InternalType* child = import_data(data);
516         if (child == nullptr)
517         {
518             closeList6(dataset);
519             delete lst;
520             return nullptr;
521         }
522
523         lst->append(child);
524     }
525
526     closeList6(dataset);
527     return lst;
528 }
529
530 static int getDimsNode(int dataset, int* complex, std::vector<int>& dims)
531 {
532     dims.clear();
533     int id = getDataSetIdFromName(dataset, "__dims__");
534     if (id < 0)
535     {
536         return 0;
537     }
538
539     //get dims dimension count
540     int dim = 0;
541     getDatasetInfo(id, complex, &dim, NULL);
542     //get dims dimension
543     std::vector<int> d(dim);
544     int size = getDatasetInfo(id, complex, &dim, d.data());
545
546     //get dims value
547     dims.resize(size);
548     readInteger32Matrix(id, dims.data());
549
550     size = dims[0];
551     for (int i = 1; i < dims.size(); ++i)
552     {
553         size *= dims[i];
554     }
555     return size;
556 }
557
558 static types::InternalType* import_struct(int dataset)
559 {
560     //get struct dims node
561     int complex = 0;
562     std::vector<int> pdims;
563     int size = getDimsNode(dataset, &complex, pdims);
564
565     types::Struct* str = new types::Struct(static_cast<int>(pdims.size()), pdims.data());
566     size = str->getSize();
567     if (size == 0)
568     {
569         //empty struct
570         closeList6(dataset);
571         return new types::Struct();
572     }
573
574     types::SingleStruct** sstr = str->get();
575
576     int fieldCount = 0;
577     int ret = getListDims6(dataset, &fieldCount);
578     if (ret < 0)
579     {
580         closeList6(dataset);
581         return str;
582     }
583
584     //open __refs__ node
585     int refs = getDataSetIdFromName(dataset, "__refs__");
586
587     H5O_info_t oinfo;
588     for (int i = 0; i < fieldCount; ++i)
589     {
590         H5Oget_info_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_NATIVE, i, &oinfo, H5P_DEFAULT);
591         ssize_t len = H5Lget_name_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_INC, i, 0, 0, H5P_DEFAULT) + 1;
592         char* name = (char*)MALLOC(sizeof(char) * len);
593         H5Lget_name_by_idx(dataset, ".", H5_INDEX_NAME, H5_ITER_INC, i, name, len, H5P_DEFAULT);
594
595         if (strcmp(name, "__dims__") != 0 && strcmp(name, "__refs__") != 0)
596         {
597             wchar_t* field = to_wide_string(name);
598             str->addField(field);
599
600             int dataref = getDataSetIdFromName(dataset, name);
601             if (dataref < 0)
602             {
603                 closeList6(dataset);
604                 FREE(name);
605                 return nullptr;
606             }
607
608             int refdim = 0;
609             getDatasetInfo(dataref, &complex, &refdim, NULL);
610             std::vector<int> refdims(refdim);
611             int refcount = getDatasetInfo(dataref, &complex, &refdim, refdims.data());
612             std::vector<hobj_ref_t> vrefs(refcount);
613             ret = H5Dread(dataref, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, vrefs.data());
614             if (ret < 0)
615             {
616                 FREE(name);
617                 return nullptr;
618             }
619
620
621             //import field
622             for (int j = 0; j < refcount; ++j)
623             {
624                 int data = H5Rdereference(refs, H5R_OBJECT, &vrefs[j]);
625                 if (data < 0)
626                 {
627                     FREE(name);
628                     return nullptr;
629                 }
630
631                 types::InternalType* val = import_data(data);
632                 if (val == nullptr)
633                 {
634                     FREE(name);
635                     return nullptr;
636                 }
637
638                 sstr[j]->set(field, val);
639
640             }
641             FREE(field);
642
643             closeDataSet(dataref);
644         }
645
646         FREE(name);
647     }
648     //str->addField();
649
650     closeList6(refs);
651     closeList6(dataset);
652     return str;
653 }
654
655 static types::InternalType* import_poly(int dataset)
656 {
657     //get poly dims node
658     int complex = 0;
659     std::vector<int> pdims;
660     int size = getDimsNode(dataset, &complex, pdims);
661
662     //get variable name
663     char* var = NULL;
664     int varname = getDataSetIdFromName(dataset, "__varname__");
665     readStringMatrix(varname, &var);
666     wchar_t* wvar = to_wide_string(var);
667     std::wstring wvarname(wvar);
668     FREE(wvar);
669     freeStringMatrix(varname, &var);
670
671     types::Polynom* p = new types::Polynom(wvarname, static_cast<int>(pdims.size()), pdims.data());
672     types::SinglePoly** pss = p->get();
673
674     //open __refs__ node
675     int refs = getDataSetIdFromName(dataset, "__refs__");
676     size = p->getSize();
677
678     //loop on children
679     for (int i = 0; i < size; ++i)
680     {
681         //forge name
682         std::string polyname(std::to_string(i));
683         int poly = getDataSetIdFromName(refs, polyname.data());
684
685         //get dims
686         complex = 0;
687         int dims = 0;
688         int ret = getDatasetInfo(poly, &complex, &dims, NULL);
689         if (ret < 0)
690         {
691             return nullptr;
692         }
693
694         std::vector<int> d(dims);
695         int datasize = getDatasetInfo(poly, &complex, &dims, d.data());
696
697         types::SinglePoly* ss = NULL;
698
699         //get coef
700         if (dims == 0 || datasize == 0)
701         {
702             ss = new types::SinglePoly();
703         }
704         else if (complex)
705         {
706             double* real = NULL;
707             double* img = NULL;
708             //create singlepoly
709             ss = new types::SinglePoly(&real, &img, datasize - 1);
710             readDoubleComplexMatrix(poly, real, img);
711         }
712         else
713         {
714             double* real = NULL;
715             ss = new types::SinglePoly(&real, datasize - 1);
716             readDoubleMatrix(poly, real);
717         }
718
719         pss[i] = ss;
720     }
721
722     closeList6(refs);
723     closeList6(dataset);
724     return p;
725 }
726
727 static types::InternalType* import_sparse(int dataset)
728 {
729     types::Sparse* sp = nullptr;
730     //get sparse dimensions
731     int complex = 0;
732     std::vector<int> pdims;
733     int size = getDimsNode(dataset, &complex, pdims);
734
735     //get non zeros count
736     int nnz = 0;
737     int datannz = getDataSetIdFromName(dataset, "__nnz__");
738     readInteger32Matrix(datannz, &nnz);
739
740     if (nnz == 0)
741     {
742         closeList6(dataset);
743         return new types::Sparse(pdims[0], pdims[1]);
744     }
745
746     //get inner vector
747     int datain = getDataSetIdFromName(dataset, "__inner__");
748     int dimin = 0;
749     int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
750     std::vector<int> dimsin(dimin);
751     sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
752
753     std::vector<int> in(sizein);
754     int ret = readInteger32Matrix(datain, in.data());
755     if (ret < 0)
756     {
757         closeList6(dataset);
758         return nullptr;
759     }
760
761     //get outer vector
762     int dataout = getDataSetIdFromName(dataset, "__outer__");
763     int dimout = 0;
764     int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
765     std::vector<int> dimsout(dimout);
766     sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
767
768     std::vector<int> out(sizeout);
769     ret = readInteger32Matrix(dataout, out.data());
770     if (ret < 0)
771     {
772         closeList6(dataset);
773         return nullptr;
774     }
775
776     //get data
777     int ddata = getDataSetIdFromName(dataset, "__data__");
778     int dimdata = 0;
779     int sizedata = getDatasetInfo(ddata, &complex, &dimdata, NULL);
780     std::vector<int> dimsdata(dimdata);
781     sizedata = getDatasetInfo(ddata, &complex, &dimdata, dimsdata.data());
782
783     std::vector<double> real(sizedata);
784
785     if (complex)
786     {
787         std::vector<double> img(sizedata);
788         ret = readDoubleComplexMatrix(ddata, real.data(), img.data());
789         if (ret < 0)
790         {
791             closeList6(dataset);
792             return nullptr;
793         }
794
795         sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), img.data());
796     }
797     else
798     {
799         ret = readDoubleMatrix(ddata, real.data());
800         if (ret < 0)
801         {
802             closeList6(dataset);
803             return nullptr;
804         }
805
806         sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), nullptr);
807     }
808
809     closeList6(dataset);
810     return sp;
811 }
812
813 static types::InternalType* import_boolean_sparse(int dataset)
814 {
815     //get sparse dimensions
816     int complex = 0;
817     std::vector<int> pdims;
818     int size = getDimsNode(dataset, &complex, pdims);
819
820     //get non zeros count
821     int nnz = 0;
822     int datannz = getDataSetIdFromName(dataset, "__nnz__");
823     readInteger32Matrix(datannz, &nnz);
824
825     if (nnz == 0)
826     {
827         closeList6(dataset);
828         return new types::SparseBool(pdims[0], pdims[1]);
829     }
830
831     //get inner vector
832     int datain = getDataSetIdFromName(dataset, "__inner__");
833     int dimin = 0;
834     int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
835     std::vector<int> dimsin(dimin);
836     sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
837
838     std::vector<int> in(sizein);
839     int ret = readInteger32Matrix(datain, in.data());
840     if (ret < 0)
841     {
842         closeList6(dataset);
843         return nullptr;
844     }
845
846     //get outer vector
847     int dataout = getDataSetIdFromName(dataset, "__outer__");
848     int dimout = 0;
849     int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
850     std::vector<int> dimsout(dimout);
851     sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
852
853     std::vector<int> out(sizeout);
854     ret = readInteger32Matrix(dataout, out.data());
855     if (ret < 0)
856     {
857         closeList6(dataset);
858         return nullptr;
859     }
860
861     closeList6(dataset);
862
863     return new types::SparseBool(pdims[0], pdims[1], nnz, in.data(), out.data());
864 }
865
866 static types::InternalType* import_cell(int dataset)
867 {
868     //get sparse dimensions
869     int complex = 0;
870     std::vector<int> pdims;
871     int size = getDimsNode(dataset, &complex, pdims);
872
873     if (size == 0)
874     {
875         closeList6(dataset);
876         return new types::Cell();
877     }
878
879     //open __refs__ node
880     int refs = getDataSetIdFromName(dataset, "__refs__");
881     std::vector<types::InternalType*> data(size);
882     for (int i = 0; i < size; ++i)
883     {
884         int ref = getDataSetIdFromName(refs, std::to_string(i).data());
885         types::InternalType* val = import_data(ref);
886         if (val == nullptr)
887         {
888             return nullptr;
889         }
890
891         data[i] = val;
892     }
893
894     types::Cell* cell = new types::Cell(static_cast<int>(pdims.size()), pdims.data(), data.data());
895
896     closeList6(refs);
897     closeList6(dataset);
898     return cell;
899 }
900
901 static types::InternalType* import_handles(int dataset)
902 {
903     //get sparse dimensions
904     int complex = 0;
905     std::vector<int> pdims;
906     int size = getDimsNode(dataset, &complex, pdims);
907
908     if (size == 0)
909     {
910         closeList6(dataset);
911         return nullptr;
912     }
913
914     //open __refs__ node
915     int refs = getDataSetIdFromName(dataset, "__refs__");
916     types::GraphicHandle* handles = new types::GraphicHandle(static_cast<int>(pdims.size()), pdims.data());
917     long long* h = handles->get();
918     for (int i = 0; i < size; ++i)
919     {
920         int ref = getDataSetIdFromName(refs, std::to_string(i).data());
921         int val = import_handle(ref, -1);
922         if (val < 0)
923         {
924             return nullptr;
925         }
926
927         h[i] = getHandle(val);
928     }
929
930     closeList6(refs);
931     closeList6(dataset);
932
933
934     //update links property of legend handle
935     if (Links::count())
936     {
937         std::list<int> legends = Links::legends();
938         for (auto& i : legends)
939         {
940             Links::PathList paths = Links::get(i);
941             update_link_path(i, paths);
942         }
943     }
944     return handles;
945
946 }
947
948 static types::InternalType* import_macro(int dataset)
949 {
950     int complex = 0;
951     int dims = 0;
952     int size = 0;
953     std::vector<int> d(2);
954
955     std::list<symbol::Variable*>* inputList = new std::list<symbol::Variable*>();
956     std::list<symbol::Variable*>* outputList = new std::list<symbol::Variable*>();
957     ast::Exp* body = nullptr;
958
959     symbol::Context* ctx = symbol::Context::getInstance();
960
961     //inputs
962     int inputNode = getDataSetIdFromName(dataset, "inputs");
963     size = getDatasetInfo(inputNode, &complex, &dims, d.data());
964     std::vector<char*> inputNames(size);
965
966     if (size != 0)
967     {
968         readStringMatrix(inputNode, inputNames.data());
969
970         for (auto& input : inputNames)
971         {
972             wchar_t* winput = to_wide_string(input);
973             symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(winput));
974             FREE(winput);
975             inputList->push_back(var);
976         }
977
978         freeStringMatrix(inputNode, inputNames.data());
979     }
980     else
981     {
982         closeDataSet(inputNode);
983     }
984
985     //outputs
986     int outputNode = getDataSetIdFromName(dataset, "outputs");
987     size = getDatasetInfo(outputNode, &complex, &dims, d.data());
988     std::vector<char*> outputNames(size);
989
990     if (size != 0)
991     {
992         readStringMatrix(outputNode, outputNames.data());
993
994         for (auto& output : outputNames)
995         {
996             wchar_t* woutput = to_wide_string(output);
997             symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(woutput));
998             FREE(woutput);
999             outputList->push_back(var);
1000         }
1001
1002         freeStringMatrix(outputNode, outputNames.data());
1003     }
1004     else
1005     {
1006         closeDataSet(outputNode);
1007     }
1008
1009     //body
1010     int bodyNode = getDataSetIdFromName(dataset, "body");
1011     size = getDatasetInfo(bodyNode, &complex, &dims, d.data());
1012     std::vector<unsigned char> bodybin(size);
1013     readUnsignedInteger8Matrix(bodyNode, bodybin.data());
1014
1015     ast::DeserializeVisitor ds(bodybin.data());
1016     body = ds.deserialize();
1017
1018     //wname+1 is to remove "/" at the start of the var name from HDF5
1019     types::Macro* macro = new types::Macro(L"", *inputList, *outputList, *body->getAs<ast::SeqExp>(), L"script");
1020
1021     closeList6(dataset);
1022     return macro;
1023 }
1024
1025 static types::InternalType* import_usertype(int dataset)
1026 {
1027     types::InternalType* it = import_struct(dataset);
1028     if (it == nullptr || it->isStruct() == false)
1029     {
1030         delete it;
1031         return nullptr;
1032     }
1033
1034
1035     types::Struct* str = it->getAs<types::Struct>();
1036
1037     if (str->isScalar() == false)
1038     {
1039         delete it;
1040         return nullptr;
1041     }
1042
1043     types::SingleStruct* ss = str->get()[0];
1044
1045     //extract type from struct
1046     types::InternalType* itType  = ss->get(L"type");
1047     if (itType == nullptr || itType->getId() != types::InternalType::IdScalarString)
1048     {
1049         delete it;
1050         return nullptr;
1051     }
1052
1053     types::String* s = it->getAs<types::String>();
1054     wchar_t* type = s->get()[0];
1055
1056     types::InternalType* data = ss->get(L"data");
1057     if (data == nullptr)
1058     {
1059         delete it;
1060         return nullptr;
1061     }
1062
1063     //call %yourtype_load overload
1064     types::typed_list in;
1065     in.push_back(data);
1066
1067     types::typed_list out;
1068     //overload
1069     ast::ExecVisitor exec;
1070     // rational case
1071     std::wstring wstFuncName = L"%" + data->getShortTypeStr() + L"_load";
1072     types::Callable::ReturnValue ret = Overload::call(wstFuncName, in, 1, out, &exec);
1073
1074     //clean temporary variables
1075     delete it; //included type and data
1076
1077     if (ret != types::Callable::OK)
1078     {
1079         return nullptr;
1080     }
1081
1082     if (out.size() != 1)
1083     {
1084         for (auto& i : out)
1085         {
1086             i->killMe();
1087         }
1088
1089         return nullptr;
1090     }
1091
1092     return out[0];
1093 }