diff options
author | David Robillard <d@drobilla.net> | 2011-12-12 05:10:49 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2011-12-12 05:10:49 +0000 |
commit | 22ac239266b01f067ece83eb6addcdc9f825780e (patch) | |
tree | 918516d71f7303d6e05699f8b60d20a6f6372409 /src/serd_internal.h | |
parent | e731c88e809459ef4adb4988e433d6be7b043aa6 (diff) | |
download | serd-22ac239266b01f067ece83eb6addcdc9f825780e.tar.gz serd-22ac239266b01f067ece83eb6addcdc9f825780e.tar.bz2 serd-22ac239266b01f067ece83eb6addcdc9f825780e.zip |
Make bulk writer internal and inlinable to avoid function call overhead in the writer.
git-svn-id: http://svn.drobilla.net/serd/trunk@254 490d8e77-9747-427b-9fa3-0b8f29cee8a0
Diffstat (limited to 'src/serd_internal.h')
-rw-r--r-- | src/serd_internal.h | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/serd_internal.h b/src/serd_internal.h index bf1f630f..5fb9f0ef 100644 --- a/src/serd_internal.h +++ b/src/serd_internal.h @@ -34,6 +34,12 @@ #define SERD_PAGE_SIZE 4096 +#ifndef MIN +# define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +/* File and Buffer Utilities */ + static inline FILE* serd_fopen(const char* path, const char* mode) { @@ -60,6 +66,8 @@ serd_bufalloc(size_t size) #endif } +/* Stack */ + /** A dynamic stack in memory. */ typedef struct { uint8_t* buf; ///< Stack memory @@ -115,6 +123,71 @@ serd_stack_pop(SerdStack* stack, size_t n_bytes) stack->size -= n_bytes; } +/* Bulk Sink */ + +typedef struct SerdBulkSinkImpl { + SerdSink sink; + void* stream; + uint8_t* buf; + size_t size; + size_t block_size; +} SerdBulkSink; + +static inline SerdBulkSink +serd_bulk_sink_new(SerdSink sink, void* stream, size_t block_size) +{ + SerdBulkSink bsink; + bsink.sink = sink; + bsink.stream = stream; + bsink.size = 0; + bsink.block_size = block_size; + bsink.buf = serd_bufalloc(block_size); + return bsink; +} + +static inline void +serd_bulk_sink_flush(SerdBulkSink* bsink) +{ + if (bsink->size > 0) { + bsink->sink(bsink->buf, bsink->size, bsink->stream); + } + bsink->size = 0; +} + +static inline void +serd_bulk_sink_free(SerdBulkSink* bsink) +{ + if (bsink) { + serd_bulk_sink_flush(bsink); + free(bsink->buf); + } +} + +static inline size_t +serd_bulk_sink_write(const void* buf, size_t len, SerdBulkSink* bsink) +{ + 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 = (uint8_t*)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; +} + +/* Character utilities */ + /** Return true if @a c lies within [min...max] (inclusive) */ static inline bool in_range(const uint8_t c, const uint8_t min, const uint8_t max) |