tizen 2.3.1 release
[framework/uifw/embryo.git] / src / lib / embryo_str.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #ifdef STDC_HEADERS
6 # include <stdlib.h>
7 # include <stddef.h>
8 #else
9 # ifdef HAVE_STDLIB_H
10 #  include <stdlib.h>
11 # endif
12 #endif
13 #ifdef HAVE_ALLOCA_H
14 # include <alloca.h>
15 #elif !defined alloca
16 # ifdef __GNUC__
17 #  define alloca __builtin_alloca
18 # elif defined _AIX
19 #  define alloca __alloca
20 # elif defined _MSC_VER
21 #  include <malloc.h>
22 #  define alloca _alloca
23 # elif !defined HAVE_ALLOCA
24 #  ifdef  __cplusplus
25 extern "C"
26 #  endif
27 void *alloca (size_t);
28 # endif
29 #endif
30
31 #ifdef HAVE_EXOTIC
32 # include <Exotic.h>
33 #endif
34
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <fnmatch.h>
39
40 #include "Embryo.h"
41 #include "embryo_private.h"
42
43 #define STRGET(ep, str, par) { \
44    Embryo_Cell *___cptr; \
45    str = NULL; \
46    if ((___cptr = embryo_data_address_get(ep, par))) { \
47         int ___l; \
48         ___l = embryo_data_string_length_get(ep, ___cptr); \
49         (str) = alloca(___l + 1); \
50         if (str) embryo_data_string_get(ep, ___cptr, str); \
51      } }
52 #define STRSET(ep, par, str) { \
53    Embryo_Cell *___cptr; \
54    if ((___cptr = embryo_data_address_get(ep, par))) { \
55       embryo_data_string_set(ep, str, ___cptr); \
56    } }
57
58 /* exported string api */
59
60 static Embryo_Cell
61 _embryo_str_atoi(Embryo_Program *ep, Embryo_Cell *params)
62 {
63    char *s1;
64
65    /* params[1] = str */
66    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
67    STRGET(ep, s1, params[1]);
68    if (!s1) return 0;
69    return (Embryo_Cell)atoi(s1);
70 }
71
72 static Embryo_Cell
73 _embryo_str_fnmatch(Embryo_Program *ep, Embryo_Cell *params)
74 {
75    char *s1, *s2;
76
77    /* params[1] = glob */
78    /* params[2] = str */
79    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
80    STRGET(ep, s1, params[1]);
81    STRGET(ep, s2, params[2]);
82    if ((!s1) || (!s2)) return -1;
83    return (Embryo_Cell)fnmatch(s1, s2, 0);
84 }
85
86 static Embryo_Cell
87 _embryo_str_strcmp(Embryo_Program *ep, Embryo_Cell *params)
88 {
89    char *s1, *s2;
90
91    /* params[1] = str1 */
92    /* params[2] = str2 */
93    if (params[0] != (2 * sizeof(Embryo_Cell))) return -1;
94    STRGET(ep, s1, params[1]);
95    STRGET(ep, s2, params[2]);
96    if ((!s1) || (!s2)) return -1;
97    return (Embryo_Cell)strcmp(s1, s2);
98 }
99
100 static Embryo_Cell
101 _embryo_str_strncmp(Embryo_Program *ep, Embryo_Cell *params)
102 {
103    char *s1, *s2;
104
105    /* params[1] = str1 */
106    /* params[2] = str2 */
107    /* params[3] = n */
108    if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
109    if (params[3] < 0) params[3] = 0;
110    STRGET(ep, s1, params[1]);
111    STRGET(ep, s2, params[2]);
112    if ((!s1) || (!s2)) return -1;
113    return (Embryo_Cell)strncmp(s1, s2, (size_t)params[3]);
114 }
115
116 static Embryo_Cell
117 _embryo_str_strcpy(Embryo_Program *ep, Embryo_Cell *params)
118 {
119    char *s1;
120
121    /* params[1] = dst */
122    /* params[2] = str */
123    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
124    STRGET(ep, s1, params[2]);
125    if (!s1) return 0;
126    STRSET(ep, params[1], s1);
127    return 0;
128 }
129
130 static Embryo_Cell
131 _embryo_str_strncpy(Embryo_Program *ep, Embryo_Cell *params)
132 {
133    char *s1;
134    int l;
135
136    /* params[1] = dst */
137    /* params[2] = str */
138    /* params[3] = n */
139    if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
140    if (params[3] < 0) params[3] = 0;
141    STRGET(ep, s1, params[2]);
142    if (!s1) return 0;
143    l = strlen(s1);
144    if (l > params[3]) s1[params[3]] = 0;
145    STRSET(ep, params[1], s1);
146    return 0;
147 }
148
149 static Embryo_Cell
150 _embryo_str_strlen(Embryo_Program *ep, Embryo_Cell *params)
151 {
152    char *s1;
153
154    /* params[1] = str */
155    if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
156    STRGET(ep, s1, params[1]);
157    if (!s1) return 0;
158    return (Embryo_Cell)strlen(s1);
159 }
160
161 static Embryo_Cell
162 _embryo_str_strcat(Embryo_Program *ep, Embryo_Cell *params)
163 {
164    char *s1, *s2, *s3;
165
166    /* params[1] = dsr */
167    /* params[2] = str */
168    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
169    STRGET(ep, s1, params[1]);
170    STRGET(ep, s2, params[2]);
171    if ((!s1) || (!s2)) return 0;
172    s3 = alloca(strlen(s1) + strlen(s2) + 1);
173    if (!s3) return 0;
174    strcpy(s3, s1);
175    strcat(s3, s2);
176    STRSET(ep, params[1], s3);
177    return 0;
178 }
179
180 static Embryo_Cell
181 _embryo_str_strncat(Embryo_Program *ep, Embryo_Cell *params)
182 {
183    char *s1, *s2, *s3;
184    int l1, l2;
185
186    /* params[1] = dst */
187    /* params[2] = str */
188    /* params[3] = n */
189    if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
190    if (params[3] < 0) params[3] = 0;
191    STRGET(ep, s1, params[1]);
192    STRGET(ep, s2, params[2]);
193    if ((!s1) || (!s2)) return 0;
194    l1 = strlen(s1);
195    l2 = strlen(s2);
196    s3 = alloca(l1 + l2 + 1);
197    if (!s3) return 0;
198    strcpy(s3, s1);
199    strncat(s3, s2, params[3]);
200    if (l2 >= params[3]) s3[l1 + params[3]] = 0;
201    STRSET(ep, params[1], s3);
202    return 0;
203 }
204
205 static Embryo_Cell
206 _embryo_str_strprep(Embryo_Program *ep, Embryo_Cell *params)
207 {
208    char *s1, *s2, *s3;
209
210    /* params[1] = dst */
211    /* params[2] = str */
212    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
213    STRGET(ep, s1, params[1]);
214    STRGET(ep, s2, params[2]);
215    if ((!s1) || (!s2)) return 0;
216    s3 = alloca(strlen(s1) + strlen(s2) + 1);
217    if (!s3) return 0;
218    strcpy(s3, s2);
219    strcat(s3, s1);
220    STRSET(ep, params[1], s3);
221    return 0;
222 }
223
224 static Embryo_Cell
225 _embryo_str_strnprep(Embryo_Program *ep, Embryo_Cell *params)
226 {
227    char *s1, *s2, *s3;
228    int l1, l2;
229
230    /* params[1] = dst */
231    /* params[2] = str */
232    /* params[3] = n */
233    if (params[0] != (3 * sizeof(Embryo_Cell))) return 0;
234    if (params[3] < 0) params[3] = 0;
235    STRGET(ep, s1, params[1]);
236    STRGET(ep, s2, params[2]);
237    if ((!s1) || (!s2)) return 0;
238    l1 = strlen(s1);
239    l2 = strlen(s2);
240    s3 = alloca(l1 + l2 + 1);
241    if (!s3) return 0;
242    strncpy(s3, s2, params[3]);
243    if (params[3] <= l2) s3[params[3]] = 0;
244    strcat(s3, s1);
245    STRSET(ep, params[1], s3);
246    return 0;
247 }
248
249 static Embryo_Cell
250 _embryo_str_strcut(Embryo_Program *ep, Embryo_Cell *params)
251 {
252    char *s1, *s2;
253    int l1;
254
255    /* params[1] = dst */
256    /* params[2] = str */
257    /* params[3] = n */
258    /* params[4] = n2 */
259    if (params[0] != (4 * sizeof(Embryo_Cell))) return 0;
260    if (params[3] < 0) params[3] = 0;
261    if (params[4] < params[3]) params[4] = params[3];
262    STRGET(ep, s1, params[2]);
263    if (!s1) return 0;
264    l1 = strlen(s1);
265    if (params[3] >= l1) params[3] = l1;
266    if (params[4] >= l1) params[4] = l1;
267    if (params[4] == params[3])
268      {
269         STRSET(ep, params[1], "");
270         return 0;
271      }
272    s2 = alloca(params[4] - params[3] + 1);
273    strncpy(s2, s1 + params[3], params[4] - params[3]);
274    s2[params[4] - params[3]] = 0;
275    STRSET(ep, params[1], s2);
276    return 0;
277 }
278
279 static Embryo_Cell
280 _embryo_str_snprintf(Embryo_Program *ep, Embryo_Cell *params)
281 {
282    char *s1, *s2;
283    int i, o;
284    int inesc = 0;
285    int insub = 0;
286    int p, pnum;
287
288    /* params[1] = buf */
289    /* params[2] = bufsize */
290    /* params[3] = format_string */
291    /* params[4] = first arg ... */
292    if (params[0] < (Embryo_Cell)(3 * sizeof(Embryo_Cell))) return 0;
293    if (params[2] <= 0) return 0;
294    STRGET(ep, s1, params[3]);
295    if (!s1) return -1;
296    s2 = alloca(params[2] + 1);
297    if (!s2) return -1;
298    s2[0] = 0;
299    pnum = (params[0] / sizeof(Embryo_Cell)) - 3;
300    for (p = 0, o = 0, i = 0; (s1[i]) && (o < (params[2] - 1)) && (p < (pnum + 1)); i++)
301      {
302         if ((!inesc) && (!insub))
303           {
304              if      (s1[i] == '\\') inesc = 1;
305              else if (s1[i] == '%')  insub = 1;
306              if ((!inesc) && (!insub))
307                {
308                   s2[o] = s1[i];
309                   o++;
310                }
311           }
312         else
313           {
314              Embryo_Cell *cptr;
315
316              if (inesc)
317                {
318                   switch (s1[i])
319                     {
320                      case 't':
321                        s2[o] = '\t';
322                        o++;
323                        break;
324                      case 'n':
325                        s2[o] = '\n';
326                        o++;
327                        break;
328                      default:
329                        s2[o] = s1[i];
330                        o++;
331                        break;
332                     }
333                   inesc = 0;
334                }
335              if ((insub) && (s1[i] == '%')) pnum++;
336              if ((insub) && (p < pnum))
337                {
338                   switch (s1[i])
339                     {
340                      case '%':
341                        s2[o] = '%';
342                        o++;
343                        break;
344                      case 'c':
345                        cptr = embryo_data_address_get(ep, params[4 + p]);
346                        if (cptr) s2[o] = (char)(*cptr);
347                        p++;
348                        o++;
349                        break;
350                      case 'i':
351                      case 'd':
352                      case 'x':
353                      case 'X':
354                          {
355                             char fmt[10] = "";
356                             char tmp[256] = "";
357                             int l;
358
359                             if      (s1[i] == 'i') strcpy(fmt, "%i");
360                             else if (s1[i] == 'd') strcpy(fmt, "%d");
361                             else if (s1[i] == 'x') strcpy(fmt, "%x");
362                             else if (s1[i] == 'X') strcpy(fmt, "%08x");
363                             cptr = embryo_data_address_get(ep, params[4 + p]);
364                             if (cptr) snprintf(tmp, sizeof(tmp), fmt, (int)(*cptr));
365                             l = strlen(tmp);
366                             if ((o + l) > (params[2] - 1))
367                               {
368                                  l = params[2] - 1 - o;
369                                  if (l < 0) l = 0;
370                                  tmp[l] = 0;
371                               }
372                             strcpy(s2 + o, tmp);
373                             o += l;
374                             p++;
375                          }
376                        break;
377                      case 'f':
378                          {
379                             char tmp[256] = "";
380                             int l;
381
382                             cptr = embryo_data_address_get(ep, params[4 + p]);
383                             if (cptr) snprintf(tmp, sizeof(tmp), "%f", (double)EMBRYO_CELL_TO_FLOAT(*cptr));
384                             l = strlen(tmp);
385                             if ((o + l) > (params[2] - 1))
386                               {
387                                  l = params[2] - 1 - o;
388                                  if (l < 0) l = 0;
389                                  tmp[l] = 0;
390                               }
391                             strcpy(s2 + o, tmp);
392                             o += l;
393                             p++;
394                          }
395                        break;
396                      case 's':
397                          {
398                             char *tmp;
399                             int l;
400
401                             STRGET(ep, tmp, params[4 + p]);
402              if (tmp)
403                {
404                   l = strlen(tmp);
405                   if ((o + l) > (params[2] - 1))
406                     {
407                        l = params[2] - 1 - o;
408                        if (l < 0) l = 0;
409                        tmp[l] = 0;
410                     }
411                   strcpy(s2 + o, tmp);
412                   o += l;
413                }
414                             p++;
415                          }
416                        break;
417                      default:
418                        break;
419                     }
420                   insub = 0;
421                }
422              else if (insub)
423                insub = 0;
424           }
425      }
426    s2[o] = 0;
427
428    STRSET(ep, params[1], s2);
429    return o;
430 }
431
432 static Embryo_Cell
433 _embryo_str_strstr(Embryo_Program *ep, Embryo_Cell *params)
434 {
435    char *s1, *s2, *p;
436
437    /* params[1] = str */
438    /* params[2] = ndl */
439    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
440    STRGET(ep, s1, params[1]);
441    STRGET(ep, s2, params[2]);
442    if ((!s1) || (!s2)) return -1;
443    p = strstr(s1, s2);
444    if (!p) return -1;
445    return (Embryo_Cell)(p - s1);
446 }
447
448 static Embryo_Cell
449 _embryo_str_strchr(Embryo_Program *ep, Embryo_Cell *params)
450 {
451    char *s1, *s2, *p;
452
453    /* params[1] = str */
454    /* params[2] = ch */
455    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
456    STRGET(ep, s1, params[1]);
457    STRGET(ep, s2, params[2]);
458    if ((!s1) || (!s2)) return -1;
459    p = strchr(s1, s2[0]);
460    if (!p) return -1;
461    return (Embryo_Cell)(p - s1);
462 }
463
464 static Embryo_Cell
465 _embryo_str_strrchr(Embryo_Program *ep, Embryo_Cell *params)
466 {
467    char *s1, *s2, *p;
468
469    /* params[1] = str */
470    /* params[2] = ch */
471    if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
472    STRGET(ep, s1, params[1]);
473    STRGET(ep, s2, params[2]);
474    if ((!s1) || (!s2)) return -1;
475    p = strrchr(s1, s2[0]);
476    if (!p) return -1;
477    return (Embryo_Cell)(p - s1);
478 }
479
480 /* functions used by the rest of embryo */
481
482 void
483 _embryo_str_init(Embryo_Program *ep)
484 {
485    embryo_program_native_call_add(ep, "atoi",     _embryo_str_atoi);
486    embryo_program_native_call_add(ep, "fnmatch",  _embryo_str_fnmatch);
487    embryo_program_native_call_add(ep, "strcmp",   _embryo_str_strcmp);
488    embryo_program_native_call_add(ep, "strncmp",  _embryo_str_strncmp);
489    embryo_program_native_call_add(ep, "strcpy",   _embryo_str_strcpy);
490    embryo_program_native_call_add(ep, "strncpy",  _embryo_str_strncpy);
491    embryo_program_native_call_add(ep, "strlen",   _embryo_str_strlen);
492    embryo_program_native_call_add(ep, "strcat",   _embryo_str_strcat);
493    embryo_program_native_call_add(ep, "strncat",  _embryo_str_strncat);
494    embryo_program_native_call_add(ep, "strprep",  _embryo_str_strprep);
495    embryo_program_native_call_add(ep, "strnprep", _embryo_str_strnprep);
496    embryo_program_native_call_add(ep, "strcut",   _embryo_str_strcut);
497    embryo_program_native_call_add(ep, "snprintf", _embryo_str_snprintf);
498    embryo_program_native_call_add(ep, "strstr",   _embryo_str_strstr);
499    embryo_program_native_call_add(ep, "strchr",   _embryo_str_strchr);
500    embryo_program_native_call_add(ep, "strrchr",  _embryo_str_strrchr);
501 }