bug 13981: fix string corruption in error cases
[scilab.git] / scilab / modules / hdf5 / sci_gateway / cpp / sci_hdf5_load.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
4 *
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
10 *
11 */
12
13 #include <hdf5.h>
14 #include "hdf5_gw.hxx"
15 #include "function.hxx"
16 #include "string.hxx"
17 #include "list.hxx"
18 #include "overload.hxx"
19 #include "execvisitor.hxx"
20 #include "loadlib.hxx"
21
22 extern "C"
23 {
24 #include "sci_malloc.h"
25 #include "Scierror.h"
26 #include "FileExist.h"
27 #include "expandPathVariable.h"
28 #include "h5_fileManagement.h"
29 #include "h5_attributeConstants.h"
30 #include "h5_readDataFromFile.h"
31 }
32
33 static const std::string fname("load");
34
35 Function::ReturnValue sci_hdf5_load(typed_list &in, int _iRetCount, typed_list& out)
36 {
37     int rhs = static_cast<int>(in.size());
38     if (rhs < 1)
39     {
40         Scierror(999, _("%s: Wrong number of input argument(s): at least %d expected.\n"), fname.data(), 1);
41         return Function::Error;
42     }
43
44     if (in[0]->getId() != InternalType::IdScalarString)
45     {
46         Scierror(999, _("%s: Wrong size for input argument #%d: A string expected.\n"), fname.data(), 1);
47         return Function::Error;
48     }
49
50     wchar_t* wcfilename = expandPathVariableW(in[0]->getAs<String>()->get()[0]);
51     char* cfilename = wide_string_to_UTF8(wcfilename);
52     std::string filename(cfilename);
53     std::wstring wfilename(wcfilename);
54     FREE(cfilename);
55     FREE(wcfilename);
56
57     if (FileExistW(wfilename.data()) == FALSE)
58     {
59         Scierror(999, _("%s: Unable to open file: '%s'.\n"), fname.data(), filename.data());
60         return Function::Error;
61     }
62
63     //library ?
64     if (isHDF5File(filename.data()) == false)
65     {
66         //lib file
67         int err = 0;
68         Library* lib = loadlib(in[0]->getAs<String>()->get()[0], &err);
69
70         switch (err)
71         {
72             case 1:
73                 Scierror(999, _("%s: %s is not a valid lib file.\n"), fname.data(), filename.data());
74                 return Function::Error;
75             case 2:
76                 Scierror(999, "%s: %s", fname.data(), _("Redefining permanent variable.\n"));
77                 return Function::Error;
78             default:
79                 break;
80         }
81
82         lib->killMe();
83         return Function::OK;
84     }
85
86     int iFile = openHDF5File(filename.data(), 0);
87     if (iFile < 0)
88     {
89         Scierror(999, _("%s: Unable to open file: %s\n"), fname.data(), filename.data());
90         return Function::Error;
91     }
92
93     std::wstring wstFuncName;
94     //manage version information
95     int version = getSODFormatAttribute(iFile);
96     closeHDF5File(iFile);
97
98     bool needReprocess = false;
99     switch (version)
100     {
101         case -1:
102         case 1:
103         {
104             wstFuncName = L"hdf5_load_v1";
105             needReprocess = true;
106             break;
107         }
108         case 2:
109         {
110             wstFuncName = L"hdf5_load_v2";
111             needReprocess = true;
112             break;
113         }
114         case 3:
115         {
116             wstFuncName = L"hdf5_load_v3";
117             break;
118         }
119         default :
120         {
121             Scierror(999, _("%s: Wrong SOD file format version. Max Expected: %d Found: %d\n"), fname.data(), SOD_FILE_VERSION, version);
122             return Function::Error;
123         }
124     }
125
126
127     ast::ExecVisitor exec;
128     typed_list out1;
129     Function::ReturnValue ret = Overload::call(wstFuncName, in, _iRetCount, out1, &exec);
130
131     if (ret != Function::OK)
132     {
133         Scierror(999, _("%s: Unable to load '%s'\n"), fname.data(), filename.data());
134         return Function::Error;
135     }
136
137     if (needReprocess)
138     {
139         //call %sodload
140         String* vars = out1[0]->getAs<String>();
141         vars->IncreaseRef();
142         int size = vars->getSize();
143         typed_list in2(1, vars);
144         typed_list out2;
145         std::wstring wstFuncName = L"%_sodload";
146         ret = Overload::call(wstFuncName, in2, size, out2, &exec);
147         vars->DecreaseRef();
148
149         symbol::Context* ctx = symbol::Context::getInstance();
150         wchar_t** names = vars->get();
151
152         //update context with values return by %_sodload
153         for (int i = 0; i < size; ++i)
154         {
155             ctx->put(symbol::Symbol(names[i]), out2[i]);
156         }
157
158         vars->killMe();
159     }
160
161     return ret;
162 }