36cc2d9a3a98d931d4d266811825304e83c6d016
[scilab.git] / scilab / modules / ui_data / src / cpp / BrowseVarManager.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - DIGITEO - Allan CORNET
4  * Copyright (C) 2010 - DIGITEO - Bruno JOFRET
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #include <iostream>
18 #include <sstream>
19 #include <string>
20 #include <iterator>
21 #include <set>
22 #include <cmath>
23 #include "alltypes.hxx"
24 #include "types_tools.hxx"
25
26 #include "BrowseVar.hxx"
27 #ifdef _MSC_VER
28 #ifdef max
29 #undef max
30 #endif
31 #ifdef min
32 #undef min
33 #endif
34 #endif
35 #include "context.hxx"
36
37 extern "C"
38 {
39 #include "BrowseVarManager.h"
40 #include "localization.h"
41 #include "sci_malloc.h"
42 #include "BOOL.h"
43 #include "getScilabJavaVM.h"
44 #include "Scierror.h"
45 #include "freeArrayOfString.h"
46 #include "os_string.h"
47 #include "api_scilab.h"
48 #include "sci_types.h"
49 #include "sciprint.h"
50 }
51
52 #define N_A             "N/A"
53 #define EMPTY_MATRIX    "[ ]"
54 #define EMPTY_CELL      "{}"
55 #define EMPTY_LIST      "()"
56 #define LOCAL_STR       "local"
57 #define GLOBAL_STR      "global"
58 #define INHERITED_STR   "inherited"
59 #define NEG_INF_STR     "-Inf"
60 #define INF_STR         "Inf"
61 #define NAN_STR         "NaN"
62 #define PLUS_STR        " + "
63 #define MINUS_STR       " - "
64 #define I_STR           "i"
65 #define LBRACKET_STR    "["
66 #define RBRACKET_STR    "]"
67 #define COMMA_STR       ", "
68 #define SEMICOLON_STR   "; "
69
70 using namespace org_scilab_modules_ui_data;
71 using std::string;
72
73 static std::set<string> createScilabDefaultVariablesSet();
74 static char * getListName(char * variableName);
75 static std::string formatMatrix(int nbRows, int nbCols, double *pdblReal, double *pdblImg);
76 static char * valueToDisplay(types::InternalType* pIT);
77 void OpenBrowseVar()
78 {
79     BrowseVar::openVariableBrowser(getScilabJavaVM());
80     SetBrowseVarData();
81 }
82
83 void UpdateBrowseVar()
84 {
85     if (BrowseVar::isVariableBrowserOpened(getScilabJavaVM()))
86     {
87         SetBrowseVarData();
88     }
89 }
90
91 void SetBrowseVarData()
92 {
93     SciErr err;
94     int iLocalVariablesUsed = 0;
95     int i = 0;
96
97     symbol::Context* ctx = symbol::Context::getInstance();
98
99     std::list<symbol::Variable*> lstVars;
100     std::list<symbol::Library*> lstLibs;
101
102     iLocalVariablesUsed = ctx->getVarsToVariableBrowser(lstVars);
103     iLocalVariablesUsed += ctx->getLibsToVariableBrowser(lstLibs);
104
105     char **pstAllVariableNames = new char*[iLocalVariablesUsed]();
106     char **pstAllVariableVisibility = new char*[iLocalVariablesUsed]();
107     char **pstAllVariableListTypes = new char*[iLocalVariablesUsed]();
108     int *piAllVariableBytes = new int[iLocalVariablesUsed]();
109     char **pstAllVariableSizes = new char*[iLocalVariablesUsed]();
110     int *piAllVariableTypes = new int[iLocalVariablesUsed]();
111     int *piAllVariableIntegerTypes = new int[iLocalVariablesUsed]();
112     bool *piAllVariableFromUser = new bool[iLocalVariablesUsed]();
113     /* Necessary for the plots in the var browser */
114     int *piAllVariableNbRows = new int[iLocalVariablesUsed]();
115     int *piAllVariableNbCols = new int[iLocalVariablesUsed]();
116
117     int nbRows, nbCols;
118     char *sizeStr = NULL;
119
120     std::set<string> scilabDefaultVariablesSet = createScilabDefaultVariablesSet();
121     int iLevel = ctx->getScopeLevel();
122
123     // for each local variable get information
124     for (auto var : lstVars)
125     {
126         //get top level value
127         symbol::ScopedVariable* sv = var->top();
128         //get value
129         types::InternalType* pIT = sv->m_pIT;
130
131         // get name
132         pstAllVariableNames[i] = wide_string_to_UTF8(var->getSymbol().getName().data());
133
134         // get visibility
135         if (sv->m_globalVisible == true)
136         {
137             pstAllVariableVisibility[i] = os_strdup(GLOBAL_STR);
138             pIT = var->getGlobalValue();
139         }
140         else if (sv->m_iLevel != iLevel)
141         {
142             pstAllVariableVisibility[i] = os_strdup(INHERITED_STR);
143         }
144         else
145         {
146             pstAllVariableVisibility[i] = os_strdup(LOCAL_STR);
147         }
148
149         // type with Scilab < 6 compatibility (structs and cells have type 17)
150         err = getVarType(NULL, (int*)pIT, &piAllVariableTypes[i]);
151         if (err.iErr)
152         {
153             return;
154         }
155         err = getVarDimension(NULL, (int*)pIT, &nbRows, &nbCols);
156         if (err.iErr)
157         {
158             return;
159         }
160
161         if (pIT->isArrayOf() || pIT->isSparse())
162         {
163             int nbRows = pIT->getAs<types::GenericType>()->getRows();
164             int nbCols = pIT->getAs<types::GenericType>()->getCols();
165             piAllVariableNbRows[i] = nbRows;
166             piAllVariableNbCols[i] = nbCols;
167             if (nbRows * nbCols == 0)
168             {
169                 pstAllVariableSizes[i] = pIT->isCell() ? os_strdup(EMPTY_CELL) : os_strdup(EMPTY_MATRIX);
170             }
171             else if (pIT->isArrayOf())
172             {
173                 pstAllVariableSizes[i] = valueToDisplay(pIT);
174             }
175             else
176             {
177                 std::string sizeString = std::to_string(nbRows) + "x" + std::to_string(nbCols);
178                 pstAllVariableSizes[i] =  os_strdup(sizeString.data());
179             }
180         }
181         else if (pIT->isMList() || pIT->isTList() || pIT->isList() )
182         {
183             pstAllVariableSizes[i] = pIT->getAs<types::List>()->getSize() == 0 ? os_strdup(EMPTY_LIST) : os_strdup(N_A);
184         }
185         else
186         {
187             pstAllVariableSizes[i] =  os_strdup(N_A);
188         }
189
190         if (piAllVariableTypes[i] == sci_ints)
191         {
192             // Integer case
193             int iPrec       = 0;
194             err = getMatrixOfIntegerPrecision(NULL, (int*)pIT, &iPrec);
195             if (err.iErr)
196             {
197                 return;
198             }
199             switch (iPrec)
200             {
201                 case SCI_INT8:
202                     piAllVariableIntegerTypes[i] = 8;
203                     break;
204                 case SCI_INT16:
205                     piAllVariableIntegerTypes[i] = 16;
206                     break;
207                 case SCI_INT32:
208                     piAllVariableIntegerTypes[i] = 32;
209                     break;
210 #ifdef __SCILAB_INT64__
211                 case SCI_INT64:
212                     piAllVariableIntegerTypes[i] = 64;
213                     break;
214 #endif
215                 default:
216                     piAllVariableIntegerTypes[i] = 0; // Should never occurs
217                     break;
218             }
219         }
220         else
221         {
222             piAllVariableIntegerTypes[i] = -1;
223         }
224
225         if (pIT->isTList() || pIT->isMList())
226         {
227             pstAllVariableListTypes[i] = getListName(pstAllVariableNames[i]);
228         }
229         else if (pIT->isStruct())
230         {
231             piAllVariableTypes[i] = sci_struct;
232             pstAllVariableListTypes[i] = os_strdup("");
233         }
234         else if (pIT->isCell())
235         {
236             piAllVariableTypes[i] = sci_cell;
237             pstAllVariableListTypes[i] = os_strdup("");
238         }
239         else
240         {
241             pstAllVariableListTypes[i] = os_strdup("");
242         }
243
244         if (scilabDefaultVariablesSet.find(string(pstAllVariableNames[i])) == scilabDefaultVariablesSet.end() && piAllVariableTypes[i] != sci_lib)
245         {
246             piAllVariableFromUser[i] = TRUE;
247         }
248         else
249         {
250             piAllVariableFromUser[i] = FALSE;
251         }
252
253         int bytesWithoutOverHead;
254         pIT->getMemory(&bytesWithoutOverHead, &piAllVariableBytes[i]);
255
256         ++i;
257     }
258
259     for (auto lib : lstLibs)
260     {
261         //get top level value
262         symbol::ScopedLibrary* sl = lib->top();
263
264         // get name
265         pstAllVariableNames[i] = wide_string_to_UTF8(lib->getSymbol().getName().data());
266
267         // get visibility
268         if (sl->m_iLevel != iLevel)
269         {
270             pstAllVariableVisibility[i] = os_strdup(INHERITED_STR);
271         }
272         else
273         {
274             pstAllVariableVisibility[i] = os_strdup(LOCAL_STR);
275         }
276         //type
277         piAllVariableTypes[i] = sci_lib;
278         pstAllVariableSizes[i] = os_strdup(N_A);
279         piAllVariableIntegerTypes[i] = -1;
280         pstAllVariableListTypes[i] = os_strdup("");
281         piAllVariableFromUser[i] = FALSE;
282         piAllVariableNbRows[i] = 1;
283         piAllVariableNbCols[i] = 1;
284         //get value and bytes
285         types::GenericType* pIT = sl->m_pLib;
286         int bytesWithoutOverHead;
287         pIT->getMemory(&bytesWithoutOverHead, &piAllVariableBytes[i]);
288
289         ++i;
290     }
291
292     // Launch Java Variable Browser through JNI
293     BrowseVar::setVariableBrowserData(getScilabJavaVM(),
294                                       pstAllVariableNames, iLocalVariablesUsed,
295                                       piAllVariableBytes, iLocalVariablesUsed,
296                                       piAllVariableTypes, iLocalVariablesUsed,
297                                       piAllVariableIntegerTypes, iLocalVariablesUsed,
298                                       pstAllVariableListTypes, iLocalVariablesUsed,
299                                       pstAllVariableSizes, iLocalVariablesUsed,
300                                       piAllVariableNbRows, iLocalVariablesUsed,
301                                       piAllVariableNbCols, iLocalVariablesUsed,
302                                       pstAllVariableVisibility, iLocalVariablesUsed,
303                                       piAllVariableFromUser, iLocalVariablesUsed);
304
305     for (int i = 0; i < iLocalVariablesUsed; ++i)
306     {
307         FREE(pstAllVariableNames[i]);
308         FREE(pstAllVariableVisibility[i]);
309         FREE(pstAllVariableSizes[i]);
310         FREE(pstAllVariableListTypes[i]);
311     }
312
313     delete[] pstAllVariableNames;
314     delete[] pstAllVariableVisibility;
315     delete[] pstAllVariableSizes;
316     delete[] pstAllVariableListTypes;
317
318     delete[] piAllVariableFromUser;
319     delete[] piAllVariableBytes;
320     delete[] piAllVariableTypes;
321     delete[] piAllVariableIntegerTypes;
322     delete[] piAllVariableNbRows;
323     delete[] piAllVariableNbCols;
324 }
325
326 /*--------------------------------------------------------------------------*/
327 static std::set<string> createScilabDefaultVariablesSet()
328 {
329     string arr[] =
330     {
331         "home",
332         "PWD",
333         "%tk",
334         "%pvm",
335         "MSDOS",
336         "%F",
337         "%T",
338         "%f",
339         "%t",
340         "%e",
341         "%pi",
342         "%modalWarning",
343         "%nan",
344         "%inf",
345         "SCI",
346         "WSCI",
347         "SCIHOME",
348         "TMPDIR",
349         "%gui",
350         "%fftw",
351         "%helps",
352         "%eps",
353         "%io",
354         "%i",
355         "demolist",
356         "%z",
357         "%s",
358         "$",
359         "%toolboxes",
360         "%toolboxes_dir",
361         "TICTOC",
362         "%helps_modules",
363         "%_atoms_cache",
364         "evoid", // Constant for external object
365         "jvoid", // Constant for external object Java (jims)
366         "jnull", // Constant for external object Java (jims)
367         "enull"  // Constant for external object
368     };
369     int i = 0;
370
371 #define NBELEMENT 37
372     std::set<string> ScilabDefaultVariables;
373
374     for (i = 0; i < NBELEMENT; i++)
375     {
376         ScilabDefaultVariables.insert(arr[i]);
377     }
378
379     return ScilabDefaultVariables;
380 }
381
382 static char * getListName(char * variableName)
383 {
384     SciErr sciErr;
385     int *piAddr = NULL;
386     int* piAddr1 = NULL;
387     int iRows = 0;
388     int iCols = 0;
389     char **pstType;
390     char *tmpChar;
391     sciErr = getVarAddressFromName(NULL, variableName, &piAddr);
392     if (sciErr.iErr)
393     {
394         return os_strdup("");
395     }
396
397     sciErr = getListItemAddress(NULL, piAddr, 1, &piAddr1);
398     if (sciErr.iErr)
399     {
400         return os_strdup("");
401     }
402
403     if (getAllocatedMatrixOfString(NULL, piAddr1, &iRows, &iCols, &pstType))
404     {
405
406         return os_strdup("");
407     }
408     tmpChar = os_strdup(pstType[0]);
409     freeAllocatedMatrixOfString(iRows, iCols, pstType);
410     return tmpChar;
411 }
412
413 static char *valueToDisplay(types::InternalType* pIT)
414 {
415     types::GenericType *pGT = pIT->getAs<types::GenericType>();
416     int *piDims = pGT->getDimsArray();
417
418     if (pIT->isDouble() && pGT->getDims() < 3 && pGT->getSize() <= 4)
419     {
420         // 4 is the dimension max to which display the content
421         types::Double* pD = pIT->getAs<types::Double>();
422         // Small double value, display it
423         double* pdblReal = nullptr;
424         double* pdblImg = nullptr;
425         pdblReal = pD->get();
426
427         if (pD->isComplex())
428         {
429             pdblImg = pD->getImg();
430         }
431
432         return os_strdup(formatMatrix(piDims[0], piDims[1], pdblReal, pdblImg).c_str());
433     }
434     else
435     {
436         std::string sizeStr = std::to_string(piDims[0]);
437         for (int i = 1; i < pGT->getDims(); i++)
438         {
439             sizeStr.append("x");
440             sizeStr.append(std::to_string(piDims[i]));
441         }
442
443         return os_strdup(sizeStr.data());
444     }
445 }
446
447 std::string addDouble(double dbl)
448 {
449 #define PRECISION_DISPLAY 3
450     std::ostringstream os;
451     if (ISNAN(dbl))
452     {
453         os << NAN_STR;
454     }
455     else if (finite(dbl))
456     {
457         os.precision(PRECISION_DISPLAY);
458         os << dbl; // Convert the double to string
459     }
460     else
461     {
462         if (dbl > 0)
463         {
464             os << INF_STR;
465         }
466         else
467         {
468             os << NEG_INF_STR;
469         }
470     }
471
472     return os.str();
473 }
474 std::string formatMatrix(int nbRows, int nbCols, double *pdblReal, double *pdblImg)
475 {
476     int i, j ;
477     if (nbRows * nbCols == 1)
478     {
479         std::ostringstream os;
480         std::string formatted = addDouble(pdblReal[0]);
481         if (pdblImg)
482         {
483             double img = pdblImg[0];
484             if (img > 0)
485             {
486                 formatted += PLUS_STR;
487             }
488             else
489             {
490                 formatted += MINUS_STR;
491             }
492             formatted += addDouble(std::fabs(img));
493             formatted += I_STR;
494         }
495         return formatted;
496     }
497
498     std::string formatted = LBRACKET_STR;
499     for (j = 0 ; j < nbRows ; j++)
500     {
501         for (i = 0 ; i < nbCols ; i++)
502         {
503             /* Display the formatted matrix ... the way the user
504              * expect */
505             formatted += addDouble(pdblReal[i * nbRows + j]);
506             if (pdblImg)
507             {
508                 double img = pdblImg[i * nbRows + j];
509                 if (img > 0)
510                 {
511                     formatted += PLUS_STR;
512                 }
513                 else
514                 {
515                     formatted += MINUS_STR;
516                 }
517
518                 formatted += addDouble(std::fabs(img));
519                 formatted += I_STR;
520             }
521
522
523             if (i + 1 != nbCols) // Not the last element of the matrix
524             {
525                 formatted += COMMA_STR;
526             }
527         }
528         if (j + 1 != nbRows) // Not the last line of the matrix
529         {
530             formatted += SEMICOLON_STR;
531         }
532     }
533     return formatted + "]";
534 }