cb5d002c219e641339ce9058698254905fed8d61
[scilab.git] / scilab / modules / string / src / c / strsubst.c
1
2 /*
3  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
4  * Copyright (C) INRIA - Allan CORNET
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 /*--------------------------------------------------------------------------*/
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <wchar.h>
22 #include "strsubst.h"
23 #include "sci_malloc.h"
24 #include "pcre_private.h"
25 #include "os_string.h"
26 #include "charEncoding.h"
27 #include "pcre_error.h"
28 /*--------------------------------------------------------------------------*/
29 char **strsubst(const char **strings_input, int strings_dim, const char *string_to_search, const char *replacement_string)
30 {
31     char **replacedStrings = NULL;
32
33     if ( (strings_input) && (string_to_search) && (replacement_string) )
34     {
35         int i = 0;
36         replacedStrings = (char**)MALLOC(sizeof(char*) * strings_dim);
37         for (i = 0; i < strings_dim; i++)
38         {
39             const char *str = strings_input[i];
40             replacedStrings[i] = strsub (str, string_to_search, replacement_string);
41         }
42     }
43     return replacedStrings;
44 }
45 /*--------------------------------------------------------------------------*/
46 char **strsubst_reg(const char **strings_input, int strings_dim, const char *string_to_search, const char *replacement_string, int *ierr)
47 {
48     char **replacedStrings = NULL;
49
50     if ( (strings_input) && (string_to_search) && (replacement_string) )
51     {
52         int i = 0;
53         replacedStrings = (char**)MALLOC(sizeof(char*) * strings_dim);
54         for (i = 0; i < strings_dim; i++)
55         {
56             const char *str = strings_input[i];
57             replacedStrings[i] = strsub_reg(str, string_to_search, replacement_string, ierr);
58         }
59     }
60     return replacedStrings;
61 }
62 /*-------------------------------------------------------------------------------------*/
63 char *strsub(const char* input_string, const char* string_to_search, const char* replacement_string)
64 {
65     const char *occurrence_str = NULL;
66     char* result_str = NULL;
67     char *replacedString = NULL;
68     int count = 0, len = 0;
69
70     if (input_string == NULL)
71     {
72         return NULL;
73     }
74
75     if (string_to_search == NULL || replacement_string == NULL)
76     {
77         return os_strdup(input_string);
78     }
79
80     occurrence_str = strstr (input_string, string_to_search);
81     if (occurrence_str == NULL)
82     {
83         return os_strdup(input_string);
84     }
85
86     if (strlen (replacement_string) > strlen (string_to_search))
87     {
88         count = 0;
89         len = (int)strlen (string_to_search);
90         if (len)
91         {
92             occurrence_str = input_string;
93             while (occurrence_str != NULL && *occurrence_str != '\0')
94             {
95                 occurrence_str = strstr (occurrence_str, string_to_search);
96                 if (occurrence_str != NULL)
97                 {
98                     occurrence_str += len;
99                     count++;
100                 }
101             }
102         }
103         len = count * ((int)strlen(replacement_string) - (int)strlen(string_to_search)) + (int)strlen(input_string);
104     }
105     else
106     {
107         len = (int)strlen(input_string);
108     }
109
110     replacedString = (char*)MALLOC (sizeof(char) * (len + 1));
111     if (replacedString == NULL)
112     {
113         return NULL;
114     }
115
116     occurrence_str = input_string;
117     result_str = replacedString;
118     len = (int)strlen (string_to_search);
119     while (*occurrence_str != '\0')
120     {
121         if (*occurrence_str == string_to_search[0] && strncmp (occurrence_str, string_to_search, len) == 0)
122         {
123             const char *N = NULL;
124             N = replacement_string;
125             while (*N != '\0')
126             {
127                 *result_str++ = *N++;
128             }
129             occurrence_str += len;
130         }
131         else
132         {
133             *result_str++ = *occurrence_str++;
134         }
135     }
136     *result_str = '\0';
137
138     return replacedString;
139 }/*-------------------------------------------------------------------------------------*/
140 char *strsub_reg(const char* input_string, const char* string_to_search, const char* replacement_string, int *ierr)
141 {
142     pcre_error_code w = PCRE_FINISHED_OK;
143
144     int Output_Start = 0;
145     int Output_End = 0;
146
147     char *replacedString = NULL;
148     wchar_t *wcreplacedString = NULL;
149
150     wchar_t *wcreplacement_string = NULL;
151     wchar_t *wcinput_string = NULL;
152
153     int len = 0;
154
155     *ierr = (int)PCRE_FINISHED_OK;
156
157     if (input_string == NULL)
158     {
159         return NULL;
160     }
161
162     if (string_to_search == NULL || replacement_string == NULL)
163     {
164         return os_strdup(input_string);
165     }
166
167     w = pcre_private((char*)input_string, (char*)string_to_search, &Output_Start, &Output_End, NULL, NULL);
168     if (w != PCRE_FINISHED_OK)
169     {
170         *ierr = (int)w;
171         return os_strdup(input_string);
172     }
173
174     wcreplacement_string = to_wide_string((char*)replacement_string);
175     wcinput_string = to_wide_string((char*)input_string);
176
177     if (wcreplacement_string == NULL)
178     {
179         FREE(wcinput_string);
180         *ierr = (int)NOT_ENOUGH_MEMORY_FOR_VECTOR;
181         return os_strdup(input_string);
182     }
183
184     len = (int)wcslen(wcreplacement_string) + (int)wcslen(wcinput_string);
185
186     wcreplacedString = (wchar_t*)MALLOC (sizeof(wchar_t) * (len + 1));
187     if (wcreplacedString == NULL)
188     {
189         FREE(wcreplacement_string);
190         FREE(wcinput_string);
191         return NULL;
192     }
193
194     {
195         /* converts to wide characters */
196
197         wchar_t *wctail = NULL;
198
199         int wcOutput_Start = 0;
200         int wcOutput_End = 0;
201
202         char *  strOutput_Start = os_strdup(input_string);
203         char *  strOutput_End =  os_strdup(input_string);
204
205         wchar_t *wcstrOutput_Start = NULL;
206         wchar_t *wcstrOutput_End = NULL;
207
208         /* calculates positions with wide characters */
209         strOutput_Start[Output_Start] = '\0';
210         strOutput_End[Output_End] = '\0';
211
212         wcstrOutput_Start = to_wide_string(strOutput_Start);
213         wcstrOutput_End = to_wide_string(strOutput_End);
214
215         FREE(strOutput_Start);
216         FREE(strOutput_End);
217
218         if (wcstrOutput_Start)
219         {
220             wcOutput_Start = (int)wcslen(wcstrOutput_Start);
221             FREE(wcstrOutput_Start);
222         }
223         else
224         {
225             wcOutput_Start = 0;
226         }
227
228         if (wcstrOutput_End)
229         {
230             wcOutput_End = (int)wcslen(wcstrOutput_End);
231             FREE(wcstrOutput_End);
232         }
233         else
234         {
235             wcOutput_End = 0;
236         }
237
238         wcsncpy(wcreplacedString, wcinput_string, wcOutput_Start);
239         wcreplacedString[wcOutput_Start] = L'\0';
240         wcscat(wcreplacedString, wcreplacement_string);
241         wctail = wcinput_string + wcOutput_End;
242         wcscat(wcreplacedString, wctail);
243         replacedString = wide_string_to_UTF8(wcreplacedString);
244
245         FREE(wcreplacedString);
246     }
247
248     FREE(wcinput_string);
249     FREE(wcreplacement_string);
250
251     return replacedString;
252 }
253 /*-------------------------------------------------------------------------------------*/
254 wchar_t *wcssub_reg(const wchar_t* _pwstInput, const wchar_t* _pwstSearch, const wchar_t* _pwstReplace, int* _piErr)
255 {
256     pcre_error_code iPcreStatus = PCRE_FINISHED_OK;
257     int iStart = 0;
258     int iEnd = 0;
259     int len = 0;
260     int* arriStart = NULL;
261     int* arriEnd = NULL;
262     int iOccurs = 0;
263     int iJump = 0;
264
265     wchar_t* result = NULL;
266
267     if (_pwstInput == NULL)
268     {
269         return NULL;
270     }
271
272     len = (int)wcslen(_pwstInput);
273     arriStart = (int*)MALLOC(sizeof(int) * len);
274     arriEnd = (int*)MALLOC(sizeof(int) * len);
275
276     if (_pwstSearch == NULL || _pwstReplace == NULL)
277     {
278         FREE(arriStart);
279         FREE(arriEnd);
280         return os_wcsdup(_pwstInput);
281     }
282
283     do
284     {
285         iPcreStatus = wide_pcre_private(_pwstInput + iJump, _pwstSearch, &iStart, &iEnd, NULL, NULL);
286         if (iPcreStatus == PCRE_FINISHED_OK)
287         {
288             if (iEnd != iStart)
289             {
290                 arriStart[iOccurs] = iStart + iJump;
291                 arriEnd[iOccurs++] = iEnd + iJump;
292                 iJump += iEnd;
293             }
294             else if (iEnd == 0 && _pwstInput[iJump] != L'\0')
295             {
296                 //avoid infinite loop
297                 iJump++;
298             }
299         }
300         else if (iPcreStatus != NO_MATCH)
301         {
302             pcre_error("strsubst", iPcreStatus);
303             FREE(arriStart);
304             FREE(arriEnd);
305             return NULL;
306         }
307     }
308     while (iPcreStatus == PCRE_FINISHED_OK && iStart != iEnd);
309
310     if (iOccurs)
311     {
312         int i = 0;
313         int replaceLen = (int)wcslen(_pwstReplace);
314         int finalSize = len;
315
316         //compute final size
317         for (i = 0; i < iOccurs; ++i)
318         {
319             finalSize -= (arriEnd[i] - arriStart[i]);
320             finalSize += replaceLen;
321         }
322
323         result = (wchar_t*)MALLOC(sizeof(wchar_t) * (finalSize + 1));
324         result[0] = '\0';
325
326         //from start to first occurence
327         wcsncat(result, _pwstInput, arriStart[0]);
328         result[arriStart[0]] = '\0';
329
330         for (i = 0; i < iOccurs - 1; ++i)
331         {
332             int curLen = (int)wcslen(result);
333             int partLen = arriStart[i + 1] - arriEnd[i];
334             //insert replace string
335             wcscat(result, _pwstReplace);
336             //copy part between 2 occurences
337             wcsncat(result, _pwstInput + arriEnd[i], partLen);
338             result[curLen + replaceLen + partLen] = '\0';
339         }
340
341         wcscat(result, _pwstReplace);
342         //copy part after last occurence
343         wcscat(result, _pwstInput + arriEnd[iOccurs - 1]);
344     }
345     else
346     {
347         *_piErr = iPcreStatus;
348         result = os_wcsdup(_pwstInput);
349     }
350
351     FREE(arriStart);
352     FREE(arriEnd);
353
354     return result;
355 }
356 /*-------------------------------------------------------------------------------------*/
357 wchar_t **wcssubst_reg(const wchar_t** _pwstInput, int _iInputSize, const wchar_t* _pwstSearch, const wchar_t* _pwstReplace, int* _piErr)
358 {
359     wchar_t** pwstOutput = NULL;
360
361     if (_pwstInput != NULL && _pwstSearch != NULL && _pwstReplace != NULL)
362     {
363         int i = 0;
364         pwstOutput = (wchar_t**)MALLOC(sizeof(wchar_t*) * _iInputSize);
365         for (i = 0 ; i < _iInputSize ; i++)
366         {
367             const wchar_t* pwst = _pwstInput[i];
368             pwstOutput[i] = wcssub_reg(pwst, _pwstSearch, _pwstReplace, _piErr);
369         }
370     }
371     return pwstOutput;
372 }
373 /*-------------------------------------------------------------------------------------*/
374 wchar_t **wcssubst(const wchar_t** _pwstInput, int _iInputSize, const wchar_t* _pwstSearch, const wchar_t* _pwstReplace)
375 {
376     wchar_t** pwstOutput = NULL;
377
378     if (_pwstInput != NULL && _pwstSearch != NULL && _pwstReplace != NULL)
379     {
380         int i = 0;
381         pwstOutput = (wchar_t**)MALLOC(sizeof(wchar_t*) * _iInputSize);
382         for (i = 0 ; i < _iInputSize ; i++)
383         {
384             const wchar_t* pwst = _pwstInput[i];
385             if (wcslen(pwst) == 0)
386             {
387                 if (wcslen(_pwstSearch) == 0)
388                 {
389                     pwstOutput[i] = os_wcsdup(_pwstReplace);
390                 }
391                 else
392                 {
393                     pwstOutput[i] = os_wcsdup(L"");
394                 }
395             }
396             else
397             {
398                 pwstOutput[i] = wcssub(pwst, _pwstSearch, _pwstReplace);
399             }
400         }
401     }
402     return pwstOutput;
403 }
404 /*-------------------------------------------------------------------------------------*/
405 wchar_t *wcssub(const wchar_t* _pwstInput, const wchar_t* _pwstSearch, const wchar_t* _pwstReplace)
406 {
407     int i               = 0;
408     int iOccurs         = 0;
409     size_t iReplace     = 0;
410     size_t iSearch      = 0;
411     size_t iOffset      = 0;
412
413     size_t* piStart     = NULL;
414
415     const wchar_t* pwstPos  = NULL;
416     wchar_t* pwstOutput     = NULL;
417
418     if (_pwstInput == NULL)
419     {
420         return NULL;
421     }
422
423     if (_pwstSearch == NULL || _pwstReplace == NULL)
424     {
425         return os_wcsdup(_pwstInput);
426     }
427
428     //no needle
429     if (_pwstSearch[0] == L'\0')
430     {
431         //no input
432         if (_pwstInput[0] == L'\0')
433         {
434             return os_wcsdup(_pwstReplace);
435         }
436         else
437         {
438             return os_wcsdup(_pwstInput);
439         }
440     }
441
442     //no input
443     if (_pwstInput[0] == L'\0')
444     {
445         return os_wcsdup(_pwstInput);
446     }
447
448     iSearch     = wcslen(_pwstSearch);
449     iReplace    = wcslen(_pwstReplace);
450     piStart     = (size_t*)MALLOC(sizeof(size_t) * wcslen(_pwstInput));
451     pwstPos     = _pwstInput;
452
453     while (pwstPos)
454     {
455         pwstPos = wcsstr(pwstPos, _pwstSearch);
456         if (pwstPos)
457         {
458             piStart[iOccurs++]  = pwstPos - _pwstInput;
459             iOffset             += iReplace - iSearch;
460             pwstPos             += iSearch;
461         }
462     }
463
464     pwstOutput = (wchar_t*)MALLOC(sizeof(wchar_t) * (wcslen(_pwstInput) + iOffset + 1));
465     memset(pwstOutput, 0x00, sizeof(wchar_t) * (wcslen(_pwstInput) + iOffset + 1));
466
467     if (iOccurs == 0)
468     {
469         wcscpy(pwstOutput, _pwstInput);
470     }
471     else
472     {
473         for (i = 0 ; i < iOccurs ; i++)
474         {
475             if (i == 0)
476             {
477                 //copy start of original string
478                 wcsncpy(pwstOutput, _pwstInput, piStart[i]);
479             }
480             else
481             {
482                 //copy start of original string
483                 wcsncpy(pwstOutput + wcslen(pwstOutput), _pwstInput + piStart[i - 1] + iSearch, piStart[i] - (iSearch + piStart[i - 1]));
484             }
485             //copy replace string
486             wcscpy(pwstOutput + wcslen(pwstOutput), _pwstReplace);
487         }
488         //copy end of original string
489         wcscpy(pwstOutput + wcslen(pwstOutput), _pwstInput + piStart[iOccurs - 1] + iSearch);
490     }
491
492     FREE(piStart);
493     return pwstOutput;
494 }
495 /*-------------------------------------------------------------------------------------*/