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 3 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, see <http://www.gnu.org/licenses/>.
24 #include "scripting/ejs/smbcalls.h"
25 #include "lib/appweb/ejs/ejs.h"
29 var len = strlen(str);
31 static int ejs_strlen(MprVarHandle eid, int argc, char **argv)
34 ejsSetErrorMsg(eid, "strlen invalid arguments");
37 mpr_Return(eid, mprCreateIntegerVar(strlen_m(argv[0])));
43 var s = strlower("UPPER");
45 static int ejs_strlower(MprVarHandle eid, int argc, char **argv)
49 ejsSetErrorMsg(eid, "strlower invalid arguments");
52 s = strlower_talloc(mprMemCtx(), argv[0]);
53 mpr_Return(eid, mprString(s));
60 var s = strupper("lower");
62 static int ejs_strupper(MprVarHandle eid, int argc, char **argv)
66 ejsSetErrorMsg(eid, "strupper invalid arguments");
69 s = strupper_talloc(mprMemCtx(), argv[0]);
70 mpr_Return(eid, mprString(s));
77 var s = strstr(string, substring);
79 static int ejs_strstr(MprVarHandle eid, int argc, char **argv)
83 ejsSetErrorMsg(eid, "strstr invalid arguments");
86 s = strstr(argv[0], argv[1]);
87 mpr_Return(eid, mprString(s));
93 var s = strspn(string, legal_chars_string);
95 static int ejs_strspn(MprVarHandle eid, int argc, char **argv)
99 ejsSetErrorMsg(eid, "strspn invalid arguments");
102 len = strspn(argv[0], argv[1]);
103 mpr_Return(eid, mprCreateIntegerVar(len));
109 list = split(".", "a.foo.bar");
110 list = split(".", "a.foo.bar", count);
112 count is an optional count of how many splits to make
114 NOTE: does not take a regular expression, unlike perl split()
116 static int ejs_split(MprVarHandle eid, int argc, struct MprVar **argv)
118 const char *separator, *s;
121 int count = 0, maxcount=0;
122 TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
124 argv[0]->type != MPR_TYPE_STRING ||
125 argv[1]->type != MPR_TYPE_STRING) {
126 ejsSetErrorMsg(eid, "split invalid arguments");
129 separator = mprToString(argv[0]);
130 s = mprToString(argv[1]);
132 maxcount = mprToInt(argv[2]);
135 ret = mprArray("list");
137 while ((p = strstr(s, separator))) {
138 char *s2 = talloc_strndup(tmp_ctx, s, (int)(p-s));
139 mprAddArray(&ret, count++, mprString(s2));
141 s = p + strlen(separator);
142 if (maxcount != 0 && count >= maxcount) {
147 mprAddArray(&ret, count++, mprString(s));
149 talloc_free(tmp_ctx);
150 mpr_Return(eid, ret);
156 str = substr(orig[, start_offset[, length]]);
159 if start_offset < 0 then start_offset+=strlen(orig)
160 if length < 0 then length+=strlen(orig)-start_offset
162 (as found in many other languages)
164 static int ejs_substr(MprVarHandle eid, int argc, struct MprVar **argv)
166 int start_offset = 0;
171 if (argc < 1 || argc > 3 ||
172 argv[0]->type != MPR_TYPE_STRING) {
173 ejsSetErrorMsg(eid, "substr invalid arguments");
178 mpr_Return(eid, *argv[0]);
182 orig = mprToString(argv[0]);
183 start_offset = mprToInt(argv[1]);
184 length = strlen(orig);
185 if (start_offset < 0) start_offset += strlen(orig);
186 if (start_offset < 0 || start_offset > strlen(orig)) {
187 ejsSetErrorMsg(eid, "substr arg 2 out of bounds ([%s], %d)", orig, start_offset);
192 length = mprToInt(argv[2]);
193 if (length < 0) length += strlen(orig) - start_offset;
194 if (length < 0 || length+start_offset > strlen(orig)) {
195 ejsSetErrorMsg(eid, "substr arg 3 out of bounds ([%s], %d, %d)", orig, start_offset, length);
200 target = talloc_strndup(mprMemCtx(), orig+start_offset, length);
202 mpr_Return(eid, mprString(target));
211 str = join("DC=", list);
213 static int ejs_join(MprVarHandle eid, int argc, struct MprVar **argv)
216 const char *separator;
219 TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
221 argv[0]->type != MPR_TYPE_STRING ||
222 argv[1]->type != MPR_TYPE_OBJECT) {
223 ejsSetErrorMsg(eid, "join invalid arguments");
227 separator = mprToString(argv[0]);
228 list = mprToArray(tmp_ctx, argv[1]);
230 if (list == NULL || list[0] == NULL) {
231 talloc_free(tmp_ctx);
232 mpr_Return(eid, mprString(NULL));
236 ret = talloc_strdup(tmp_ctx, list[0]);
240 for (i=1;list[i];i++) {
241 ret = talloc_asprintf_append_buffer(ret, "%s%s", separator, list[i]);
246 mpr_Return(eid, mprString(ret));
247 talloc_free(tmp_ctx);
250 ejsSetErrorMsg(eid, "out of memory");
256 blergh, C certainly makes this hard!
258 str = sprintf("i=%d s=%7s", 7, "foo");
260 typedef char *(*_asprintf_append_t)(char *, const char *, ...);
261 static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv)
267 _asprintf_append_t _asprintf_append;
269 if (argc < 1 || argv[0]->type != MPR_TYPE_STRING) {
270 ejsSetErrorMsg(eid, "sprintf invalid arguments");
273 format = mprToString(argv[0]);
274 tmp_ctx = talloc_new(mprMemCtx());
275 ret = talloc_strdup(tmp_ctx, "");
277 /* avoid all the format string warnings */
278 _asprintf_append = (_asprintf_append_t)talloc_asprintf_append_buffer;
283 while ((p = strchr(format, '%'))) {
285 int len, len_count=0;
287 ret = talloc_asprintf_append_buffer(ret, "%*.*s",
288 (int)(p-format), (int)(p-format),
290 if (ret == NULL) goto failed;
291 format += (int)(p-format);
292 len = strcspn(p+1, "dxuiofgGpXeEFcs%") + 1;
293 fmt2 = talloc_strndup(tmp_ctx, p, len+1);
294 if (fmt2 == NULL) goto failed;
295 len_count = count_chars(fmt2, '*');
296 /* find the type string */
298 while (tstr > fmt2 && isalpha((unsigned char)tstr[-1])) {
301 if (strcmp(tstr, "%") == 0) {
302 ret = talloc_asprintf_append_buffer(ret, "%%");
310 argc < a + len_count + 1) {
311 ejsSetErrorMsg(eid, "sprintf: not enough arguments for format");
314 #define FMT_ARG(fn, type) do { \
315 switch (len_count) { \
317 ret = _asprintf_append(ret, fmt2, \
318 (type)fn(argv[a])); \
321 ret = _asprintf_append(ret, fmt2, \
322 (int)mprVarToNumber(argv[a]), \
323 (type)fn(argv[a+1])); \
326 ret = _asprintf_append(ret, fmt2, \
327 (int)mprVarToNumber(argv[a]), \
328 (int)mprVarToNumber(argv[a+1]), \
329 (type)fn(argv[a+2])); \
332 a += len_count + 1; \
338 if (strcmp(tstr, "s")==0) FMT_ARG(mprToString, const char *);
339 else if (strcmp(tstr, "c")==0) FMT_ARG(*mprToString, char);
340 else if (strcmp(tstr, "d")==0) FMT_ARG(mprVarToNumber, int);
341 else if (strcmp(tstr, "ld")==0) FMT_ARG(mprVarToNumber, long);
342 else if (strcmp(tstr, "lld")==0) FMT_ARG(mprVarToNumber, long long);
343 else if (strcmp(tstr, "x")==0) FMT_ARG(mprVarToNumber, int);
344 else if (strcmp(tstr, "lx")==0) FMT_ARG(mprVarToNumber, long);
345 else if (strcmp(tstr, "llx")==0) FMT_ARG(mprVarToNumber, long long);
346 else if (strcmp(tstr, "X")==0) FMT_ARG(mprVarToNumber, int);
347 else if (strcmp(tstr, "lX")==0) FMT_ARG(mprVarToNumber, long);
348 else if (strcmp(tstr, "llX")==0) FMT_ARG(mprVarToNumber, long long);
349 else if (strcmp(tstr, "u")==0) FMT_ARG(mprVarToNumber, int);
350 else if (strcmp(tstr, "lu")==0) FMT_ARG(mprVarToNumber, long);
351 else if (strcmp(tstr, "llu")==0) FMT_ARG(mprVarToNumber, long long);
352 else if (strcmp(tstr, "i")==0) FMT_ARG(mprVarToNumber, int);
353 else if (strcmp(tstr, "li")==0) FMT_ARG(mprVarToNumber, long);
354 else if (strcmp(tstr, "lli")==0) FMT_ARG(mprVarToNumber, long long);
355 else if (strcmp(tstr, "o")==0) FMT_ARG(mprVarToNumber, int);
356 else if (strcmp(tstr, "lo")==0) FMT_ARG(mprVarToNumber, long);
357 else if (strcmp(tstr, "llo")==0) FMT_ARG(mprVarToNumber, long long);
358 else if (strcmp(tstr, "f")==0) FMT_ARG(mprVarToFloat, double);
359 else if (strcmp(tstr, "lf")==0) FMT_ARG(mprVarToFloat, double);
360 else if (strcmp(tstr, "g")==0) FMT_ARG(mprVarToFloat, double);
361 else if (strcmp(tstr, "lg")==0) FMT_ARG(mprVarToFloat, double);
362 else if (strcmp(tstr, "e")==0) FMT_ARG(mprVarToFloat, double);
363 else if (strcmp(tstr, "le")==0) FMT_ARG(mprVarToFloat, double);
364 else if (strcmp(tstr, "E")==0) FMT_ARG(mprVarToFloat, double);
365 else if (strcmp(tstr, "lE")==0) FMT_ARG(mprVarToFloat, double);
366 else if (strcmp(tstr, "F")==0) FMT_ARG(mprVarToFloat, double);
367 else if (strcmp(tstr, "lF")==0) FMT_ARG(mprVarToFloat, double);
369 ejsSetErrorMsg(eid, "sprintf: unknown format string '%s'", fmt2);
375 ret = talloc_asprintf_append_buffer(ret, "%s", format);
376 mpr_Return(eid, mprString(ret));
377 talloc_free(tmp_ctx);
381 talloc_free(tmp_ctx);
386 used to build your own print function
387 str = vsprintf(args);
389 static int ejs_vsprintf(MprVarHandle eid, int argc, struct MprVar **argv)
391 struct MprVar **args, *len, *v;
393 if (argc != 1 || argv[0]->type != MPR_TYPE_OBJECT) {
394 ejsSetErrorMsg(eid, "vsprintf invalid arguments");
398 len = mprGetProperty(v, "length", NULL);
400 ejsSetErrorMsg(eid, "vsprintf takes an array");
403 length = mprToInt(len);
404 args = talloc_array(mprMemCtx(), struct MprVar *, length);
409 for (i=0;i<length;i++) {
411 mprItoa(i, idx, sizeof(idx));
412 args[i] = mprGetProperty(v, idx, NULL);
415 ret = ejs_sprintf(eid, length, args);
422 encode a string, replacing all non-alpha with %02x form
424 static int ejs_encodeURIComponent(MprVarHandle eid, int argc, char **argv)
430 ejsSetErrorMsg(eid, "encodeURIComponent invalid arguments");
437 if (!isalnum(s[i])) count++;
440 ret = talloc_array(mprMemCtx(), char, i + count*2 + 1);
444 for (i=j=0;s[i];i++,j++) {
445 if (!isalnum(s[i])) {
446 snprintf(ret+j, 4, "%%%02X", (unsigned)s[i]);
453 mpr_Return(eid, mprString(ret));
459 encode a string, replacing all non-alpha of %02x form
461 static int ejs_decodeURIComponent(MprVarHandle eid, int argc, char **argv)
467 ejsSetErrorMsg(eid, "decodeURIComponent invalid arguments");
473 ret = talloc_array(mprMemCtx(), char, strlen(s) + 1);
478 for (i=j=0;s[i];i++,j++) {
481 if (sscanf(s+i+1, "%02X", &c) != 1) {
482 ejsSetErrorMsg(eid, "decodeURIComponent bad format");
490 if (!isalnum(s[i])) count++;
494 mpr_Return(eid, mprString(ret));
500 initialise string ejs subsystem
502 static int ejs_string_init(MprVarHandle eid, int argc, struct MprVar **argv)
504 struct MprVar *obj = mprInitObject(eid, "string", argc, argv);
506 mprSetCFunction(obj, "substr", ejs_substr);
507 mprSetStringCFunction(obj, "strlen", ejs_strlen);
508 mprSetStringCFunction(obj, "strlower", ejs_strlower);
509 mprSetStringCFunction(obj, "strupper", ejs_strupper);
510 mprSetStringCFunction(obj, "strstr", ejs_strstr);
511 mprSetStringCFunction(obj, "strspn", ejs_strspn);
512 mprSetCFunction(obj, "split", ejs_split);
513 mprSetCFunction(obj, "join", ejs_join);
514 mprSetCFunction(obj, "sprintf", ejs_sprintf);
515 mprSetCFunction(obj, "vsprintf", ejs_vsprintf);
516 mprSetStringCFunction(obj, "encodeURIComponent", ejs_encodeURIComponent);
517 mprSetStringCFunction(obj, "decodeURIComponent", ejs_decodeURIComponent);
523 setup C functions that be called from ejs
525 NTSTATUS smb_setup_ejs_string(void)
527 ejsDefineCFunction(-1, "string_init", ejs_string_init, NULL, MPR_VAR_SCRIPT_HANDLE);