a69979690fb7036b6b374ec9d13843ed6748bdad
[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 * This file must be used under the terms of the CeCILL.
8 * This source file is licensed as described in the file COPYING, which
9 * you should have received as part of this distribution.  The terms
10 * are also available at
11 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
12 *
13 */
14
15 /* desc : concatenate character strings                                   */
16 /* Examples: strcat(string(1:10),',')                                     */
17 /*                                                                        */
18 /*------------------------------------------------------------------------*/
19
20 #include "string_gw.hxx"
21 #include "function.hxx"
22 #include "string.hxx"
23 #include "double.hxx"
24
25 extern "C"
26 {
27 #include <string.h>
28 #include <stdio.h>
29 #include "sci_malloc.h"
30 #include "Scierror.h"
31 #include "localization.h"
32 }
33 /*-------------------------------------------------------------------------------------*/
34 #define STAR '*'
35 #define COL 'c'
36 #define ROW 'r'
37 #define ONE_CHAR 1
38 #define EMPTY_CHAR ""
39 /*-------------------------------------------------------------------------------------*/
40 static int sci_strcat_three_rhs(char *fname);
41 static int sci_strcat_two_rhs(char *fname);
42 static int sci_strcat_one_rhs(char *fname);
43 static int sci_strcat_rhs_one_is_a_matrix(char *fname);
44 static int sumlengthstring(int rhspos);
45 static int *lengthEachString(int rhspos, int *sizeArrayReturned);
46 /*-------------------------------------------------------------------------------------*/
47 types::Function::ReturnValue sci_strcat(types::typed_list &in, int _iRetCount, types::typed_list &out)
48 {
49     int iMode = 0;
50     char* pstToInsert = NULL;
51
52     //check input paramters
53     if (in.size() < 1 || in.size() > 3)
54     {
55         Scierror(999, _("%s: Wrong number of input arguments: %d or %d expected.\n"), "strcat", 1, 3);
56         return types::Function::Error;
57     }
58
59     for (int i = 1 ; i < in.size() ; i++)
60     {
61         if (in[i]->isString() == false)
62         {
63             Scierror(999, _("%s: Wrong type for input argument #%d: Matrix of strings expected.\n"), "strcat", i + 1);
64             return types::Function::Error;
65         }
66     }
67
68     if (in[0]->isDouble() && in[0]->getAs<types::Double>()->getSize() == 0)
69     {
70         types::String *pOut = new types::String(1, 1);
71         pOut->set(0, "");
72         out.push_back(pOut);
73         return types::Function::OK;
74     }
75     else if (in[0]->isString() == false)
76     {
77         Scierror(999, _("%s: Wrong type for input argument #%d: String expected.\n"), "strcat", 1);
78         return types::Function::Error;
79     }
80
81     if (in.size() == 3)
82     {
83         wchar_t wcMode = in[2]->getAs<types::String>()->get(0)[0];
84         switch (wcMode)
85         {
86             case L'r' :
87                 iMode = 1;
88                 break;
89             case L'c' :
90                 iMode = 2;
91                 break;
92             default :
93                 Scierror(999, _("%s: Wrong type for input argument #%d: ''%s'' or ''%s'' expected.\n"), "strcat", 3, "c", "r");
94                 return types::Function::Error;
95         }
96     }
97
98     if (in.size() > 1)
99     {
100         if (in[1]->getAs<types::String>()->getSize() != 1)
101         {
102             Scierror(999, _("%s: Wrong type for input argument #%d: String expected.\n"), "strcat", 2);
103             return types::Function::Error;
104         }
105
106         pstToInsert = in[1]->getAs<types::String>()->get(0);
107     }
108
109     types::String* pS = in[0]->getAs<types::String>();
110
111     types::String* pOut = NULL;
112     switch (iMode)
113     {
114         case 0 : //"*"
115         {
116             pOut = new types::String(1, 1);
117             /*compute final size*/
118             int iLen = 1; //L'\0'
119             for (int i = 0 ; i < pS->getSize() ; i++)
120             {
121                 iLen += (int)strlen(pS->get(i));
122             }
123
124             if (pstToInsert != NULL)
125             {
126                 iLen += (int)strlen(pstToInsert) * (pS->getSize() - 1);
127             }
128
129             char* pstOut = (char*)MALLOC(sizeof(char) * iLen);
130             pstOut[0] = '\0';
131             for (int i = 0 ; i < pS->getSize() ; i++)
132             {
133                 size_t iOffset = strlen(pstOut);
134                 if (iOffset != 0 && pstToInsert != NULL)
135                 {
136                     strcat(pstOut + iOffset, pstToInsert);
137                 }
138                 strcat(pstOut + iOffset, pS->get(i));
139             }
140
141             pOut->set(0, pstOut);
142             FREE(pstOut);
143         }
144         break;
145         case 1 : //"r"
146         {
147             pOut = new types::String(1, pS->getCols());
148             /*compute final size*/
149             for (int i = 0 ; i < pS->getCols() ; i++)
150             {
151                 int iLen = 1; //L'\0'
152                 for (int j = 0 ; j < pS->getRows() ; j++)
153                 {
154                     iLen += (int)strlen(pS->get(j, i));
155                 }
156
157                 if (pstToInsert != NULL)
158                 {
159                     iLen += (int)strlen(pstToInsert) * (pS->getRows() - 1);
160                 }
161
162                 char* pstOut = (char*)MALLOC(sizeof(char) * iLen);
163                 pstOut[0] = '\0';
164
165                 for (int j = 0 ; j < pS->getRows() ; j++)
166                 {
167                     size_t iOffset = strlen(pstOut);
168                     if (iOffset != 0 && pstToInsert != NULL)
169                     {
170                         strcat(pstOut + iOffset, pstToInsert);
171                     }
172                     strcat(pstOut + iOffset, pS->get(j, i));
173                 }
174                 pOut->set(0, i, pstOut);
175                 FREE(pstOut);
176             }
177             break;
178         }
179         case 2 : //"c"
180         {
181             pOut = new types::String(pS->getRows(), 1);
182             /*compute final size*/
183             for (int i = 0 ; i < pS->getRows() ; i++)
184             {
185                 int iLen = 1; //L'\0'
186                 for (int j = 0 ; j < pS->getCols() ; j++)
187                 {
188                     iLen += (int)strlen(pS->get(i, j));
189                 }
190
191                 if (pstToInsert != NULL)
192                 {
193                     iLen += (int)strlen(pstToInsert) * (pS->getCols() - 1);
194                 }
195
196                 char* pstOut = (char*)MALLOC(sizeof(char) * iLen);
197                 pstOut[0] = '\0';
198
199                 for (int j = 0 ; j < pS->getCols() ; j++)
200                 {
201                     size_t iOffset = strlen(pstOut);
202                     if (iOffset != 0 && pstToInsert != NULL)
203                     {
204                         strcat(pstOut + iOffset, pstToInsert);
205                     }
206                     strcat(pstOut + iOffset, pS->get(i, j));
207                 }
208                 pOut->set(i, 0, pstOut);
209                 FREE(pstOut);
210             }
211             break;
212         }
213     }
214
215     out.push_back(pOut);
216     return types::Function::OK;
217 }
218 /*-------------------------------------------------------------------------------------*/