8a8a2879b97dc8e0a185d120dc36ba72dc207cff
[scilab.git] / scilab / modules / webtools / sci_gateway / cpp / sci_toJSON.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2017 - ESI-Group - Antoine ELIAS
4 *
5 *
6 * This file is hereby licensed under the terms of the GNU GPL v2.0,
7 * pursuant to article 5.3.4 of the CeCILL v.2.1.
8 * This file was originally licensed under the terms of the CeCILL v2.1,
9 * and continues to be available under such terms.
10 * For more information, see the COPYING file which you should have received
11 * along with this program.
12 *
13 */
14 /*--------------------------------------------------------------------------*/
15
16 #include <sstream>
17 #include <string>
18 #include <fstream>
19 #include <iomanip>
20 #include <vector>
21 #include <regex>
22 #include <chrono>
23
24 #define __API_SCILAB_UNSAFE__
25 #include "json.hxx"
26
27 //#define SHOW_TIMER
28
29 extern "C"
30 {
31 #include "gw_webtools.h"
32 #include "api_scilab.h"
33 #include "Scierror.h"
34 #include "sciprint.h"
35 #include "sci_malloc.h"
36 #include <localization.h>
37 }
38
39 bool exportJSON(scilabEnv env, scilabVar var, int indent, const std::wstring &file, scilabVar* const  out);
40 bool export_data(scilabEnv env, scilabVar var, int indent, std::wostringstream &os);
41
42 const std::string name("toJSON");
43
44 //A: toJSON(x) -> return inline string
45 //B: toJSON(x, y) -> return string array with y spaces increment
46 //C: toJSON(x, "file") -> write JSON in file return %t/%f
47 //D: toJSON(x, y, "file") -> write JSON in file with indention return %t/%f
48 /* ==================================================================== */
49
50 int sci_toJSON(scilabEnv env, int nin, scilabVar *in, int nopt, scilabOpt opt, int nout, scilabVar *out)
51 {
52 #ifdef SHOW_TIMER
53     std::chrono::steady_clock::time_point ttotal = std::chrono::steady_clock::now();
54     std::chrono::steady_clock::time_point tinput = std::chrono::steady_clock::now();
55 #endif
56
57     int indent = 0;
58     std::wstring file;
59
60     if (1 > nin || nin > 3)
61     {
62         Scierror(999, _("%s: Wrong number of input arguments: %d to %d expected.\n"), name.data(), 1, 3);
63         return STATUS_ERROR;
64     }
65
66     switch (nin)
67     {
68         case 1:
69             //OK
70             break;
71
72         case 2:
73         {
74             //must be a scalar double or single string
75             if ((!scilab_isDouble(env, in[1]) && !scilab_isString(env, in[1])) || !scilab_isScalar(env, in[1]))
76             {
77                 Scierror(999, "%s: Wrong type for input argument #%d: double or string expected.\n", name.data(), 2);
78                 return STATUS_ERROR;
79             }
80
81             if (scilab_isDouble(env, in[1]))
82             {
83                 double dbl = 0;
84                 scilab_getDouble(env, in[1], &dbl);
85                 indent = (int)dbl;
86             }
87             else
88             {
89                 //string
90                 wchar_t *wf = nullptr;
91                 scilab_getString(env, in[1], &wf);
92                 file = wf;
93             }
94             break;
95         }
96         case 3:
97         {
98             //must be a scalar double or single string
99             if (!scilab_isDouble(env, in[1]) && !scilab_isScalar(env, in[1]))
100             {
101                 Scierror(999, "%s: Wrong type for input argument #%d: double expected.\n", name.data(), 2);
102                 return STATUS_ERROR;
103             }
104
105             double dbl = 0;
106             scilab_getDouble(env, in[1], &dbl);
107             indent = (int)dbl;
108
109             //must be a scalar double or single string
110             if (!scilab_isString(env, in[2]) && !isScalar(env, in[2]))
111             {
112                 Scierror(999, "%s: Wrong type for input argument #%d: string expected.\n", name.data(), 3);
113                 return STATUS_ERROR;
114             }
115
116             //string
117             wchar_t *wf = nullptr;
118             scilab_getString(env, in[2], &wf);
119             file = wf;
120             break;
121         }
122
123         default:
124         {
125             Scierror(999, "%s: bad input arguments.\n", name.data());
126             return STATUS_ERROR;
127         }
128     }
129
130 #ifdef SHOW_TIMER
131     std::chrono::steady_clock::time_point tinputend = std::chrono::steady_clock::now();
132     sciprint("Input\t: %d ms\n", std::chrono::duration_cast<std::chrono::milliseconds>(tinputend - tinput).count());
133 #endif
134
135     exportJSON(env, in[0], indent, file, out);
136
137 #ifdef SHOW_TIMER
138     std::chrono::steady_clock::time_point ttotalend = std::chrono::steady_clock::now();
139     sciprint("Total\t: %d ms\n", std::chrono::duration_cast<std::chrono::milliseconds>(ttotalend - ttotal).count());
140 #endif
141
142     return 0;
143 }
144
145 bool exportJSON(scilabEnv env, scilabVar var, int indent, const std::wstring& file, scilabVar* const out)
146 {
147 #ifdef SHOW_TIMER
148     std::chrono::steady_clock::time_point tprocess = std::chrono::steady_clock::now();
149 #endif
150
151     std::string s = toJSON(env, var, indent);
152
153 #ifdef SHOW_TIMER
154     std::chrono::steady_clock::time_point tprocessend = std::chrono::steady_clock::now();
155     sciprint("Process\t: %d ms\n", std::chrono::duration_cast<std::chrono::milliseconds>(tprocessend - tprocess).count());
156
157     std::chrono::steady_clock::time_point toutput = std::chrono::steady_clock::now();
158 #endif
159
160     if (file.empty() == false)
161     {
162         char *_filename = wide_string_to_UTF8(file.c_str());
163         if (_filename == NULL)
164         {
165             return false;
166         }
167
168         std::ofstream outfile(_filename);
169         outfile << s.data();
170         outfile.close();
171         FREE(_filename);
172     }
173     else
174     {
175         wchar_t* w = to_wide_string(s.data());
176         out[0] = scilab_createString(env, w);
177         FREE(w);
178     }
179
180 #ifdef SHOW_TIMER
181     std::chrono::steady_clock::time_point toutputend = std::chrono::steady_clock::now();
182     sciprint("Output\t: %d ms\n", std::chrono::duration_cast<std::chrono::milliseconds>(toutputend - toutput).count());
183 #endif
184
185     return true;
186 }