2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
15 #include "hdf5_gw.hxx"
16 #include "context.hxx"
25 #include "polynom.hxx"
27 #include "graphichandle.hxx"
30 #include "listundefined.hxx"
31 #include "context.hxx"
32 #include "handle_properties.hxx"
33 #include "deserializervisitor.hxx"
34 #include "execvisitor.hxx"
36 std::unordered_map<int, Links::PathList> Links::paths;
40 #include "sci_malloc.h"
42 #include "localization.h"
43 #include "freeArrayOfString.h"
44 #include "os_string.h"
45 #include "deleteafile.h"
46 #include "expandPathVariable.h"
47 #include "h5_fileManagement.h"
48 #include "h5_writeDataToFile.h"
49 #include "h5_readDataFromFile.h"
50 #include "h5_attributeConstants.h"
51 #include "HandleManagement.h"
54 /*--------------------------------------------------------------------------*/
55 static bool import_variable(int file, std::string& name);
56 types::InternalType* import_data(int dataset);
57 static types::InternalType* import_double(int dataset);
58 static types::InternalType* import_string(int dataset);
59 static types::InternalType* import_boolean(int dataset);
60 static types::InternalType* import_int(int dataset);
61 static types::InternalType* import_list(int dataset, types::List* lst);
62 static types::InternalType* import_struct(int dataset);
63 static types::InternalType* import_poly(int dataset);
64 static types::InternalType* import_cell(int dataset);
65 static types::InternalType* import_handles(int dataset);
66 static types::InternalType* import_sparse(int dataset);
67 static types::InternalType* import_boolean_sparse(int dataset);
68 static types::InternalType* import_macro(int dataset);
69 static types::InternalType* import_usertype(int dataset);
72 /*--------------------------------------------------------------------------*/
73 static const std::string fname("load");
74 /*--------------------------------------------------------------------------*/
75 types::Function::ReturnValue sci_hdf5_load_v3(types::typed_list &in, int _iRetCount, types::typed_list &out)
78 int rhs = static_cast<int>(in.size());
82 Scierror(999, _("%s: Wrong number of input argument(s): at least %d expected.\n"), fname.data(), 1);
83 return types::Function::Error;
86 if (in[0]->getId() != types::InternalType::IdScalarString)
88 Scierror(999, _("%s: Wrong size for input argument #%d: A string expected.\n"), fname.data(), 1);
89 return types::Function::Error;
92 wchar_t* wfilename = expandPathVariableW(in[0]->getAs<types::String>()->get()[0]);
93 char* cfilename = wide_string_to_UTF8(wfilename);
98 int iFile = openHDF5File(filename.data(), 0);
101 Scierror(999, _("%s: Unable to open file: %s\n"), fname.data(), filename.data());
102 return types::Function::Error;
105 //manage version information
106 int iVersion = getSODFormatAttribute(iFile);
107 if (iVersion != SOD_FILE_VERSION)
109 //can't read file with version newer that me !
110 Scierror(999, _("%s: Wrong SOD file format version. Expected: %d Found: %d\n"), fname.data(), SOD_FILE_VERSION, iVersion);
111 return types::Function::Error;
116 for (int i = 1; i < rhs; ++i)
119 char* cvar = wide_string_to_UTF8(in[i]->getAs<types::String>()->get()[0]);
123 if (import_variable(iFile, var) == false)
125 Scierror(999, _("%s: Unable to load \'%s\'.\n"), fname.data(), var.data());
126 return types::Function::Error;
132 //restore all variables
134 iNbItem = getVariableNames6(iFile, NULL);
137 std::vector<char*> vars(iNbItem);
138 iNbItem = getVariableNames6(iFile, vars.data());
139 for (auto &var : vars)
142 if (import_variable(iFile, s) == false)
144 Scierror(999, _("%s: Unable to load \'%s\'.\n"), fname.data(), var);
145 return types::Function::Error;
152 closeHDF5File(iFile);
154 out.push_back(new types::Bool(1));
155 return types::Function::OK;
158 static bool import_variable(int file, std::string& name)
160 int dataset = getDataSetIdFromName(file, name.data());
166 types::InternalType* data = import_data(dataset);
169 wchar_t* var = to_wide_string(name.data());
173 types::Macro* macro = data->getAs<types::Macro>();
175 symbol::Context::getInstance()->addMacro(macro);
180 symbol::Context::getInstance()->put(symbol::Symbol(var), data);
189 types::InternalType* import_data(int dataset)
192 char* ctype = getScilabTypeFromDataSet6(dataset);
193 std::string type(ctype);
196 if (type == g_SCILAB_CLASS_DOUBLE)
198 return import_double(dataset);
201 if (type == g_SCILAB_CLASS_STRING)
203 return import_string(dataset);
206 if (type == g_SCILAB_CLASS_INT)
208 return import_int(dataset);
211 if (type == g_SCILAB_CLASS_BOOLEAN)
213 return import_boolean(dataset);
216 if (type == g_SCILAB_CLASS_LIST)
218 return import_list(dataset, new types::List());
221 if (type == g_SCILAB_CLASS_TLIST)
223 return import_list(dataset, new types::TList());
226 if (type == g_SCILAB_CLASS_MLIST)
228 return import_list(dataset, new types::MList());
231 if (type == g_SCILAB_CLASS_STRUCT)
233 return import_struct(dataset);
236 if (type == g_SCILAB_CLASS_POLY)
238 return import_poly(dataset);
241 if (type == g_SCILAB_CLASS_SPARSE)
243 return import_sparse(dataset);
246 if (type == g_SCILAB_CLASS_BSPARSE)
248 return import_boolean_sparse(dataset);
251 if (type == g_SCILAB_CLASS_CELL)
253 return import_cell(dataset);
256 if (type == g_SCILAB_CLASS_HANDLE)
258 return import_handles(dataset);
261 if (type == g_SCILAB_CLASS_MACRO)
263 return import_macro(dataset);
266 if (type == g_SCILAB_CLASS_VOID)
268 closeDataSet(dataset);
269 return new types::Void();
272 if (type == g_SCILAB_CLASS_UNDEFINED)
274 closeDataSet(dataset);
275 return new types::ListUndefined();
278 if (type == g_SCILAB_CLASS_USERTYPE)
280 return import_usertype(dataset);
287 static types::InternalType* import_double(int dataset)
291 int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
294 closeDataSet(dataset);
298 std::vector<int> d(dims);
299 int size = getDatasetInfo(dataset, &complex, &dims, d.data());
302 if (dims == 0 || size == 0)
304 closeDataSet(dataset);
305 return types::Double::Empty();
308 types::Double* dbl = new types::Double(dims, d.data(), complex == 1);
310 double* real = dbl->get();
311 double* img = dbl->getImg();
315 readDoubleComplexMatrix(dataset, real, img);
319 readDoubleMatrix(dataset, real);
324 static types::InternalType* import_string(int dataset)
328 int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
331 closeDataSet(dataset);
336 std::vector<int> d(dims);
337 int size = getDatasetInfo(dataset, &complex, &dims, d.data());
340 if (dims == 0 || size == 0)
342 closeDataSet(dataset);
343 return types::Double::Empty();
346 std::vector<char*> s(size);
347 ret = readStringMatrix(dataset, s.data());
349 types::String* str = new types::String(dims, d.data());
350 wchar_t** pstr = str->get();
352 for (int i = 0; i < size; ++i)
354 pstr[i] = to_wide_string(s[i]);
357 freeStringMatrix(dataset, s.data());
362 static types::InternalType* import_boolean(int dataset)
366 int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
369 closeDataSet(dataset);
373 std::vector<int> d(dims);
374 int size = getDatasetInfo(dataset, &complex, &dims, d.data());
377 if (dims == 0 || size == 0)
379 closeDataSet(dataset);
380 return types::Double::Empty();
383 types::Bool* bools = new types::Bool(dims, d.data());
385 int* b = bools->get();
386 readBooleanMatrix(dataset, b);
390 static types::InternalType* import_int(int dataset)
392 types::InternalType* pOut = nullptr;
395 int ret = getDatasetInfo(dataset, &complex, &dims, NULL);
398 closeDataSet(dataset);
402 std::vector<int> d(dims);
403 int size = getDatasetInfo(dataset, &complex, &dims, d.data());
406 if (dims == 0 || size == 0)
408 closeDataSet(dataset);
409 return types::Double::Empty();
413 ret = getDatasetPrecision(dataset, &prec);
416 closeDataSet(dataset);
424 types::Int8* pi = new types::Int8(dims, d.data());
425 ret = readInteger8Matrix(dataset, pi->get());
431 types::Int16* pi = new types::Int16(dims, d.data());
432 ret = readInteger16Matrix(dataset, pi->get());
438 types::Int32* pi = new types::Int32(dims, d.data());
439 ret = readInteger32Matrix(dataset, pi->get());
445 types::Int64* pi = new types::Int64(dims, d.data());
446 ret = readInteger64Matrix(dataset, pi->get());
452 types::UInt8* pi = new types::UInt8(dims, d.data());
453 ret = readUnsignedInteger8Matrix(dataset, pi->get());
459 types::UInt16* pi = new types::UInt16(dims, d.data());
460 ret = readUnsignedInteger16Matrix(dataset, pi->get());
466 types::UInt32* pi = new types::UInt32(dims, d.data());
467 ret = readUnsignedInteger32Matrix(dataset, pi->get());
473 types::UInt64* pi = new types::UInt64(dims, d.data());
474 ret = readUnsignedInteger64Matrix(dataset, pi->get());
486 static types::InternalType* import_list(int dataset, types::List* lst)
489 int ret = getListDims6(dataset, &count);
505 for (int i = 0; i < count; ++i)
507 int data = getDataSetIdFromName(dataset, std::to_string(i).data());
515 types::InternalType* child = import_data(data);
516 if (child == nullptr)
530 static int getDimsNode(int dataset, int* complex, std::vector<int>& dims)
533 int id = getDataSetIdFromName(dataset, "__dims__");
539 //get dims dimension count
541 getDatasetInfo(id, complex, &dim, NULL);
543 std::vector<int> d(dim);
544 int size = getDatasetInfo(id, complex, &dim, d.data());
548 readInteger32Matrix(id, dims.data());
551 for (int i = 1; i < dims.size(); ++i)
558 static types::InternalType* import_struct(int dataset)
560 //get struct dims node
562 std::vector<int> pdims;
563 int size = getDimsNode(dataset, &complex, pdims);
565 types::Struct* str = new types::Struct(static_cast<int>(pdims.size()), pdims.data());
566 size = str->getSize();
571 return new types::Struct();
574 types::SingleStruct** sstr = str->get();
577 int ret = getListDims6(dataset, &fieldCount);
585 int dfield = getDataSetIdFromName(dataset, "__fields__");
587 getDatasetInfo(dfield, &complex, &dim, NULL);
588 std::vector<int> d(dim);
589 size = getDatasetInfo(dfield, &complex, &dim, d.data());
592 std::vector<char*> fields(size);
593 readStringMatrix(dfield, fields.data());
596 int refs = getDataSetIdFromName(dataset, "__refs__");
598 for (const auto& name : fields)
600 wchar_t* field = to_wide_string(name);
601 str->addField(field);
603 int dataref = getDataSetIdFromName(dataset, name);
607 freeStringMatrix(dfield, fields.data());
612 getDatasetInfo(dataref, &complex, &refdim, NULL);
613 std::vector<int> refdims(refdim);
614 int refcount = getDatasetInfo(dataref, &complex, &refdim, refdims.data());
615 std::vector<hobj_ref_t> vrefs(refcount);
616 ret = H5Dread(dataref, H5T_STD_REF_OBJ, H5S_ALL, H5S_ALL, H5P_DEFAULT, vrefs.data());
619 freeStringMatrix(dfield, fields.data());
625 for (int j = 0; j < refcount; ++j)
627 int data = H5Rdereference(refs, H5R_OBJECT, &vrefs[j]);
630 freeStringMatrix(dfield, fields.data());
634 types::InternalType* val = import_data(data);
637 freeStringMatrix(dfield, fields.data());
641 sstr[j]->set(field, val);
646 closeDataSet(dataref);
649 freeStringMatrix(dfield, fields.data());
655 static types::InternalType* import_poly(int dataset)
659 std::vector<int> pdims;
660 int size = getDimsNode(dataset, &complex, pdims);
664 int varname = getDataSetIdFromName(dataset, "__varname__");
665 readStringMatrix(varname, &var);
666 wchar_t* wvar = to_wide_string(var);
667 std::wstring wvarname(wvar);
669 freeStringMatrix(varname, &var);
671 types::Polynom* p = new types::Polynom(wvarname, static_cast<int>(pdims.size()), pdims.data());
672 types::SinglePoly** pss = p->get();
675 int refs = getDataSetIdFromName(dataset, "__refs__");
679 for (int i = 0; i < size; ++i)
682 std::string polyname(std::to_string(i));
683 int poly = getDataSetIdFromName(refs, polyname.data());
688 int ret = getDatasetInfo(poly, &complex, &dims, NULL);
694 std::vector<int> d(dims);
695 int datasize = getDatasetInfo(poly, &complex, &dims, d.data());
697 types::SinglePoly* ss = NULL;
700 if (dims == 0 || datasize == 0)
702 ss = new types::SinglePoly();
709 ss = new types::SinglePoly(&real, &img, datasize - 1);
710 readDoubleComplexMatrix(poly, real, img);
715 ss = new types::SinglePoly(&real, datasize - 1);
716 readDoubleMatrix(poly, real);
727 static types::InternalType* import_sparse(int dataset)
729 types::Sparse* sp = nullptr;
730 //get sparse dimensions
732 std::vector<int> pdims;
733 int size = getDimsNode(dataset, &complex, pdims);
735 //get non zeros count
737 int datannz = getDataSetIdFromName(dataset, "__nnz__");
738 readInteger32Matrix(datannz, &nnz);
743 return new types::Sparse(pdims[0], pdims[1]);
747 int datain = getDataSetIdFromName(dataset, "__inner__");
749 int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
750 std::vector<int> dimsin(dimin);
751 sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
753 std::vector<int> in(sizein);
754 int ret = readInteger32Matrix(datain, in.data());
762 int dataout = getDataSetIdFromName(dataset, "__outer__");
764 int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
765 std::vector<int> dimsout(dimout);
766 sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
768 std::vector<int> out(sizeout);
769 ret = readInteger32Matrix(dataout, out.data());
777 int ddata = getDataSetIdFromName(dataset, "__data__");
779 int sizedata = getDatasetInfo(ddata, &complex, &dimdata, NULL);
780 std::vector<int> dimsdata(dimdata);
781 sizedata = getDatasetInfo(ddata, &complex, &dimdata, dimsdata.data());
783 std::vector<double> real(sizedata);
787 std::vector<double> img(sizedata);
788 ret = readDoubleComplexMatrix(ddata, real.data(), img.data());
795 sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), img.data());
799 ret = readDoubleMatrix(ddata, real.data());
806 sp = new types::Sparse(pdims[0], pdims[1], nnz, in.data(), out.data(), real.data(), nullptr);
813 static types::InternalType* import_boolean_sparse(int dataset)
815 //get sparse dimensions
817 std::vector<int> pdims;
818 int size = getDimsNode(dataset, &complex, pdims);
820 //get non zeros count
822 int datannz = getDataSetIdFromName(dataset, "__nnz__");
823 readInteger32Matrix(datannz, &nnz);
828 return new types::SparseBool(pdims[0], pdims[1]);
832 int datain = getDataSetIdFromName(dataset, "__inner__");
834 int sizein = getDatasetInfo(datain, &complex, &dimin, NULL);
835 std::vector<int> dimsin(dimin);
836 sizein = getDatasetInfo(datain, &complex, &dimin, dimsin.data());
838 std::vector<int> in(sizein);
839 int ret = readInteger32Matrix(datain, in.data());
847 int dataout = getDataSetIdFromName(dataset, "__outer__");
849 int sizeout = getDatasetInfo(dataout, &complex, &dimout, NULL);
850 std::vector<int> dimsout(dimout);
851 sizeout = getDatasetInfo(dataout, &complex, &dimout, dimsout.data());
853 std::vector<int> out(sizeout);
854 ret = readInteger32Matrix(dataout, out.data());
863 return new types::SparseBool(pdims[0], pdims[1], nnz, in.data(), out.data());
866 static types::InternalType* import_cell(int dataset)
868 //get sparse dimensions
870 std::vector<int> pdims;
871 int size = getDimsNode(dataset, &complex, pdims);
876 return new types::Cell();
880 int refs = getDataSetIdFromName(dataset, "__refs__");
881 std::vector<types::InternalType*> data(size);
882 for (int i = 0; i < size; ++i)
884 int ref = getDataSetIdFromName(refs, std::to_string(i).data());
885 types::InternalType* val = import_data(ref);
894 types::Cell* cell = new types::Cell(static_cast<int>(pdims.size()), pdims.data(), data.data());
901 static types::InternalType* import_handles(int dataset)
903 //get sparse dimensions
905 std::vector<int> pdims;
906 int size = getDimsNode(dataset, &complex, pdims);
915 int refs = getDataSetIdFromName(dataset, "__refs__");
916 types::GraphicHandle* handles = new types::GraphicHandle(static_cast<int>(pdims.size()), pdims.data());
917 long long* h = handles->get();
918 for (int i = 0; i < size; ++i)
920 int ref = getDataSetIdFromName(refs, std::to_string(i).data());
921 int val = import_handle(ref, -1);
927 h[i] = getHandle(val);
934 //update links property of legend handle
937 std::list<int> legends = Links::legends();
938 for (auto& i : legends)
940 Links::PathList paths = Links::get(i);
941 update_link_path(i, paths);
948 static types::InternalType* import_macro(int dataset)
953 std::vector<int> d(2);
955 std::list<symbol::Variable*>* inputList = new std::list<symbol::Variable*>();
956 std::list<symbol::Variable*>* outputList = new std::list<symbol::Variable*>();
957 ast::Exp* body = nullptr;
959 symbol::Context* ctx = symbol::Context::getInstance();
962 int inputNode = getDataSetIdFromName(dataset, "inputs");
963 size = getDatasetInfo(inputNode, &complex, &dims, d.data());
964 std::vector<char*> inputNames(size);
968 readStringMatrix(inputNode, inputNames.data());
970 for (auto& input : inputNames)
972 wchar_t* winput = to_wide_string(input);
973 symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(winput));
975 inputList->push_back(var);
978 freeStringMatrix(inputNode, inputNames.data());
982 closeDataSet(inputNode);
986 int outputNode = getDataSetIdFromName(dataset, "outputs");
987 size = getDatasetInfo(outputNode, &complex, &dims, d.data());
988 std::vector<char*> outputNames(size);
992 readStringMatrix(outputNode, outputNames.data());
994 for (auto& output : outputNames)
996 wchar_t* woutput = to_wide_string(output);
997 symbol::Variable* var = ctx->getOrCreate(symbol::Symbol(woutput));
999 outputList->push_back(var);
1002 freeStringMatrix(outputNode, outputNames.data());
1006 closeDataSet(outputNode);
1010 int bodyNode = getDataSetIdFromName(dataset, "body");
1011 size = getDatasetInfo(bodyNode, &complex, &dims, d.data());
1012 std::vector<unsigned char> bodybin(size);
1013 readUnsignedInteger8Matrix(bodyNode, bodybin.data());
1015 ast::DeserializeVisitor ds(bodybin.data());
1016 body = ds.deserialize();
1018 //wname+1 is to remove "/" at the start of the var name from HDF5
1019 types::Macro* macro = new types::Macro(L"", *inputList, *outputList, *body->getAs<ast::SeqExp>(), L"script");
1021 closeList6(dataset);
1025 static types::InternalType* import_usertype(int dataset)
1027 types::InternalType* it = import_struct(dataset);
1028 if (it == nullptr || it->isStruct() == false)
1035 types::Struct* str = it->getAs<types::Struct>();
1037 if (str->isScalar() == false)
1043 types::SingleStruct* ss = str->get()[0];
1045 //extract type from struct
1046 types::InternalType* itType = ss->get(L"type");
1047 if (itType == nullptr || itType->getId() != types::InternalType::IdScalarString)
1053 types::String* s = it->getAs<types::String>();
1054 wchar_t* type = s->get()[0];
1056 types::InternalType* data = ss->get(L"data");
1057 if (data == nullptr)
1063 //call %yourtype_load overload
1064 types::typed_list in;
1067 types::typed_list out;
1069 ast::ExecVisitor exec;
1071 std::wstring wstFuncName = L"%" + data->getShortTypeStr() + L"_load";
1072 types::Callable::ReturnValue ret = Overload::call(wstFuncName, in, 1, out, &exec);
1074 //clean temporary variables
1075 delete it; //included type and data
1077 if (ret != types::Callable::OK)
1082 if (out.size() != 1)