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