aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2020-09-10 22:29:21 +0100
committerTomasz Kramkowski <tk@the-tk.com>2020-09-10 22:35:16 +0100
commitfa6635d7c7d10a820754eda9668e54c226823ec9 (patch)
treeb8bffb3ed429988482ed9d43188a8f4e5103b7aa
parenta06c89e8de9cb681a4dbdb6c66ef923010b97081 (diff)
downloadpack-fa6635d7c7d10a820754eda9668e54c226823ec9.tar.gz
pack-fa6635d7c7d10a820754eda9668e54c226823ec9.tar.xz
pack-fa6635d7c7d10a820754eda9668e54c226823ec9.zip
Implement unpacking arrays
-rw-r--r--test_gen.c5
-rw-r--r--unpack.c26
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 <ctype.h>
+#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
+#include <stdlib.h>
#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;