From fa6635d7c7d10a820754eda9668e54c226823ec9 Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Thu, 10 Sep 2020 22:29:21 +0100 Subject: Implement unpacking arrays --- test_gen.c | 5 ++++- unpack.c | 26 ++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/test_gen.c b/test_gen.c index 7a559b6..d6b162d 100644 --- a/test_gen.c +++ b/test_gen.c @@ -172,6 +172,9 @@ static void generate_simple(FILE *out, enum fmt fmt, int arraysize) int main(void) { FILE *out = stdout; - for (enum fmt fmt = FMT_BEGIN; fmt < FMT_END; fmt++) + for (enum fmt fmt = FMT_BEGIN; fmt < FMT_END; fmt++) { generate_simple(out, fmt, 0); + for (int i = 2; i < 4; i++) + generate_simple(out, fmt, i); + } } diff --git a/unpack.c b/unpack.c index c34099f..2ae79dd 100644 --- a/unpack.c +++ b/unpack.c @@ -3,11 +3,13 @@ * SPDX-License-Identifier: MIT */ #include +#include #include #include #include #include #include +#include #include "common.h" #include "pack.h" @@ -38,9 +40,8 @@ enum pack_status unpack(void *buf_, size_t size, const char *fmt, ...) va_start(ap, fmt); for (int i = 0; fmt[i] != '\0'; i++) { - bool sign = islower(fmt[i]); - unsigned long long count = 1; - size_t s; + bool sign; + size_t count = 1, s; union { signed char *b; unsigned char *B; @@ -54,7 +55,24 @@ enum pack_status unpack(void *buf_, size_t size, const char *fmt, ...) unsigned long long *Q; } arg; union { uintmax_t u; intmax_t s; } val; - tr_debug("i: %d, fmt[i]: %c, sign: %ssigned", i, fmt[i], sign ? "" : "un"); + tr_debug("i: %d, fmt[i]: %c", i, fmt[i]); + if (isdigit(fmt[i])) { + unsigned long long c; + char *end; + + errno = 0; + c = strtoull(&fmt[i], &end, 10); + if ((c == ULLONG_MAX && errno == ERANGE) || c > SIZE_MAX) + return PACK_FMTINVAL; + count = c; + i += end - &fmt[i]; + } else if (fmt[i] == '*') { + count = va_arg(ap, size_t); + i++; + } + sign = islower(fmt[i]); + tr_debug("count: %zu, i: %d, fmt[i]: %c, sign: %ssigned", + count, i, fmt[i], sign ? "" : "un"); switch (fmt[i]) { case '>': endianness = BIG; continue; case '<': endianness = LITTLE; continue; -- cgit v1.2.3-54-g00ecf