summaryrefslogtreecommitdiffhomepage
path: root/lib.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-02-11 18:13:02 +0100
committerJo-Philipp Wich <jo@mein.io>2022-02-11 18:13:02 +0100
commit86f0662f891ac83f474a412b4271af996f1ea44e (patch)
tree58032802705426c0f66fe1c13399140a95e21903 /lib.c
parent116a8ce35fd50e586d1c79d6f99237428adfa2ef (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.c35
1 files changed, 12 insertions, 23 deletions
diff --git a/lib.c b/lib.c
index aaa3eac..dc48d84 100644
--- a/lib.c
+++ b/lib.c
@@ -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 *