aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-06-03 22:15:53 +0200
committerDavid Robillard <d@drobilla.net>2018-11-25 22:12:47 +0100
commit47e35393464abc9d92f92974ecef173c7e1b372f (patch)
tree8c1b1a473e804d07fb73c135d9fc78625f8ce3f6
parent191392584bebb14bed9bb325f54a035e0072622a (diff)
downloadserd-47e35393464abc9d92f92974ecef173c7e1b372f.tar.gz
serd-47e35393464abc9d92f92974ecef173c7e1b372f.tar.bz2
serd-47e35393464abc9d92f92974ecef173c7e1b372f.zip
Add SerdCursor to public API
-rw-r--r--serd/serd.h51
-rw-r--r--src/byte_source.c23
-rw-r--r--src/byte_source.h17
-rw-r--r--src/cursor.c35
-rw-r--r--src/cursor.h28
-rw-r--r--src/reader.c18
-rw-r--r--src/serdi.c9
-rw-r--r--src/world.c12
-rw-r--r--wscript1
9 files changed, 157 insertions, 37 deletions
diff --git a/serd/serd.h b/serd/serd.h
index 825726d6..4fa5a70d 100644
--- a/serd/serd.h
+++ b/serd/serd.h
@@ -70,6 +70,11 @@ typedef struct SerdWorldImpl SerdWorld;
typedef struct SerdStatementImpl SerdStatement;
/**
+ Cursor, the origin of a statement in a document.
+*/
+typedef struct SerdCursorImpl SerdCursor;
+
+/**
Environment.
Represents the state required to resolve a CURIE or relative URI, e.g. the
@@ -263,12 +268,10 @@ typedef struct {
An error description.
*/
typedef struct {
- SerdStatus status; /**< Error code */
- const char* filename; /**< File where error was encountered, or NULL */
- unsigned line; /**< Line where error was encountered, or 0 */
- unsigned col; /**< Column where error was encountered */
- const char* fmt; /**< Message format string (printf style) */
- va_list* args; /**< Arguments for fmt */
+ SerdStatus status; /**< Error code */
+ const SerdCursor* cursor; /**< Origin of error, or NULL */
+ const char* fmt; /**< Message format string (printf style) */
+ va_list* args; /**< Arguments for fmt */
} SerdError;
/**
@@ -1074,7 +1077,7 @@ serd_reader_start_stream(SerdReader* reader,
SerdReadFunc read_func,
SerdStreamErrorFunc error_func,
void* stream,
- const char* name,
+ const SerdNode* name,
size_t page_size);
/**
@@ -1082,7 +1085,9 @@ serd_reader_start_stream(SerdReader* reader,
*/
SERD_API
SerdStatus
-serd_reader_start_string(SerdReader* reader, const char* utf8);
+serd_reader_start_string(SerdReader* reader,
+ const char* utf8,
+ const SerdNode* name);
/**
Read a single "chunk" of data during an incremental read.
@@ -1265,6 +1270,36 @@ serd_statement_get_graph(const SerdStatement* statement);
/**
@}
+ @name Cursor
+ @{
+*/
+
+/**
+ Return the document name.
+
+ This is typically a file URI, but may be a descriptive string node for
+ statements that originate from streams.
+*/
+SERD_API
+const SerdNode*
+serd_cursor_get_name(const SerdCursor* cursor);
+
+/**
+ Return the one-relative line number in the document.
+*/
+SERD_API
+unsigned
+serd_cursor_get_line(const SerdCursor* cursor);
+
+/**
+ Return the zero-relative column number in the line.
+*/
+SERD_API
+unsigned
+serd_cursor_get_column(const SerdCursor* cursor);
+
+/**
+ @}
@}
*/
diff --git a/src/byte_source.c b/src/byte_source.c
index a3f50a14..93ba972f 100644
--- a/src/byte_source.c
+++ b/src/byte_source.c
@@ -46,20 +46,21 @@ serd_byte_source_open_source(SerdByteSource* source,
SerdStreamErrorFunc error_func,
SerdStreamCloseFunc close_func,
void* stream,
- const char* name,
+ const SerdNode* name,
size_t page_size)
{
- 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->page_size = page_size;
- source->cur = cur;
+ source->name = serd_node_copy(name);
source->from_stream = true;
+ const SerdCursor cur = { source->name, 1, 1 };
+ source->cur = cur;
+
if (page_size > 1) {
source->file_buf = (uint8_t*)serd_allocate_buffer(page_size);
source->read_buf = source->file_buf;
@@ -86,13 +87,18 @@ serd_byte_source_prepare(SerdByteSource* source)
}
SerdStatus
-serd_byte_source_open_string(SerdByteSource* source, const char* utf8)
+serd_byte_source_open_string(SerdByteSource* source,
+ const char* utf8,
+ const SerdNode* name)
{
- const Cursor cur = { "(string)", 1, 1 };
-
memset(source, '\0', sizeof(*source));
- source->cur = cur;
+
+ source->name = name ? serd_node_copy(name) : serd_new_string("string");
source->read_buf = (const uint8_t*)utf8;
+
+ const SerdCursor cur = {source->name, 1, 1};
+ source->cur = cur;
+
return SERD_SUCCESS;
}
@@ -107,6 +113,7 @@ serd_byte_source_close(SerdByteSource* source)
if (source->page_size > 1) {
free(source->file_buf);
}
+ serd_node_free(source->name);
memset(source, '\0', sizeof(*source));
return st;
}
diff --git a/src/byte_source.h b/src/byte_source.h
index e0c9e349..34df4fa3 100644
--- a/src/byte_source.h
+++ b/src/byte_source.h
@@ -17,6 +17,8 @@
#ifndef SERD_BYTE_SOURCE_H
#define SERD_BYTE_SOURCE_H
+#include "cursor.h"
+
#include "serd/serd.h"
#include <assert.h>
@@ -28,18 +30,13 @@
typedef int (*SerdStreamCloseFunc)(void*);
typedef struct {
- const char* filename;
- unsigned line;
- unsigned col;
-} Cursor;
-
-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
- Cursor cur; ///< Cursor for error reporting
+ SerdNode* name; ///< Name of stream (referenced by cur)
+ SerdCursor cur; ///< Cursor for error reporting
uint8_t* file_buf; ///< Buffer iff reading pages from a file
const uint8_t* read_buf; ///< Pointer to file_buf or read_byte
size_t read_head; ///< Offset into read_buf
@@ -50,7 +47,9 @@ typedef struct {
} SerdByteSource;
SerdStatus
-serd_byte_source_open_string(SerdByteSource* source, const char* utf8);
+serd_byte_source_open_string(SerdByteSource* source,
+ const char* utf8,
+ const SerdNode* name);
SerdStatus
serd_byte_source_open_source(SerdByteSource* source,
@@ -58,7 +57,7 @@ serd_byte_source_open_source(SerdByteSource* source,
SerdStreamErrorFunc error_func,
SerdStreamCloseFunc close_func,
void* stream,
- const char* name,
+ const SerdNode* name,
size_t page_size);
SerdStatus
diff --git a/src/cursor.c b/src/cursor.c
new file mode 100644
index 00000000..7d72954b
--- /dev/null
+++ b/src/cursor.c
@@ -0,0 +1,35 @@
+/*
+ Copyright 2018 David Robillard <http://drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include "cursor.h"
+
+const SerdNode*
+serd_cursor_get_name(const SerdCursor* cursor)
+{
+ return cursor->file;
+}
+
+unsigned
+serd_cursor_get_line(const SerdCursor* cursor)
+{
+ return cursor->line;
+}
+
+unsigned
+serd_cursor_get_column(const SerdCursor* cursor)
+{
+ return cursor->col;
+}
diff --git a/src/cursor.h b/src/cursor.h
new file mode 100644
index 00000000..51fbf6e8
--- /dev/null
+++ b/src/cursor.h
@@ -0,0 +1,28 @@
+/*
+ Copyright 2018 David Robillard <http://drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#ifndef SERD_CURSOR_H
+#define SERD_CURSOR_H
+
+#include "serd/serd.h"
+
+struct SerdCursorImpl {
+ const SerdNode* file;
+ unsigned line;
+ unsigned col;
+};
+
+#endif // SERD_CURSOR_H
diff --git a/src/reader.c b/src/reader.c
index 0c32fbc7..b34f5a0f 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -36,8 +36,7 @@ r_err(SerdReader* reader, SerdStatus st, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- const Cursor* const cur = &reader->source.cur;
- const SerdError e = { st, cur->filename, cur->line, cur->col, fmt, &args };
+ const SerdError e = { st, &reader->source.cur, fmt, &args };
serd_world_error(reader->world, &e);
va_end(args);
return st;
@@ -243,7 +242,7 @@ serd_reader_start_stream(SerdReader* reader,
SerdReadFunc read_func,
SerdStreamErrorFunc error_func,
void* stream,
- const char* name,
+ const SerdNode* name,
size_t page_size)
{
return serd_byte_source_open_source(
@@ -264,20 +263,25 @@ serd_reader_start_file(SerdReader* reader, const char* uri, bool bulk)
return SERD_ERR_UNKNOWN;
}
- return serd_byte_source_open_source(
+ SerdNode* const name = serd_new_uri(uri);
+ const SerdStatus st = serd_byte_source_open_source(
&reader->source,
bulk ? (SerdReadFunc)fread : serd_file_read_byte,
(SerdStreamErrorFunc)ferror,
(SerdStreamCloseFunc)fclose,
fd,
- uri,
+ name,
bulk ? SERD_PAGE_SIZE : 1);
+ serd_node_free(name);
+ return st;
}
SerdStatus
-serd_reader_start_string(SerdReader* reader, const char* utf8)
+serd_reader_start_string(SerdReader* reader,
+ const char* utf8,
+ const SerdNode* name)
{
- return serd_byte_source_open_string(&reader->source, utf8);
+ return serd_byte_source_open_string(&reader->source, utf8, name);
}
static SerdStatus
diff --git a/src/serdi.c b/src/serdi.c
index 7543ed7c..1e562ff0 100644
--- a/src/serdi.c
+++ b/src/serdi.c
@@ -234,15 +234,18 @@ main(int argc, char** argv)
serd_reader_add_blank_prefix(reader, add_prefix);
serd_node_free(root);
- SerdStatus status = SERD_SUCCESS;
+ SerdStatus status = SERD_SUCCESS;
+ SerdNode* input_name = NULL;
if (from_string) {
- status = serd_reader_start_string(reader, input);
+ input_name = serd_new_string("string");
+ status = serd_reader_start_string(reader, input, input_name);
} else if (from_stdin) {
+ input_name = serd_new_string("stdin");
status = serd_reader_start_stream(reader,
serd_file_read_byte,
(SerdStreamErrorFunc)ferror,
stdin,
- "(stdin)",
+ input_name,
1);
} else {
status = serd_reader_start_file(reader, input, bulk_read);
diff --git a/src/world.c b/src/world.c
index 2a89993f..862676ee 100644
--- a/src/world.c
+++ b/src/world.c
@@ -18,6 +18,7 @@
#include "world.h"
+#include "cursor.h"
#include "node.h"
#include "serd_config.h"
@@ -54,7 +55,14 @@ serd_world_error(const SerdWorld* world, const SerdError* e)
if (world->error_sink) {
world->error_sink(world->error_handle, e);
} else {
- fprintf(stderr, "error: %s:%u:%u: ", e->filename, e->line, e->col);
+ fprintf(stderr, "error: ");
+ if (e->cursor) {
+ fprintf(stderr,
+ "%s:%u:%u: ",
+ serd_node_get_string(e->cursor->file),
+ e->cursor->line,
+ e->cursor->col);
+ }
vfprintf(stderr, e->fmt, *e->args);
}
return e->status;
@@ -65,7 +73,7 @@ serd_world_errorf(const SerdWorld* world, SerdStatus st, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- const SerdError e = { st, NULL, 0, 0, fmt, &args };
+ const SerdError e = { st, NULL, fmt, &args };
serd_world_error(world, &e);
va_end(args);
return st;
diff --git a/wscript b/wscript
index 87c9d1e2..b552b62b 100644
--- a/wscript
+++ b/wscript
@@ -76,6 +76,7 @@ def configure(conf):
lib_source = ['src/base64.c',
'src/byte_source.c',
+ 'src/cursor.c',
'src/env.c',
'src/n3.c',
'src/node.c',