2 Unix SMB/CIFS implementation.
4 provide access to string functions
6 Copyright (C) Andrew Tridgell 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 list = split(".", "a.foo.bar");
95 NOTE: does not take a regular expression, unlink perl split()
97 static int ejs_split(MprVarHandle eid, int argc, char **argv)
99 const char *separator;
103 TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
105 ejsSetErrorMsg(eid, "split invalid arguments");
111 ret = mprObject("list");
113 while ((p = strstr(s, separator))) {
114 char *s2 = talloc_strndup(tmp_ctx, s, (int)(p-s));
115 mprAddArray(&ret, count++, mprString(s2));
117 s = p + strlen(separator);
120 mprAddArray(&ret, count++, mprString(s));
122 talloc_free(tmp_ctx);
123 mpr_Return(eid, ret);
130 str = join("DC=", list);
132 static int ejs_join(MprVarHandle eid, int argc, struct MprVar **argv)
135 const char *separator;
138 TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
140 argv[0]->type != MPR_TYPE_STRING ||
141 argv[1]->type != MPR_TYPE_OBJECT) {
142 ejsSetErrorMsg(eid, "join invalid arguments");
146 separator = mprToString(argv[0]);
147 list = mprToArray(tmp_ctx, argv[1]);
149 if (list == NULL || list[0] == NULL) {
150 talloc_free(tmp_ctx);
151 mpr_Return(eid, mprString(NULL));
155 ret = talloc_strdup(tmp_ctx, list[0]);
159 for (i=1;list[i];i++) {
160 ret = talloc_asprintf_append(ret, "%s%s", separator, list[i]);
165 mpr_Return(eid, mprString(ret));
166 talloc_free(tmp_ctx);
169 ejsSetErrorMsg(eid, "out of memory");
175 blergh, C certainly makes this hard!
177 str = sprintf("i=%d s=%7s", 7, "foo");
179 static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv)
185 char *(*_asprintf_append)(char *, const char *, ...);
187 if (argc < 1 || argv[0]->type != MPR_TYPE_STRING) {
188 ejsSetErrorMsg(eid, "sprintf invalid arguments");
191 format = mprToString(argv[0]);
192 tmp_ctx = talloc_new(mprMemCtx());
193 ret = talloc_strdup(tmp_ctx, "");
195 /* avoid all the format string warnings */
196 _asprintf_append = talloc_asprintf_append;
201 while ((p = strchr(format, '%'))) {
203 int len, len_count=0;
205 ret = talloc_asprintf_append(ret, "%*.*s",
206 (int)(p-format), (int)(p-format),
208 if (ret == NULL) goto failed;
209 format += (int)(p-format);
210 len = strcspn(p+1, "dxuiofgGpXeEFcs%") + 1;
211 fmt2 = talloc_strndup(tmp_ctx, p, len+1);
212 if (fmt2 == NULL) goto failed;
213 len_count = count_chars(fmt2, '*');
214 /* find the type string */
216 while (tstr > fmt2 && isalpha((unsigned char)tstr[-1])) {
219 if (strcmp(tstr, "%") == 0) {
220 ret = talloc_asprintf_append(ret, "%%");
228 argc < a + len_count + 1) {
229 ejsSetErrorMsg(eid, "sprintf: not enough arguments for format");
232 #define FMT_ARG(fn, type) do { \
233 switch (len_count) { \
235 ret = _asprintf_append(ret, fmt2, \
236 (type)fn(argv[a])); \
239 ret = _asprintf_append(ret, fmt2, \
240 (int)mprVarToNumber(argv[a]), \
241 (type)fn(argv[a+1])); \
244 ret = _asprintf_append(ret, fmt2, \
245 (int)mprVarToNumber(argv[a]), \
246 (int)mprVarToNumber(argv[a+1]), \
247 (type)fn(argv[a+2])); \
250 a += len_count + 1; \
256 if (strcmp(tstr, "s")==0) FMT_ARG(mprToString, const char *);
257 else if (strcmp(tstr, "c")==0) FMT_ARG(*mprToString, char);
258 else if (strcmp(tstr, "d")==0) FMT_ARG(mprVarToNumber, int);
259 else if (strcmp(tstr, "ld")==0) FMT_ARG(mprVarToNumber, long);
260 else if (strcmp(tstr, "lld")==0) FMT_ARG(mprVarToNumber, long long);
261 else if (strcmp(tstr, "x")==0) FMT_ARG(mprVarToNumber, int);
262 else if (strcmp(tstr, "lx")==0) FMT_ARG(mprVarToNumber, long);
263 else if (strcmp(tstr, "llx")==0) FMT_ARG(mprVarToNumber, long long);
264 else if (strcmp(tstr, "X")==0) FMT_ARG(mprVarToNumber, int);
265 else if (strcmp(tstr, "lX")==0) FMT_ARG(mprVarToNumber, long);
266 else if (strcmp(tstr, "llX")==0) FMT_ARG(mprVarToNumber, long long);
267 else if (strcmp(tstr, "u")==0) FMT_ARG(mprVarToNumber, int);
268 else if (strcmp(tstr, "lu")==0) FMT_ARG(mprVarToNumber, long);
269 else if (strcmp(tstr, "llu")==0) FMT_ARG(mprVarToNumber, long long);
270 else if (strcmp(tstr, "i")==0) FMT_ARG(mprVarToNumber, int);
271 else if (strcmp(tstr, "li")==0) FMT_ARG(mprVarToNumber, long);
272 else if (strcmp(tstr, "lli")==0) FMT_ARG(mprVarToNumber, long long);
273 else if (strcmp(tstr, "o")==0) FMT_ARG(mprVarToNumber, int);
274 else if (strcmp(tstr, "lo")==0) FMT_ARG(mprVarToNumber, long);
275 else if (strcmp(tstr, "llo")==0) FMT_ARG(mprVarToNumber, long long);
276 else if (strcmp(tstr, "f")==0) FMT_ARG(mprVarToFloat, double);
277 else if (strcmp(tstr, "lf")==0) FMT_ARG(mprVarToFloat, double);
278 else if (strcmp(tstr, "g")==0) FMT_ARG(mprVarToFloat, double);
279 else if (strcmp(tstr, "lg")==0) FMT_ARG(mprVarToFloat, double);
280 else if (strcmp(tstr, "e")==0) FMT_ARG(mprVarToFloat, double);
281 else if (strcmp(tstr, "le")==0) FMT_ARG(mprVarToFloat, double);
282 else if (strcmp(tstr, "E")==0) FMT_ARG(mprVarToFloat, double);
283 else if (strcmp(tstr, "lE")==0) FMT_ARG(mprVarToFloat, double);
284 else if (strcmp(tstr, "F")==0) FMT_ARG(mprVarToFloat, double);
285 else if (strcmp(tstr, "lF")==0) FMT_ARG(mprVarToFloat, double);
287 ejsSetErrorMsg(eid, "sprintf: unknown format string '%s'", fmt2);
293 ret = talloc_asprintf_append(ret, "%s", format);
294 mpr_Return(eid, mprString(ret));
295 talloc_free(tmp_ctx);
299 talloc_free(tmp_ctx);
304 used to build your own print function
305 str = vsprintf(args);
307 static int ejs_vsprintf(MprVarHandle eid, int argc, struct MprVar **argv)
309 struct MprVar **args, *len, *v;
311 if (argc != 1 || argv[0]->type != MPR_TYPE_OBJECT) {
312 ejsSetErrorMsg(eid, "vsprintf invalid arguments");
316 len = mprGetProperty(v, "length", NULL);
318 ejsSetErrorMsg(eid, "vsprintf takes an array");
321 length = mprToInt(len);
322 args = talloc_array(mprMemCtx(), struct MprVar *, length);
327 for (i=0;i<length;i++) {
329 mprItoa(i, idx, sizeof(idx));
330 args[i] = mprGetProperty(v, idx, NULL);
333 ret = ejs_sprintf(eid, length, args);
340 encode a string, replacing all non-alpha with %02x form
342 static int ejs_encodeURIComponent(MprVarHandle eid, int argc, char **argv)
348 ejsSetErrorMsg(eid, "encodeURIComponent invalid arguments");
355 if (!isalnum(s[i])) count++;
358 ret = talloc_size(mprMemCtx(), i + count*2 + 1);
362 for (i=j=0;s[i];i++,j++) {
363 if (!isalnum(s[i])) {
364 snprintf(ret+j, 4, "%%%02X", (unsigned)s[i]);
371 mpr_Return(eid, mprString(ret));
377 encode a string, replacing all non-alpha of %02x form
379 static int ejs_decodeURIComponent(MprVarHandle eid, int argc, char **argv)
385 ejsSetErrorMsg(eid, "decodeURIComponent invalid arguments");
391 ret = talloc_size(mprMemCtx(), strlen(s) + 1);
396 for (i=j=0;s[i];i++,j++) {
399 if (sscanf(s+i+1, "%02X", &c) != 1) {
400 ejsSetErrorMsg(eid, "decodeURIComponent bad format");
408 if (!isalnum(s[i])) count++;
412 mpr_Return(eid, mprString(ret));
418 initialise string ejs subsystem
420 static int ejs_string_init(MprVarHandle eid, int argc, struct MprVar **argv)
422 struct MprVar *obj = mprInitObject(eid, "string", argc, argv);
424 mprSetStringCFunction(obj, "strlen", ejs_strlen);
425 mprSetStringCFunction(obj, "strlower", ejs_strlower);
426 mprSetStringCFunction(obj, "strupper", ejs_strupper);
427 mprSetStringCFunction(obj, "strstr", ejs_strstr);
428 mprSetStringCFunction(obj, "split", ejs_split);
429 mprSetCFunction(obj, "join", ejs_join);
430 mprSetCFunction(obj, "sprintf", ejs_sprintf);
431 mprSetCFunction(obj, "vsprintf", ejs_vsprintf);
432 mprSetStringCFunction(obj, "encodeURIComponent", ejs_encodeURIComponent);
433 mprSetStringCFunction(obj, "decodeURIComponent", ejs_decodeURIComponent);
439 setup C functions that be called from ejs
441 void smb_setup_ejs_string(void)
443 ejsDefineCFunction(-1, "string_init", ejs_string_init, NULL, MPR_VAR_SCRIPT_HANDLE);