From b56591a0838bd9e402d366e53b3f0cacc1ddc35d Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 25 Jan 2011 19:26:19 +0000 Subject: Add serd_reader_read_string. git-svn-id: http://svn.drobilla.net/serd/trunk@69 490d8e77-9747-427b-9fa3-0b8f29cee8a0 --- serd/serd.h | 5 ++++ src/reader.c | 52 ++++++++++++++++++++++++++------------ src/serdi.c | 81 +++++++++++++++++++++++++++++++++++------------------------- wscript | 4 ++- 4 files changed, 92 insertions(+), 50 deletions(-) diff --git a/serd/serd.h b/serd/serd.h index 17f00a80..a096c475 100644 --- a/serd/serd.h +++ b/serd/serd.h @@ -259,6 +259,11 @@ serd_reader_read_file(SerdReader reader, FILE* file, const uint8_t* name); +/** Read @a utf8. */ +SERD_API +bool +serd_reader_read_string(SerdReader me, const uint8_t* utf8); + /** Free @a reader. */ SERD_API void diff --git a/src/reader.c b/src/reader.c index bd82ec9d..a0d74642 100644 --- a/src/reader.c +++ b/src/reader.c @@ -87,6 +87,7 @@ struct SerdReaderImpl { int err; uint8_t* read_buf; int32_t read_head; ///< Offset into read_buf + bool from_file; ///< True iff reading from @ref fd bool eof; #ifdef STACK_DEBUG Ref* alloc_stack; ///< Stack of push offsets @@ -121,6 +122,7 @@ make_node(SerdType type, Ref value, Ref datatype, Ref lang) static inline bool page(SerdReader reader) { + assert(reader->from_file); reader->read_head = 0; const size_t n_read = fread(reader->read_buf, 1, READ_BUF_LEN, reader->fd); if (n_read == 0) { @@ -138,7 +140,7 @@ peek_string(SerdReader reader, uint8_t* pre, int n) { uint8_t* ptr = reader->read_buf + reader->read_head; for (int i = 0; i < n; ++i) { - if (reader->read_head + i >= READ_BUF_LEN) { + if (reader->from_file && (reader->read_head + i >= READ_BUF_LEN)) { if (!page(reader)) { return false; } @@ -173,10 +175,10 @@ eat_byte(SerdReader reader, const uint8_t byte) if (c != byte) { return error(reader, "expected `%c', not `%c'\n", byte, c); } - if (reader->read_head == READ_BUF_LEN) { + if (reader->from_file && (reader->read_head == READ_BUF_LEN)) { TRY_RET(page(reader)); + assert(reader->read_head < READ_BUF_LEN); } - assert(reader->read_head < READ_BUF_LEN); if (reader->read_buf[reader->read_head] == '\0') { reader->eof = true; } @@ -1353,7 +1355,7 @@ serd_reader_new(SerdSyntax syntax, me->stack = serd_stack_new(STACK_PAGE_SIZE); me->cur = cur; me->next_id = 1; - me->read_buf = (uint8_t*)malloc(READ_BUF_LEN * 2); + me->read_buf = 0; me->read_head = 0; me->eof = false; #ifdef STACK_DEBUG @@ -1361,14 +1363,6 @@ serd_reader_new(SerdSyntax syntax, me->n_allocs = 0; #endif - memset(me->read_buf, '\0', READ_BUF_LEN * 2); - - /* Read into the second page of the buffer. Occasionally peek_string - will move the read_head to before this point when readahead causes - a page fault. - */ - me->read_buf += READ_BUF_LEN; // Read 1 page in - #define RDF_FIRST NS_RDF "first" #define RDF_REST NS_RDF "rest" #define RDF_NIL NS_RDF "nil" @@ -1392,7 +1386,6 @@ serd_reader_free(SerdReader reader) free(me->alloc_stack); #endif free(me->stack.buf); - free(me->read_buf - READ_BUF_LEN); free(me); } @@ -1401,14 +1394,41 @@ bool serd_reader_read_file(SerdReader me, FILE* file, const uint8_t* name) { const Cursor cur = { name, 1, 1 }; + me->fd = file; + me->read_buf = (uint8_t*)malloc(READ_BUF_LEN * 2); + me->read_head = 0; + me->cur = cur; + me->from_file = true; - me->fd = file; - me->cur = cur; + /* Read into the second page of the buffer. Occasionally peek_string + will move the read_head to before this point when readahead causes + a page fault. + */ + memset(me->read_buf, '\0', READ_BUF_LEN * 2); + me->read_buf += READ_BUF_LEN; page(me); const bool ret = read_turtleDoc(me); - me->fd = 0; + free(me->read_buf - READ_BUF_LEN); + me->fd = 0; + me->read_buf = NULL; + return ret; +} + +SERD_API +bool +serd_reader_read_string(SerdReader me, const uint8_t* utf8) +{ + const Cursor cur = { (const uint8_t*)"(string)", 1, 1 }; + + me->read_buf = (uint8_t*)utf8; + me->read_head = 0; + me->cur = cur; + me->from_file = false; + + const bool ret = read_turtleDoc(me); + me->read_buf = NULL; return ret; } diff --git a/src/serdi.c b/src/serdi.c index fb104fbd..a9f67205 100644 --- a/src/serdi.c +++ b/src/serdi.c @@ -181,7 +181,7 @@ event_end(void* handle, int print_version() { - printf("serdi " SERD_VERSION "\n"); + printf("serdi " SERD_VERSION " \n"); printf("Copyright (C) 2011 David Robillard .\n" "\nLicense: GNU LGPL version 3 or later " ".\n" @@ -198,6 +198,7 @@ print_usage(const char* name, bool error) fprintf(os, "Read and write RDF syntax.\n\n"); fprintf(os, " -h Display this help and exit\n"); fprintf(os, " -o SYNTAX Output syntax (`turtle' or `ntriples')\n"); + fprintf(os, " -s INPUT Parse INPUT as string (terminates options)\n"); fprintf(os, " -v Display version information and exit\n"); return error ? 1 : 0; } @@ -216,21 +217,28 @@ main(int argc, char** argv) return print_usage(argv[0], true); } - FILE* in_fd = NULL; - SerdSyntax output_syntax = SERD_NTRIPLES; - + FILE* in_fd = NULL; + SerdSyntax output_syntax = SERD_NTRIPLES; + bool from_file = true; + const char* in_name = NULL; int a = 1; for (; a < argc && argv[a][0] == '-'; ++a) { if (argv[a][1] == '\0') { - in_fd = stdin; + in_name = "(stdin)"; + in_fd = stdin; break; } else if (argv[a][1] == 'h') { return print_usage(argv[0], false); } else if (argv[a][1] == 'v') { return print_version(); + } else if (argv[a][1] == 's') { + in_name = "(string)"; + from_file = false; + ++a; + break; } else if (argv[a][1] == 'o') { if (++a == argc) { - fprintf(stderr, "missing value for -i\n"); + fprintf(stderr, "missing value for -o\n"); return 1; } if (!strcmp(argv[a], "turtle")) { @@ -247,17 +255,26 @@ main(int argc, char** argv) } } - const uint8_t* in_filename = (const uint8_t*)argv[a++]; - - if (!in_fd && serd_uri_string_has_scheme(in_filename)) { - // Input is an absolute URI, ensure it's a file: URI and chop scheme - if (strncmp((const char*)in_filename, "file:", 5)) { - fprintf(stderr, "unsupported URI scheme `%s'\n", in_filename); - return 1; - } else if (!strncmp((const char*)in_filename, "file://", 7)) { - in_filename += 7; - } else { - in_filename += 5; + const uint8_t* input = (const uint8_t*)argv[a++]; + if (from_file) { + in_name = in_name ? in_name : (const char*)input; + if (!in_fd) { + if (serd_uri_string_has_scheme(input)) { + // INPUT is an absolute URI, ensure it a file and chop scheme + if (strncmp((const char*)input, "file:", 5)) { + fprintf(stderr, "unsupported URI scheme `%s'\n", input); + return 1; + } else if (!strncmp((const char*)input, "file://", 7)) { + input += 7; + } else { + input += 5; + } + } + in_fd = fopen((const char*)input, "r"); + if (!in_fd) { + fprintf(stderr, "failed to open file %s\n", input); + return 1; + } } } @@ -271,26 +288,18 @@ main(int argc, char** argv) return 1; } base_uri_str = copy_string(in_base_uri, &base_uri_n_bytes); - } else { // Use input file URI - base_uri_str = copy_string(in_filename, &base_uri_n_bytes); + } else if (from_file) { // Use input file URI + base_uri_str = copy_string(input, &base_uri_n_bytes); + } else { + base_uri_str = copy_string((const uint8_t*)"", &base_uri_n_bytes); } if (!serd_uri_parse(base_uri_str, &base_uri)) { fprintf(stderr, "invalid base URI `%s'\n", base_uri_str); } - if (!in_fd) { - in_fd = fopen((const char*)in_filename, "r"); - } - - FILE* out_fd = stdout; - - if (!in_fd) { - fprintf(stderr, "failed to open file %s\n", in_filename); - return 1; - } - - SerdEnv env = serd_env_new(); + FILE* out_fd = stdout; + SerdEnv env = serd_env_new(); SerdStyle output_style = (output_syntax == SERD_NTRIPLES) ? SERD_STYLE_ASCII @@ -310,9 +319,15 @@ main(int argc, char** argv) SerdReader reader = serd_reader_new( SERD_TURTLE, &state, event_base, event_prefix, event_statement, event_end); - const bool success = serd_reader_read_file(reader, in_fd, in_filename); + const bool success = (from_file) + ? serd_reader_read_file(reader, in_fd, input) + : serd_reader_read_string(reader, input); + serd_reader_free(reader); - fclose(in_fd); + + if (from_file) { + fclose(in_fd); + } serd_writer_finish(state.writer); serd_writer_free(state.writer); diff --git a/wscript b/wscript index 0c6d23c1..c41a99c3 100644 --- a/wscript +++ b/wscript @@ -126,7 +126,9 @@ def test(ctx): autowaf.run_tests(ctx, APPNAME, ['./serdi_static file:../tests/manifest.ttl > /dev/null', './serdi_static file://../tests/manifest.ttl > /dev/null', - './serdi_static ../tests/UTF-8.ttl > /dev/null'], + './serdi_static ../tests/UTF-8.ttl > /dev/null', + './serdi_static -v > /dev/null', + './serdi_static -s " a <#Thingie> ." > /dev/null'], 0, name='serdi-cmd-good') autowaf.run_tests(ctx, APPNAME, -- cgit v1.2.1