From 32d61d7c48b7cf0eb7445fb410e339bbcadd1d61 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 6 Jan 2020 19:55:41 +0000 Subject: [PATCH] Add some more marshalling functions, for file parsing. There are new functions here to get the next contiguous string of characters from a given set (like strspn/strcspn, only for BinarySource, and returning a ptrlen of what they skipped over). Also we can get a line of text with the trailing newline chomped off. Finally, I've provided a function to rewind a BinarySource to a previous position with error checking. --- marshal.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ marshal.h | 15 ++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/marshal.c b/marshal.c index a9b1074a..fd287aa1 100644 --- a/marshal.c +++ b/marshal.c @@ -218,6 +218,53 @@ const char *BinarySource_get_asciz(BinarySource *src) return start; } +static ptrlen BinarySource_get_chars_internal( + BinarySource *src, const char *set, bool include) +{ + const char *start = here; + while (avail(1)) { + bool present = NULL != strchr(set, *(const char *)consume(0)); + if (present != include) + break; + consume(1); + } + const char *end = here; + return make_ptrlen(start, end - start); +} + +ptrlen BinarySource_get_chars(BinarySource *src, const char *include_set) +{ + return BinarySource_get_chars_internal(src, include_set, true); +} + +ptrlen BinarySource_get_nonchars(BinarySource *src, const char *exclude_set) +{ + return BinarySource_get_chars_internal(src, exclude_set, false); +} + +ptrlen BinarySource_get_chomped_line(BinarySource *src) +{ + const char *start, *end; + + if (src->err) + return make_ptrlen(here, 0); + + start = here; + end = memchr(start, '\n', src->len - src->pos); + if (end) + advance(end + 1 - start); + else + advance(src->len - src->pos); + end = here; + + if (end > start && end[-1] == '\n') + end--; + if (end > start && end[-1] == '\r') + end--; + + return make_ptrlen(start, end - start); +} + ptrlen BinarySource_get_pstring(BinarySource *src) { const unsigned char *ucp; @@ -235,6 +282,17 @@ ptrlen BinarySource_get_pstring(BinarySource *src) return make_ptrlen(consume(len), len); } +void BinarySource_REWIND_TO__(BinarySource *src, size_t pos) +{ + if (pos <= src->len) { + src->pos = pos; + src->err = BSE_NO_ERROR; /* clear any existing error */ + } else { + src->pos = src->len; + src->err = BSE_OUT_OF_DATA; /* new error if we rewind out of range */ + } +} + static void stdio_sink_write(BinarySink *bs, const void *data, size_t len) { stdio_sink *sink = BinarySink_DOWNCAST(bs, stdio_sink); diff --git a/marshal.h b/marshal.h index bc020a8d..108d8aeb 100644 --- a/marshal.h +++ b/marshal.h @@ -255,6 +255,10 @@ static inline void BinarySource_INIT__(BinarySource *src, ptrlen data) (object)->binarysource_) #define BinarySource_COPIED(obj) \ ((obj)->binarysource_->binarysource_ = (obj)->binarysource_) +#define BinarySource_REWIND_TO(src, pos) \ + BinarySource_REWIND_TO__((src)->binarysource_, pos) +#define BinarySource_REWIND(src) \ + BinarySource_REWIND_TO__((src)->binarysource_, 0) #define get_data(src, len) \ BinarySource_get_data(BinarySource_UPCAST(src), len) @@ -272,6 +276,12 @@ static inline void BinarySource_INIT__(BinarySource *src, ptrlen data) BinarySource_get_string(BinarySource_UPCAST(src)) #define get_asciz(src) \ BinarySource_get_asciz(BinarySource_UPCAST(src)) +#define get_chars(src, include) \ + BinarySource_get_chars(BinarySource_UPCAST(src), include) +#define get_nonchars(src, exclude) \ + BinarySource_get_nonchars(BinarySource_UPCAST(src), exclude) +#define get_chomped_line(src) \ + BinarySource_get_chomped_line(BinarySource_UPCAST(src)) #define get_pstring(src) \ BinarySource_get_pstring(BinarySource_UPCAST(src)) #define get_mp_ssh1(src) \ @@ -301,10 +311,15 @@ unsigned long BinarySource_get_uint32(BinarySource *); uint64_t BinarySource_get_uint64(BinarySource *); ptrlen BinarySource_get_string(BinarySource *); const char *BinarySource_get_asciz(BinarySource *); +ptrlen BinarySource_get_chars(BinarySource *, const char *include_set); +ptrlen BinarySource_get_nonchars(BinarySource *, const char *exclude_set); +ptrlen BinarySource_get_chomped_line(BinarySource *); ptrlen BinarySource_get_pstring(BinarySource *); mp_int *BinarySource_get_mp_ssh1(BinarySource *src); mp_int *BinarySource_get_mp_ssh2(BinarySource *src); +void BinarySource_REWIND_TO__(BinarySource *src, size_t pos); + /* * A couple of useful standard BinarySink implementations, which live * as sensibly here as anywhere else: one that makes a BinarySink