diff options
Diffstat (limited to 'src/block_dumper.h')
-rw-r--r-- | src/block_dumper.h | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/src/block_dumper.h b/src/block_dumper.h index 038f0a82..9820ed03 100644 --- a/src/block_dumper.h +++ b/src/block_dumper.h @@ -7,15 +7,16 @@ #include "serd/output_stream.h" #include "serd/status.h" #include "serd/world.h" +#include "serd/write_result.h" #include "zix/allocator.h" #include "zix/attributes.h" #include <stddef.h> #include <string.h> +/// The partially inlinable sink interface used by the writer typedef struct { - ZixAllocator* ZIX_NONNULL allocator; ///< Buffer allocator - + ZixAllocator* ZIX_NONNULL allocator; ///< Buffer allocator SerdOutputStream* ZIX_ALLOCATED out; ///< Output stream to write to char* ZIX_ALLOCATED buf; ///< Local buffer if needed size_t size; ///< Bytes pending for this block @@ -34,6 +35,12 @@ serd_block_dumper_open(const SerdWorld* ZIX_NONNULL world, SerdOutputStream* ZIX_NONNULL output, size_t block_size); +/** + Flush any pending writes. + + This is typically used before closing to ensure that all of the writes have + actually been written to disk. +*/ SerdStatus serd_block_dumper_flush(SerdBlockDumper* ZIX_NONNULL dumper); @@ -46,37 +53,43 @@ serd_block_dumper_close(SerdBlockDumper* ZIX_NONNULL dumper); This works like any other SerdWriteFunc, but will append to an internal buffer and only actually write to the output when a whole block is ready. */ -static inline size_t -serd_block_dumper_write(const void* ZIX_NONNULL buf, - const size_t size, - const size_t nmemb, - SerdBlockDumper* ZIX_NONNULL const dumper) +static inline SerdWriteResult +serd_block_dumper_write(SerdBlockDumper* ZIX_NONNULL const dumper, + const void* ZIX_NONNULL buf, + const size_t size) { - if (dumper->block_size == 1) { - return dumper->out->write(buf, size, nmemb, dumper->out->stream); + SerdWriteResult result = {SERD_SUCCESS, 0U}; + const size_t block_size = dumper->block_size; + const SerdOutputStream* const out = dumper->out; + + if (block_size == 1) { + result.count = out->write(buf, 1U, size, out->stream); + result.status = result.count == size ? SERD_SUCCESS : SERD_BAD_WRITE; + return result; } - size_t len = size * nmemb; - const size_t orig_len = len; - while (len) { - const size_t space = dumper->block_size - dumper->size; - const size_t n = space < len ? space : len; + while (result.count < size) { + const size_t unwritten = size - result.count; + const size_t space = block_size - dumper->size; + const size_t n = space < unwritten ? space : unwritten; // Write as much as possible into the remaining buffer space - memcpy(dumper->buf + dumper->size, buf, n); + memcpy(dumper->buf + dumper->size, (const char*)buf + result.count, n); dumper->size += n; - buf = (const char*)buf + n; - len -= n; + result.count += n; // Flush page if buffer is full - if (dumper->size == dumper->block_size) { - dumper->out->write( - dumper->buf, 1, dumper->block_size, dumper->out->stream); + if (dumper->size == block_size) { + if (out->write(dumper->buf, 1, block_size, out->stream) != block_size) { + result.status = SERD_BAD_WRITE; + return result; + } + dumper->size = 0; } } - return orig_len; + return result; } #endif // SERD_SRC_DUMPER_H |