* Bug 16365 fixed: median(m,'r'|'c') was wrong after 5dc990
[scilab.git] / scilab / modules / string / sci_gateway / cpp / sci_strsplit.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2013 - Scilab Enterprises - Cedric Delamarre
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15
16 #include "string_gw.hxx"
17 #include "function.hxx"
18 #include "string.hxx"
19 #include "double.hxx"
20 #include "bool.hxx"
21 #include "overload.hxx"
22
23 extern "C"
24 {
25 #include "sci_malloc.h"
26 #include "Scierror.h"
27 #include "localization.h"
28 #include "strsplit.h"
29 #include "freeArrayOfString.h"
30 }
31
32 types::Function::ReturnValue sci_strsplit(types::typed_list &in, int _iRetCount, types::typed_list &out)
33 {
34     types::String* pStrIn = NULL;
35     int iValueThree = 0;
36
37     if (in.size() < 1 || in.size() > 3)
38     {
39         Scierror(999, _("%s: Wrong number of input arguments: %d to %d expected.\n"), "strsplit", 1, 3);
40         return types::Function::Error;
41     }
42
43     if (_iRetCount > 2)
44     {
45         Scierror(999, _("%s: Wrong number of output arguments: %d to %d expected.\n"), "strsplit", 1, 2);
46         return types::Function::Error;
47     }
48
49     // [[], ""] = strsplit([],...)
50     if (in[0]->isDouble() && in[0]->getAs<types::Double>()->isEmpty())
51     {
52         out.push_back(types::Double::Empty());
53
54         if (_iRetCount == 2)
55         {
56             out.push_back(new types::String(L""));
57         }
58
59         return types::Function::OK;
60     }
61
62     if (in[0]->isString() == false)
63     {
64         Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), "strsplit", 1);
65         return types::Function::Error;
66     }
67
68     pStrIn = in[0]->getAs<types::String>();
69
70     if (pStrIn->isScalar() == false)
71     {
72         Scierror(999, _("%s: Wrong size for input argument #%d: A single string expected.\n"), "strsplit", 1);
73         return types::Function::Error;
74     }
75
76     if (in.size() > 2)
77     {
78         if (in[2]->isDouble() == false)
79         {
80             Scierror(999, _("%s: Wrong type for input argument #%d: A double expected.\n"), "strsplit", 3);
81             return types::Function::Error;
82         }
83
84         types::Double* pDblIn = in[2]->getAs<types::Double>();
85
86         if (pDblIn->isScalar() == false)
87         {
88             Scierror(999, _("%s: Wrong size for input argument #%d: A scalar double expected.\n"), "strsplit", 3);
89             return types::Function::Error;
90         }
91
92         iValueThree = (int)pDblIn->get(0);
93
94         if ( (double)iValueThree != pDblIn->get(0))
95         {
96             Scierror(999, _("%s: Wrong value for input argument #%d: An integer value expected.\n"), "strsplit", 3);
97             return types::Function::Error;
98         }
99
100         if ((iValueThree < 1) && (iValueThree != -1))
101         {
102             Scierror(999, _("%s: Wrong size for input argument #%d: A positive value expected.\n"), "strsplit", 3);
103             return types::Function::Error;
104         }
105     }
106
107     if (in.size() > 1)
108     {
109         if (in[1]->isDouble())
110         {
111             types::Double* pDbl = in[1]->getAs<types::Double>();
112
113             if (_iRetCount == 2)
114             {
115                 Scierror(999, _("%s: Wrong number of output arguments: %d expected.\n"), "strsplit", 1);
116                 return types::Function::Error;
117             }
118
119             if (pDbl->getRows() != 1 && pDbl->getCols() != 1)
120             {
121                 Scierror(999, _("%s: Wrong size for input argument #%d: A Scalar or vector expected.\n"), "strsplit", 2);
122                 return types::Function::Error;
123             }
124
125             strsplit_error ierr = STRSPLIT_NO_ERROR;
126             wchar_t **results = strsplit(pStrIn->get(0), pDbl->get(), pDbl->getSize(), &ierr);
127
128             switch (ierr)
129             {
130                 case STRSPLIT_NO_ERROR:
131                 {
132                     types::String* pStrOut = new types::String(pDbl->getSize() + 1, 1);
133                     pStrOut->set(results);
134
135                     freeArrayOfWideString(results, pDbl->getSize() + 1);
136                     out.push_back(pStrOut);
137                     return types::Function::OK;
138                 }
139                 break;
140                 case STRSPLIT_INCORRECT_VALUE_ERROR:
141                 {
142                     freeArrayOfWideString(results, pDbl->getSize() + 1);
143                     Scierror(999, _("%s: Wrong value for input argument #%d.\n"), "strsplit", 2);
144                     return types::Function::Error;
145                 }
146                 break;
147                 case STRSPLIT_INCORRECT_ORDER_ERROR:
148                 {
149                     freeArrayOfWideString(results, pDbl->getSize() + 1);
150                     Scierror(999, _("%s: Elements of %dth argument must be in increasing order.\n"), "strsplit", 2);
151                     return types::Function::Error;
152                 }
153                 break;
154                 case STRSPLIT_MEMORY_ALLOCATION_ERROR:
155                 {
156                     freeArrayOfWideString(results, pDbl->getSize() + 1);
157                     Scierror(999, _("%s: Memory allocation error.\n"), "strsplit");
158                     return types::Function::Error;
159                 }
160                 break;
161                 default:
162                 {
163                     freeArrayOfWideString(results, pDbl->getSize() + 1);
164                     Scierror(999, _("%s: error.\n"), "strsplit");
165                     return types::Function::Error;
166                 }
167                 break;
168             }
169         }
170         else if (in[1]->isString())
171         {
172             types::String* pStr = in[1]->getAs<types::String>();
173             if (pStr->isScalar() == false)
174             {
175                 // checks that 2nd parameter is not an array of regexp pattern
176                 wchar_t** pwcsStr = pStr->get();
177                 for (int i = 0; i < pStr->getSize(); i++)
178                 {
179                     if (pwcsStr[i])
180                     {
181                         int iLen = (int)wcslen(pwcsStr[i]);
182                         if (iLen > 2 && pwcsStr[i][0] == L'/' && pwcsStr[i][iLen - 1] == L'/')
183                         {
184                             Scierror(999, _("%s: Wrong value for input argument #%d: a string expected, not a regexp pattern.\n"), "strsplit", 2);
185                             return types::Function::Error;
186                         }
187                     }
188                 }
189             }
190         }
191         else
192         {
193             Scierror(999, _("%s: Wrong type for input argument #%d: A double or string expected.\n"), "strsplit", 2);
194             return types::Function::Error;
195         }
196     }
197
198     return Overload::call(L"%_strsplit", in, _iRetCount, out);
199 }
200 /*-------------------------------------------------------------------------------------*/