diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-02-11 18:13:02 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-02-11 18:13:02 +0100 |
commit | 86f0662f891ac83f474a412b4271af996f1ea44e (patch) | |
tree | 58032802705426c0f66fe1c13399140a95e21903 /lib.c | |
parent | 116a8ce35fd50e586d1c79d6f99237428adfa2ef (diff) |
lib: change `ord()` to always return single byte value
The most common usecase is extracting the value of a single byte at a
specific offset, e.g. to scan a string char-by-char to construct a hash.
Furthermore, constructing an array which contains the results of multiple
`ord()` invocations is trivial while efficiently extracting a single byte
value without the overhead of an intermediate array is not.
Due to that, change `ord()` to always return a single integer byte value
at the offset specified as second argument or at offset 0 in case no
argument was supplied.
That means that `ord("Abc", 0, 1, 2)` will now return `65` instead of the
former `[ 65, 98, 99 ]` result.
Code relying on the former behaviour should either perform multiple calls
to `ord()`, passing different offsets each time or switch to the `struct`
module which allows efficient unpacking of string data.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 35 |
1 files changed, 12 insertions, 23 deletions
@@ -648,10 +648,9 @@ static uc_value_t * uc_ord(uc_vm_t *vm, size_t nargs) { uc_value_t *obj = uc_fn_arg(0); - uc_value_t *rv, *pos; const char *str; - size_t i, len; - int64_t n; + int64_t n = 0; + size_t len; if (ucv_type(obj) != UC_STRING) return NULL; @@ -659,30 +658,20 @@ uc_ord(uc_vm_t *vm, size_t nargs) str = ucv_string_get(obj); len = ucv_string_length(obj); - if (nargs == 1) - return str[0] ? ucv_int64_new((int64_t)str[0]) : NULL; - - rv = ucv_array_new(vm); - - for (i = 1; i < nargs; i++) { - pos = uc_fn_arg(i); - - if (ucv_type(pos) == UC_INTEGER) { - n = ucv_int64_get(pos); - - if (n < 0) - n += len; + if (nargs > 1) { + n = ucv_int64_get(uc_fn_arg(1)); - if (n >= 0 && (uint64_t)n < len) { - ucv_array_push(rv, ucv_int64_new((int64_t)str[n])); - continue; - } - } + if (errno == EINVAL) + return NULL; - ucv_array_push(rv, NULL); + if (n < 0) + n += len; } - return rv; + if (n < 0 || (uint64_t)n >= len) + return NULL; + + return ucv_int64_new((uint8_t)str[n]); } static uc_value_t * |