f6446774339164222e18b4f95226ae5d5021ac22
[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  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11  *
12  */
13
14 /*--------------------------------------------------------------------------*/
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <wchar.h>
19 #include "strsubst.h"
20 #include "sci_malloc.h"
21 #include "pcre_private.h"
22 #include "os_string.h"
23 #include "charEncoding.h"
24 /*--------------------------------------------------------------------------*/
25 char **strsubst(const char **strings_input, int strings_dim, const char *string_to_search, const char *replacement_string)
26 {
27     char **replacedStrings = NULL;
28
29     if ( (strings_input) && (string_to_search) && (replacement_string) )
30     {
31         int i = 0;
32         replacedStrings = (char**)MALLOC(sizeof(char*) * strings_dim);
33         for (i = 0; i < strings_dim; i++)
34         {
35             const char *str = strings_input[i];
36             replacedStrings[i] = strsub (str, string_to_search, replacement_string);
37         }
38     }
39     return replacedStrings;
40 }
41 /*--------------------------------------------------------------------------*/
42 char **strsubst_reg(const char **strings_input, int strings_dim, const char *string_to_search, const char *replacement_string, int *ierr)
43 {
44     char **replacedStrings = NULL;
45
46     if ( (strings_input) && (string_to_search) && (replacement_string) )
47     {
48         int i = 0;
49         replacedStrings = (char**)MALLOC(sizeof(char*) * strings_dim);
50         for (i = 0; i < strings_dim; i++)
51         {
52             const char *str = strings_input[i];
53             replacedStrings[i] = strsub_reg(str, string_to_search, replacement_string, ierr);
54         }
55     }
56     return replacedStrings;
57 }
58 /*-------------------------------------------------------------------------------------*/
59 char *strsub(const char* input_string, const char* string_to_search, const char* replacement_string)
60 {
61     const char *occurrence_str = NULL;
62     char* result_str = NULL;
63     char *replacedString = NULL;
64     int count = 0, len = 0;
65
66     if (input_string == NULL)
67     {
68         return NULL;
69     }
70
71     if (string_to_search == NULL || replacement_string == NULL)
72     {
73         return os_strdup(input_string);
74     }
75
76     occurrence_str = strstr (input_string, string_to_search);
77     if (occurrence_str == NULL)
78     {
79         return os_strdup(input_string);
80     }
81
82     if (strlen (replacement_string) > strlen (string_to_search))
83     {
84         count = 0;
85         len = (int)strlen (string_to_search);
86         if (len)
87         {
88             occurrence_str = input_string;
89             while (occurrence_str != NULL && *occurrence_str != '\0')
90             {
91                 occurrence_str = strstr (occurrence_str, string_to_search);
92                 if (occurrence_str != NULL)
93                 {
94                     occurrence_str += len;
95                     count++;
96                 }
97             }
98         }
99         len = count * ((int)strlen(replacement_string) - (int)strlen(string_to_search)) + (int)strlen(input_string);
100     }
101     else
102     {
103         len = (int)strlen(input_string);
104     }
105
106     replacedString = (char*)MALLOC (sizeof(char) * (len + 1));
107     if (replacedString == NULL)
108     {
109         return NULL;
110     }
111
112     occurrence_str = input_string;
113     result_str = replacedString;
114     len = (int)strlen (string_to_search);
115     while (*occurrence_str != '\0')
116     {
117         if (*occurrence_str == string_to_search[0] && strncmp (occurrence_str, string_to_search, len) == 0)
118         {
119             const char *N = NULL;
120             N = replacement_string;
121             while (*N != '\0')
122             {
123                 *result_str++ = *N++;
124             }
125             occurrence_str += len;
126         }
127         else
128         {
129             *result_str++ = *occurrence_str++;
130         }
131     }
132     *result_str = '\0';
133
134     return replacedString;
135 }/*-------------------------------------------------------------------------------------*/
136 char *strsub_reg(const char* input_string, const char* string_to_search, const char* replacement_string, int *ierr)
137 {
138     pcre_error_code w = PCRE_FINISHED_OK;
139
140     int Output_Start = 0;
141     int Output_End = 0;
142
143     char *replacedString = NULL;
144     wchar_t *wcreplacedString = NULL;
145
146     wchar_t *wcreplacement_string = NULL;
147     wchar_t *wcinput_string = NULL;
148
149     int len = 0;
150
151     *ierr = (int)PCRE_FINISHED_OK;
152
153     if (input_string == NULL)
154     {
155         return NULL;
156     }
157
158     if (string_to_search == NULL || replacement_string == NULL)
159     {
160         return os_strdup(input_string);
161     }
162
163     w = pcre_private((char*)input_string, (char*)string_to_search, &Output_Start, &Output_End, NULL, NULL);
164     if (w != PCRE_FINISHED_OK)
165     {
166         *ierr = (int)w;
167         return os_strdup(input_string);
168     }
169
170     wcreplacement_string = to_wide_string((char*)replacement_string);
171     wcinput_string = to_wide_string((char*)input_string);
172
173     if (wcreplacement_string == NULL)
174     {
175         FREE(wcinput_string);
176         *ierr = (int)NOT_ENOUGH_MEMORY_FOR_VECTOR;
177         return os_strdup(input_string);
178     }
179
180     len = (int)wcslen(wcreplacement_string) + (int)wcslen(wcinput_string);
181
182     wcreplacedString = (wchar_t*)MALLOC (sizeof(wchar_t) * (len + 1));
183     if (wcreplacedString == NULL)
184     {
185         FREE(replacement_string);
186         FREE(wcinput_string);
187         return NULL;
188     }
189
190     {
191         /* converts to wide characters */
192
193         wchar_t *wctail = NULL;
194
195         int wcOutput_Start = 0;
196         int wcOutput_End = 0;
197
198         char *  strOutput_Start = os_strdup(input_string);
199         char *  strOutput_End =  os_strdup(input_string);
200
201         wchar_t *wcstrOutput_Start = NULL;
202         wchar_t *wcstrOutput_End = NULL;
203
204         /* calculates positions with wide characters */
205         strOutput_Start[Output_Start] = '\0';
206         strOutput_End[Output_End] = '\0';
207
208         wcstrOutput_Start = to_wide_string(strOutput_Start);
209         wcstrOutput_End = to_wide_string(strOutput_End);
210
211         FREE(strOutput_Start);
212         FREE(strOutput_End);
213
214         if (wcstrOutput_Start)
215         {
216             wcOutput_Start = (int)wcslen(wcstrOutput_Start);
217             FREE(wcstrOutput_Start);
218         }
219         else
220         {
221             wcOutput_Start = 0;
222         }
223
224         if (wcstrOutput_End)
225         {
226             wcOutput_End = (int)wcslen(wcstrOutput_End);
227             FREE(wcstrOutput_End);
228         }
229         else
230         {
231             wcOutput_End = 0;
232         }
233
234         wcsncpy(wcreplacedString, wcinput_string, wcOutput_Start);
235         wcreplacedString[wcOutput_Start] = L'\0';
236         wcscat(wcreplacedString, wcreplacement_string);
237         wctail = wcinput_string + wcOutput_End;
238         wcscat(wcreplacedString, wctail);
239         replacedString = wide_string_to_UTF8(wcreplacedString);
240
241         FREE(wcreplacedString);
242     }
243
244     FREE(wcinput_string);
245     FREE(wcreplacement_string);
246
247     return replacedString;
248 }
249 /*-------------------------------------------------------------------------------------*/
250 wchar_t *wcssub_reg(const wchar_t* _pwstInput, const wchar_t* _pwstSearch, const wchar_t* _pwstReplace, int* _piErr)
251 {
252     pcre_error_code iPcreStatus = PCRE_FINISHED_OK;
253     int iStart = 0;
254     int iEnd = 0;
255     int iLen = 0;
256
257     wchar_t* pwstOutput = NULL;
258
259     if (_pwstInput == NULL)
260     {
261         return NULL;
262     }
263
264     if (_pwstSearch == NULL || _pwstReplace == NULL)
265     {
266         return os_wcsdup(_pwstInput);
267     }
268
269     iPcreStatus = wide_pcre_private((wchar_t*)_pwstInput, (wchar_t*)_pwstSearch, &iStart, &iEnd, NULL, NULL);
270     if (iPcreStatus != PCRE_FINISHED_OK)
271     {
272         *_piErr = iPcreStatus;
273         return os_wcsdup(_pwstInput);
274     }
275
276     //compute new size of output string
277     iLen += (int)wcslen(_pwstReplace) - (iEnd - iStart);
278
279     pwstOutput = (wchar_t*)MALLOC(sizeof(wchar_t) * (wcslen(_pwstInput) + iLen + 1));
280     memset(pwstOutput, 0x00, sizeof(wchar_t) * (wcslen(_pwstInput) + iLen + 1));
281
282     //copy start of original string
283     wcsncpy(pwstOutput, _pwstInput, iStart);
284     //copy replace string
285     wcscpy(pwstOutput + wcslen(pwstOutput), _pwstReplace);
286     //copy end of original string
287     wcscpy(pwstOutput + wcslen(pwstOutput), _pwstInput + iEnd);
288
289     *_piErr = iPcreStatus;
290     return pwstOutput;
291 }
292 /*-------------------------------------------------------------------------------------*/
293 wchar_t **wcssubst_reg(const wchar_t** _pwstInput, int _iInputSize, const wchar_t* _pwstSearch, const wchar_t* _pwstReplace, int* _piErr)
294 {
295     wchar_t** pwstOutput = NULL;
296
297     if (_pwstInput != NULL && _pwstSearch != NULL && _pwstReplace != NULL)
298     {
299         int i = 0;
300         pwstOutput = (wchar_t**)MALLOC(sizeof(wchar_t*) * _iInputSize);
301         for (i = 0 ; i < _iInputSize ; i++)
302         {
303             const wchar_t* pwst = _pwstInput[i];
304             pwstOutput[i] = wcssub_reg(pwst, _pwstSearch, _pwstReplace, _piErr);
305         }
306     }
307     return pwstOutput;
308 }
309 /*-------------------------------------------------------------------------------------*/
310 wchar_t **wcssubst(const wchar_t** _pwstInput, int _iInputSize, const wchar_t* _pwstSearch, const wchar_t* _pwstReplace)
311 {
312     wchar_t** pwstOutput = NULL;
313
314     if (_pwstInput != NULL && _pwstSearch != NULL && _pwstReplace != NULL)
315     {
316         int i = 0;
317         pwstOutput = (wchar_t**)MALLOC(sizeof(wchar_t*) * _iInputSize);
318         for (i = 0 ; i < _iInputSize ; i++)
319         {
320             const wchar_t* pwst = _pwstInput[i];
321             if (wcslen(pwst) == 0)
322             {
323                 pwstOutput[i] = os_wcsdup(L"");
324             }
325             else
326             {
327                 pwstOutput[i] = wcssub(pwst, _pwstSearch, _pwstReplace);
328             }
329         }
330     }
331     return pwstOutput;
332 }
333 /*-------------------------------------------------------------------------------------*/
334 wchar_t *wcssub(const wchar_t* _pwstInput, const wchar_t* _pwstSearch, const wchar_t* _pwstReplace)
335 {
336     int i               = 0;
337     int iOccurs         = 0;
338     size_t iReplace     = 0;
339     size_t iSearch      = 0;
340     size_t iOffset      = 0;
341
342     size_t* piStart     = NULL;
343
344     const wchar_t* pwstPos  = NULL;
345     wchar_t* pwstOutput     = NULL;
346
347     if (_pwstInput == NULL)
348     {
349         return NULL;
350     }
351
352     if (_pwstInput[0] == L'\0')
353     {
354         return os_wcsdup(L"");
355     }
356
357     if (_pwstSearch == NULL || _pwstReplace == NULL)
358     {
359         return os_wcsdup(_pwstInput);
360     }
361
362     iSearch     = wcslen(_pwstSearch);
363     iReplace    = wcslen(_pwstReplace);
364     piStart     = (size_t*)MALLOC(sizeof(size_t) * wcslen(_pwstInput));
365     pwstPos     = _pwstInput;
366
367     while (pwstPos)
368     {
369         pwstPos = wcsstr(pwstPos, _pwstSearch);
370         if (pwstPos)
371         {
372             piStart[iOccurs++]  = pwstPos - _pwstInput;
373             iOffset             += iReplace - iSearch;
374             pwstPos++;
375         }
376     }
377
378     pwstOutput = (wchar_t*)MALLOC(sizeof(wchar_t) * (wcslen(_pwstInput) + iOffset + 1));
379     memset(pwstOutput, 0x00, sizeof(wchar_t) * (wcslen(_pwstInput) + iOffset + 1));
380
381     if (iOccurs == 0)
382     {
383         wcscpy(pwstOutput, _pwstInput);
384     }
385     else
386     {
387         for (i = 0 ; i < iOccurs ; i++)
388         {
389             if (i == 0)
390             {
391                 //copy start of original string
392                 wcsncpy(pwstOutput, _pwstInput, piStart[i]);
393             }
394             else
395             {
396                 //copy start of original string
397                 wcsncpy(pwstOutput + wcslen(pwstOutput), _pwstInput + piStart[i - 1] + iSearch, piStart[i] - (iSearch + piStart[i - 1]));
398             }
399             //copy replace string
400             wcscpy(pwstOutput + wcslen(pwstOutput), _pwstReplace);
401         }
402         //copy end of original string
403         wcscpy(pwstOutput + wcslen(pwstOutput), _pwstInput + piStart[iOccurs - 1] + iSearch);
404     }
405
406     FREE(piStart);
407     return pwstOutput;
408 }
409 /*-------------------------------------------------------------------------------------*/