diff options
author | David Robillard <d@drobilla.net> | 2018-04-29 14:07:29 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2018-05-27 18:21:57 +0200 |
commit | aa41376304f135bfc54d2b5c16fa8ecd7302ad24 (patch) | |
tree | 76f1eba1a5f7dd5ee1e56c74840b8babc4a0e474 /src/byte_sink.h | |
parent | 9252a3f52012e6199b7a27b5c329c226614cc127 (diff) | |
download | serd-aa41376304f135bfc54d2b5c16fa8ecd7302ad24.tar.gz serd-aa41376304f135bfc54d2b5c16fa8ecd7302ad24.tar.bz2 serd-aa41376304f135bfc54d2b5c16fa8ecd7302ad24.zip |
Clean up and separate internal headers
Diffstat (limited to 'src/byte_sink.h')
-rw-r--r-- | src/byte_sink.h | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/byte_sink.h b/src/byte_sink.h new file mode 100644 index 00000000..dca08825 --- /dev/null +++ b/src/byte_sink.h @@ -0,0 +1,93 @@ +/* + Copyright 2011-2018 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef SERD_BYTE_SINK_H +#define SERD_BYTE_SINK_H + +#include <stddef.h> +#include <string.h> + +#include "serd/serd.h" + +typedef struct SerdByteSinkImpl { + SerdSink sink; + void* stream; + char* buf; + size_t size; + size_t block_size; +} SerdByteSink; + +static inline SerdByteSink +serd_byte_sink_new(SerdSink sink, void* stream, size_t block_size) +{ + SerdByteSink bsink; + bsink.sink = sink; + bsink.stream = stream; + bsink.size = 0; + bsink.block_size = block_size; + bsink.buf = ((block_size > 1) + ? (char*)serd_bufalloc(block_size) + : NULL); + return bsink; +} + +static inline void +serd_byte_sink_flush(SerdByteSink* bsink) +{ + if (bsink->block_size > 1 && bsink->size > 0) { + bsink->sink(bsink->buf, bsink->size, bsink->stream); + bsink->size = 0; + } +} + +static inline void +serd_byte_sink_free(SerdByteSink* bsink) +{ + serd_byte_sink_flush(bsink); + free(bsink->buf); + bsink->buf = NULL; +} + +static inline size_t +serd_byte_sink_write(const void* buf, size_t len, SerdByteSink* bsink) +{ + if (len == 0) { + return 0; + } else if (bsink->block_size == 1) { + return bsink->sink(buf, len, bsink->stream); + } + + const size_t orig_len = len; + while (len) { + const size_t space = bsink->block_size - bsink->size; + const size_t n = MIN(space, len); + + // Write as much as possible into the remaining buffer space + memcpy(bsink->buf + bsink->size, buf, n); + bsink->size += n; + buf = (const char*)buf + n; + len -= n; + + // Flush page if buffer is full + if (bsink->size == bsink->block_size) { + bsink->sink(bsink->buf, bsink->block_size, bsink->stream); + bsink->size = 0; + } + } + return orig_len; +} + +#endif // SERD_BYTE_SINK_H |