3909143c0fa5c35bf844a98c05c1040f362062b9
[scilab.git] / scilab / modules / ast / src / cpp / types / string.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2008-2008 - DIGITEO - 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-en.txt
10 *
11 */
12
13 #include <sstream>
14 #include "core_math.h"
15 #include "string.hxx"
16 #include "stringexp.hxx"
17 #include "tostring_common.hxx"
18 #include "configvariable.hxx"
19
20 extern "C"
21 {
22 #include "charEncoding.h"
23 #include "os_wcsdup.h"
24 #include "sci_malloc.h"
25 }
26
27 using namespace std;
28
29 #define SIZE_BETWEEN_TWO_STRING_VALUES  2
30 #define SPACE_BETWEEN_TWO_STRING_VALUES L"  "
31
32 namespace types
33 {
34 String::~String()
35 {
36     if (isDeletable() == true)
37     {
38         deleteAll();
39     }
40 #ifndef NDEBUG
41     Inspector::removeItem(this);
42 #endif
43 }
44
45 String::String(int _iDims, int* _piDims)
46 {
47     wchar_t** pwsData = NULL;
48     create(_piDims, _iDims, &pwsData, NULL);
49 #ifndef NDEBUG
50     Inspector::addItem(this);
51 #endif
52 }
53
54 String::String(const wchar_t* _pwstData)
55 {
56     wchar_t** pwsData = NULL;
57     int piDims[] = {1, 1};
58     create(piDims, 2, &pwsData, NULL);
59     set(0, 0, _pwstData);
60 #ifndef NDEBUG
61     Inspector::addItem(this);
62 #endif
63 }
64
65 String::String(const char *_pstData)
66 {
67     wchar_t** pwsData = NULL;
68     int piDims[] = {1, 1};
69     create(piDims, 2, &pwsData, NULL);
70     wchar_t* data = to_wide_string(const_cast<char*>(_pstData));
71     set(0, 0, data);
72     FREE(data);
73 #ifndef NDEBUG
74     Inspector::addItem(this);
75 #endif
76 }
77
78 String::String(int _iRows, int _iCols)
79 {
80     wchar_t** pwsData = NULL;
81     int piDims[] = {_iRows, _iCols};
82     create(piDims, 2, &pwsData, NULL);
83 #ifndef NDEBUG
84     Inspector::addItem(this);
85 #endif
86 }
87
88 String::String(int _iRows, int _iCols, wchar_t const* const* _pstData)
89 {
90     wchar_t** pwsData = NULL;
91     int piDims[] = {_iRows, _iCols};
92     create(piDims, 2, &pwsData, NULL);
93     for (int i = 0 ; i < m_iSize ; i++)
94     {
95         set(i, os_wcsdup(_pstData[i]));
96     }
97 #ifndef NDEBUG
98     Inspector::addItem(this);
99 #endif
100 }
101
102 InternalType* String::clone()
103 {
104     String *pstClone = new String(getDims(), getDimsArray());
105     pstClone->set(m_pRealData);
106     return pstClone;
107 }
108
109 void String::whoAmI()
110 {
111     cout << "types::String";
112 }
113
114 void String::deleteString(int _iPos)
115 {
116     if (m_pRealData != NULL)
117     {
118         if (m_pRealData[_iPos] != NULL)
119         {
120             FREE(m_pRealData[_iPos]);
121             m_pRealData[_iPos] = NULL;
122         }
123     }
124 }
125
126 void String::deleteAll()
127 {
128     for (int i = 0 ; i < getSize() ; i++)
129     {
130         deleteString(i);
131     }
132     delete[] m_pRealData;
133     m_pRealData = NULL;
134 }
135
136 void String::deleteImg()
137 {
138     return;
139 }
140
141 bool String::subMatrixToString(wostringstream& ostr, int* _piDims, int /*_iDims*/)
142 {
143     int iPrecision = ConfigVariable::getFormatSize();
144     int iLineLen = ConfigVariable::getConsoleWidth();
145     int iMaxLines = ConfigVariable::getConsoleLines();
146     int iCurrentLine = 0;
147
148     if (isScalar())
149     {
150         _piDims[0] = 0;
151         _piDims[1] = 0;
152         int iPos = getIndex(_piDims);
153         ostr << L" " << get(iPos) << endl;
154     }
155     else if (getCols() == 1)
156     {
157         int iMaxLen = 0;
158         for (int i = 0 ; i < getRows() ; i++)
159         {
160             _piDims[1] = 0;
161             _piDims[0] = i;
162             int iPos = getIndex(_piDims);
163             iMaxLen = std::max(iMaxLen, static_cast<int>(wcslen(get(iPos))));
164         }
165
166         iMaxLen += 2;
167
168         for (int i = m_iRows1PrintState ; i < getRows() ; i++)
169         {
170             iCurrentLine += 2;
171             if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) || (iMaxLines != 0 && iCurrentLine >= iMaxLines))
172             {
173                 m_iRows1PrintState = i;
174                 return false;
175             }
176
177             _piDims[1] = 0;
178             _piDims[0] = i;
179             int iPos = getIndex(_piDims);
180
181             ostr << L"!";
182             configureStream(&ostr, iMaxLen, iPrecision, ' ');
183             ostr << left << get(iPos);
184             ostr << L"!" << endl;
185             if ((i + 1) < m_iSize)
186             {
187                 //for all but last one
188                 ostr << L"!";
189                 configureStream(&ostr, iMaxLen, iPrecision, ' ');
190                 ostr << left << L" ";
191                 ostr << L"!" << endl;
192             }
193         }
194     }
195     else if (getRows() == 1)
196     {
197         wostringstream ostemp;
198         int iLastVal = m_iCols1PrintState;
199
200         for (int i = m_iCols1PrintState ; i < getCols() ; i++)
201         {
202             _piDims[0] = 0;
203             _piDims[1] = i;
204             int iPos = getIndex(_piDims);
205
206             int iLen = 0;
207             int iCurLen = static_cast<int>(wcslen(get(iPos)));
208             iLen = iCurLen + SIZE_BETWEEN_TWO_STRING_VALUES + static_cast<int>(ostemp.str().size());
209             if (iLen > iLineLen)
210             {
211                 //Max length, new line
212                 iCurrentLine += 4; //"column x to Y" + empty line + value + empty line
213                 if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) || (iMaxLines != 0 && iCurrentLine >= iMaxLines))
214                 {
215                     m_iCols1PrintState = iLastVal;
216                     return false;
217                 }
218
219                 ostr << endl << L"       column " << iLastVal + 1 << L" to " << i << endl << endl;
220                 ostr << L"!" << ostemp.str() << L"!" << endl;
221                 ostemp.str(L"");
222                 iLastVal = i;
223             }
224
225             configureStream(&ostemp, iCurLen + 2, iPrecision, ' ');
226             ostemp << left << get(iPos);
227         }
228
229         if (iLastVal != 0)
230         {
231             ostr << endl << L"       column " << iLastVal + 1 << L" to " << getCols() << endl << endl;
232         }
233         ostr << L"!" << ostemp.str() << L"!" << endl;
234     }
235     else //Matrix
236     {
237         wostringstream ostemp;
238         int iLen = 0;
239         int iLastCol = m_iCols1PrintState;
240
241         //Array with the max printed size of each col
242         int *piSize = new int[getCols()];
243         memset(piSize, 0x00, getCols() * sizeof(int));
244
245         for (int iCols1 = m_iCols1PrintState ; iCols1 < getCols() ; iCols1++)
246         {
247             for (int iRows1 = 0 ; iRows1 < getRows() ; iRows1++)
248             {
249                 _piDims[1] = iCols1;
250                 _piDims[0] = iRows1;
251                 int iPos = getIndex(_piDims);
252                 piSize[iCols1] = std::max(piSize[iCols1], static_cast<int>(wcslen(get(iPos))));
253             }
254
255             if (iLen + piSize[iCols1] > iLineLen)
256             {
257                 //find the limit, print this part
258                 for (int iRows2 = m_iRows2PrintState ; iRows2 < getRows() ; iRows2++)
259                 {
260                     iCurrentLine += 2;
261                     if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) ||
262                             ( (iMaxLines != 0 && iCurrentLine + 3 >= iMaxLines && iRows2 == m_iRows2PrintState) ||
263                               (iMaxLines != 0 && iCurrentLine + 1 >= iMaxLines && iRows2 != m_iRows2PrintState)))
264                     {
265                         if (m_iRows2PrintState == 0 && iRows2 != 0)
266                         {
267                             //add header
268                             ostr << std::endl << L"       column " << iLastCol + 1 << L" to " << iCols1 << std::endl << std::endl;
269                         }
270                         ostr << ostemp.str();
271                         m_iRows2PrintState = iRows2;
272                         m_iCols1PrintState = iLastCol;
273                         return false;
274                     }
275
276                     ostemp << L"!";
277                     for (int iCols2 = iLastCol ; iCols2 < iCols1 ; iCols2++)
278                     {
279                         _piDims[0] = iRows2;
280                         _piDims[1] = iCols2;
281                         int iPos = getIndex(_piDims);
282                         configureStream(&ostemp, piSize[iCols2], iPrecision, ' ');
283                         ostemp << left << get(iPos) << SPACE_BETWEEN_TWO_STRING_VALUES;
284                     }
285
286                     ostemp << L"!" << endl;
287                     if ((iRows2 + 1) != m_iRows)
288                     {
289                         ostemp << L"!";
290                         configureStream(&ostemp, iLen, iPrecision, ' ');
291                         ostemp << left << L" ";
292                         ostemp << L"!" << endl;
293                     }
294                 }
295
296                 iLen = 0;
297                 iCurrentLine += 2;
298                 if (m_iRows2PrintState == 0)
299                 {
300                     iCurrentLine += 3;
301                     ostr << std::endl << L"       column " << iLastCol + 1 << L" to " << iCols1 << std::endl << std::endl;
302                 }
303                 ostr << ostemp.str();
304                 ostemp.str(L"");
305                 iLastCol = iCols1;
306                 m_iRows2PrintState = 0;
307                 m_iCols1PrintState = 0;
308             }
309             iLen += piSize[iCols1] + SIZE_BETWEEN_TWO_STRING_VALUES;
310         }
311
312         for (int iRows2 = m_iRows2PrintState ; iRows2 < getRows() ; iRows2++)
313         {
314             iCurrentLine += 2;
315             if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) || (iMaxLines != 0 && iCurrentLine >= iMaxLines))
316             {
317                 if (m_iRows2PrintState == 0 && iLastCol != 0)
318                 {
319                     //add header
320                     ostr << std::endl << L"       column " << iLastCol + 1 << L" to " << getCols() << std::endl << std::endl;
321                 }
322
323                 ostr << ostemp.str();
324                 m_iRows2PrintState = iRows2;
325                 m_iCols1PrintState = iLastCol;
326                 return false;
327             }
328
329             ostemp << L"!";
330             iLen = 0;
331             for (int iCols2 = iLastCol ; iCols2 < getCols() ; iCols2++)
332             {
333                 _piDims[0] = iRows2;
334                 _piDims[1] = iCols2;
335                 int iPos = getIndex(_piDims);
336
337                 configureStream(&ostemp, piSize[iCols2], iPrecision, ' ');
338                 ostemp << left << get(iPos) << SPACE_BETWEEN_TWO_STRING_VALUES;
339                 iLen += piSize[iCols2] + SIZE_BETWEEN_TWO_STRING_VALUES;
340             }
341             ostemp << L"!" << endl;
342             if ((iRows2 + 1) != m_iRows)
343             {
344                 ostemp << L"!";
345                 configureStream(&ostemp, iLen, iPrecision, ' ');
346                 ostemp << left << L" ";
347                 ostemp << L"!" << endl;
348             }
349         }
350
351         if (m_iRows2PrintState == 0 && iLastCol != 0)
352         {
353             ostr << std::endl << L"       column " << iLastCol + 1 << L" to " << getCols() << std::endl << std::endl;
354         }
355         ostr << ostemp.str();
356     }
357
358     return true;
359 }
360
361 bool String::operator==(const InternalType& it)
362 {
363     if (const_cast<InternalType&>(it).isString() == false)
364     {
365         return false;
366     }
367
368     String* pS = const_cast<InternalType&>(it).getAs<types::String>();
369
370     if (pS->getRows() != getRows() || pS->getCols() != getCols())
371     {
372         return false;
373     }
374
375     wchar_t **p1 = get();
376     wchar_t **p2 = pS->get();
377
378     for (int i = 0 ; i < getSize() ; i++)
379     {
380         if (wcscmp(p1[i], p2[i]) != 0)
381         {
382             return false;
383         }
384     }
385     return true;
386 }
387
388 bool String::operator!=(const InternalType& it)
389 {
390     return !(*this == it);
391 }
392
393 wchar_t* String::getNullValue()
394 {
395     return os_wcsdup(L"");
396 }
397
398 String* String::createEmpty(int _iDims, int* _piDims, bool /*_bComplex*/)
399 {
400     return new String(_iDims, _piDims);
401 }
402
403 wchar_t* String::copyValue(wchar_t* _pwstData)
404 {
405     return os_wcsdup(_pwstData);
406 }
407
408 wchar_t* String::copyValue(const wchar_t* _pwstData)
409 {
410     return os_wcsdup(_pwstData);
411 }
412
413 bool String::set(int _iPos, const wchar_t* _pwstData)
414 {
415     if (m_pRealData == NULL || _iPos >= m_iSize)
416     {
417         return false;
418     }
419     m_pRealData[_iPos] = copyValue(_pwstData);
420     return true;
421 }
422
423 bool String::set(int _iRows, int _iCols, const wchar_t* _pwstData)
424 {
425     int piIndexes[2] = {_iRows, _iCols};
426     return set(getIndex(piIndexes), _pwstData);
427 }
428
429 bool String::set(const wchar_t* const* _pwstData)
430 {
431     if (m_pRealData == NULL)
432     {
433         return false;
434     }
435
436     for (int i = 0 ; i < getSize() ; i++)
437     {
438         if (set(i, _pwstData[i]) == false)
439         {
440             return false;
441         }
442     }
443     return true;
444 }
445
446 bool String::set(int _iPos, const char* _pcData)
447 {
448     if (m_pRealData == NULL || _iPos >= m_iSize)
449     {
450         return false;
451     }
452     m_pRealData[_iPos] = to_wide_string(_pcData);
453     return true;
454 }
455
456 bool String::set(int _iRows, int _iCols, const char* _pcData)
457 {
458     int piIndexes[2] = {_iRows, _iCols};
459     return set(getIndex(piIndexes), _pcData);
460 }
461
462 bool String::set(const char* const* _pstrData)
463 {
464     if (m_pRealData == NULL)
465     {
466         return false;
467     }
468
469     for (int i = 0 ; i < getSize() ; i++)
470     {
471         if (set(i, _pstrData[i]) == false)
472         {
473             return false;
474         }
475     }
476     return true;
477 }
478
479 wchar_t** String::allocData(int _iSize)
480 {
481     wchar_t** pStr = new wchar_t*[_iSize];
482     memset(pStr, 0x00, _iSize * sizeof(wchar_t*));
483     return pStr;
484 }
485
486 ast::Exp* String::getExp(const Location& loc)
487 {
488     return new ast::StringExp(loc, this);
489 }
490
491 }
492