return naStr_substr(naNewString(c), src, start, len);
}
+static naRef f_left(naContext c, naRef me, int argc, naRef* args)
+{
+ int len;
+ naRef src = argc > 0 ? args[0] : naNil();
+ naRef lenr = argc > 1 ? naNumValue(args[1]) : naNil();
+ if(!naIsString(src)) ARGERR();
+ if(!naIsNum(lenr)) ARGERR();
+ len = (int)lenr.num;
+ if(len < 0) len = 0;
+ return naStr_substr(naNewString(c), src, 0, len);
+}
+
+static naRef f_right(naContext c, naRef me, int argc, naRef* args)
+{
+ int len, srclen;
+ naRef src = argc > 0 ? args[0] : naNil();
+ naRef lenr = argc > 1 ? naNumValue(args[1]) : naNil();
+ if(!naIsString(src)) ARGERR();
+ if(!naIsNum(lenr)) ARGERR();
+ srclen = naStr_len(src);
+ len = (int)lenr.num;
+ if (len > srclen) len = srclen;
+ if(len < 0) len = 0;
+ return naStr_substr(naNewString(c), src, srclen - len, len);
+}
+
static naRef f_chr(naContext c, naRef me, int argc, naRef* args)
{
char chr[1];
callargs = argc > 1 ? args[1] : naNil();
callme = argc > 2 ? args[2] : naNil(); // Might be nil, that's OK
callns = argc > 3 ? args[3] : naNil(); // ditto
- if(!IS_HASH(callme)) callme = naNil();
+ if(!IS_HASH(callme) && !IS_GHOST(callme)) callme = naNil();
if(!IS_HASH(callns)) callns = naNil();
if(argc==0 || !IS_FUNC(args[0]) || (!IS_NIL(callargs) && !IS_VEC(callargs)))
ARGERR();
{ "streq", f_streq },
{ "cmp", f_cmp },
{ "substr", f_substr },
+ { "left", f_left },
+ { "right", f_right },
{ "chr", f_chr },
{ "contains", f_contains },
{ "typeof", f_typeof },