diff options
author | David Robillard <d@drobilla.net> | 2021-02-25 15:48:04 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2021-03-07 15:32:24 -0500 |
commit | e6abc21f9bde66d8f60078493354ba3713f9fcd8 (patch) | |
tree | d509c89987e44ba6cbffa52603ab9394fcc7c3e1 /src | |
parent | b085fe7aa38e5e2caf82b1fec6b7e6094779dd5a (diff) | |
download | serd-e6abc21f9bde66d8f60078493354ba3713f9fcd8.tar.gz serd-e6abc21f9bde66d8f60078493354ba3713f9fcd8.tar.bz2 serd-e6abc21f9bde66d8f60078493354ba3713f9fcd8.zip |
Simplify reader interface
Diffstat (limited to 'src')
-rw-r--r-- | src/byte_source.c | 15 | ||||
-rw-r--r-- | src/byte_source.h | 8 | ||||
-rw-r--r-- | src/reader.c | 76 | ||||
-rw-r--r-- | src/serdi.c | 97 | ||||
-rw-r--r-- | src/system.h | 17 |
5 files changed, 78 insertions, 135 deletions
diff --git a/src/byte_source.c b/src/byte_source.c index 04836984..2f09d634 100644 --- a/src/byte_source.c +++ b/src/byte_source.c @@ -50,6 +50,7 @@ SerdStatus serd_byte_source_open_source(SerdByteSource* source, SerdReadFunc read_func, SerdStreamErrorFunc error_func, + SerdStreamCloseFunc close_func, void* stream, const char* name, size_t page_size) @@ -57,13 +58,14 @@ serd_byte_source_open_source(SerdByteSource* source, const Cursor cur = {name, 1, 1}; memset(source, '\0', sizeof(*source)); + source->read_func = read_func; + source->error_func = error_func; + source->close_func = close_func; source->stream = stream; - source->from_stream = true; source->page_size = page_size; source->buf_size = page_size; source->cur = cur; - source->error_func = error_func; - source->read_func = read_func; + source->from_stream = true; if (page_size > 1) { source->file_buf = (uint8_t*)serd_allocate_buffer(page_size); @@ -103,10 +105,15 @@ serd_byte_source_open_string(SerdByteSource* source, const char* utf8) SerdStatus serd_byte_source_close(SerdByteSource* source) { + SerdStatus st = SERD_SUCCESS; + if (source->close_func) { + st = source->close_func(source->stream) ? SERD_ERR_UNKNOWN : SERD_SUCCESS; + } + if (source->page_size > 1) { serd_free_aligned(source->file_buf); } memset(source, '\0', sizeof(*source)); - return SERD_SUCCESS; + return st; } diff --git a/src/byte_source.h b/src/byte_source.h index f0df9bf3..d2c19de3 100644 --- a/src/byte_source.h +++ b/src/byte_source.h @@ -23,7 +23,8 @@ #include <stdbool.h> #include <stddef.h> #include <stdint.h> -#include <stdio.h> + +typedef int (*SerdStreamCloseFunc)(void*); typedef struct { const char* filename; @@ -34,6 +35,7 @@ typedef struct { typedef struct { SerdReadFunc read_func; ///< Read function (e.g. fread) SerdStreamErrorFunc error_func; ///< Error function (e.g. ferror) + SerdStreamCloseFunc close_func; ///< Function for closing stream void* stream; ///< Stream (e.g. FILE) size_t page_size; ///< Number of bytes to read at a time size_t buf_size; ///< Number of bytes in file_buf @@ -48,15 +50,13 @@ typedef struct { } SerdByteSource; SerdStatus -serd_byte_source_open_file(SerdByteSource* source, FILE* file, bool bulk); - -SerdStatus serd_byte_source_open_string(SerdByteSource* source, const char* utf8); SerdStatus serd_byte_source_open_source(SerdByteSource* source, SerdReadFunc read_func, SerdStreamErrorFunc error_func, + SerdStreamCloseFunc close_func, void* stream, const char* name, size_t page_size); diff --git a/src/reader.c b/src/reader.c index 805d41a7..ab9e54b5 100644 --- a/src/reader.c +++ b/src/reader.c @@ -16,11 +16,10 @@ #include "reader.h" #include "byte_source.h" +#include "serd_internal.h" #include "stack.h" #include "system.h" -#include "serd_internal.h" - #include <errno.h> #include <stdarg.h> #include <stdio.h> @@ -207,6 +206,7 @@ serd_reader_free(SerdReader* reader) pop_node(reader, reader->rdf_nil); pop_node(reader, reader->rdf_rest); pop_node(reader, reader->rdf_first); + serd_reader_finish(reader); serd_node_free(reader->default_graph); #ifdef SERD_STACK_CHECK @@ -239,39 +239,6 @@ serd_reader_set_default_graph(SerdReader* reader, const SerdNode* graph) reader->default_graph = serd_node_copy(graph); } -SerdStatus -serd_reader_read_file(SerdReader* reader, const char* uri) -{ - char* const path = serd_parse_file_uri(uri, NULL); - if (!path) { - return SERD_ERR_BAD_ARG; - } - - FILE* fd = serd_fopen(path, "rb"); - if (!fd) { - serd_free(path); - return SERD_ERR_UNKNOWN; - } - - SerdStatus st = serd_reader_start_stream(reader, - (SerdReadFunc)fread, - (SerdStreamErrorFunc)ferror, - fd, - path, - SERD_PAGE_SIZE); - - if (!st) { - st = serd_reader_read_document(reader); - } - - const SerdStatus est = serd_reader_end_stream(reader); - - fclose(fd); - free(path); - - return st ? st : est; -} - static SerdStatus skip_bom(SerdReader* me) { @@ -298,7 +265,31 @@ serd_reader_start_stream(SerdReader* reader, size_t page_size) { return serd_byte_source_open_source( - &reader->source, read_func, error_func, stream, name, page_size); + &reader->source, read_func, error_func, NULL, stream, name, page_size); +} + +SerdStatus +serd_reader_start_file(SerdReader* reader, const char* uri, bool bulk) +{ + char* const path = serd_parse_file_uri(uri, NULL); + if (!path) { + return SERD_ERR_BAD_ARG; + } + + FILE* fd = serd_fopen(path, "rb"); + free(path); + if (!fd) { + return SERD_ERR_UNKNOWN; + } + + return serd_byte_source_open_source(&reader->source, + bulk ? (SerdReadFunc)fread + : serd_file_read_byte, + (SerdStreamErrorFunc)ferror, + (SerdStreamCloseFunc)fclose, + fd, + uri, + bulk ? SERD_PAGE_SIZE : 1); } SerdStatus @@ -340,18 +331,7 @@ serd_reader_read_chunk(SerdReader* reader) } SerdStatus -serd_reader_end_stream(SerdReader* reader) +serd_reader_finish(SerdReader* reader) { return serd_byte_source_close(&reader->source); } - -SerdStatus -serd_reader_read_string(SerdReader* reader, const char* utf8) -{ - serd_reader_start_string(reader, utf8); - - const SerdStatus st = serd_reader_read_document(reader); - const SerdStatus est = serd_byte_source_close(&reader->source); - - return st ? st : est; -} diff --git a/src/serdi.c b/src/serdi.c index e7b8d7ba..6049c31b 100644 --- a/src/serdi.c +++ b/src/serdi.c @@ -14,10 +14,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define _POSIX_C_SOURCE 200809L /* for fileno and posix_fadvise */ - #include "serd_config.h" #include "string_utils.h" +#include "system.h" #include "serd/serd.h" @@ -29,15 +28,8 @@ # include <io.h> #endif -#if USE_POSIX_FADVISE && USE_FILENO -# include <fcntl.h> -#endif - -#include <errno.h> #include <stdbool.h> -#include <stdint.h> #include <stdio.h> -#include <stdlib.h> #include <string.h> #define SERDI_ERROR(msg) fprintf(stderr, "serdi: " msg) @@ -135,38 +127,6 @@ quiet_error_sink(void* handle, const SerdError* e) return SERD_SUCCESS; } -static inline FILE* -serd_fopen(const char* path, const char* mode) -{ - FILE* fd = fopen(path, mode); - if (!fd) { - SERDI_ERRORF("failed to open file %s (%s)\n", path, strerror(errno)); - return NULL; - } - -#if USE_POSIX_FADVISE && USE_FILENO - posix_fadvise(fileno(fd), 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE); -#endif - - return fd; -} - -/** fread-like wrapper for getc (which is faster). */ -static size_t -serd_file_read_byte(void* buf, size_t size, size_t nmemb, void* stream) -{ - (void)size; - (void)nmemb; - - const int c = getc((FILE*)stream); - if (c == EOF) { - *((uint8_t*)buf) = 0; - return 0; - } - *((uint8_t*)buf) = (uint8_t)c; - return 1; -} - static SerdWriterFlags choose_style(const SerdSyntax input_syntax, const SerdSyntax output_syntax, @@ -204,25 +164,23 @@ main(int argc, char** argv) return print_usage(argv[0], true); } - FILE* in_fd = NULL; SerdSyntax input_syntax = (SerdSyntax)0; SerdSyntax output_syntax = (SerdSyntax)0; - bool from_file = true; + bool from_string = false; + bool from_stdin = false; bool ascii = false; bool bulk_read = true; bool bulk_write = false; bool full_uris = false; bool lax = false; bool quiet = false; - const char* in_name = NULL; const char* add_prefix = NULL; const char* chop_prefix = NULL; const char* root_uri = NULL; int a = 1; for (; a < argc && argv[a][0] == '-'; ++a) { if (argv[a][1] == '\0') { - in_name = (const char*)"(stdin)"; - in_fd = stdin; + from_stdin = true; break; } @@ -243,8 +201,7 @@ main(int argc, char** argv) } else if (argv[a][1] == 'v') { return print_version(); } else if (argv[a][1] == 's') { - in_name = (const char*)"(string)"; - from_file = false; + from_string = true; ++a; break; } else if (argv[a][1] == 'i') { @@ -297,22 +254,9 @@ main(int argc, char** argv) _setmode(_fileno(stdout), _O_BINARY); #endif - char* input_path = NULL; - const char* input = (const char*)argv[a++]; - if (from_file) { - in_name = in_name ? in_name : input; - if (!in_fd) { - if (!strncmp(input, "file:", 5)) { - input_path = serd_parse_file_uri(input, NULL); - input = input_path; - } - if (!input || !(in_fd = serd_fopen(input, "rb"))) { - return 1; - } - } - } + const char* input = argv[a++]; - if (!input_syntax && !(input_syntax = guess_syntax(in_name))) { + if (!input_syntax && !(input_syntax = guess_syntax(input))) { input_syntax = SERD_TRIG; } @@ -329,7 +273,7 @@ main(int argc, char** argv) SerdNode* base = NULL; if (a < argc) { // Base URI given on command line base = serd_new_uri(SERD_MEASURE_STRING((const char*)argv[a])); - } else if (from_file && in_fd != stdin) { // Use input file URI + } else if (!from_string && !from_stdin) { // Use input file URI base = serd_new_file_uri(SERD_MEASURE_STRING(input), SERD_EMPTY_STRING()); } @@ -355,36 +299,31 @@ main(int argc, char** argv) serd_node_free(root); SerdStatus st = SERD_SUCCESS; - if (!from_file) { + if (from_string) { st = serd_reader_start_string(reader, input); - } else { + } else if (from_stdin) { st = serd_reader_start_stream(reader, - bulk_read ? (SerdReadFunc)fread - : serd_file_read_byte, + serd_file_read_byte, (SerdStreamErrorFunc)ferror, - in_fd, - in_name, - bulk_read ? 4096 : 1); + stdin, + "(stdin)", + 1); + } else { + st = serd_reader_start_file(reader, input, bulk_read); } if (!st) { st = serd_reader_read_document(reader); } - serd_reader_end_stream(reader); - + serd_reader_finish(reader); serd_reader_free(reader); serd_writer_finish(writer); serd_writer_free(writer); serd_env_free(env); serd_node_free(base); - free(input_path); - - if (from_file) { - fclose(in_fd); - } - if (fclose(out_fd)) { + if (fclose(stdout)) { perror("serdi: write error"); st = SERD_ERR_UNKNOWN; } diff --git a/src/system.h b/src/system.h index fdfab4a4..df5827de 100644 --- a/src/system.h +++ b/src/system.h @@ -19,6 +19,7 @@ #include "attributes.h" +#include <stdint.h> #include <stdio.h> /// Open a file configured for fast sequential reading @@ -37,4 +38,20 @@ serd_allocate_buffer(size_t size); void serd_free_aligned(void* ptr); +/** fread-like wrapper for getc (which is faster). */ +static inline size_t +serd_file_read_byte(void* buf, size_t size, size_t nmemb, void* stream) +{ + (void)size; + (void)nmemb; + + const int c = getc((FILE*)stream); + if (c == EOF) { + *((uint8_t*)buf) = 0; + return 0; + } + *((uint8_t*)buf) = (uint8_t)c; + return 1; +} + #endif // SERD_SYSTEM_H |