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