From cae15d15c847faba203e40e2a327b23a1ebffb48 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 28 Jun 2020 19:46:47 +0200 Subject: Make Writer always write to a ByteSink --- src/byte_sink.c | 108 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 44 deletions(-) (limited to 'src/byte_sink.c') diff --git a/src/byte_sink.c b/src/byte_sink.c index 6436f9d8..e93e5a07 100644 --- a/src/byte_sink.c +++ b/src/byte_sink.c @@ -14,32 +14,46 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "serd_internal.h" +#include "byte_sink.h" + +#include "serd_config.h" #include "system.h" #include "serd/serd.h" -#include #include +#include #include -#include -struct SerdByteSinkImpl { - SerdWriteFunc sink; - void* stream; - char* buf; - size_t size; - size_t block_size; -}; +#if USE_POSIX_FADVISE && USE_FILENO +# include +#endif SerdByteSink* -serd_byte_sink_new(SerdWriteFunc write_func, void* stream, size_t block_size) +serd_byte_sink_new_buffer(SerdBuffer* const buffer) { SerdByteSink* sink = (SerdByteSink*)calloc(1, sizeof(SerdByteSink)); - sink->sink = write_func; + sink->write_func = serd_buffer_sink; + sink->stream = buffer; + sink->block_size = 1; + sink->type = TO_BUFFER; + + return sink; +} + +static SerdByteSink* +serd_byte_sink_new_internal(const SerdWriteFunc write_func, + void* const stream, + const size_t block_size, + const SerdByteSinkType type) +{ + SerdByteSink* sink = (SerdByteSink*)calloc(1, sizeof(SerdByteSink)); + + sink->write_func = write_func; sink->stream = stream; sink->block_size = block_size; + sink->type = type; if (block_size > 1) { sink->buf = (char*)serd_allocate_buffer(block_size); @@ -48,58 +62,64 @@ serd_byte_sink_new(SerdWriteFunc write_func, void* stream, size_t block_size) return sink; } -size_t -serd_byte_sink_write(const void* buf, - size_t size, - size_t nmemb, - SerdByteSink* sink) +SerdByteSink* +serd_byte_sink_new_filename(const char* const path, const size_t block_size) { - assert(size == 1); - (void)size; - - if (nmemb == 0) { - return 0; + if (!block_size) { + return NULL; } - if (sink->block_size == 1) { - return sink->sink(buf, 1, nmemb, sink->stream); + FILE* const file = fopen(path, "wb"); + if (!file) { + return NULL; } - const size_t orig_len = nmemb; - while (nmemb) { - const size_t space = sink->block_size - sink->size; - const size_t n = MIN(space, nmemb); - - // Write as much as possible into the remaining buffer space - memcpy(sink->buf + sink->size, buf, n); - sink->size += n; - buf = (const char*)buf + n; - nmemb -= n; - - // Flush page if buffer is full - if (sink->size == sink->block_size) { - sink->sink(sink->buf, 1, sink->block_size, sink->stream); - sink->size = 0; - } - } +#if USE_POSIX_FADVISE && USE_FILENO + posix_fadvise(fileno(file), 0, 0, POSIX_FADV_SEQUENTIAL); +#endif - return orig_len; + return serd_byte_sink_new_internal( + (SerdWriteFunc)fwrite, file, block_size, TO_FILENAME); +} + +SerdByteSink* +serd_byte_sink_new_function(const SerdWriteFunc write_func, + void* const stream, + const size_t block_size) +{ + return block_size ? serd_byte_sink_new_internal( + write_func, stream, block_size, TO_FUNCTION) + : NULL; } void serd_byte_sink_flush(SerdByteSink* sink) { if (sink->block_size > 1 && sink->size > 0) { - sink->sink(sink->buf, 1, sink->size, sink->stream); + sink->write_func(sink->buf, 1, sink->size, sink->stream); sink->size = 0; } } +SerdStatus +serd_byte_sink_close(SerdByteSink* sink) +{ + serd_byte_sink_flush(sink); + + if (sink->type == TO_FILENAME && sink->stream) { + const int st = fclose((FILE*)sink->stream); + sink->stream = NULL; + return st ? SERD_ERR_UNKNOWN : SERD_SUCCESS; + } + + return SERD_SUCCESS; +} + void serd_byte_sink_free(SerdByteSink* const sink) { if (sink) { - serd_byte_sink_flush(sink); + serd_byte_sink_close(sink); serd_free_aligned(sink->buf); free(sink); } -- cgit v1.2.1