From 991e22c9bb83b67dcb74a2338ebd99da0d87dc49 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 9 Nov 2022 18:53:34 +0000 Subject: [PATCH] Implement a BinarySink writing to a fixed-size buffer. This is one of marshal.c's small collection of handy BinarySink adapters to existing kinds of thing, alongside stdio_sink and bufchain_sink. It writes into a fixed-size buffer, discarding all writes after the buffer fills up, and sets a flag to let you know if it overflowed. There was one of these in Windows Pageant a while back, under the name 'struct PageantReply' (introduced in commit b6cbad89fc56c1f, removed again in 98538caa39d20f3 when the named-pipe revamp made it unnecessary). This is the same idea but centralised for reusability. --- defs.h | 1 + marshal.h | 7 +++++++ utils/marshal.c | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/defs.h b/defs.h index 286e0c96..d7e2f338 100644 --- a/defs.h +++ b/defs.h @@ -91,6 +91,7 @@ typedef struct BinarySink BinarySink; typedef struct BinarySource BinarySource; typedef struct stdio_sink stdio_sink; typedef struct bufchain_sink bufchain_sink; +typedef struct buffer_sink buffer_sink; typedef struct handle_sink handle_sink; typedef struct IdempotentCallback IdempotentCallback; diff --git a/marshal.h b/marshal.h index b9136292..34a0572f 100644 --- a/marshal.h +++ b/marshal.h @@ -353,7 +353,14 @@ struct bufchain_sink { bufchain *ch; BinarySink_IMPLEMENTATION; }; +struct buffer_sink { + char *out; + size_t space; + bool overflowed; + BinarySink_IMPLEMENTATION; +}; void stdio_sink_init(stdio_sink *sink, FILE *fp); void bufchain_sink_init(bufchain_sink *sink, bufchain *ch); +void buffer_sink_init(buffer_sink *sink, void *buffer, size_t len); #endif /* PUTTY_MARSHAL_H */ diff --git a/utils/marshal.c b/utils/marshal.c index 534ecf50..ec6a5806 100644 --- a/utils/marshal.c +++ b/utils/marshal.c @@ -336,3 +336,23 @@ void bufchain_sink_init(bufchain_sink *sink, bufchain *ch) sink->ch = ch; BinarySink_INIT(sink, bufchain_sink_write); } + +static void buffer_sink_write(BinarySink *bs, const void *data, size_t len) +{ + buffer_sink *sink = BinarySink_DOWNCAST(bs, buffer_sink); + if (len > sink->space) { + len = sink->space; + sink->overflowed = true; + } + memcpy(sink->out, data, len); + sink->space -= len; + sink->out += len; +} + +void buffer_sink_init(buffer_sink *sink, void *buffer, size_t len) +{ + sink->out = buffer; + sink->space = len; + sink->overflowed = false; + BinarySink_INIT(sink, buffer_sink_write); +}