diff options
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 153 |
1 files changed, 138 insertions, 15 deletions
@@ -285,39 +285,68 @@ uc_length(uc_vm_t *vm, size_t nargs) } } +static int +uc_uniq_ucv_equal(const void *k1, const void *k2); + static uc_value_t * uc_index(uc_vm_t *vm, size_t nargs, bool right) { uc_value_t *stack = uc_fn_arg(0); uc_value_t *needle = uc_fn_arg(1); const char *sstr, *nstr, *p; - size_t arridx, len; + size_t arridx, slen, nlen; ssize_t ret = -1; switch (ucv_type(stack)) { case UC_ARRAY: - for (arridx = 0, len = ucv_array_length(stack); arridx < len; arridx++) { - if (ucv_compare(I_EQ, ucv_array_get(stack, arridx), needle, NULL)) { - ret = (ssize_t)arridx; - - if (!right) + if (right) { + for (arridx = ucv_array_length(stack); arridx > 0; arridx--) { + if (uc_uniq_ucv_equal(ucv_array_get(stack, arridx - 1), needle)) { + ret = (ssize_t)(arridx - 1); break; + } + } + } + else { + for (arridx = 0, slen = ucv_array_length(stack); arridx < slen; arridx++) { + if (uc_uniq_ucv_equal(ucv_array_get(stack, arridx), needle)) { + ret = (ssize_t)arridx; + break; + } } } return ucv_int64_new(ret); case UC_STRING: - sstr = ucv_string_get(stack); - nstr = needle ? ucv_string_get(needle) : NULL; - len = needle ? strlen(nstr) : 0; - - for (p = sstr; *p && len; p++) { - if (!strncmp(p, nstr, len)) { - ret = (ssize_t)(p - sstr); + if (ucv_type(needle) == UC_STRING) { + sstr = ucv_string_get(stack); + slen = ucv_string_length(stack); + nstr = ucv_string_get(needle); + nlen = ucv_string_length(needle); + + if (slen == nlen) { + if (memcmp(sstr, nstr, nlen) == 0) + ret = 0; + } + else if (slen > nlen) { + if (right) { + p = sstr + slen - nlen; + + do { + if (memcmp(p, nstr, nlen) == 0) { + ret = (ssize_t)(p - sstr); + break; + } + } + while (--p != sstr); + } + else { + p = (const char *)memmem(sstr, slen, nstr, nlen); - if (!right) - break; + if (p) + ret = (ssize_t)(p - sstr); + } } } @@ -3352,6 +3381,98 @@ uc_clock(uc_vm_t *vm, size_t nargs) return res; } +static uc_value_t * +uc_hexenc(uc_vm_t *vm, size_t nargs) +{ + const char *hex = "0123456789abcdef"; + uc_value_t *input = uc_fn_arg(0); + uc_stringbuf_t *buf; + size_t off, len; + uint8_t byte; + + if (!input) + return NULL; + + buf = ucv_stringbuf_new(); + off = printbuf_length(buf); + + ucv_to_stringbuf(vm, buf, input, false); + + len = printbuf_length(buf) - off; + + /* memset the last expected output char to grow the output buffer */ + printbuf_memset(buf, off + len * 2, 0, 1); + + /* translate string into hex back to front to reuse the same buffer */ + while (len > 0) { + byte = buf->buf[--len + off]; + buf->buf[off + len * 2 + 0] = hex[byte / 16]; + buf->buf[off + len * 2 + 1] = hex[byte % 16]; + } + + /* do not include sentinel `\0` in string length */ + buf->bpos--; + + return ucv_stringbuf_finish(buf); +} + +static inline uint8_t +hexval(unsigned char c, bool lo) +{ + return ((c > '9') ? (c - 'a') + 10 : c - '0') << (lo ? 0 : 4); +} + +static uc_value_t * +uc_hexdec(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *input = uc_fn_arg(0); + uc_value_t *skip = uc_fn_arg(1); + size_t len, off, n, i; + uc_stringbuf_t *buf; + unsigned char *p; + const char *s; + + if (ucv_type(input) != UC_STRING) + return NULL; + + if (skip && ucv_type(skip) != UC_STRING) + return NULL; + + p = (unsigned char *)ucv_string_get(input); + len = ucv_string_length(input); + + s = skip ? (const char *)ucv_string_get(skip) : " \t\n"; + + for (i = 0, n = 0; i < len; i++) { + if (isxdigit(p[i])) + n++; + else if (!s || !strchr(s, p[i])) + return NULL; + } + + if (n & 1) + return NULL; + + buf = ucv_stringbuf_new(); + off = printbuf_length(buf); + + /* preallocate the output buffer */ + printbuf_memset(buf, off, 0, n / 2 + 1); + + for (i = 0, n = 0; i < len; i++) { + if (!isxdigit(p[i])) + continue; + + buf->buf[off + (n >> 1)] |= hexval(p[i] | 32, n & 1); + n++; + } + + /* do not include sentinel `\0` in string length */ + buf->bpos--; + + return ucv_stringbuf_finish(buf); +} + const uc_function_list_t uc_stdlib_functions[] = { { "chr", uc_chr }, @@ -3417,6 +3538,8 @@ const uc_function_list_t uc_stdlib_functions[] = { { "timelocal", uc_timelocal }, { "timegm", uc_timegm }, { "clock", uc_clock }, + { "hexdec", uc_hexdec }, + { "hexenc", uc_hexenc }, }; |