b07ac8f1e150a4b286cffc4686da20bfd5b9fe2b
[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     if (size < 0)
555     {
556         return 0;
557     }
558
559     //get dims value
560     dims.resize(size);
561     readInteger32Matrix(id, dims.data());
562
563     size = dims[0];
564     for (int i = 1; i < dims.size(); ++i)
565     {
566         size *= dims[i];
567     }
568     return size;
569 }
570
571 static types::InternalType* import_struct(int dataset)
572 {
573     //get struct dims node
574     int complex = 0;
575     std::vector<int> pdims;
576     int size = getDimsNode(dataset, &complex, pdims);
577
578     types::Struct* str = new types::Struct(static_cast<int>(pdims.size()), pdims.data());
579     size = str->getSize();
580     if (size == 0)
581     {
582         //empty struct
583         closeList6(dataset);
584         delete str;
585         return new types::Struct();
586     }
587
588     types::SingleStruct** sstr = str->get();
589
590     int fieldCount = 0;
591     int ret = getListDims6(dataset, &fieldCount);
592     if (ret < 0)
593     {
594         closeList6(dataset);
595         return str;
596     }
597
598     //get fields name
599     int dfield = getDataSetIdFromName(dataset, "__fields__");
600     int dim = 0;
601     getDatasetInfo(dfield, &complex, &dim, NULL);
602     std::vector<int> d(dim);
603     size = getDatasetInfo(dfield, &complex, &dim, d.data());
604     if (size < 0)
605     {
606         closeList6(dataset);
607         delete str;
608         return nullptr;
609     }
610
611     //get dims value
612     std::vector<char*> fields(size);
613     readStringMatrix(dfield, fields.data());
614
615     //open __refs__ node
616     int refs = getDataSetIdFromName(dataset, "__refs__");
617
618     for (const auto & name : fields)
619     {
620         wchar_t* field = to_wide_string(name);
621         str->addField(field);
622
623         int dataref = getDataSetIdFromName(dataset, name);
624         if (dataref < 0)
625         {
626             closeList6(dataset);
627             freeStringMatrix(dfield, fields.data());
628             FREE(field);
629             delete str;
630             return nullptr;
631         }
632
633         int refdim = 0;
634         getDatasetInfo(dataref, &complex, &refdim, NULL);
635         std::vector<int> refdims(refdim);
636         int refcount = getDatasetInfo(dataref, &complex, &refdim, refdims.data());
637         std::vector<hobj_ref_t> vrefs(refcount);
638         ret = H5Dread(dataref, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, vrefs.data());
639         if (ret < 0)
640         {
641             freeStringMatrix(dfield, fields.data());
642             FREE(field);
643             delete str;
644             return nullptr;
645         }
646
647
648         //import field
649         for (int j = 0; j < refcount; ++j)
650         {
651             int data = H5Rdereference(refs, H5R_OBJECT, &vrefs[j]);
652             if (data < 0)
653             {
654                 freeStringMatrix(dfield, fields.data());
655                 FREE(field);
656                 delete str;
657                 return nullptr;
658             }
659
660             types::InternalType* val = import_data(data);
661             if (val == nullptr)
662             {
663                 freeStringMatrix(dfield, fields.data());
664                 FREE(field);
665                 delete str;
666                 return nullptr;
667             }
668
669             sstr[j]->set(field, val);
670
671         }
672
673         FREE(field);
674         closeDataSet(dataref);
675     }
676
677     freeStringMatrix(dfield, fields.data());
678     closeList6(refs);
679     closeList6(dataset);
680     return str;
681 }
682
683 static types::InternalType* import_poly(int dataset)
684 {
685     //get poly dims node
686     int complex = 0;
687     std::vector<int> pdims;
688     int size = getDimsNode(dataset, &complex, pdims);
689
690     //get variable name
691     char* var = NULL;
692     int varname = getDataSetIdFromName(dataset, "__varname__");
693     readStringMatrix(varname, &var);
694     wchar_t* wvar = to_wide_string(var);
695     std::wstring wvarname(wvar);
696     FREE(wvar);
697     freeStringMatrix(varname, &var);
698
699     types::Polynom* p = new types::Polynom(wvarname, static_cast<int>(pdims.size()), pdims.data());
700     types::SinglePoly** pss = p->get();
701
702     //open __refs__ node
703     int refs = getDataSetIdFromName(dataset, "__refs__");
704     size = p->getSize();
705
706     //loop on children
707     for (int i = 0; i < size; ++i)
708     {
709         //forge name
710         std::string polyname(std::to_string(i));
711         int poly = getDataSetIdFromName(refs, polyname.data());
712
713         //get dims
714         complex = 0;
715         int dims = 0;
716         int ret = getDatasetInfo(poly, &complex, &dims, NULL);
717         if (ret < 0)
718         {
719             return nullptr;
720         }
721
722         std::vector<int> d(dims);
723         int datasize = getDatasetInfo(poly, &complex, &dims, d.data());
724
725         types::SinglePoly* ss = NULL;
726
727         //get coef
728         if (dims == 0 || datasize <= 0)
729         {
730             ss = new types::SinglePoly();
731         }
732         else if (complex)
733         {
734             double* real = NULL;
735             double* img = NULL;
736             //create singlepoly
737             ss = new types::SinglePoly(&real, &img, datasize - 1);
738             readDoubleComplexMatrix(poly, real, img);
739         }
740         else
741         {
742             double* real = NULL;
743             ss = new types::SinglePoly(&real, datasize - 1);
744             readDoubleMatrix(poly, real);
745         }
746
747         pss[i] = ss;
748     }
749
750     closeList6(refs);
751     closeList6(dataset);
752     return p;
753 }
754
755 static types::InternalType* import_sparse(int dataset)
756 {
757     types::Sparse* sp = nullptr;
758     //get sparse dimensions
759     int complex = 0;
760     std::vector<int> pdims;
761     int size = getDimsNode(dataset, &complex, pdims);
762
763     //get non zeros count
764     int nnz = 0;
765     int datannz = getDataSetIdFromName(dataset, "__nnz__");
766     readInteger32Matrix(datannz, &nnz);
767
768     if (nnz == 0)
769     {
770         closeList6(dataset);
771         return new types::Sparse(pdims[0], pdims[1]);
772     }
773
774     //get inner vector
775     int datain = getDataSetIdFromName(dataset, "__inner__");
776     int dimin = 0;
777     int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
778     std::vector<int> dimsin(dimin);
779     sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
780     if (sizein < 0)
781     {
782         closeList6(dataset);
783         return nullptr;
784     }
785
786     std::vector<int> in(sizein);
787     int ret = readInteger32Matrix(datain, in.data());
788     if (ret < 0)
789     {
790         closeList6(dataset);
791         return nullptr;
792     }
793
794     //get outer vector
795     int dataout = getDataSetIdFromName(dataset, "__outer__");
796     int dimout = 0;
797     int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
798     std::vector<int> dimsout(dimout);
799     sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
800     if (sizeout < 0)
801     {
802         closeList6(dataset);
803         return nullptr;
804     }
805
806     std::vector<int> out(sizeout);
807     ret = readInteger32Matrix(dataout, out.data());
808     if (ret < 0)
809     {
810         closeList6(dataset);
811         return nullptr;
812     }
813
814     //get data
815     int ddata = getDataSetIdFromName(dataset, "__data__");
816     int dimdata = 0;
817     int sizedata = getDatasetInfo(ddata, &complex, &dimdata, NULL);
818     std::vector<int> dimsdata(dimdata);
819     sizedata = getDatasetInfo(ddata, &complex, &dimdata, dimsdata.data());
820     if (sizedata < 0)
821     {
822         closeList6(dataset);
823         return nullptr;
824     }
825
826     std::vector<double> real(sizedata);
827
828     if (complex)
829     {
830         std::vector<double> img(sizedata);
831         ret = readDoubleComplexMatrix(ddata, real.data(), img.data());
832         if (ret < 0)
833         {
834             closeList6(dataset);
835             return nullptr;
836         }
837
838         sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), img.data());
839     }
840     else
841     {
842         ret = readDoubleMatrix(ddata, real.data());
843         if (ret < 0)
844         {
845             closeList6(dataset);
846             return nullptr;
847         }
848
849         sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), nullptr);
850     }
851
852     closeList6(dataset);
853     return sp;
854 }
855
856 static types::InternalType* import_boolean_sparse(int dataset)
857 {
858     //get sparse dimensions
859     int complex = 0;
860     std::vector<int> pdims;
861     int size = getDimsNode(dataset, &complex, pdims);
862
863     //get non zeros count
864     int nnz = 0;
865     int datannz = getDataSetIdFromName(dataset, "__nnz__");
866     readInteger32Matrix(datannz, &nnz);
867
868     if (nnz == 0)
869     {
870         closeList6(dataset);
871         return new types::SparseBool(pdims[0], pdims[1]);
872     }
873
874     //get inner vector
875     int datain = getDataSetIdFromName(dataset, "__inner__");
876     int dimin = 0;
877     int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
878     std::vector<int> dimsin(dimin);
879     sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
880     if (sizein < 0)
881     {
882         closeList6(dataset);
883         return nullptr;
884     }
885
886     std::vector<int> in(sizein);
887     int ret = readInteger32Matrix(datain, in.data());
888     if (ret < 0)
889     {
890         closeList6(dataset);
891         return nullptr;
892     }
893
894     //get outer vector
895     int dataout = getDataSetIdFromName(dataset, "__outer__");
896     int dimout = 0;
897     int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
898     std::vector<int> dimsout(dimout);
899     sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
900     if (sizeout < 0)
901     {
902         closeList6(dataset);
903         return nullptr;
904     }
905
906     std::vector<int> out(sizeout);
907     ret = readInteger32Matrix(dataout, out.data());
908     if (ret < 0)
909     {
910         closeList6(dataset);
911         return nullptr;
912     }
913
914     closeList6(dataset);
915
916     return new types::SparseBool(pdims[0], pdims[1], nnz, in.data(), out.data());
917 }
918
919 static types::InternalType* import_cell(int dataset)
920 {
921     //get sparse dimensions
922     int complex = 0;
923     std::vector<int> pdims;
924     int size = getDimsNode(dataset, &complex, pdims);
925
926     if (size == 0)
927     {
928         closeList6(dataset);
929         return new types::Cell();
930     }
931
932     //open __refs__ node
933     int refs = getDataSetIdFromName(dataset, "__refs__");
934     std::vector<types::InternalType*> data(size);
935     for (int i = 0; i < size; ++i)
936     {
937         int ref = getDataSetIdFromName(refs, std::to_string(i).data());
938         types::InternalType* val = import_data(ref);
939         if (val == nullptr)
940         {
941             return nullptr;
942         }
943
944         data[i] = val;
945     }
946
947     types::Cell* cell = new types::Cell(static_cast<int>(pdims.size()), pdims.data(), data.data());
948
949     closeList6(refs);
950     closeList6(dataset);
951     return cell;
952 }
953
954 static types::InternalType* import_handles(int dataset)
955 {
956     //get sparse dimensions
957     int complex = 0;
958     std::vector<int> pdims;
959     int size = getDimsNode(dataset, &complex, pdims);
960
961     if (size == 0)
962     {
963         closeList6(dataset);
964         return nullptr;
965     }
966
967     //open __refs__ node
968     int refs = getDataSetIdFromName(dataset, "__refs__");
969     types::GraphicHandle* handles = new types::GraphicHandle(static_cast<int>(pdims.size()), pdims.data());
970     long long* h = handles->get();
971
972     if (size == 1)
973     {
974         //%h_copy
975         int ref = getDataSetIdFromName(refs, std::to_string(0).data());
976         int val = add_current_entity(ref);
977         if (val < 0)
978         {
979             return nullptr;
980         }
981
982         h[0] = getHandle(val);
983     }
984     else
985     {
986         for (int i = 0; i < size; ++i)
987         {
988             int ref = getDataSetIdFromName(refs, std::to_string(i).data());
989             int val = import_handle(ref, -1);
990             if (val < 0)
991             {
992                 return nullptr;
993             }
994
995             h[i] = getHandle(val);
996         }
997     }
998     closeList6(refs);
999     closeList6(dataset);
1000
1001
1002     //update links property of legend handle
1003     if (Links::count())
1004     {
1005         std::list<int> legends = Links::legends();
1006         for (auto & i : legends)
1007         {
1008             Links::PathList paths = Links::get(i);
1009             update_link_path(i, paths);
1010         }
1011     }
1012
1013     return handles;
1014 }
1015
1016 static types::InternalType* import_macro(int dataset)
1017 {
1018     int complex = 0;
1019     int dims = 0;
1020     int size = 0;
1021     std::vector<int> d(2);
1022
1023     std::list<symbol::Variable*>* inputList = new std::list<symbol::Variable*>();
1024     std::list<symbol::Variable*>* outputList = new std::list<symbol::Variable*>();
1025     ast::Exp* body = nullptr;
1026
1027     symbol::Context* ctx = symbol::Context::getInstance();
1028
1029     //inputs
1030     int inputNode = getDataSetIdFromName(dataset, "inputs");
1031     size = getDatasetInfo(inputNode, &complex, &dims, d.data());
1032     if (size < 0)
1033     {
1034         delete inputList;
1035         delete outputList;
1036         closeList6(dataset);
1037         return nullptr;
1038     }
1039     std::vector<char*> inputNames(size);
1040
1041     if (size != 0)
1042     {
1043         readStringMatrix(inputNode, inputNames.data());
1044
1045         for (auto & input : inputNames)
1046         {
1047             wchar_t* winput = to_wide_string(input);
1048             symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(winput));
1049             FREE(winput);
1050             inputList->push_back(var);
1051         }
1052
1053         freeStringMatrix(inputNode, inputNames.data());
1054     }
1055     else
1056     {
1057         closeDataSet(inputNode);
1058     }
1059
1060     //outputs
1061     int outputNode = getDataSetIdFromName(dataset, "outputs");
1062     size = getDatasetInfo(outputNode, &complex, &dims, d.data());
1063     if (size < 0)
1064     {
1065         delete inputList;
1066         delete outputList;
1067         closeList6(dataset);
1068         return nullptr;
1069     }
1070     std::vector<char*> outputNames(size);
1071
1072     if (size != 0)
1073     {
1074         readStringMatrix(outputNode, outputNames.data());
1075
1076         for (auto & output : outputNames)
1077         {
1078             wchar_t* woutput = to_wide_string(output);
1079             symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(woutput));
1080             FREE(woutput);
1081             outputList->push_back(var);
1082         }
1083
1084         freeStringMatrix(outputNode, outputNames.data());
1085     }
1086     else
1087     {
1088         closeDataSet(outputNode);
1089     }
1090
1091     //body
1092     int bodyNode = getDataSetIdFromName(dataset, "body");
1093     size = getDatasetInfo(bodyNode, &complex, &dims, d.data());
1094     if (size < 0)
1095     {
1096         delete inputList;
1097         delete outputList;
1098         closeList6(dataset);
1099         return nullptr;
1100     }
1101     std::vector<unsigned char> bodybin(size);
1102     readUnsignedInteger8Matrix(bodyNode, bodybin.data());
1103
1104     ast::DeserializeVisitor ds(bodybin.data());
1105     body = ds.deserialize();
1106
1107     //wname+1 is to remove "/" at the start of the var name from HDF5
1108     types::Macro* macro = new types::Macro(L"", *inputList, *outputList, *body->getAs<ast::SeqExp>(), L"script");
1109     delete body;
1110     closeList6(dataset);
1111     return macro;
1112 }
1113
1114 static types::InternalType* import_usertype(int dataset)
1115 {
1116     types::InternalType* it = import_struct(dataset);
1117     if (it == nullptr || it->isStruct() == false)
1118     {
1119         delete it;
1120         return nullptr;
1121     }
1122
1123
1124     types::Struct* str = it->getAs<types::Struct>();
1125
1126     if (str->isScalar() == false)
1127     {
1128         delete it;
1129         return nullptr;
1130     }
1131
1132     types::SingleStruct* ss = str->get()[0];
1133
1134     //extract type from struct
1135     types::InternalType* itType  = ss->get(L"type");
1136     if (itType == nullptr || itType->getId() != types::InternalType::IdScalarString)
1137     {
1138         delete it;
1139         return nullptr;
1140     }
1141
1142     types::String* s = it->getAs<types::String>();
1143     wchar_t* type = s->get()[0];
1144
1145     types::InternalType* data = ss->get(L"data");
1146     if (data == nullptr)
1147     {
1148         delete it;
1149         return nullptr;
1150     }
1151
1152     //call %yourtype_load overload
1153     types::typed_list in;
1154     in.push_back(data);
1155
1156     types::typed_list out;
1157     //overload
1158     // rational case
1159     std::wstring wstFuncName = L"%" + data->getShortTypeStr() + L"_load";
1160     types::Callable::ReturnValue ret = Overload::call(wstFuncName, in, 1, out);
1161
1162     //clean temporary variables
1163     delete it; //included type and data
1164
1165     if (ret != types::Callable::OK)
1166     {
1167         return nullptr;
1168     }
1169
1170     if (out.size() != 1)
1171     {
1172         for (auto & i : out)
1173         {
1174             i->killMe();
1175         }
1176
1177         return nullptr;
1178     }
1179
1180     return out[0];
1181 }