2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
16 #include <unordered_map>
19 #include "hdf5_gw.hxx"
20 #include "context.hxx"
29 #include "polynom.hxx"
31 #include "graphichandle.hxx"
34 #include "listundefined.hxx"
35 #include "context.hxx"
36 #include "handle_properties.hxx"
37 #include "deserializervisitor.hxx"
38 #include "overload.hxx"
40 std::unordered_map<int, Links::PathList> Links::paths;
44 #include "sci_malloc.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"
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);
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)
82 int rhs = static_cast<int>(in.size());
86 Scierror(999, _("%s: Wrong number of input argument(s): at least %d expected.\n"), fname.data(), 1);
87 return types::Function::Error;
90 if (in[0]->getId() != types::InternalType::IdScalarString)
92 Scierror(999, _("%s: Wrong size for input argument #%d: string expected.\n"), fname.data(), 1);
93 return types::Function::Error;
96 wchar_t* wfilename = expandPathVariableW(in[0]->getAs<types::String>()->get()[0]);
97 char* cfilename = wide_string_to_UTF8(wfilename);
102 int iFile = openHDF5File(filename.data(), 0);
105 Scierror(999, _("%s: Unable to open file: %s\n"), fname.data(), filename.data());
106 return types::Function::Error;
109 //manage version information
110 int iVersion = getSODFormatAttribute(iFile);
111 if (iVersion != SOD_FILE_VERSION)
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;
120 for (int i = 1; i < rhs; ++i)
123 char* cvar = wide_string_to_UTF8(in[i]->getAs<types::String>()->get()[0]);
127 if (import_variable(iFile, var) == false)
129 Scierror(999, _("%s: Unable to load \'%s\'.\n"), fname.data(), var.data());
130 return types::Function::Error;
136 //restore all variables
138 iNbItem = getVariableNames6(iFile, NULL);
141 std::vector<char*> vars(iNbItem);
142 iNbItem = getVariableNames6(iFile, vars.data());
143 for (auto & var : vars)
147 if (import_variable(iFile, s) == false)
149 Scierror(999, _("%s: Unable to load \'%s\'.\n"), fname.data(), s.data());
150 return types::Function::Error;
157 closeHDF5File(iFile);
159 out.push_back(new types::Bool(1));
160 return types::Function::OK;
163 static bool import_variable(int file, std::string& name)
165 int dataset = getDataSetIdFromName(file, name.data());
171 types::InternalType* data = import_data(dataset);
174 wchar_t* var = to_wide_string(name.data());
178 types::Macro* macro = data->getAs<types::Macro>();
180 symbol::Context::getInstance()->addMacro(macro);
185 symbol::Context::getInstance()->put(symbol::Symbol(var), data);
194 types::InternalType* import_data(int dataset)
197 char* ctype = getScilabTypeFromDataSet6(dataset);
198 std::string type(ctype);
201 if (type == g_SCILAB_CLASS_DOUBLE)
203 return import_double(dataset);
206 if (type == g_SCILAB_CLASS_STRING)
208 return import_string(dataset);
211 if (type == g_SCILAB_CLASS_INT)
213 return import_int(dataset);
216 if (type == g_SCILAB_CLASS_BOOLEAN)
218 return import_boolean(dataset);
221 if (type == g_SCILAB_CLASS_LIST)
223 return import_list(dataset, new types::List());
226 if (type == g_SCILAB_CLASS_TLIST)
228 return import_list(dataset, new types::TList());
231 if (type == g_SCILAB_CLASS_MLIST)
233 return import_list(dataset, new types::MList());
236 if (type == g_SCILAB_CLASS_STRUCT)
238 return import_struct(dataset);
241 if (type == g_SCILAB_CLASS_POLY)
243 return import_poly(dataset);
246 if (type == g_SCILAB_CLASS_SPARSE)
248 return import_sparse(dataset);
251 if (type == g_SCILAB_CLASS_BSPARSE)
253 return import_boolean_sparse(dataset);
256 if (type == g_SCILAB_CLASS_CELL)
258 return import_cell(dataset);
261 if (type == g_SCILAB_CLASS_HANDLE)
263 return import_handles(dataset);
266 if (type == g_SCILAB_CLASS_MACRO)
268 return import_macro(dataset);
271 if (type == g_SCILAB_CLASS_VOID)
273 closeDataSet(dataset);
274 return new types::Void();
277 if (type == g_SCILAB_CLASS_UNDEFINED)
279 closeDataSet(dataset);
280 return new types::ListUndefined();
283 if (type == g_SCILAB_CLASS_USERTYPE)
285 return import_usertype(dataset);
292 static types::InternalType* import_double(int dataset)
296 int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
299 closeDataSet(dataset);
303 std::vector<int> d(dims);
304 int size = getDatasetInfo(dataset, &complex, &dims, d.data());
307 if (dims == 0 || size == 0)
309 closeDataSet(dataset);
310 return types::Double::Empty();
313 types::Double* dbl = new types::Double(dims, d.data(), complex == 1);
315 double* real = dbl->get();
316 double* img = dbl->getImg();
320 readDoubleComplexMatrix(dataset, real, img);
324 readDoubleMatrix(dataset, real);
329 static types::InternalType* import_string(int dataset)
333 int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
336 closeDataSet(dataset);
341 std::vector<int> d(dims);
342 int size = getDatasetInfo(dataset, &complex, &dims, d.data());
345 if (dims == 0 || size == 0)
347 closeDataSet(dataset);
348 return types::Double::Empty();
351 std::vector<char*> s(size);
352 ret = readStringMatrix(dataset, s.data());
354 types::String* str = new types::String(dims, d.data());
355 wchar_t** pstr = str->get();
357 for (int i = 0; i < size; ++i)
359 pstr[i] = to_wide_string(s[i]);
362 freeStringMatrix(dataset, s.data());
367 static types::InternalType* import_boolean(int dataset)
371 int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
374 closeDataSet(dataset);
378 std::vector<int> d(dims);
379 int size = getDatasetInfo(dataset, &complex, &dims, d.data());
382 if (dims == 0 || size == 0)
384 closeDataSet(dataset);
385 return types::Double::Empty();
388 types::Bool* bools = new types::Bool(dims, d.data());
390 int* b = bools->get();
391 readBooleanMatrix(dataset, b);
395 static types::InternalType* import_int(int dataset)
397 types::InternalType* pOut = nullptr;
400 int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
403 closeDataSet(dataset);
407 std::vector<int> d(dims);
408 int size = getDatasetInfo(dataset, &complex, &dims, d.data());
411 if (dims == 0 || size == 0)
413 closeDataSet(dataset);
414 return types::Double::Empty();
418 ret = getDatasetPrecision(dataset, &prec);
421 closeDataSet(dataset);
429 types::Int8* pi = new types::Int8(dims, d.data());
430 ret = readInteger8Matrix(dataset, pi->get());
436 types::Int16* pi = new types::Int16(dims, d.data());
437 ret = readInteger16Matrix(dataset, pi->get());
443 types::Int32* pi = new types::Int32(dims, d.data());
444 ret = readInteger32Matrix(dataset, pi->get());
450 types::Int64* pi = new types::Int64(dims, d.data());
451 ret = readInteger64Matrix(dataset, pi->get());
457 types::UInt8* pi = new types::UInt8(dims, d.data());
458 ret = readUnsignedInteger8Matrix(dataset, pi->get());
464 types::UInt16* pi = new types::UInt16(dims, d.data());
465 ret = readUnsignedInteger16Matrix(dataset, pi->get());
471 types::UInt32* pi = new types::UInt32(dims, d.data());
472 ret = readUnsignedInteger32Matrix(dataset, pi->get());
478 types::UInt64* pi = new types::UInt64(dims, d.data());
479 ret = readUnsignedInteger64Matrix(dataset, pi->get());
491 static types::InternalType* import_list(int dataset, types::List* lst)
494 int ret = getListDims6(dataset, &count);
510 for (int i = 0; i < count; ++i)
512 int data = getDataSetIdFromName(dataset, std::to_string(i).data());
520 types::InternalType* child = import_data(data);
521 if (child == nullptr)
539 static int getDimsNode(int dataset, int* complex, std::vector<int>& dims)
542 int id = getDataSetIdFromName(dataset, "__dims__");
548 //get dims dimension count
550 getDatasetInfo(id, complex, &dim, NULL);
552 std::vector<int> d(dim);
553 int size = getDatasetInfo(id, complex, &dim, d.data());
557 readInteger32Matrix(id, dims.data());
560 for (int i = 1; i < dims.size(); ++i)
567 static types::InternalType* import_struct(int dataset)
569 //get struct dims node
571 std::vector<int> pdims;
572 int size = getDimsNode(dataset, &complex, pdims);
574 types::Struct* str = new types::Struct(static_cast<int>(pdims.size()), pdims.data());
575 size = str->getSize();
581 return new types::Struct();
584 types::SingleStruct** sstr = str->get();
587 int ret = getListDims6(dataset, &fieldCount);
595 int dfield = getDataSetIdFromName(dataset, "__fields__");
597 getDatasetInfo(dfield, &complex, &dim, NULL);
598 std::vector<int> d(dim);
599 size = getDatasetInfo(dfield, &complex, &dim, d.data());
602 std::vector<char*> fields(size);
603 readStringMatrix(dfield, fields.data());
606 int refs = getDataSetIdFromName(dataset, "__refs__");
608 for (const auto & name : fields)
610 wchar_t* field = to_wide_string(name);
611 str->addField(field);
613 int dataref = getDataSetIdFromName(dataset, name);
617 freeStringMatrix(dfield, fields.data());
624 getDatasetInfo(dataref, &complex, &refdim, NULL);
625 std::vector<int> refdims(refdim);
626 int refcount = getDatasetInfo(dataref, &complex, &refdim, refdims.data());
627 std::vector<hobj_ref_t> vrefs(refcount);
628 ret = H5Dread(dataref, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, vrefs.data());
631 freeStringMatrix(dfield, fields.data());
639 for (int j = 0; j < refcount; ++j)
641 int data = H5Rdereference(refs, H5R_OBJECT, &vrefs[j]);
644 freeStringMatrix(dfield, fields.data());
650 types::InternalType* val = import_data(data);
653 freeStringMatrix(dfield, fields.data());
659 sstr[j]->set(field, val);
664 closeDataSet(dataref);
667 freeStringMatrix(dfield, fields.data());
673 static types::InternalType* import_poly(int dataset)
677 std::vector<int> pdims;
678 int size = getDimsNode(dataset, &complex, pdims);
682 int varname = getDataSetIdFromName(dataset, "__varname__");
683 readStringMatrix(varname, &var);
684 wchar_t* wvar = to_wide_string(var);
685 std::wstring wvarname(wvar);
687 freeStringMatrix(varname, &var);
689 types::Polynom* p = new types::Polynom(wvarname, static_cast<int>(pdims.size()), pdims.data());
690 types::SinglePoly** pss = p->get();
693 int refs = getDataSetIdFromName(dataset, "__refs__");
697 for (int i = 0; i < size; ++i)
700 std::string polyname(std::to_string(i));
701 int poly = getDataSetIdFromName(refs, polyname.data());
706 int ret = getDatasetInfo(poly, &complex, &dims, NULL);
712 std::vector<int> d(dims);
713 int datasize = getDatasetInfo(poly, &complex, &dims, d.data());
715 types::SinglePoly* ss = NULL;
718 if (dims == 0 || datasize == 0)
720 ss = new types::SinglePoly();
727 ss = new types::SinglePoly(&real, &img, datasize - 1);
728 readDoubleComplexMatrix(poly, real, img);
733 ss = new types::SinglePoly(&real, datasize - 1);
734 readDoubleMatrix(poly, real);
745 static types::InternalType* import_sparse(int dataset)
747 types::Sparse* sp = nullptr;
748 //get sparse dimensions
750 std::vector<int> pdims;
751 int size = getDimsNode(dataset, &complex, pdims);
753 //get non zeros count
755 int datannz = getDataSetIdFromName(dataset, "__nnz__");
756 readInteger32Matrix(datannz, &nnz);
761 return new types::Sparse(pdims[0], pdims[1]);
765 int datain = getDataSetIdFromName(dataset, "__inner__");
767 int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
768 std::vector<int> dimsin(dimin);
769 sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
771 std::vector<int> in(sizein);
772 int ret = readInteger32Matrix(datain, in.data());
780 int dataout = getDataSetIdFromName(dataset, "__outer__");
782 int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
783 std::vector<int> dimsout(dimout);
784 sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
786 std::vector<int> out(sizeout);
787 ret = readInteger32Matrix(dataout, out.data());
795 int ddata = getDataSetIdFromName(dataset, "__data__");
797 int sizedata = getDatasetInfo(ddata, &complex, &dimdata, NULL);
798 std::vector<int> dimsdata(dimdata);
799 sizedata = getDatasetInfo(ddata, &complex, &dimdata, dimsdata.data());
801 std::vector<double> real(sizedata);
805 std::vector<double> img(sizedata);
806 ret = readDoubleComplexMatrix(ddata, real.data(), img.data());
813 sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), img.data());
817 ret = readDoubleMatrix(ddata, real.data());
824 sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), nullptr);
831 static types::InternalType* import_boolean_sparse(int dataset)
833 //get sparse dimensions
835 std::vector<int> pdims;
836 int size = getDimsNode(dataset, &complex, pdims);
838 //get non zeros count
840 int datannz = getDataSetIdFromName(dataset, "__nnz__");
841 readInteger32Matrix(datannz, &nnz);
846 return new types::SparseBool(pdims[0], pdims[1]);
850 int datain = getDataSetIdFromName(dataset, "__inner__");
852 int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
853 std::vector<int> dimsin(dimin);
854 sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
856 std::vector<int> in(sizein);
857 int ret = readInteger32Matrix(datain, in.data());
865 int dataout = getDataSetIdFromName(dataset, "__outer__");
867 int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
868 std::vector<int> dimsout(dimout);
869 sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
871 std::vector<int> out(sizeout);
872 ret = readInteger32Matrix(dataout, out.data());
881 return new types::SparseBool(pdims[0], pdims[1], nnz, in.data(), out.data());
884 static types::InternalType* import_cell(int dataset)
886 //get sparse dimensions
888 std::vector<int> pdims;
889 int size = getDimsNode(dataset, &complex, pdims);
894 return new types::Cell();
898 int refs = getDataSetIdFromName(dataset, "__refs__");
899 std::vector<types::InternalType*> data(size);
900 for (int i = 0; i < size; ++i)
902 int ref = getDataSetIdFromName(refs, std::to_string(i).data());
903 types::InternalType* val = import_data(ref);
912 types::Cell* cell = new types::Cell(static_cast<int>(pdims.size()), pdims.data(), data.data());
919 static types::InternalType* import_handles(int dataset)
921 //get sparse dimensions
923 std::vector<int> pdims;
924 int size = getDimsNode(dataset, &complex, pdims);
933 int refs = getDataSetIdFromName(dataset, "__refs__");
934 types::GraphicHandle* handles = new types::GraphicHandle(static_cast<int>(pdims.size()), pdims.data());
935 long long* h = handles->get();
940 int ref = getDataSetIdFromName(refs, std::to_string(0).data());
941 int val = add_current_entity(ref);
947 h[0] = getHandle(val);
951 for (int i = 0; i < size; ++i)
953 int ref = getDataSetIdFromName(refs, std::to_string(i).data());
954 int val = import_handle(ref, -1);
960 h[i] = getHandle(val);
967 //update links property of legend handle
970 std::list<int> legends = Links::legends();
971 for (auto & i : legends)
973 Links::PathList paths = Links::get(i);
974 update_link_path(i, paths);
981 static types::InternalType* import_macro(int dataset)
986 std::vector<int> d(2);
988 std::list<symbol::Variable*>* inputList = new std::list<symbol::Variable*>();
989 std::list<symbol::Variable*>* outputList = new std::list<symbol::Variable*>();
990 ast::Exp* body = nullptr;
992 symbol::Context* ctx = symbol::Context::getInstance();
995 int inputNode = getDataSetIdFromName(dataset, "inputs");
996 size = getDatasetInfo(inputNode, &complex, &dims, d.data());
997 std::vector<char*> inputNames(size);
1001 readStringMatrix(inputNode, inputNames.data());
1003 for (auto & input : inputNames)
1005 wchar_t* winput = to_wide_string(input);
1006 symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(winput));
1008 inputList->push_back(var);
1011 freeStringMatrix(inputNode, inputNames.data());
1015 closeDataSet(inputNode);
1019 int outputNode = getDataSetIdFromName(dataset, "outputs");
1020 size = getDatasetInfo(outputNode, &complex, &dims, d.data());
1021 std::vector<char*> outputNames(size);
1025 readStringMatrix(outputNode, outputNames.data());
1027 for (auto & output : outputNames)
1029 wchar_t* woutput = to_wide_string(output);
1030 symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(woutput));
1032 outputList->push_back(var);
1035 freeStringMatrix(outputNode, outputNames.data());
1039 closeDataSet(outputNode);
1043 int bodyNode = getDataSetIdFromName(dataset, "body");
1044 size = getDatasetInfo(bodyNode, &complex, &dims, d.data());
1045 std::vector<unsigned char> bodybin(size);
1046 readUnsignedInteger8Matrix(bodyNode, bodybin.data());
1048 ast::DeserializeVisitor ds(bodybin.data());
1049 body = ds.deserialize();
1051 //wname+1 is to remove "/" at the start of the var name from HDF5
1052 types::Macro* macro = new types::Macro(L"", *inputList, *outputList, *body->getAs<ast::SeqExp>(), L"script");
1054 closeList6(dataset);
1058 static types::InternalType* import_usertype(int dataset)
1060 types::InternalType* it = import_struct(dataset);
1061 if (it == nullptr || it->isStruct() == false)
1068 types::Struct* str = it->getAs<types::Struct>();
1070 if (str->isScalar() == false)
1076 types::SingleStruct* ss = str->get()[0];
1078 //extract type from struct
1079 types::InternalType* itType = ss->get(L"type");
1080 if (itType == nullptr || itType->getId() != types::InternalType::IdScalarString)
1086 types::String* s = it->getAs<types::String>();
1087 wchar_t* type = s->get()[0];
1089 types::InternalType* data = ss->get(L"data");
1090 if (data == nullptr)
1096 //call %yourtype_load overload
1097 types::typed_list in;
1100 types::typed_list out;
1103 std::wstring wstFuncName = L"%" + data->getShortTypeStr() + L"_load";
1104 types::Callable::ReturnValue ret = Overload::call(wstFuncName, in, 1, out);
1106 //clean temporary variables
1107 delete it; //included type and data
1109 if (ret != types::Callable::OK)
1114 if (out.size() != 1)
1116 for (auto & i : out)