summaryrefslogtreecommitdiffhomepage
path: root/lib
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-06-08 12:22:23 +0200
committerJo-Philipp Wich <jo@mein.io>2022-06-08 12:28:05 +0200
commita1ed5662ab1b0932a07549c39c8d435f0d2be0d7 (patch)
tree605180b77c4bdfa2378cb187e98ddd0c7970d5a8 /lib
parent8282735c2837c03e3666b65309c3162cca5b65a8 (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>
Diffstat (limited to 'lib')
-rw-r--r--lib/struct.c22
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;