* Bug #13795 fixed - grep with regexp option did not match the empty string properly
[scilab.git] / scilab / modules / string / sci_gateway / cpp / sci_grep.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2010 - DIGITEO - Antoine ELIAS
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  * === LICENSE_END ===
14 *
15 */
16
17 /* desc : search position of a character string in an other string
18 using regular express .                                         */
19 /*------------------------------------------------------------------------*/
20
21 #include "string_gw.hxx"
22 #include "function.hxx"
23 #include "double.hxx"
24 #include "string.hxx"
25
26 extern "C"
27 {
28 #include "os_string.h"
29 #include "Scierror.h"
30 #include "localization.h"
31 #include "pcre.h"
32 #include "pcreposix.h"
33 #include "sci_malloc.h" /* MALLOC */
34 #include "charEncoding.h"
35 #include "pcre_private.h"
36 #include "pcre_error.h"
37 }
38
39 /*------------------------------------------------------------------------*/
40 #define GREP_OK             0
41 #define GREP_ERROR          1
42 #define MEMORY_ALLOC_ERROR -1
43 /*------------------------------------------------------------------------*/
44 typedef struct grep_results
45 {
46     int sizeArraysMax;
47     int currentLength;
48     int *values;
49     int *positions;
50 } GREPRESULTS;
51 /*------------------------------------------------------------------------*/
52 static int GREP_NEW(GREPRESULTS *results, char **Inputs_param_one, int mn_one, char **Inputs_param_two, int mn_two);
53 static int GREP_OLD(GREPRESULTS *results, char **Inputs_param_one, int mn_one, char **Inputs_param_two, int mn_two);
54 /*------------------------------------------------------------------------*/
55 types::Function::ReturnValue sci_grep(types::typed_list &in, int _iRetCount, types::typed_list &out)
56 {
57     bool bRegularExpression = false;
58
59     //check input paramters
60     if (in.size() < 2 || in.size() > 3)
61     {
62         Scierror(999, _("%s: Wrong number of input arguments: %d or %d expected.\n"), "grep", 2, 3);
63         return types::Function::Error;
64     }
65
66     if (_iRetCount > 2)
67     {
68         Scierror(999, _("%s: Wrong number of output arguments: %d or %d expected.\n"), "grep", 1, 2);
69         return types::Function::Error;
70     }
71
72     if (in[0]->isDouble() && in[0]->getAs<types::Double>()->getSize() == 0)
73     {
74         types::Double *pD = types::Double::Empty();
75         out.push_back(pD);
76         return types::Function::OK;
77     }
78
79     if (in.size() == 3)
80     {
81         //"r" for regular expression
82         if (in[2]->isString() == false)
83         {
84             Scierror(999, _("%s: Wrong type for input argument #%d: String expected.\n"), "grep", 3);
85             return types::Function::Error;
86         }
87
88         types::String* pS = in[2]->getAs<types::String>();
89         if (pS->getSize() != 1)
90         {
91             Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), "grep", 3);
92             return types::Function::Error;
93         }
94
95         if (pS->get(0)[0] == 'r')
96         {
97             bRegularExpression = true;
98         }
99     }
100
101     if (in[0]->isString() == false)
102     {
103         Scierror(999, _("%s: Wrong type for input argument #%d: String expected.\n"), "grep", 1);
104         return types::Function::Error;
105     }
106
107     if (in[1]->isString() == false)
108     {
109         Scierror(999, _("%s: Wrong type for input argument #%d: String expected.\n"), "grep", 2);
110         return types::Function::Error;
111     }
112
113     types::String* pS1 = in[0]->getAs<types::String>();
114     types::String* pS2 = in[1]->getAs<types::String>();
115
116
117     for (int i = 0 ; i < pS2->getSize() ; i++)
118     {
119         if (wcslen(pS2->get(i)) == 0)
120         {
121             Scierror(249, _("%s: Wrong values for input argument #%d: Non-empty strings expected.\n"), "grep", 2);
122             return types::Function::Error;
123         }
124     }
125
126     GREPRESULTS grepresults;
127     int code_error_grep = GREP_OK;
128
129     grepresults.currentLength = 0;
130     grepresults.sizeArraysMax = 0;
131     grepresults.positions = NULL;
132     grepresults.values = NULL;
133
134     char** pStr1 = (char**)MALLOC(sizeof(char*) * pS1->getSize());
135     for (int i = 0 ; i < pS1->getSize() ; i++)
136     {
137         pStr1[i] = wide_string_to_UTF8(pS1->get(i));
138     }
139
140     char** pStr2 = (char**)MALLOC(sizeof(char*) * pS2->getSize());
141     for (int i = 0 ; i < pS2->getSize() ; i++)
142     {
143         pStr2[i] = wide_string_to_UTF8(pS2->get(i));
144     }
145
146     if (bRegularExpression)
147     {
148         code_error_grep = GREP_NEW(&grepresults, pStr1, pS1->getSize(), pStr2, pS2->getSize());
149     }
150     else
151     {
152         code_error_grep = GREP_OLD(&grepresults, pStr1, pS1->getSize(), pStr2, pS2->getSize());
153     }
154
155     for (int i = 0; i < pS1->getSize(); i++)
156     {
157         FREE(pStr1[i]);
158     }
159     FREE(pStr1);
160
161     for (int i = 0; i < pS2->getSize(); i++)
162     {
163         FREE(pStr2[i]);
164     }
165     FREE(pStr2);
166
167     switch (code_error_grep)
168     {
169         case GREP_OK :
170         {
171             types::Double* pD1 = NULL;
172             if (grepresults.currentLength == 0)
173             {
174                 pD1 = types::Double::Empty();
175             }
176             else
177             {
178                 pD1 = new types::Double(1, grepresults.currentLength);
179                 double* pDbl1 = pD1->getReal();
180                 for (int i = 0 ; i < grepresults.currentLength ; i++ )
181                 {
182                     pDbl1[i] = static_cast<double>(grepresults.values[i]);
183                 }
184             }
185
186             out.push_back(pD1);
187
188             if (_iRetCount == 2)
189             {
190                 types::Double* pD2 = NULL;
191                 if (grepresults.currentLength == 0)
192                 {
193                     pD2 = types::Double::Empty();
194                 }
195                 else
196                 {
197                     pD2 = new types::Double(1, grepresults.currentLength);
198                     double* pDbl2 = pD2->getReal();
199                     for (int i = 0 ; i < grepresults.currentLength ; i++ )
200                     {
201                         pDbl2[i] = static_cast<double>(grepresults.positions[i]);
202                     }
203                 }
204
205                 out.push_back(pD2);
206             }
207
208             if (grepresults.values)
209             {
210                 FREE(grepresults.values);
211                 grepresults.values = NULL;
212             }
213             if (grepresults.positions)
214             {
215                 FREE(grepresults.positions);
216                 grepresults.positions = NULL;
217             }
218         }
219         break;
220
221         case MEMORY_ALLOC_ERROR :
222             Scierror(999, _("%s: No more memory.\n"), "grep");
223             //no break, to free reserved memory.
224         case GREP_ERROR :
225         {
226             if (grepresults.values)
227             {
228                 FREE(grepresults.values);
229                 grepresults.values = NULL;
230             }
231             if (grepresults.positions)
232             {
233                 FREE(grepresults.positions);
234                 grepresults.positions = NULL;
235             }
236             return types::Function::Error;
237         }
238         break;
239     }
240
241     return types::Function::OK;
242 }
243 //Function::ReturnValue sci_grep(typed_list &in, int _iRetCount, typed_list &out)
244 //{
245 //      CheckRhs(2,3);
246 //      CheckLhs(1,2);
247 //
248 //      if (VarType(1) == sci_matrix)
249 //      {
250 //              int m1 = 0, n1 = 0;
251 //              char **Str=NULL;
252 //
253 //              GetRhsVar(1,MATRIX_OF_DOUBLE_DATATYPE,&m1,&n1,&Str);
254 //
255 //              if ((m1 == 0) && (n1 == 0))
256 //              {
257 //                      int l = 0;
258 //                      CreateVar(Rhs+1,MATRIX_OF_DOUBLE_DATATYPE,&m1,&n1,&l);
259 //                      LhsVar(1) = Rhs+1 ;
260 //                      C2F(putlhsvar)();
261 //
262 //                      return 0;
263 //              }
264 //      }
265 //
266 //      if (Rhs == 3)
267 //      {
268 //              if (VarType(3) == sci_strings)
269 //              {
270 //                      char typ = 'd'; /*default */
271 //                      int m3 = 0,n3 = 0,l3 = 0;
272 //
273 //                      GetRhsVar(3,STRING_DATATYPE,&m3,&n3,&l3);
274 //                      if ( m3*n3 != 0) typ = cstk(l3)[0];
275 //
276 //                      if (typ == 'r' )
277 //                      {
278 //                              sci_grep_common(fname,TRUE);
279 //                      }
280 //                      else
281 //                      {
282 //                              Scierror(999,_("%s: Wrong value for input argument #%d: ''%s'' expected.\n"),fname,3,"s");
283 //                              return 0;
284 //                      }
285 //              }
286 //              else
287 //              {
288 //                      Scierror(999,_("%s: Wrong type for input argument #%d: String expected.\n"),fname,3);
289 //                      return 0;
290 //              }
291 //      }
292 //      else /* Rhs == 2 */
293 //      {
294 //              sci_grep_common(fname,FALSE);
295 //      }
296 //      return 0;
297 //}
298 /*-----------------------------------------------------------------------------------*/
299 static int GREP_NEW(GREPRESULTS *results, char **Inputs_param_one, int mn_one, char **Inputs_param_two, int mn_two)
300 {
301     int x = 0, y = 0;
302     char *save = NULL;
303     int iRet = GREP_OK;
304     pcre_error_code answer = PCRE_FINISHED_OK;
305     results->sizeArraysMax = mn_one * mn_two;
306
307     results->values = (int *)MALLOC(sizeof(int) * results->sizeArraysMax);
308     results->positions = (int *)MALLOC(sizeof(int) * results->sizeArraysMax);
309
310     if ( (results->values == NULL) || (results->positions == NULL) )
311     {
312         if (results->values)
313         {
314             FREE(results->values);
315             results->values = NULL;
316         }
317         if (results->positions)
318         {
319             FREE(results->positions);
320             results->positions = NULL;
321         }
322         return MEMORY_ALLOC_ERROR;
323     }
324
325     results->currentLength = 0;
326     for ( y = 0; y < mn_one; ++y)
327     {
328         for ( x = 0; x < mn_two; ++x)
329         {
330             int Output_Start = 0;
331             int Output_End = 0;
332             save = os_strdup(Inputs_param_two[x]);
333             answer = pcre_private(Inputs_param_one[y], save, &Output_Start, &Output_End, NULL, NULL);
334
335             if ( answer == PCRE_FINISHED_OK )
336             {
337                 results->values[results->currentLength] = y + 1;
338                 results->positions[results->currentLength] = x + 1;
339                 results->currentLength++;
340             }
341             else if (answer != NO_MATCH)
342             {
343                 pcre_error("grep", answer);
344                 return GREP_ERROR;
345             }
346
347             if (save)
348             {
349                 FREE(save);
350                 save = NULL;
351             }
352         }
353     }
354
355     return iRet;
356 }
357 /*-----------------------------------------------------------------------------------*/
358 static int GREP_OLD(GREPRESULTS *results, char **Inputs_param_one, int mn_one, char **Inputs_param_two, int mn_two)
359 {
360     int x = 0, y = 0;
361
362     results->values = (int *)MALLOC(sizeof(int) * (mn_one * mn_two + 1));
363     results->positions = (int *)MALLOC(sizeof(int) * (mn_one * mn_two + 1));
364
365     for (y = 0; y < mn_one; ++y)
366     {
367         for (x = 0; x < mn_two; ++x)
368         {
369             wchar_t* wcInputOne = to_wide_string(Inputs_param_one[y]);
370             wchar_t* wcInputTwo = to_wide_string(Inputs_param_two[x]);
371
372             if (wcInputOne && wcInputTwo)
373             {
374                 if (wcsstr(wcInputOne, wcInputTwo) != NULL)
375                 {
376                     results->values[results->currentLength] = y + 1;
377                     results->positions[results->currentLength] = x + 1;
378                     results->currentLength++;
379                 }
380             }
381
382             if (wcInputOne)
383             {
384                 FREE(wcInputOne);
385                 wcInputOne = NULL;
386             }
387             if (wcInputTwo)
388             {
389                 FREE(wcInputTwo);
390                 wcInputTwo = NULL;
391             }
392         }
393     }
394     return GREP_OK;
395 }
396 /*-----------------------------------------------------------------------------------*/
397 //static int sci_grep_common(char *fname,BOOL new_grep)
398 //{
399 //      int i = 0;
400 //
401 //      int m1 = 0, n1 = 0;
402 //      char **Strings_Input_One = NULL;
403 //      int m1n1 = 0; /* m1 * n1 */
404 //
405 //      int m2 = 0, n2 = 0;
406 //      char **Strings_Input_Two = NULL;
407 //      int m2n2 = 0; /* m2 * n2 */
408 //
409 //      GREPRESULTS grepresults;
410 //      int code_error_grep = GREP_OK;
411 //
412 //      GetRhsVar(1,MATRIX_OF_STRING_DATATYPE,&m1,&n1,&Strings_Input_One);
413 //      m1n1 = m1*n1;
414 //      GetRhsVar(2,MATRIX_OF_STRING_DATATYPE,&m2,&n2,&Strings_Input_Two);
415 //      m2n2 = m2*n2;
416 //
417 //      for (i = 0;i < m2n2;i++)
418 //      {
419 //              if ( strlen(Strings_Input_Two[i]) == 0)
420 //              {
421 //                      freeArrayOfString(Strings_Input_One,m1n1);
422 //                      freeArrayOfString(Strings_Input_Two,m2n2);
423 //                      Scierror(249,_("%s: Wrong values for input argument #%d: Non-empty strings expected.\n"),fname,2);
424 //                      return 0;
425 //              }
426 //      }
427 //
428 //      grepresults.currentLength = 0;
429 //      grepresults.sizeArraysMax = 0;
430 //      grepresults.positions = NULL;
431 //      grepresults.values = NULL;
432 //
433 //      if (new_grep)
434 //      {
435 //              code_error_grep = GREP_NEW(&grepresults,Strings_Input_One,m1n1,Strings_Input_Two,m2n2);
436 //      }
437 //      else
438 //      {
439 //              code_error_grep = GREP_OLD(&grepresults,Strings_Input_One,m1n1,Strings_Input_Two,m2n2);
440 //      }
441 //
442 //      freeArrayOfString(Strings_Input_One,m1n1);
443 //      freeArrayOfString(Strings_Input_Two,m2n2);
444 //
445 //      switch (code_error_grep)
446 //      {
447 //      case GREP_OK :
448 //              {
449 //                      int x = 0;
450 //                      int numRow   = 0;
451 //                      int outIndex = 0;
452 //
453 //                      numRow   = 1;  /* Output values[]*/
454 //                      outIndex = 0;
455 //                      CreateVar(Rhs+1,MATRIX_OF_DOUBLE_DATATYPE,&numRow,&grepresults.currentLength,&outIndex);
456 //                      for ( x = 0 ; x < grepresults.currentLength ; x++ )
457 //                      {
458 //                              stk(outIndex)[x] = (double)grepresults.values[x] ;
459 //                      }
460 //                      LhsVar(1) = Rhs+1 ;
461 //                      if (Lhs == 2)
462 //                      {
463 //                              /* Output positions[]*/
464 //                              numRow   = 1;
465 //                              outIndex = 0;
466 //                              CreateVar(Rhs+2,MATRIX_OF_DOUBLE_DATATYPE,&numRow,&grepresults.currentLength,&outIndex);
467 //                              for ( x = 0 ; x < grepresults.currentLength ; x++ )
468 //                              {
469 //                                      stk(outIndex)[x] = (double)grepresults.positions[x] ;
470 //                              }
471 //                              LhsVar(2) = Rhs+2;
472 //                      }
473 //                      C2F(putlhsvar)();
474 //                      if (grepresults.values) {FREE(grepresults.values); grepresults.values = NULL;}
475 //                      if (grepresults.positions) {FREE(grepresults.positions); grepresults.positions = NULL;}
476 //              }
477 //              break;
478 //
479 //      case MEMORY_ALLOC_ERROR :
480 //              {
481 //                      if (grepresults.values) {FREE(grepresults.values); grepresults.values = NULL;}
482 //                      if (grepresults.positions) {FREE(grepresults.positions); grepresults.positions = NULL;}
483 //                      Scierror(999,_("%s: No more memory.\n"),fname);
484 //              }
485 //              break;
486 //      }
487 //      return 0;
488 //}
489
490 /*-----------------------------------------------------------------------------------*/