diff options
Diffstat (limited to 'src/byte_source.c')
-rw-r--r-- | src/byte_source.c | 187 |
1 files changed, 118 insertions, 69 deletions
diff --git a/src/byte_source.c b/src/byte_source.c index ca02ff3e..1c86fcce 100644 --- a/src/byte_source.c +++ b/src/byte_source.c @@ -20,118 +20,167 @@ #include "serd/serd.h" +#if defined(USE_POSIX_FADVISE) && defined(USE_FILENO) +# include <fcntl.h> +#endif + #include <stdbool.h> #include <stdint.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> -SerdStatus -serd_byte_source_page(SerdByteSource* source) +SerdByteSource* +serd_byte_source_new_string(const char* string, const SerdNode* name) { - uint8_t* const buf = - (source->page_size > 1 ? source->file_buf : &source->read_byte); + SerdByteSource* source = (SerdByteSource*)calloc(1, sizeof(SerdByteSource)); - const size_t n_read = - source->read_func(buf, 1, source->page_size, source->stream); + source->page_size = 1; + source->read_buf = (const uint8_t*)string; + source->type = FROM_STRING; - source->buf_size = n_read; - source->read_head = 0; - source->eof = false; + source->name = + name ? serd_node_copy(name) : serd_new_string(SERD_STATIC_STRING("string")); - if (n_read < source->page_size) { - buf[n_read] = '\0'; - if (n_read == 0) { - source->eof = true; - return (source->error_func(source->stream) ? SERD_ERR_UNKNOWN - : SERD_FAILURE); - } - } + const SerdCursor cur = {source->name, 1, 1}; + source->cur = cur; - return SERD_SUCCESS; + return source; } -SerdStatus -serd_byte_source_open_source(SerdByteSource* source, - SerdReadFunc read_func, - SerdStreamErrorFunc error_func, - SerdStreamCloseFunc close_func, - void* stream, - const SerdNode* name, - size_t page_size) +SerdByteSource* +serd_byte_source_new_filename(const char* path, size_t block_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->from_stream = true; + if (!path || !block_size) { + return NULL; + } + + FILE* fd = fopen(path, "rb"); + if (!fd) { + return NULL; + } + + 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 = block_size; + source->buf_size = block_size; + source->name = + serd_new_file_uri(SERD_MEASURE_STRING(path), SERD_EMPTY_STRING()); + source->type = FROM_FILENAME; const SerdCursor cur = {source->name, 1, 1}; source->cur = cur; - if (page_size > 1) { - source->file_buf = (uint8_t*)serd_allocate_buffer(page_size); + if (block_size > 1) { + source->file_buf = (uint8_t*)serd_allocate_buffer(block_size); source->read_buf = source->file_buf; - memset(source->file_buf, '\0', page_size); + memset(source->file_buf, '\0', block_size); } else { source->read_buf = &source->read_byte; } - return SERD_SUCCESS; +#if defined(USE_POSIX_FADVISE) && defined(USE_FILENO) + posix_fadvise(fileno(fd), 0, 0, POSIX_FADV_SEQUENTIAL); +#endif + + return source; } -SerdStatus -serd_byte_source_prepare(SerdByteSource* source) +SerdByteSource* +serd_byte_source_new_function(SerdReadFunc read_func, + SerdStreamErrorFunc error_func, + void* stream, + const SerdNode* name, + size_t block_size) { - if (source->page_size == 0) { - return SERD_FAILURE; + if (!read_func || !block_size) { + return NULL; } - source->prepared = true; + SerdByteSource* source = (SerdByteSource*)calloc(1, sizeof(SerdByteSource)); + + source->read_func = read_func; + source->error_func = error_func; + // source->close_func = close_func; FIXME + source->stream = stream; + source->page_size = block_size; + source->buf_size = block_size; + source->type = FROM_FUNCTION; + + source->name = + name ? serd_node_copy(name) : serd_new_string(SERD_STATIC_STRING("func")); + + const SerdCursor cur = {source->name, 1, 1}; + source->cur = cur; - if (source->from_stream) { - return (source->page_size > 1 ? serd_byte_source_page(source) - : serd_byte_source_advance(source)); + if (block_size > 1) { + source->file_buf = (uint8_t*)serd_allocate_buffer(block_size); + source->read_buf = source->file_buf; + memset(source->file_buf, '\0', block_size); + } else { + source->read_buf = &source->read_byte; } - return SERD_SUCCESS; + return source; +} + +void +serd_byte_source_free(SerdByteSource* source) +{ + if (source) { + if (source->close_func) { + source->close_func(source->stream); + } + + if (source->page_size > 1) { + free(source->file_buf); + } + + serd_node_free(source->name); + free(source); + } } SerdStatus -serd_byte_source_open_string(SerdByteSource* source, - const char* utf8, - const SerdNode* name) +serd_byte_source_page(SerdByteSource* source) { - memset(source, '\0', sizeof(*source)); + uint8_t* const buf = + (source->page_size > 1 ? source->file_buf : &source->read_byte); - source->page_size = 1; - source->name = - name ? serd_node_copy(name) : serd_new_string(SERD_STATIC_STRING("string")); + const size_t n_read = + source->read_func(buf, 1, source->page_size, source->stream); - source->read_buf = (const uint8_t*)utf8; + source->buf_size = n_read; + source->read_head = 0; + source->eof = false; - const SerdCursor cur = {source->name, 1, 1}; - source->cur = cur; + if (n_read < source->page_size) { + buf[n_read] = '\0'; + if (n_read == 0) { + source->eof = true; + return (source->error_func(source->stream) ? SERD_ERR_UNKNOWN + : SERD_FAILURE); + } + } return SERD_SUCCESS; } SerdStatus -serd_byte_source_close(SerdByteSource* source) +serd_byte_source_prepare(SerdByteSource* 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; } |