aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--serd/serd.h5
-rw-r--r--src/reader.c52
-rw-r--r--src/serdi.c81
-rw-r--r--wscript4
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 " <http://drobilla.net/software/serd>\n");
printf("Copyright (C) 2011 David Robillard <http://drobilla.net>.\n"
"\nLicense: GNU LGPL version 3 or later "
"<http://gnu.org/licenses/lgpl.html>.\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 "<foo> a <#Thingie> ." > /dev/null'],
0, name='serdi-cmd-good')
autowaf.run_tests(ctx, APPNAME,