diff options
author | David Robillard <d@drobilla.net> | 2020-06-28 23:26:48 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2022-01-13 23:05:24 -0500 |
commit | 55e28966226268a57edb07419ac419ef53ac437d (patch) | |
tree | 317a3e50480f97a415dae5a7d096726a0c730c0a /src/byte_source.c | |
parent | b98bd7a32cf4302e0a210dd8558edd3ab2088525 (diff) | |
download | serd-55e28966226268a57edb07419ac419ef53ac437d.tar.gz serd-55e28966226268a57edb07419ac419ef53ac437d.tar.bz2 serd-55e28966226268a57edb07419ac419ef53ac437d.zip |
Make Reader always read from a ByteSource
Diffstat (limited to 'src/byte_source.c')
-rw-r--r-- | src/byte_source.c | 165 |
1 files changed, 117 insertions, 48 deletions
diff --git a/src/byte_source.c b/src/byte_source.c index 2e4f66cb..ef6bf3bb 100644 --- a/src/byte_source.c +++ b/src/byte_source.c @@ -17,12 +17,21 @@ #include "byte_source.h" #include "caret.h" +#include "serd_config.h" #include "system.h" #include "serd/serd.h" +#include <sys/stat.h> + +#if USE_POSIX_FADVISE && USE_FILENO +# include <fcntl.h> +#endif + #include <stdbool.h> #include <stdint.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> SerdStatus @@ -50,28 +59,34 @@ serd_byte_source_page(SerdByteSource* const source) return SERD_SUCCESS; } -SerdStatus -serd_byte_source_open_source(SerdByteSource* const source, - const SerdReadFunc read_func, - const SerdStreamErrorFunc error_func, - const SerdStreamCloseFunc close_func, - void* const stream, - const SerdNode* const name, - const size_t page_size) +SerdByteSource* +serd_byte_source_new_function(const SerdReadFunc read_func, + const SerdStreamErrorFunc error_func, + const SerdStreamCloseFunc close_func, + void* const stream, + const SerdNode* const name, + const size_t page_size) { - assert(page_size > 0); - memset(source, '\0', sizeof(*source)); - source->read_func = read_func; - source->error_func = error_func; - source->close_func = close_func; - source->stream = stream; - source->page_size = page_size; - source->buf_size = page_size; - source->name = serd_node_copy(name); - source->caret.file = source->name; - source->caret.line = 1u; - source->caret.col = 1u; - source->from_stream = true; + if (!page_size) { + return NULL; + } + + SerdByteSource* source = (SerdByteSource*)calloc(1, sizeof(SerdByteSource)); + + source->read_func = read_func; + source->error_func = error_func; + source->close_func = close_func; + source->stream = stream; + source->page_size = page_size; + source->buf_size = page_size; + source->type = FROM_FUNCTION; + + source->name = + name ? serd_node_copy(name) : serd_new_string(SERD_STRING("func")); + + source->caret.file = source->name; + source->caret.line = 1u; + source->caret.col = 1u; if (page_size > 1) { source->file_buf = (uint8_t*)serd_allocate_buffer(page_size); @@ -81,58 +96,112 @@ serd_byte_source_open_source(SerdByteSource* const source, source->read_buf = &source->read_byte; } - return SERD_SUCCESS; + return source; } -SerdStatus -serd_byte_source_prepare(SerdByteSource* const source) +static bool +is_directory(const char* const path) { - if (source->page_size == 0) { - return SERD_FAILURE; +#ifdef _MSC_VER + struct stat st; + return !stat(path, &st) && (st.st_mode & _S_IFDIR); +#else + struct stat st; + return !stat(path, &st) && S_ISDIR(st.st_mode); +#endif +} + +SerdByteSource* +serd_byte_source_new_filename(const char* const path, const size_t page_size) +{ + if (page_size == 0 || is_directory(path)) { + return NULL; } - source->prepared = true; + FILE* const fd = fopen(path, "rb"); + if (!fd) { + return NULL; + } - if (source->from_stream) { - return (source->page_size > 1 ? serd_byte_source_page(source) - : serd_byte_source_advance(source)); + SerdByteSource* source = (SerdByteSource*)calloc(1, sizeof(SerdByteSource)); + + source->read_func = (SerdReadFunc)fread; + source->error_func = (SerdStreamErrorFunc)ferror; + source->close_func = (SerdStreamCloseFunc)fclose; + source->stream = fd; + source->page_size = page_size; + source->buf_size = page_size; + + source->name = serd_new_file_uri(SERD_STRING(path), SERD_EMPTY_STRING()); + source->type = FROM_FILENAME; + + source->caret.file = source->name; + source->caret.line = 1u; + source->caret.col = 1u; + + if (page_size > 1) { + source->file_buf = (uint8_t*)serd_allocate_buffer(page_size); + source->read_buf = source->file_buf; + memset(source->file_buf, '\0', page_size); + } else { + source->read_buf = &source->read_byte; } - return SERD_SUCCESS; +#if USE_POSIX_FADVISE && USE_FILENO + posix_fadvise(fileno(fd), 0, 0, POSIX_FADV_SEQUENTIAL); +#endif + + return source; } -SerdStatus -serd_byte_source_open_string(SerdByteSource* const source, - const char* const utf8, - const SerdNode* const name) +SerdByteSource* +serd_byte_source_new_string(const char* const string, + const SerdNode* const name) { - memset(source, '\0', sizeof(*source)); + SerdByteSource* source = (SerdByteSource*)calloc(1, sizeof(SerdByteSource)); source->page_size = 1; + source->read_buf = (const uint8_t*)string; + source->type = FROM_STRING; + source->name = name ? serd_node_copy(name) : serd_new_string(SERD_STRING("string")); - source->read_buf = (const uint8_t*)utf8; source->caret.file = source->name; source->caret.line = 1u; source->caret.col = 1u; - return SERD_SUCCESS; + return source; } SerdStatus -serd_byte_source_close(SerdByteSource* const source) +serd_byte_source_prepare(SerdByteSource* const source) { - SerdStatus st = SERD_SUCCESS; - if (source->close_func) { - st = source->close_func(source->stream) ? SERD_ERR_UNKNOWN : SERD_SUCCESS; - } + source->prepared = true; + if (source->type != FROM_STRING) { + if (source->page_size > 1) { + return serd_byte_source_page(source); + } - if (source->page_size > 1) { - serd_free_aligned(source->file_buf); + return serd_byte_source_advance(source); } - serd_node_free(source->name); - memset(source, '\0', sizeof(*source)); - return st; + return SERD_SUCCESS; +} + +void +serd_byte_source_free(SerdByteSource* const source) +{ + if (source) { + if (source->close_func) { + source->close_func(source->stream); + } + + if (source->page_size > 1) { + serd_free_aligned(source->file_buf); + } + + serd_node_free(source->name); + free(source); + } } |