2 Unix SMB/CIFS implementation.
4 provide access to string functions
6 Copyright (C) Andrew Tridgell 2005
7 Copyright (C) Jelmer Vernooij 2005 (substr)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "scripting/ejs/smbcalls.h"
26 #include "lib/appweb/ejs/ejs.h"
30 var len = strlen(str);
32 static int ejs_strlen(MprVarHandle eid
, int argc
, char **argv
)
35 ejsSetErrorMsg(eid
, "strlen invalid arguments");
38 mpr_Return(eid
, mprCreateIntegerVar(strlen_m(argv
[0])));
44 var s = strlower("UPPER");
46 static int ejs_strlower(MprVarHandle eid
, int argc
, char **argv
)
50 ejsSetErrorMsg(eid
, "strlower invalid arguments");
53 s
= strlower_talloc(mprMemCtx(), argv
[0]);
54 mpr_Return(eid
, mprString(s
));
61 var s = strupper("lower");
63 static int ejs_strupper(MprVarHandle eid
, int argc
, char **argv
)
67 ejsSetErrorMsg(eid
, "strupper invalid arguments");
70 s
= strupper_talloc(mprMemCtx(), argv
[0]);
71 mpr_Return(eid
, mprString(s
));
78 var s = strstr(string, substring);
80 static int ejs_strstr(MprVarHandle eid
, int argc
, char **argv
)
84 ejsSetErrorMsg(eid
, "strstr invalid arguments");
87 s
= strstr(argv
[0], argv
[1]);
88 mpr_Return(eid
, mprString(s
));
94 list = split(".", "a.foo.bar");
96 NOTE: does not take a regular expression, unlink perl split()
98 static int ejs_split(MprVarHandle eid
, int argc
, char **argv
)
100 const char *separator
;
104 TALLOC_CTX
*tmp_ctx
= talloc_new(mprMemCtx());
106 ejsSetErrorMsg(eid
, "split invalid arguments");
112 ret
= mprObject("list");
114 while ((p
= strstr(s
, separator
))) {
115 char *s2
= talloc_strndup(tmp_ctx
, s
, (int)(p
-s
));
116 mprAddArray(&ret
, count
++, mprString(s2
));
118 s
= p
+ strlen(separator
);
121 mprAddArray(&ret
, count
++, mprString(s
));
123 talloc_free(tmp_ctx
);
124 mpr_Return(eid
, ret
);
130 str = substr(orig[, start_offset[, length]]);
133 if start_offset < 0 then start_offset+=strlen(orig)
134 if length < 0 then length+=strlen(orig)-start_offset
136 (as found in many other languages)
138 static int ejs_substr(MprVarHandle eid
, int argc
, struct MprVar
**argv
)
140 int start_offset
= 0;
145 if (argc
< 1 || argc
> 3 ||
146 argv
[0]->type
!= MPR_TYPE_STRING
) {
147 ejsSetErrorMsg(eid
, "substr invalid arguments");
152 mpr_Return(eid
, *argv
[0]);
156 orig
= mprToString(argv
[0]);
157 start_offset
= mprToInt(argv
[1]);
158 length
= strlen(orig
);
159 if (start_offset
< 0) start_offset
+= strlen(orig
);
160 if (start_offset
< 0 || start_offset
> strlen(orig
)) {
161 ejsSetErrorMsg(eid
, "substr arg 2 out of bounds");
166 length
= mprToInt(argv
[2]);
167 if (length
< 0) length
+= strlen(orig
) - start_offset
;
168 if (length
< 0 || length
+start_offset
> strlen(orig
)) {
169 ejsSetErrorMsg(eid
, "substr arg 3 out of bounds");
174 target
= talloc_strndup(mprMemCtx(), orig
+start_offset
, length
);
176 mpr_Return(eid
, mprString(target
));
185 str = join("DC=", list);
187 static int ejs_join(MprVarHandle eid
, int argc
, struct MprVar
**argv
)
190 const char *separator
;
193 TALLOC_CTX
*tmp_ctx
= talloc_new(mprMemCtx());
195 argv
[0]->type
!= MPR_TYPE_STRING
||
196 argv
[1]->type
!= MPR_TYPE_OBJECT
) {
197 ejsSetErrorMsg(eid
, "join invalid arguments");
201 separator
= mprToString(argv
[0]);
202 list
= mprToArray(tmp_ctx
, argv
[1]);
204 if (list
== NULL
|| list
[0] == NULL
) {
205 talloc_free(tmp_ctx
);
206 mpr_Return(eid
, mprString(NULL
));
210 ret
= talloc_strdup(tmp_ctx
, list
[0]);
214 for (i
=1;list
[i
];i
++) {
215 ret
= talloc_asprintf_append(ret
, "%s%s", separator
, list
[i
]);
220 mpr_Return(eid
, mprString(ret
));
221 talloc_free(tmp_ctx
);
224 ejsSetErrorMsg(eid
, "out of memory");
230 blergh, C certainly makes this hard!
232 str = sprintf("i=%d s=%7s", 7, "foo");
234 static int ejs_sprintf(MprVarHandle eid
, int argc
, struct MprVar
**argv
)
240 char *(*_asprintf_append
)(char *, const char *, ...);
242 if (argc
< 1 || argv
[0]->type
!= MPR_TYPE_STRING
) {
243 ejsSetErrorMsg(eid
, "sprintf invalid arguments");
246 format
= mprToString(argv
[0]);
247 tmp_ctx
= talloc_new(mprMemCtx());
248 ret
= talloc_strdup(tmp_ctx
, "");
250 /* avoid all the format string warnings */
251 _asprintf_append
= talloc_asprintf_append
;
256 while ((p
= strchr(format
, '%'))) {
258 int len
, len_count
=0;
260 ret
= talloc_asprintf_append(ret
, "%*.*s",
261 (int)(p
-format
), (int)(p
-format
),
263 if (ret
== NULL
) goto failed
;
264 format
+= (int)(p
-format
);
265 len
= strcspn(p
+1, "dxuiofgGpXeEFcs%") + 1;
266 fmt2
= talloc_strndup(tmp_ctx
, p
, len
+1);
267 if (fmt2
== NULL
) goto failed
;
268 len_count
= count_chars(fmt2
, '*');
269 /* find the type string */
271 while (tstr
> fmt2
&& isalpha((unsigned char)tstr
[-1])) {
274 if (strcmp(tstr
, "%") == 0) {
275 ret
= talloc_asprintf_append(ret
, "%%");
283 argc
< a
+ len_count
+ 1) {
284 ejsSetErrorMsg(eid
, "sprintf: not enough arguments for format");
287 #define FMT_ARG(fn, type) do { \
288 switch (len_count) { \
290 ret = _asprintf_append(ret, fmt2, \
291 (type)fn(argv[a])); \
294 ret = _asprintf_append(ret, fmt2, \
295 (int)mprVarToNumber(argv[a]), \
296 (type)fn(argv[a+1])); \
299 ret = _asprintf_append(ret, fmt2, \
300 (int)mprVarToNumber(argv[a]), \
301 (int)mprVarToNumber(argv[a+1]), \
302 (type)fn(argv[a+2])); \
305 a += len_count + 1; \
311 if (strcmp(tstr
, "s")==0) FMT_ARG(mprToString
, const char *);
312 else if (strcmp(tstr
, "c")==0) FMT_ARG(*mprToString
, char);
313 else if (strcmp(tstr
, "d")==0) FMT_ARG(mprVarToNumber
, int);
314 else if (strcmp(tstr
, "ld")==0) FMT_ARG(mprVarToNumber
, long);
315 else if (strcmp(tstr
, "lld")==0) FMT_ARG(mprVarToNumber
, long long);
316 else if (strcmp(tstr
, "x")==0) FMT_ARG(mprVarToNumber
, int);
317 else if (strcmp(tstr
, "lx")==0) FMT_ARG(mprVarToNumber
, long);
318 else if (strcmp(tstr
, "llx")==0) FMT_ARG(mprVarToNumber
, long long);
319 else if (strcmp(tstr
, "X")==0) FMT_ARG(mprVarToNumber
, int);
320 else if (strcmp(tstr
, "lX")==0) FMT_ARG(mprVarToNumber
, long);
321 else if (strcmp(tstr
, "llX")==0) FMT_ARG(mprVarToNumber
, long long);
322 else if (strcmp(tstr
, "u")==0) FMT_ARG(mprVarToNumber
, int);
323 else if (strcmp(tstr
, "lu")==0) FMT_ARG(mprVarToNumber
, long);
324 else if (strcmp(tstr
, "llu")==0) FMT_ARG(mprVarToNumber
, long long);
325 else if (strcmp(tstr
, "i")==0) FMT_ARG(mprVarToNumber
, int);
326 else if (strcmp(tstr
, "li")==0) FMT_ARG(mprVarToNumber
, long);
327 else if (strcmp(tstr
, "lli")==0) FMT_ARG(mprVarToNumber
, long long);
328 else if (strcmp(tstr
, "o")==0) FMT_ARG(mprVarToNumber
, int);
329 else if (strcmp(tstr
, "lo")==0) FMT_ARG(mprVarToNumber
, long);
330 else if (strcmp(tstr
, "llo")==0) FMT_ARG(mprVarToNumber
, long long);
331 else if (strcmp(tstr
, "f")==0) FMT_ARG(mprVarToFloat
, double);
332 else if (strcmp(tstr
, "lf")==0) FMT_ARG(mprVarToFloat
, double);
333 else if (strcmp(tstr
, "g")==0) FMT_ARG(mprVarToFloat
, double);
334 else if (strcmp(tstr
, "lg")==0) FMT_ARG(mprVarToFloat
, double);
335 else if (strcmp(tstr
, "e")==0) FMT_ARG(mprVarToFloat
, double);
336 else if (strcmp(tstr
, "le")==0) FMT_ARG(mprVarToFloat
, double);
337 else if (strcmp(tstr
, "E")==0) FMT_ARG(mprVarToFloat
, double);
338 else if (strcmp(tstr
, "lE")==0) FMT_ARG(mprVarToFloat
, double);
339 else if (strcmp(tstr
, "F")==0) FMT_ARG(mprVarToFloat
, double);
340 else if (strcmp(tstr
, "lF")==0) FMT_ARG(mprVarToFloat
, double);
342 ejsSetErrorMsg(eid
, "sprintf: unknown format string '%s'", fmt2
);
348 ret
= talloc_asprintf_append(ret
, "%s", format
);
349 mpr_Return(eid
, mprString(ret
));
350 talloc_free(tmp_ctx
);
354 talloc_free(tmp_ctx
);
359 used to build your own print function
360 str = vsprintf(args);
362 static int ejs_vsprintf(MprVarHandle eid
, int argc
, struct MprVar
**argv
)
364 struct MprVar
**args
, *len
, *v
;
366 if (argc
!= 1 || argv
[0]->type
!= MPR_TYPE_OBJECT
) {
367 ejsSetErrorMsg(eid
, "vsprintf invalid arguments");
371 len
= mprGetProperty(v
, "length", NULL
);
373 ejsSetErrorMsg(eid
, "vsprintf takes an array");
376 length
= mprToInt(len
);
377 args
= talloc_array(mprMemCtx(), struct MprVar
*, length
);
382 for (i
=0;i
<length
;i
++) {
384 mprItoa(i
, idx
, sizeof(idx
));
385 args
[i
] = mprGetProperty(v
, idx
, NULL
);
388 ret
= ejs_sprintf(eid
, length
, args
);
395 encode a string, replacing all non-alpha with %02x form
397 static int ejs_encodeURIComponent(MprVarHandle eid
, int argc
, char **argv
)
403 ejsSetErrorMsg(eid
, "encodeURIComponent invalid arguments");
410 if (!isalnum(s
[i
])) count
++;
413 ret
= talloc_size(mprMemCtx(), i
+ count
*2 + 1);
417 for (i
=j
=0;s
[i
];i
++,j
++) {
418 if (!isalnum(s
[i
])) {
419 snprintf(ret
+j
, 4, "%%%02X", (unsigned)s
[i
]);
426 mpr_Return(eid
, mprString(ret
));
432 encode a string, replacing all non-alpha of %02x form
434 static int ejs_decodeURIComponent(MprVarHandle eid
, int argc
, char **argv
)
440 ejsSetErrorMsg(eid
, "decodeURIComponent invalid arguments");
446 ret
= talloc_size(mprMemCtx(), strlen(s
) + 1);
451 for (i
=j
=0;s
[i
];i
++,j
++) {
454 if (sscanf(s
+i
+1, "%02X", &c
) != 1) {
455 ejsSetErrorMsg(eid
, "decodeURIComponent bad format");
463 if (!isalnum(s
[i
])) count
++;
467 mpr_Return(eid
, mprString(ret
));
473 initialise string ejs subsystem
475 static int ejs_string_init(MprVarHandle eid
, int argc
, struct MprVar
**argv
)
477 struct MprVar
*obj
= mprInitObject(eid
, "string", argc
, argv
);
479 mprSetCFunction(obj
, "substr", ejs_substr
);
480 mprSetStringCFunction(obj
, "strlen", ejs_strlen
);
481 mprSetStringCFunction(obj
, "strlower", ejs_strlower
);
482 mprSetStringCFunction(obj
, "strupper", ejs_strupper
);
483 mprSetStringCFunction(obj
, "strstr", ejs_strstr
);
484 mprSetStringCFunction(obj
, "split", ejs_split
);
485 mprSetCFunction(obj
, "join", ejs_join
);
486 mprSetCFunction(obj
, "sprintf", ejs_sprintf
);
487 mprSetCFunction(obj
, "vsprintf", ejs_vsprintf
);
488 mprSetStringCFunction(obj
, "encodeURIComponent", ejs_encodeURIComponent
);
489 mprSetStringCFunction(obj
, "decodeURIComponent", ejs_decodeURIComponent
);
495 setup C functions that be called from ejs
497 void smb_setup_ejs_string(void)
499 ejsDefineCFunction(-1, "string_init", ejs_string_init
, NULL
, MPR_VAR_SCRIPT_HANDLE
);