aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-11-25 18:08:54 +0100
committerDavid Robillard <d@drobilla.net>2019-04-13 19:48:23 +0200
commit5443876d8e15c6ad011ede7d46ed36325a6cb282 (patch)
tree69fbb26e35f44a6d49d60c4a8969e6d2cca63a3e
parent3b1252125ca66387f904ce107fb4c6130d5c582d (diff)
downloadserd-5443876d8e15c6ad011ede7d46ed36325a6cb282.tar.gz
serd-5443876d8e15c6ad011ede7d46ed36325a6cb282.tar.bz2
serd-5443876d8e15c6ad011ede7d46ed36325a6cb282.zip
Remove reader status and handle errors more precisely
-rw-r--r--serd/serd.h3
-rw-r--r--src/byte_source.h5
-rw-r--r--src/n3.c53
-rw-r--r--src/reader.c13
-rw-r--r--src/reader.h8
-rw-r--r--src/string.c1
-rw-r--r--tests/serd_test.c2
7 files changed, 40 insertions, 45 deletions
diff --git a/serd/serd.h b/serd/serd.h
index 0b798abc..145a424a 100644
--- a/serd/serd.h
+++ b/serd/serd.h
@@ -110,7 +110,8 @@ typedef enum {
SERD_ERR_BAD_CURIE, ///< Invalid CURIE (e.g. prefix does not exist)
SERD_ERR_INTERNAL, ///< Unexpected internal error (should not happen)
SERD_ERR_OVERFLOW, ///< Stack overflow
- SERD_ERR_INVALID ///< Invalid data
+ SERD_ERR_INVALID, ///< Invalid data
+ SERD_ERR_NO_DATA ///< Unexpected end of input
} SerdStatus;
/// RDF syntax type
diff --git a/src/byte_source.h b/src/byte_source.h
index f88fa6c9..4dfff70f 100644
--- a/src/byte_source.h
+++ b/src/byte_source.h
@@ -87,13 +87,14 @@ serd_byte_source_advance(SerdByteSource* source)
}
if (source->from_stream) {
- source->eof = false;
if (source->page_size > 1) {
if (++source->read_head == source->page_size) {
+ source->eof = false;
st = serd_byte_source_page(source);
}
} else {
if (!source->read_func(&source->read_byte, 1, 1, source->stream)) {
+ source->eof = true;
st = source->error_func(source->stream) ? SERD_ERR_UNKNOWN
: SERD_FAILURE;
}
@@ -102,7 +103,7 @@ serd_byte_source_advance(SerdByteSource* source)
++source->read_head; // Move to next character in string
}
- return source->eof ? SERD_FAILURE : st;
+ return st ? st : source->eof ? SERD_FAILURE : SERD_SUCCESS;
}
#endif // SERD_BYTE_SOURCE_H
diff --git a/src/n3.c b/src/n3.c
index 7c470c93..a41d1b8f 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -199,9 +199,10 @@ read_utf8_character(SerdReader* reader, SerdNode* dest, uint8_t c)
uint32_t size;
uint8_t bytes[4];
SerdStatus st = read_utf8_bytes(reader, bytes, &size, c);
- if (st) {
- push_bytes(reader, dest, replacement_char, 3);
+ if (st && reader->strict) {
return st;
+ } else if (st) {
+ return push_bytes(reader, dest, replacement_char, 3);
}
return push_bytes(reader, dest, bytes, size);
@@ -213,9 +214,10 @@ read_utf8_code(SerdReader* reader, SerdNode* dest, uint32_t* code, uint8_t c)
uint32_t size;
uint8_t bytes[4] = { 0, 0, 0, 0 };
SerdStatus st = read_utf8_bytes(reader, bytes, &size, c);
- if (st) {
- push_bytes(reader, dest, replacement_char, 3);
+ if (st && reader->strict) {
return st;
+ } else if (st) {
+ return push_bytes(reader, dest, replacement_char, 3);
}
if (!(st = push_bytes(reader, dest, bytes, size))) {
@@ -303,7 +305,7 @@ static SerdStatus
read_STRING_LITERAL_LONG(SerdReader* reader, SerdNode* dest, uint8_t q)
{
SerdStatus st = SERD_SUCCESS;
- while (!reader->status && !(st && reader->strict)) {
+ while (!st || (st == SERD_ERR_BAD_SYNTAX && !reader->strict)) {
const uint8_t c = peek_byte(reader);
if (c == '\\') {
eat_byte_safe(reader, c);
@@ -316,6 +318,9 @@ read_STRING_LITERAL_LONG(SerdReader* reader, SerdNode* dest, uint8_t q)
peek_byte(reader));
return SERD_ERR_BAD_SYNTAX;
}
+ } else if (reader->source.eof) {
+ st = r_err(reader, SERD_ERR_NO_DATA,
+ "unexpected end of file\n");
} else if (c == q) {
eat_byte_safe(reader, q);
const uint8_t q2 = eat_byte_safe(reader, peek_byte(reader));
@@ -332,6 +337,7 @@ read_STRING_LITERAL_LONG(SerdReader* reader, SerdNode* dest, uint8_t q)
reader, dest, &dest->flags, eat_byte_safe(reader, c));
}
}
+
return st;
}
@@ -341,24 +347,25 @@ static SerdStatus
read_STRING_LITERAL(SerdReader* reader, SerdNode* dest, uint8_t q)
{
SerdStatus st = SERD_SUCCESS;
- while (!reader->status && !(st && reader->strict)) {
+ while (!st || (st == SERD_ERR_BAD_SYNTAX && !reader->strict)) {
const uint8_t c = peek_byte(reader);
uint32_t code = 0;
switch (c) {
case '\n': case '\r':
- r_err(reader, SERD_ERR_BAD_SYNTAX, "line end in short string\n");
- return SERD_ERR_BAD_SYNTAX;
+ st = r_err(reader, SERD_ERR_NO_DATA,
+ "line end in short string\n");
+ break;
case '\\':
eat_byte_safe(reader, c);
if ((st = read_ECHAR(reader, dest, &dest->flags)) &&
(st = read_UCHAR(reader, dest, &code))) {
- return r_err(reader, st,
- "invalid escape `\\%c'\n", peek_byte(reader));
+ st = r_err(reader, st,
+ "invalid escape `\\%c'\n", peek_byte(reader));
}
break;
default:
if (c == q) {
- eat_byte_check(reader, q);
+ eat_byte_safe(reader, q);
return SERD_SUCCESS;
} else {
st = read_character(
@@ -367,8 +374,7 @@ read_STRING_LITERAL(SerdReader* reader, SerdNode* dest, uint8_t q)
}
}
- return st ? st
- : eat_byte_check(reader, q) ? SERD_SUCCESS : SERD_ERR_BAD_SYNTAX;
+ return st;
}
static SerdStatus
@@ -671,10 +677,7 @@ read_IRIREF(SerdReader* reader, SerdNode** dest)
} else if (!(c & 0x80)) {
push_byte(reader, *dest, c);
} else if (read_utf8_character(reader, *dest, c)) {
- if (reader->strict) {
- return SERD_ERR_BAD_SYNTAX;
- }
- st = SERD_FAILURE;
+ st = reader->strict ? SERD_ERR_BAD_SYNTAX : SERD_FAILURE;
}
}
}
@@ -1437,8 +1440,6 @@ read_n3_statement(SerdReader* reader)
ctx.subject = subj = 0;
TRY(st, read_wrappedGraph(reader, &ctx));
read_ws_star(reader);
- } else if (!ctx.subject) {
- st = r_err(reader, SERD_ERR_BAD_SYNTAX, "bad subject\n");
} else if ((st = read_triples(reader, ctx, &ate_dot))) {
if (st == SERD_FAILURE && s_type == '[') {
return SERD_SUCCESS;
@@ -1473,23 +1474,22 @@ read_turtleTrigDoc(SerdReader* reader)
const size_t orig_stack_size = reader->stack.size;
const SerdStatus st = read_n3_statement(reader);
if (st > SERD_FAILURE) {
- if (reader->strict) {
+ if (reader->strict || reader->source.eof) {
serd_stack_pop_to(&reader->stack, orig_stack_size);
return st;
}
skip_until(reader, '\n');
- reader->status = SERD_SUCCESS;
}
serd_stack_pop_to(&reader->stack, orig_stack_size);
}
- return reader->status;
+ return SERD_SUCCESS;
}
SerdStatus
read_nquadsDoc(SerdReader* reader)
{
SerdStatus st = SERD_SUCCESS;
- while (!reader->source.eof) {
+ while (!st && !reader->source.eof) {
const size_t orig_stack_size = reader->stack.size;
SerdStatementFlags flags = 0;
@@ -1534,11 +1534,8 @@ read_nquadsDoc(SerdReader* reader)
}
}
- if (emit_statement(reader, ctx, ctx.object)) {
- break;
- }
-
+ st = emit_statement(reader, ctx, ctx.object);
serd_stack_pop_to(&reader->stack, orig_stack_size);
}
- return reader->status;
+ return st;
}
diff --git a/src/reader.c b/src/reader.c
index 4235168a..2d1fbd7e 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -87,7 +87,6 @@ push_node_padded(SerdReader* reader, size_t maxlen,
&reader->stack, sizeof(SerdNode) + maxlen + 1, sizeof(SerdNode));
if (!mem) {
- reader->status = SERD_ERR_OVERFLOW;
return NULL;
}
@@ -283,15 +282,15 @@ serd_reader_start_string(SerdReader* reader,
static SerdStatus
serd_reader_prepare(SerdReader* reader)
{
- reader->status = serd_byte_source_prepare(&reader->source);
- if (reader->status == SERD_SUCCESS) {
- reader->status = skip_bom(reader);
- } else if (reader->status == SERD_FAILURE) {
+ SerdStatus st = serd_byte_source_prepare(&reader->source);
+ if (st == SERD_SUCCESS) {
+ st = skip_bom(reader);
+ } else if (st == SERD_FAILURE) {
reader->source.eof = true;
} else {
- r_err(reader, reader->status, "read error: %s\n", strerror(errno));
+ r_err(reader, st, "error preparing read: %s\n", strerror(errno));
}
- return reader->status;
+ return st;
}
SerdStatus
diff --git a/src/reader.h b/src/reader.h
index 62373fc4..88d2d864 100644
--- a/src/reader.h
+++ b/src/reader.h
@@ -55,7 +55,6 @@ struct SerdReaderImpl {
SerdStack stack;
SerdSyntax syntax;
unsigned next_id;
- SerdStatus status;
uint8_t* buf;
char* bprefix;
size_t bprefix_len;
@@ -99,11 +98,8 @@ peek_byte(SerdReader* reader)
static inline uint8_t
eat_byte(SerdReader* reader)
{
- const uint8_t c = peek_byte(reader);
- const SerdStatus st = serd_byte_source_advance(&reader->source);
- if (st) {
- reader->status = st;
- }
+ const uint8_t c = peek_byte(reader);
+ serd_byte_source_advance(&reader->source);
return c;
}
diff --git a/src/string.c b/src/string.c
index c2466c48..6a433cdb 100644
--- a/src/string.c
+++ b/src/string.c
@@ -46,6 +46,7 @@ serd_strerror(SerdStatus status)
case SERD_ERR_INTERNAL: return "Internal error";
case SERD_ERR_OVERFLOW: return "Stack overflow";
case SERD_ERR_INVALID: return "Invalid data";
+ case SERD_ERR_NO_DATA: return "Unexpectd end of input";
}
return "Unknown error"; // never reached
}
diff --git a/tests/serd_test.c b/tests/serd_test.c
index 933ea9a5..e3289a17 100644
--- a/tests/serd_test.c
+++ b/tests/serd_test.c
@@ -247,7 +247,7 @@ main(void)
const char* msg = NULL;
assert(!strcmp((msg = serd_strerror(SERD_SUCCESS)), "Success"));
- for (int i = SERD_FAILURE; i <= SERD_ERR_INVALID; ++i) {
+ for (int i = SERD_FAILURE; i <= SERD_ERR_NO_DATA; ++i) {
msg = serd_strerror((SerdStatus)i);
assert(strcmp(msg, "Success"));
}