diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-06-08 12:22:23 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-06-08 12:28:05 +0200 |
commit | a1ed5662ab1b0932a07549c39c8d435f0d2be0d7 (patch) | |
tree | 605180b77c4bdfa2378cb187e98ddd0c7970d5a8 | |
parent | 8282735c2837c03e3666b65309c3162cca5b65a8 (diff) |
struct: add optional offset argument to `unpack()`
Extend the `unpack()` function to take an optional, second offset parameter
which is useful to skip an initial portion of the input data without having
to encode pad bytes into the format string.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | lib/struct.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/lib/struct.c b/lib/struct.c index bd418b2..751127c 100644 --- a/lib/struct.c +++ b/lib/struct.c @@ -2307,6 +2307,7 @@ static uc_value_t * uc_unpack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, size_t argoff) { uc_value_t *bufval = uc_fn_arg(argoff); + uc_value_t *offset = uc_fn_arg(argoff + 1); const char *startfrom = NULL; ssize_t bufrem, size, n; uc_value_t *result; @@ -2322,6 +2323,27 @@ uc_unpack_common(uc_vm_t *vm, size_t nargs, formatstate_t *state, size_t argoff) startfrom = ucv_string_get(bufval); bufrem = ucv_string_length(bufval); + + if (offset) { + if (ucv_type(offset) != UC_INTEGER) { + uc_vm_raise_exception(vm, EXCEPTION_TYPE, + "Offset value not an integer"); + + return NULL; + } + + n = (ssize_t)ucv_int64_get(offset); + + if (n < 0) + n += bufrem; + + if (n < 0 || n >= bufrem) + return NULL; + + startfrom += n; + bufrem -= n; + } + result = ucv_array_new(vm); for (ncode = 0, code = &state->codes[0], off = 0; |