fix library path
[scilab.git] / scilab / modules / string / sci_gateway / cpp / sci_string.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
4 *  Copyright (C) 2014 - Scilab Enterprises - Anais AUBERT
5 *
6 *  This file must be used under the terms of the CeCILL.
7 *  This source file is licensed as described in the file COPYING, which
8 *  you should have received as part of this distribution.  The terms
9 *  are also available at
10 *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11 *
12 */
13
14 #include <math.h>
15 #include <sstream>
16 #include <string>
17 #include "string.hxx"
18 #include "double.hxx"
19 #include "function.hxx"
20 #include "string_gw.hxx"
21 #include "tostring_common.hxx"
22 #include "printvisitor.hxx"
23 #include "macro.hxx"
24 #include "macrofile.hxx"
25 #include "symbol.hxx"
26 #include "tlist.hxx"
27 #include "overload.hxx"
28 #include "execvisitor.hxx"
29
30 extern "C"
31 {
32 #include "os_wcsdup.h"
33 #include "Scierror.h"
34 #include "localization.h"
35 #include "sciprint.h"
36 }
37
38 using namespace types;
39
40 static void getMacroString(Macro* _pM, InternalType** _pOut, InternalType** _pIn, InternalType** _pBody)
41 {
42     //get body
43     ast::Exp* exp = _pM->getBody();
44
45     std::wostringstream ostr;
46     ast::PrintVisitor pv(ostr, false);
47
48     exp->accept(pv);
49
50     wstring wstBody = ostr.str();
51     const wchar_t* pwstBody = wstBody.c_str();
52
53     //first loop to find number of lines
54     int iLines = 2; //for first and last one-space lines
55     for (int i = 0 ; i < (int)wcslen(pwstBody) ; i++)
56     {
57         if (pwstBody[i] == L'\n')
58         {
59             iLines++;
60         }
61     }
62
63     String* pBody = new String(iLines, 1);
64     pBody->set(0, L" ");
65     //second loop to assign lines to output data
66     int iOffset = 0;
67     int iIndex = 1;
68     for (int i = 0 ; i < (int)wcslen(pwstBody) ; i++)
69     {
70         if (pwstBody[i] == L'\n')
71         {
72             int iLen = i - iOffset;
73             wchar_t* pwst = new wchar_t[iLen + 1];
74             wcsncpy(pwst, pwstBody + iOffset, iLen);
75             pwst[iLen] = L'\0';
76             pBody->set(iIndex++, pwst);
77             delete[] pwst;
78             iOffset = i + 1;
79         }
80     }
81
82     pBody->set(iIndex, L" ");
83     *_pBody = pBody;
84
85     //get inputs
86     std::list<symbol::Variable*>* pIn = _pM->inputs_get();
87
88     if (pIn->size() == 0)
89     {
90         *_pIn = Double::Empty();
91     }
92     else
93     {
94         String *pSIn = new String(1, (int)pIn->size());
95
96         list<symbol::Variable*>::iterator itIn = pIn->begin();
97         for (int i = 0 ; i < pIn->size() ; i++, itIn++)
98         {
99             pSIn->set(i, (*itIn)->getSymbol().getName().c_str());
100         }
101
102         *_pIn = pSIn;
103     }
104
105     //get outputs
106     list<symbol::Variable*>* pOut = _pM->outputs_get();
107     if (pOut->size() == 0)
108     {
109         *_pOut = Double::Empty();
110     }
111     else
112     {
113         String* pSOut = new String(1, (int)pOut->size());
114
115         list<symbol::Variable*>::iterator itOut = pOut->begin();
116         for (int i = 0 ; i < pOut->size() ; i++, itOut++)
117         {
118             pSOut->set(i, (*itOut)->getSymbol().getName().c_str());
119         }
120
121         *_pOut = pSOut;
122     }
123 }
124
125 static void DoubleComplexMatrix2String(std::wostringstream *_postr,  double _dblR, double _dblI)
126 {
127     /*
128     if R && !C -> R
129     if R && C -> R + Ci
130     if !R && !C -> 0
131     if(!R aa C  -> Ci
132     */
133     DoubleFormat dfR, dfI;
134     dfR.bPrintBlank = false;
135     dfI.bPrintBlank = false;
136
137     getDoubleFormat(_dblR, &dfR);
138     getDoubleFormat(_dblI, &dfI);
139
140     dfR.bPrintPoint = dfR.bExp;
141     dfR.bPaddSign = false;
142
143     dfI.bPrintPoint = dfI.bExp;
144     dfI.bPaddSign = false;
145
146
147     if (_dblR == 0)
148     {
149         //no real part
150         if (_dblI == 0)
151         {
152             //no imaginary part
153
154             //0
155             addDoubleValue(_postr, 0, &dfR);
156         }
157         else
158         {
159             //imaginary part
160
161             //I
162             *_postr << (_dblI < 0 ? L"-" : L"");
163             *_postr << L"%i";
164             if (fabs(_dblI) != 1)
165             {
166                 //specail case if I == 1 write only %i and not %i*1
167                 *_postr << L"*";
168                 addDoubleValue(_postr, fabs(_dblI), &dfI);
169             }
170         }
171     }
172     else
173     {
174         //real part
175         if (_dblI == 0)
176         {
177             //no imaginary part
178
179             //R
180             addDoubleValue(_postr, _dblR, &dfR);
181         }
182         else
183         {
184             //imaginary part
185
186             //R
187             addDoubleValue(_postr, _dblR, &dfR);
188             //I
189             *_postr << (_dblI < 0 ? L"-%i" : L"+%i");
190             if (fabs(_dblI) != 1)
191             {
192                 //special case if I == 1 write only %i and not %i*1
193                 *_postr << L"*";
194                 addDoubleValue(_postr, fabs(_dblI), &dfI);
195             }
196         }
197     }
198 }
199
200 template <class T>
201 Function::ReturnValue intString(T* pInt, typed_list &out)
202 {
203     int iDims = pInt->getDims();
204     int* piDimsArray = pInt->getDimsArray();
205     String *pstOutput = new String(iDims, piDimsArray);
206     int iSize = pInt->getSize();
207     for (int i = 0 ; i < iSize ; i++)
208     {
209         std::wostringstream ostr;
210         DoubleComplexMatrix2String(&ostr, pInt->get(i), 0);
211         pstOutput->set(i, ostr.str().c_str());
212     }
213
214     out.push_back(pstOutput);
215     return Function::OK;
216 }
217
218 Function::ReturnValue booleanString(types::Bool* pB, typed_list &out)
219 {
220     int iDims = pB->getDims();
221     int* piDimsArray = pB->getDimsArray();
222     int* pb = pB->get();
223     String *pstOutput = new String(iDims, piDimsArray);
224     int iSize = pB->getSize();
225     for (int i = 0 ; i < iSize ; i++)
226     {
227         pstOutput->set(i, pb[i] == 0 ? "F" : "T");
228     }
229
230     out.push_back(pstOutput);
231     return Function::OK;
232 }
233
234 Function::ReturnValue doubleString(types::Double* pDbl, typed_list &out)
235 {
236     int iDims = pDbl->getDims();
237     int* piDimsArray = pDbl->getDimsArray();
238     double* pdblReal = pDbl->get();
239
240     // Special case string([]) == []
241     if (pDbl->isEmpty())
242     {
243         out.push_back(Double::Empty());
244         return Function::OK;
245     }
246     else if (piDimsArray[0] == -1 && piDimsArray[1] == -1)
247     {
248         out.push_back(new String(L""));
249         return Function::OK;
250     }
251
252     String *pstOutput = new String(iDims, piDimsArray);
253     if (pDbl->isComplex())
254     {
255         double* pdblImg = pDbl->getImg();
256         for (int i = 0; i < pDbl->getSize(); ++i)
257         {
258             std::wostringstream ostr;
259             DoubleComplexMatrix2String(&ostr, pdblReal[i], pdblImg[i]);
260             pstOutput->set(i, ostr.str().c_str());
261         }
262     }
263     else
264     {
265         double dblImg  = 0.0;
266         for (int i = 0; i < pDbl->getSize(); ++i)
267         {
268             std::wostringstream ostr;
269             DoubleComplexMatrix2String(&ostr, pdblReal[i], dblImg);
270             pstOutput->set(i, ostr.str().c_str());
271         }
272     }
273     out.push_back(pstOutput);
274     return Function::OK;
275 }
276
277 Function::ReturnValue sci_string(typed_list &in, int _iRetCount, typed_list &out)
278 {
279     if (in.size() != 1)
280     {
281         Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "string", 1);
282         return Function::Error;
283     }
284
285     switch (in[0]->getType())
286     {
287         case GenericType::ScilabSparse :
288         {
289             //C=sparse([0 0 4 0 9;0 0 5 0 0;1 3 0 7 0;0 0 6 0 10;2 0 0 8 0]);string(C)
290             types::Sparse* pS = in[0]->getAs<Sparse>();
291             int iRows = pS->getRows();
292             int iCols = pS->getCols();
293             bool isComplex = pS->isComplex();
294             std::wostringstream ostr;
295             std::vector<std::wstring> vect;
296             int st;
297             string *stemp = new string();
298
299
300             ostr << "(" << iRows << "," << iCols << ") sparse matrix";
301
302             vect.push_back(ostr.str());
303             ostr.str(L"");
304             ostr.clear();
305
306             for (int i = 0 ; i < iRows ; i++)
307             {
308                 for (int j = 0 ; j < iCols ; j++)
309                 {
310                     std::wostringstream temp;
311                     double real = pS->getReal(i, j);
312                     double cplx = 0;
313                     if (isComplex)
314                     {
315                         cplx = pS->getImg(i, j).imag();
316                     }
317
318                     if (real || cplx )
319                     {
320                         temp << L"(" << i + 1 << L"," << j + 1 << L")    ";
321
322                         if (real)
323                         {
324                             temp << pS->getReal(i, j);
325                         }
326
327                         if (cplx)
328                         {
329                             if (real && cplx > 0)
330                             {
331                                 temp << L"+";
332                             }
333                             else if (cplx < 0)
334                             {
335                                 temp << L"-";
336                             }
337
338                             temp << L"%i*" << std::abs(cplx);
339                         }
340
341                         ostr << temp.str();
342                         vect.push_back(ostr.str());
343                         ostr.str(L"");
344                         ostr.clear();
345                     }
346                 }
347             }
348
349             types::String* pSt = new String(vect.size(), 1);
350             for (int i = 0 ; i < vect.size(); i++)
351             {
352                 pSt->set(i, vect[i].c_str());
353             }
354
355             out.push_back(pSt);
356             break;
357         }
358
359         case GenericType::ScilabInt8 :
360         {
361             return intString(in[0]->getAs<types::Int8>(), out);
362         }
363         case GenericType::ScilabUInt8 :
364         {
365             return intString(in[0]->getAs<types::UInt8>(), out);
366         }
367         case GenericType::ScilabInt16 :
368         {
369             return intString(in[0]->getAs<types::Int16>(), out);
370         }
371         case GenericType::ScilabUInt16 :
372         {
373             return intString(in[0]->getAs<types::UInt16>(), out);
374         }
375         case GenericType::ScilabInt32 :
376         {
377             return intString(in[0]->getAs<types::Int32>(), out);
378         }
379         case GenericType::ScilabUInt32 :
380         {
381             return intString(in[0]->getAs<types::UInt32>(), out);
382         }
383         case GenericType::ScilabInt64 :
384         {
385             return intString(in[0]->getAs<types::Int64>(), out);
386         }
387         case GenericType::ScilabUInt64 :
388         {
389             return intString(in[0]->getAs<types::UInt64>(), out);
390         }
391         case GenericType::ScilabDouble :
392         {
393             return doubleString(in[0]->getAs<Double>(), out);
394         }
395         case GenericType::ScilabString :
396         {
397             out.push_back(in[0]);
398             break;
399         }
400         case GenericType::ScilabMacroFile :
401         {
402             if (_iRetCount != 3)
403             {
404                 Scierror(77, _("%s: Wrong number of output argument(s): %d expected.\n"), "string", 3);
405                 return Function::Error;
406             }
407
408             MacroFile* pMF = in[0]->getAs<MacroFile>();
409             InternalType* pOut = NULL;
410             InternalType* pIn = NULL;
411             InternalType* pBody = NULL;
412
413             getMacroString(pMF->getMacro(), &pOut, &pIn, &pBody);
414
415             out.push_back(pOut);
416             out.push_back(pIn);
417             out.push_back(pBody);
418             break;
419         }
420         case GenericType::ScilabMacro :
421         {
422             if (_iRetCount != 3)
423             {
424                 Scierror(77, _("%s: Wrong number of output argument(s): %d expected.\n"), "string", 3);
425                 return Function::Error;
426             }
427
428             Macro* pM = in[0]->getAs<Macro>();
429             InternalType* pOut = NULL;
430             InternalType* pIn = NULL;
431             InternalType* pBody = NULL;
432
433             getMacroString(pM, &pOut, &pIn, &pBody);
434
435             out.push_back(pOut);
436             out.push_back(pIn);
437             out.push_back(pBody);
438             break;
439         }
440         case GenericType::ScilabTList :
441         case GenericType::ScilabMList :
442         case GenericType::ScilabPolynom :
443         {
444             std::wstring wstFuncName = L"%"  + in[0]->getShortTypeStr() + L"_string";
445             return Overload::call(wstFuncName, in, _iRetCount, out, new ast::ExecVisitor());
446         }
447         case GenericType::ScilabBool:
448         {
449             return booleanString(in[0]->getAs<Bool>(), out);
450         }
451         case GenericType::ScilabLibrary:
452         {
453             Library* pL = in[0]->getAs<Library>();
454             std::wstring path = pL->getPath();
455             std::list<std::wstring>* macros = pL->getMacrosName();
456             String* pS = new String(macros->size() + 1, 1);
457             pS->set(0, path.c_str());
458             int i = 1;
459             for (auto it = macros->begin(), itEnd = macros->end(); it != itEnd; ++it, ++i)
460             {
461                 pS->set(i, (*it).c_str());
462             }
463
464             out.push_back(pS);
465             break;
466         }
467         default:
468         {
469             std::wostringstream ostr;
470             in[0]->toString(ostr);
471             out.push_back(new types::String(ostr.str().c_str()));
472             break;
473         }
474     }
475     return Function::OK;
476 }