display of some types and lines function fixed.
[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     // less the two "!" (or two " " in scalar case)
149     // for iLineLen = 50 we will write "!48char!"
150     int iStrMaxSize = iLineLen - 2;
151
152     if (isScalar())
153     {
154         int iMaxLen = 0;
155         _piDims[0]  = 0;
156         _piDims[1]  = 0;
157
158         int iPos = getIndex(_piDims);
159         wchar_t* wcsStr = get(iPos);
160         int iCurLen = wcslen(wcsStr);
161         iMaxLen = std::max(iMaxLen, iCurLen);
162         iMaxLen = std::min(iMaxLen, iStrMaxSize);
163
164         if (iCurLen > iMaxLen)
165         {
166             int iStrPos = 0;
167             while (iCurLen > iStrMaxSize)
168             {
169                 ostr << L" ";
170                 ostr.write(wcsStr + iStrPos, iStrMaxSize);
171                 ostr << L" " << std::endl;
172                 iCurLen -= iStrMaxSize;
173                 iStrPos += iStrMaxSize;
174             }
175
176             ostr << L" ";
177             configureStream(&ostr, iStrMaxSize, iPrecision, ' ');
178             ostr << left << wcsStr + iStrPos;
179         }
180         else
181         {
182             ostr << L" " << wcsStr << endl;
183         }
184     }
185     else if (getCols() == 1)
186     {
187         std::wstring spaces(L"");
188
189         // compte max string size
190         int iMaxLen = 0;
191         for (int i = 0 ; i < getRows() ; i++)
192         {
193             _piDims[1] = 0;
194             _piDims[0] = i;
195             int iPos = getIndex(_piDims);
196             iMaxLen = std::max(iMaxLen, static_cast<int>(wcslen(get(iPos))));
197             iMaxLen = std::min(iMaxLen, iStrMaxSize);
198         }
199
200         int iEmptyLineSize = iMaxLen;
201         if (iMaxLen != iStrMaxSize)
202         {
203             // count SPACE_BETWEEN_TWO_STRING_VALUES size in padding of empty line
204             // only if all lines have not a size greater than max size of a line.
205             iEmptyLineSize += SIZE_BETWEEN_TWO_STRING_VALUES;
206             spaces = SPACE_BETWEEN_TWO_STRING_VALUES;
207         }
208
209         for (int i = m_iRows1PrintState ; i < getRows() ; i++)
210         {
211             iCurrentLine += 2;
212             if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) || (iMaxLines != 0 && iCurrentLine >= iMaxLines))
213             {
214                 m_iRows1PrintState = i;
215                 return false;
216             }
217
218             _piDims[1] = 0;
219             _piDims[0] = i;
220             int iPos = getIndex(_piDims);
221             wchar_t* wcsStr = get(iPos);
222             int iCurLen = wcslen(wcsStr);
223
224             ostr << L"!";
225             if (iCurLen > iMaxLen)
226             {
227                 int iStrPos = 0;
228                 while (iCurLen > iStrMaxSize)
229                 {
230                     ostr.write(wcsStr + iStrPos, iStrMaxSize);
231                     ostr << L"!" << std::endl << L"!";
232                     iCurLen -= iStrMaxSize;
233                     iStrPos += iStrMaxSize;
234                 }
235
236                 configureStream(&ostr, iStrMaxSize, iPrecision, ' ');
237                 ostr << left << wcsStr + iStrPos;
238             }
239             else
240             {
241                 configureStream(&ostr, iMaxLen, iPrecision, ' ');
242                 ostr << left << wcsStr << spaces;
243             }
244
245             ostr << L"!" << endl;
246
247             if ((i + 1) < m_iSize)
248             {
249                 //for all but last one
250                 ostr << L"!";
251                 configureStream(&ostr, iEmptyLineSize, iPrecision, ' ');
252                 ostr << left << L" ";
253                 ostr << L"!" << endl;
254             }
255         }
256     }
257     else if (getRows() == 1)
258     {
259         wostringstream ostemp;
260         int iLastVal = m_iCols1PrintState;
261
262         for (int i = m_iCols1PrintState ; i < getCols() ; i++)
263         {
264             _piDims[0] = 0;
265             _piDims[1] = i;
266             int iPos = getIndex(_piDims);
267
268             int iLen = 0;
269             int iCurLen = static_cast<int>(wcslen(get(iPos)));
270             iLen = iCurLen + SIZE_BETWEEN_TWO_STRING_VALUES + static_cast<int>(ostemp.str().size());
271             if (iLen > iLineLen && iLastVal != i)
272             {
273                 //Max length, new line
274                 iCurrentLine += 4; //"column x to Y" + empty line + value + empty line
275                 if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) || (iMaxLines != 0 && iCurrentLine >= iMaxLines))
276                 {
277                     m_iCols1PrintState = iLastVal;
278                     return false;
279                 }
280
281                 addColumnString(ostr, iLastVal + 1, i);
282                 ostr << L"!" << ostemp.str() << L"!" << endl;
283                 ostemp.str(L"");
284                 iLastVal = i;
285             }
286
287             // Manage case where string length is greater than max line size.
288             if (iStrMaxSize < iCurLen)
289             {
290                 wchar_t* wcsStr = get(iPos);
291                 int iStrPos = 0;
292                 while (iCurLen > iStrMaxSize) // -2 because of two "!"
293                 {
294                     ostemp.write(wcsStr + iStrPos, iStrMaxSize);
295                     ostemp << L"!" << std::endl << L"!";
296                     iCurLen -= iStrMaxSize;
297                     iStrPos += iStrMaxSize;
298                 }
299
300                 configureStream(&ostemp, iStrMaxSize, iPrecision, ' ');
301                 ostemp << left << wcsStr + iStrPos;
302             }
303             else
304             {
305                 configureStream(&ostemp, iCurLen + 2, iPrecision, ' ');
306                 ostemp << left << get(iPos);
307             }
308         }
309
310         if (iLastVal != 0)
311         {
312             addColumnString(ostr, iLastVal + 1, getCols());
313         }
314
315         ostr << L"!" << ostemp.str() << L"!" << endl;
316     }
317     else //Matrix
318     {
319         wostringstream ostemp;
320         int iLen = 0;
321         int iLastCol = m_iCols1PrintState;
322
323         //Array with the max printed size of each col
324         int *piSize = new int[getCols()];
325         memset(piSize, 0x00, getCols() * sizeof(int));
326
327         for (int iCols1 = m_iCols1PrintState ; iCols1 < getCols() ; iCols1++)
328         {
329             std::wstring spaces(L"");
330             for (int iRows1 = 0 ; iRows1 < getRows() ; iRows1++)
331             {
332                 _piDims[1] = iCols1;
333                 _piDims[0] = iRows1;
334                 int iPos = getIndex(_piDims);
335                 piSize[iCols1] = std::max(piSize[iCols1], static_cast<int>(wcslen(get(iPos))));
336                 piSize[iCols1] = std::min(piSize[iCols1], iStrMaxSize);
337             }
338
339             int iEmptyLineSize = piSize[iLastCol];
340             if (piSize[iLastCol] != iStrMaxSize)
341             {
342                 // count SPACE_BETWEEN_TWO_STRING_VALUES size in padding of empty line
343                 // only if all lines have not a size greater than max size of a line.
344                 iEmptyLineSize += SIZE_BETWEEN_TWO_STRING_VALUES;
345                 spaces = SPACE_BETWEEN_TWO_STRING_VALUES;
346             }
347
348             if (iLen + piSize[iCols1] > iLineLen && iLastCol != iCols1)
349             {
350                 //find the limit, print this part
351                 for (int iRows2 = m_iRows2PrintState ; iRows2 < getRows() ; iRows2++)
352                 {
353                     iCurrentLine += 2;
354                     if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) ||
355                             ( (iMaxLines != 0 && iCurrentLine + 3 >= iMaxLines && iRows2 == m_iRows2PrintState) ||
356                               (iMaxLines != 0 && iCurrentLine + 1 >= iMaxLines && iRows2 != m_iRows2PrintState)))
357                     {
358                         if (m_iRows2PrintState == 0 && iRows2 != 0)
359                         {
360                             //add header
361                             addColumnString(ostr, iLastCol + 1, iCols1);
362                         }
363                         ostr << ostemp.str();
364                         m_iRows2PrintState = iRows2;
365                         m_iCols1PrintState = iLastCol;
366                         return false;
367                     }
368
369                     ostemp << L"!";
370                     for (int iCols2 = iLastCol; iCols2 < iCols1; iCols2++)
371                     {
372                         _piDims[0] = iRows2;
373                         _piDims[1] = iCols2;
374                         int iPos = getIndex(_piDims);
375                         wchar_t* wcsStr = get(iPos);
376                         int iLenStr = wcslen(wcsStr);
377
378                         // Manage case where string length is greater than max line size.
379                         if (iLenStr > iStrMaxSize)
380                         {
381                             int iStrPos = 0;
382                             while (iLenStr > iStrMaxSize)
383                             {
384                                 ostemp.write(wcsStr + iStrPos, iStrMaxSize);
385                                 ostemp << L"!" << std::endl << L"!";
386                                 iLenStr -= iStrMaxSize;
387                                 iStrPos += iStrMaxSize;
388                             }
389
390                             configureStream(&ostemp, iStrMaxSize, iPrecision, ' ');
391                             ostemp << left << wcsStr + iStrPos;
392                         }
393                         else
394                         {
395                             configureStream(&ostemp, piSize[iCols2], iPrecision, ' ');
396                             ostemp << left << get(iPos) << spaces;
397                         }
398                     }
399                     ostemp << L"!" << endl;
400
401                     if ((iRows2 + 1) != m_iRows)
402                     {
403                         ostemp << L"!";
404                         // -2 because of two "!"
405                         configureStream(&ostemp, iEmptyLineSize, iPrecision, ' ');
406                         ostemp << left << L" ";
407                         ostemp << L"!" << endl;
408                     }
409                 }
410
411                 iLen = 0;
412                 iCurrentLine += 2;
413                 if (m_iRows2PrintState == 0)
414                 {
415                     iCurrentLine += 3;
416                     addColumnString(ostr, iLastCol + 1, iCols1);
417                 }
418
419                 ostr << ostemp.str();
420                 ostemp.str(L"");
421                 iLastCol = iCols1;
422                 m_iRows2PrintState = 0;
423                 m_iCols1PrintState = 0;
424             }
425             iLen += piSize[iCols1] + SIZE_BETWEEN_TWO_STRING_VALUES;
426         }
427
428         for (int iRows2 = m_iRows2PrintState ; iRows2 < getRows() ; iRows2++)
429         {
430             std::wstring spaces(L"");
431             iCurrentLine += 2;
432             if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) || (iMaxLines != 0 && iCurrentLine >= iMaxLines))
433             {
434                 if (m_iRows2PrintState == 0 && iLastCol != 0)
435                 {
436                     //add header
437                     addColumnString(ostr, iLastCol + 1, getCols());
438                 }
439
440                 ostr << ostemp.str();
441                 m_iRows2PrintState = iRows2;
442                 m_iCols1PrintState = iLastCol;
443                 return false;
444             }
445
446             int iEmptyLineSize = piSize[iLastCol];
447             if (piSize[iLastCol] != iStrMaxSize)
448             {
449                 // count SPACE_BETWEEN_TWO_STRING_VALUES size in padding of empty line
450                 // only if all lines have not a size greater than max size of a line.
451                 iEmptyLineSize += SIZE_BETWEEN_TWO_STRING_VALUES;
452                 spaces = SPACE_BETWEEN_TWO_STRING_VALUES;
453             }
454
455
456             ostemp << L"!";
457             iLen = 0;
458             for (int iCols2 = iLastCol ; iCols2 < getCols() ; iCols2++)
459             {
460                 _piDims[0] = iRows2;
461                 _piDims[1] = iCols2;
462                 int iPos = getIndex(_piDims);
463                 wchar_t* wcsStr = get(iPos);
464                 int iLenStr = wcslen(wcsStr);
465
466                 // Manage case where string length is greater than max line size.
467                 if (iStrMaxSize < iLenStr)
468                 {
469                     int iStrPos = 0;
470                     while (iLenStr > iStrMaxSize)
471                     {
472                         ostemp.write(wcsStr + iStrPos, iStrMaxSize);
473                         ostemp << L"!" << std::endl << L"!";
474                         iLenStr -= iStrMaxSize;
475                         iStrPos += iStrMaxSize;
476                     }
477
478                     configureStream(&ostemp, iStrMaxSize, iPrecision, ' ');
479                     ostemp << wcsStr + iStrPos << left;
480                     iLen = iStrMaxSize;
481                 }
482                 else
483                 {
484                     configureStream(&ostemp, piSize[iCols2], iPrecision, ' ');
485                     ostemp << left << get(iPos) << spaces;
486                     iLen += piSize[iCols2] + spaces.size();
487                 }
488             }
489             ostemp << L"!" << endl;
490
491             if ((iRows2 + 1) != m_iRows)
492             {
493                 ostemp << L"!";
494                 configureStream(&ostemp, iLen, iPrecision, ' ');
495                 ostemp << left << L" ";
496                 ostemp << L"!" << endl;
497             }
498         }
499
500         if (m_iRows2PrintState == 0 && iLastCol != 0)
501         {
502             addColumnString(ostr, iLastCol + 1, getCols());
503         }
504         ostr << ostemp.str();
505     }
506
507     return true;
508 }
509
510 bool String::operator==(const InternalType& it)
511 {
512     if (const_cast<InternalType&>(it).isString() == false)
513     {
514         return false;
515     }
516
517     String* pS = const_cast<InternalType&>(it).getAs<types::String>();
518
519     if (pS->getRows() != getRows() || pS->getCols() != getCols())
520     {
521         return false;
522     }
523
524     wchar_t **p1 = get();
525     wchar_t **p2 = pS->get();
526
527     for (int i = 0 ; i < getSize() ; i++)
528     {
529         if (wcscmp(p1[i], p2[i]) != 0)
530         {
531             return false;
532         }
533     }
534     return true;
535 }
536
537 bool String::operator!=(const InternalType& it)
538 {
539     return !(*this == it);
540 }
541
542 wchar_t* String::getNullValue()
543 {
544     return os_wcsdup(L"");
545 }
546
547 String* String::createEmpty(int _iDims, int* _piDims, bool /*_bComplex*/)
548 {
549     return new String(_iDims, _piDims);
550 }
551
552 wchar_t* String::copyValue(wchar_t* _pwstData)
553 {
554     return os_wcsdup(_pwstData);
555 }
556
557 wchar_t* String::copyValue(const wchar_t* _pwstData)
558 {
559     return os_wcsdup(_pwstData);
560 }
561
562 bool String::set(int _iPos, const wchar_t* _pwstData)
563 {
564     if (m_pRealData == NULL || _iPos >= m_iSize)
565     {
566         return false;
567     }
568     m_pRealData[_iPos] = copyValue(_pwstData);
569     return true;
570 }
571
572 bool String::set(int _iRows, int _iCols, const wchar_t* _pwstData)
573 {
574     int piIndexes[2] = {_iRows, _iCols};
575     return set(getIndex(piIndexes), _pwstData);
576 }
577
578 bool String::set(const wchar_t* const* _pwstData)
579 {
580     if (m_pRealData == NULL)
581     {
582         return false;
583     }
584
585     for (int i = 0 ; i < getSize() ; i++)
586     {
587         if (set(i, _pwstData[i]) == false)
588         {
589             return false;
590         }
591     }
592     return true;
593 }
594
595 bool String::set(int _iPos, const char* _pcData)
596 {
597     if (m_pRealData == NULL || _iPos >= m_iSize)
598     {
599         return false;
600     }
601     m_pRealData[_iPos] = to_wide_string(_pcData);
602     return true;
603 }
604
605 bool String::set(int _iRows, int _iCols, const char* _pcData)
606 {
607     int piIndexes[2] = {_iRows, _iCols};
608     return set(getIndex(piIndexes), _pcData);
609 }
610
611 bool String::set(const char* const* _pstrData)
612 {
613     if (m_pRealData == NULL)
614     {
615         return false;
616     }
617
618     for (int i = 0 ; i < getSize() ; i++)
619     {
620         if (set(i, _pstrData[i]) == false)
621         {
622             return false;
623         }
624     }
625     return true;
626 }
627
628 wchar_t** String::allocData(int _iSize)
629 {
630     wchar_t** pStr = new wchar_t*[_iSize];
631     memset(pStr, 0x00, _iSize * sizeof(wchar_t*));
632     return pStr;
633 }
634
635 ast::Exp* String::getExp(const Location& loc)
636 {
637     return new ast::StringExp(loc, this);
638 }
639
640 }
641