* Bug 16365 fixed: median(m,'r'|'c') was wrong after 5dc990
[scilab.git] / scilab / modules / string / sci_gateway / cpp / sci_strcat.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) INRIA - Allan CORNET , Cong WU
4 * Copyright (C) DIGITEO - 2010 - Allan CORNET
5 * Copyright (C) 2010 - DIGITEO - Antoine ELIAS
6 *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15 *
16 */
17
18 /* desc : concatenate character strings                                   */
19 /* Examples: strcat(string(1:10),',')                                     */
20 /*                                                                        */
21 /*------------------------------------------------------------------------*/
22
23 #include "string_gw.hxx"
24 #include "function.hxx"
25 #include "string.hxx"
26 #include "double.hxx"
27
28 extern "C"
29 {
30 #include <string.h>
31 #include <stdio.h>
32 #include "sci_malloc.h"
33 #include "Scierror.h"
34 #include "localization.h"
35 }
36 /*-------------------------------------------------------------------------------------*/
37 #define STAR '*'
38 #define COL 'c'
39 #define ROW 'r'
40 #define ONE_CHAR 1
41 #define EMPTY_CHAR ""
42 /*-------------------------------------------------------------------------------------*/
43 static int sci_strcat_three_rhs(char *fname);
44 static int sci_strcat_two_rhs(char *fname);
45 static int sci_strcat_one_rhs(char *fname);
46 static int sci_strcat_rhs_one_is_a_matrix(char *fname);
47 static int sumlengthstring(int rhspos);
48 static int *lengthEachString(int rhspos, int *sizeArrayReturned);
49 /*-------------------------------------------------------------------------------------*/
50 types::Function::ReturnValue sci_strcat(types::typed_list &in, int _iRetCount, types::typed_list &out)
51 {
52     int iMode               = 0;
53     wchar_t* pwstToInsert   = NULL;
54
55     //check input paramters
56     if (in.size() < 1 || in.size() > 3)
57     {
58         Scierror(999, _("%s: Wrong number of input arguments: %d or %d expected.\n"), "strcat", 1, 3);
59         return types::Function::Error;
60     }
61
62     for (int i = 1 ; i < in.size() ; i++)
63     {
64         if (in[i]->isString() == false)
65         {
66             Scierror(999, _("%s: Wrong type for input argument #%d: Matrix of strings expected.\n"), "strcat", i + 1);
67             return types::Function::Error;
68         }
69     }
70
71     if (in[0]->isDouble() && in[0]->getAs<types::Double>()->isEmpty())
72     {
73         out.push_back(types::Double::Empty());
74         return types::Function::OK;
75     }
76     else if (in[0]->isString() == false)
77     {
78         Scierror(999, _("%s: Wrong type for input argument #%d: String expected.\n"), "strcat", 1);
79         return types::Function::Error;
80     }
81
82     if (in.size() == 3)
83     {
84         wchar_t wcMode = in[2]->getAs<types::String>()->get(0)[0];
85         switch (wcMode)
86         {
87             case L'r' :
88                 iMode = 1;
89                 break;
90             case L'c' :
91                 iMode = 2;
92                 break;
93             default :
94                 Scierror(999, _("%s: Wrong type for input argument #%d: '%s' or '%s' expected.\n"), "strcat", 3, "c", "r");
95                 return types::Function::Error;
96         }
97     }
98
99     if (in.size() > 1)
100     {
101         if (in[1]->getAs<types::String>()->getSize() != 1)
102         {
103             Scierror(999, _("%s: Wrong type for input argument #%d: String expected.\n"), "strcat", 2);
104             return types::Function::Error;
105         }
106
107         pwstToInsert = in[1]->getAs<types::String>()->get(0);
108     }
109
110     types::String* pS = in[0]->getAs<types::String>();
111
112     types::String* pOut = NULL;
113     switch (iMode)
114     {
115         case 0 : //"*"
116         {
117             pOut = new types::String(1, 1);
118
119             int size = pS->getSize();
120             wchar_t** s = pS->get();
121
122             int insertLen = 0;
123             if (pwstToInsert)
124             {
125                 insertLen = (int)wcslen(pwstToInsert);
126             }
127
128             /*compute final size*/
129             int iLen = 1; //L'\0'
130             for (int i = 0 ; i < size ; i++)
131             {
132                 iLen += (int)wcslen(s[i]);
133             }
134
135             if (pwstToInsert != NULL)
136             {
137                 iLen += insertLen * (size - 1);
138             }
139
140             wchar_t* pwstOut = (wchar_t*)MALLOC(sizeof(wchar_t) * iLen);
141             pwstOut[0] = L'\0';
142
143             wcscpy(pwstOut, s[0]);
144             if (pwstToInsert)
145             {
146                 for (int i = 1; i < size; ++i)
147                 {
148                     wcscat(pwstOut, pwstToInsert);
149                     wcscat(pwstOut, s[i]);
150                 }
151             }
152             else
153             {
154                 for (int i = 1; i < size; ++i)
155                 {
156                     wcscat(pwstOut, s[i]);
157                 }
158             }
159
160             pOut->set(0, pwstOut);
161             FREE(pwstOut);
162         }
163         break;
164         case 1 : //"r"
165         {
166             wchar_t** s = pS->get();
167             int cols = pS->getCols();
168             int rows = pS->getRows();
169
170             pOut = new types::String(1, cols);
171
172             int insertLen = 0;
173             if (pwstToInsert)
174             {
175                 insertLen = (int)wcslen(pwstToInsert);
176             }
177             
178             /*compute final size*/
179             for (int i = 0 ; i < cols ; ++i)
180             {
181                 int iLen = 1; //L'\0'
182                 for (int j = 0 ; j < rows; ++j)
183                 {
184                     iLen += (int)wcslen(s[i * rows + j]);
185                 }
186
187                 if (pwstToInsert != NULL)
188                 {
189                     iLen += insertLen * (rows - 1);
190                 }
191
192                 wchar_t* pwstOut = (wchar_t*)MALLOC(sizeof(wchar_t) * iLen);
193                 pwstOut[0] = L'\0';
194
195                 wcscpy(pwstOut, s[i * rows]);
196                 if (pwstToInsert)
197                 {
198                     for (int j = 1; j < rows; ++j)
199                     {
200                         wcscat(pwstOut, pwstToInsert);
201                         wcscat(pwstOut, s[i * rows + j]);
202                     }
203                 }
204                 else
205                 {
206                     for (int j = 1; j < rows; ++j)
207                     {
208                         wcscat(pwstOut, s[i * rows + j]);
209                     }
210                 }
211
212                 pOut->set(0, i, pwstOut);
213                 FREE(pwstOut);
214             }
215             break;
216         }
217         case 2 : //"c"
218         {
219             wchar_t** s = pS->get();
220             int cols = pS->getCols();
221             int rows = pS->getRows();
222
223             pOut = new types::String(rows, 1);
224
225             int insertLen = 0;
226             if (pwstToInsert)
227             {
228                 insertLen = (int)wcslen(pwstToInsert);
229             }
230
231             /*compute final size*/
232             for (int i = 0 ; i < rows ; ++i)
233             {
234                 int iLen = 1; //L'\0'
235                 for (int j = 0 ; j < cols ; ++j)
236                 {
237                     iLen += (int)wcslen(s[j * rows + i]);
238                 }
239
240                 if (pwstToInsert != NULL)
241                 {
242                     iLen += insertLen * (cols - 1);
243                 }
244
245                 wchar_t* pwstOut = (wchar_t*)MALLOC(sizeof(wchar_t) * iLen);
246                 pwstOut[0] = L'\0';
247
248                 wcscpy(pwstOut, s[i]);
249                 if (pwstToInsert)
250                 {
251                     for (int j = 1; j < cols; ++j)
252                     {
253                         wcscat(pwstOut, pwstToInsert);
254                         wcscat(pwstOut, s[j * rows + i]);
255                     }
256                 }
257                 else
258                 {
259                     for (int j = 1; j < cols; ++j)
260                     {
261                         wcscat(pwstOut, s[j * rows + i]);
262                     }
263                 }
264
265                 pOut->set(i, 0, pwstOut);
266                 FREE(pwstOut);
267             }
268             break;
269         }
270     }
271
272     out.push_back(pOut);
273     return types::Function::OK;
274 }
275 /*-------------------------------------------------------------------------------------*/