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());
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());
630 freeStringMatrix(dfield, fields.data());
637 for (int j = 0; j < refcount; ++j)
639 int data = H5Rdereference(refs, H5R_OBJECT, &vrefs[j]);
642 freeStringMatrix(dfield, fields.data());
647 types::InternalType* val = import_data(data);
650 freeStringMatrix(dfield, fields.data());
655 sstr[j]->set(field, val);
660 closeDataSet(dataref);
663 freeStringMatrix(dfield, fields.data());
669 static types::InternalType* import_poly(int dataset)
673 std::vector<int> pdims;
674 int size = getDimsNode(dataset, &complex, pdims);
678 int varname = getDataSetIdFromName(dataset, "__varname__");
679 readStringMatrix(varname, &var);
680 wchar_t* wvar = to_wide_string(var);
681 std::wstring wvarname(wvar);
683 freeStringMatrix(varname, &var);
685 types::Polynom* p = new types::Polynom(wvarname, static_cast<int>(pdims.size()), pdims.data());
686 types::SinglePoly** pss = p->get();
689 int refs = getDataSetIdFromName(dataset, "__refs__");
693 for (int i = 0; i < size; ++i)
696 std::string polyname(std::to_string(i));
697 int poly = getDataSetIdFromName(refs, polyname.data());
702 int ret = getDatasetInfo(poly, &complex, &dims, NULL);
708 std::vector<int> d(dims);
709 int datasize = getDatasetInfo(poly, &complex, &dims, d.data());
711 types::SinglePoly* ss = NULL;
714 if (dims == 0 || datasize == 0)
716 ss = new types::SinglePoly();
723 ss = new types::SinglePoly(&real, &img, datasize - 1);
724 readDoubleComplexMatrix(poly, real, img);
729 ss = new types::SinglePoly(&real, datasize - 1);
730 readDoubleMatrix(poly, real);
741 static types::InternalType* import_sparse(int dataset)
743 types::Sparse* sp = nullptr;
744 //get sparse dimensions
746 std::vector<int> pdims;
747 int size = getDimsNode(dataset, &complex, pdims);
749 //get non zeros count
751 int datannz = getDataSetIdFromName(dataset, "__nnz__");
752 readInteger32Matrix(datannz, &nnz);
757 return new types::Sparse(pdims[0], pdims[1]);
761 int datain = getDataSetIdFromName(dataset, "__inner__");
763 int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
764 std::vector<int> dimsin(dimin);
765 sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
767 std::vector<int> in(sizein);
768 int ret = readInteger32Matrix(datain, in.data());
776 int dataout = getDataSetIdFromName(dataset, "__outer__");
778 int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
779 std::vector<int> dimsout(dimout);
780 sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
782 std::vector<int> out(sizeout);
783 ret = readInteger32Matrix(dataout, out.data());
791 int ddata = getDataSetIdFromName(dataset, "__data__");
793 int sizedata = getDatasetInfo(ddata, &complex, &dimdata, NULL);
794 std::vector<int> dimsdata(dimdata);
795 sizedata = getDatasetInfo(ddata, &complex, &dimdata, dimsdata.data());
797 std::vector<double> real(sizedata);
801 std::vector<double> img(sizedata);
802 ret = readDoubleComplexMatrix(ddata, real.data(), img.data());
809 sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), img.data());
813 ret = readDoubleMatrix(ddata, real.data());
820 sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), nullptr);
827 static types::InternalType* import_boolean_sparse(int dataset)
829 //get sparse dimensions
831 std::vector<int> pdims;
832 int size = getDimsNode(dataset, &complex, pdims);
834 //get non zeros count
836 int datannz = getDataSetIdFromName(dataset, "__nnz__");
837 readInteger32Matrix(datannz, &nnz);
842 return new types::SparseBool(pdims[0], pdims[1]);
846 int datain = getDataSetIdFromName(dataset, "__inner__");
848 int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
849 std::vector<int> dimsin(dimin);
850 sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
852 std::vector<int> in(sizein);
853 int ret = readInteger32Matrix(datain, in.data());
861 int dataout = getDataSetIdFromName(dataset, "__outer__");
863 int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
864 std::vector<int> dimsout(dimout);
865 sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
867 std::vector<int> out(sizeout);
868 ret = readInteger32Matrix(dataout, out.data());
877 return new types::SparseBool(pdims[0], pdims[1], nnz, in.data(), out.data());
880 static types::InternalType* import_cell(int dataset)
882 //get sparse dimensions
884 std::vector<int> pdims;
885 int size = getDimsNode(dataset, &complex, pdims);
890 return new types::Cell();
894 int refs = getDataSetIdFromName(dataset, "__refs__");
895 std::vector<types::InternalType*> data(size);
896 for (int i = 0; i < size; ++i)
898 int ref = getDataSetIdFromName(refs, std::to_string(i).data());
899 types::InternalType* val = import_data(ref);
908 types::Cell* cell = new types::Cell(static_cast<int>(pdims.size()), pdims.data(), data.data());
915 static types::InternalType* import_handles(int dataset)
917 //get sparse dimensions
919 std::vector<int> pdims;
920 int size = getDimsNode(dataset, &complex, pdims);
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();
936 int ref = getDataSetIdFromName(refs, std::to_string(0).data());
937 int val = add_current_entity(ref);
943 h[0] = getHandle(val);
947 for (int i = 0; i < size; ++i)
949 int ref = getDataSetIdFromName(refs, std::to_string(i).data());
950 int val = import_handle(ref, -1);
956 h[i] = getHandle(val);
963 //update links property of legend handle
966 std::list<int> legends = Links::legends();
967 for (auto & i : legends)
969 Links::PathList paths = Links::get(i);
970 update_link_path(i, paths);
977 static types::InternalType* import_macro(int dataset)
982 std::vector<int> d(2);
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;
988 symbol::Context* ctx = symbol::Context::getInstance();
991 int inputNode = getDataSetIdFromName(dataset, "inputs");
992 size = getDatasetInfo(inputNode, &complex, &dims, d.data());
993 std::vector<char*> inputNames(size);
997 readStringMatrix(inputNode, inputNames.data());
999 for (auto & input : inputNames)
1001 wchar_t* winput = to_wide_string(input);
1002 symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(winput));
1004 inputList->push_back(var);
1007 freeStringMatrix(inputNode, inputNames.data());
1011 closeDataSet(inputNode);
1015 int outputNode = getDataSetIdFromName(dataset, "outputs");
1016 size = getDatasetInfo(outputNode, &complex, &dims, d.data());
1017 std::vector<char*> outputNames(size);
1021 readStringMatrix(outputNode, outputNames.data());
1023 for (auto & output : outputNames)
1025 wchar_t* woutput = to_wide_string(output);
1026 symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(woutput));
1028 outputList->push_back(var);
1031 freeStringMatrix(outputNode, outputNames.data());
1035 closeDataSet(outputNode);
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());
1044 ast::DeserializeVisitor ds(bodybin.data());
1045 body = ds.deserialize();
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");
1050 closeList6(dataset);
1054 static types::InternalType* import_usertype(int dataset)
1056 types::InternalType* it = import_struct(dataset);
1057 if (it == nullptr || it->isStruct() == false)
1064 types::Struct* str = it->getAs<types::Struct>();
1066 if (str->isScalar() == false)
1072 types::SingleStruct* ss = str->get()[0];
1074 //extract type from struct
1075 types::InternalType* itType = ss->get(L"type");
1076 if (itType == nullptr || itType->getId() != types::InternalType::IdScalarString)
1082 types::String* s = it->getAs<types::String>();
1083 wchar_t* type = s->get()[0];
1085 types::InternalType* data = ss->get(L"data");
1086 if (data == nullptr)
1092 //call %yourtype_load overload
1093 types::typed_list in;
1096 types::typed_list out;
1099 std::wstring wstFuncName = L"%" + data->getShortTypeStr() + L"_load";
1100 types::Callable::ReturnValue ret = Overload::call(wstFuncName, in, 1, out);
1102 //clean temporary variables
1103 delete it; //included type and data
1105 if (ret != types::Callable::OK)
1110 if (out.size() != 1)
1112 for (auto & i : out)