summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/sord.c28
-rw-r--r--src/sord_internal.h6
-rw-r--r--src/sord_test.c56
-rw-r--r--src/syntax.c22
-rw-r--r--src/zix/hash.h2
5 files changed, 81 insertions, 33 deletions
diff --git a/src/sord.c b/src/sord.c
index ff89505..c6b2b38 100644
--- a/src/sord.c
+++ b/src/sord.c
@@ -83,11 +83,13 @@ typedef enum {
GPOS, ///< Graph, Predicate, Object, Subject
} SordOrder;
+#ifdef SORD_DEBUG_SEARCH
/** String name of each ordering (array indexed by SordOrder) */
static const char* const order_names[NUM_ORDERS] = {
"spo", "sop", "ops", "osp", "pso", "pos",
"gspo", "gsop", "gops", "gosp", "gpso", "gpos"
};
+#endif
/**
Quads of indices for each order, from most to least significant
@@ -321,19 +323,19 @@ sord_iter_forward(SordIter* iter)
return zix_btree_iter_is_end(iter->cur);
}
- SordNode** key = (SordNode**)zix_btree_get(iter->cur);
+ SordNode** key = (SordNode**)zix_btree_get(iter->cur);
const SordQuad initial = { key[0], key[1], key[2], key[3] };
- while (true) {
- zix_btree_iter_increment(iter->cur);
- if (zix_btree_iter_is_end(iter->cur))
- return true;
-
+ zix_btree_iter_increment(iter->cur);
+ while (!zix_btree_iter_is_end(iter->cur)) {
key = (SordNode**)zix_btree_get(iter->cur);
for (int i = 0; i < 3; ++i)
if (key[i] != initial[i])
return false;
+
+ zix_btree_iter_increment(iter->cur);
}
- assert(false);
+
+ return true;
}
/**
@@ -612,7 +614,7 @@ sord_best_index(SordModel* sord,
switch (sig) {
PAT_CASE(0x011, FILTER_RANGE, OSP, PSO, 1);
PAT_CASE(0x101, FILTER_RANGE, SPO, OPS, 1);
- PAT_CASE(0x110, FILTER_RANGE, SOP, POS, 1);
+ // SPO is always present, so 0x110 is never reached here
default: break;
}
@@ -900,16 +902,14 @@ SordNodeType
sord_node_get_type(const SordNode* node)
{
switch (node->node.type) {
- case SERD_BLANK:
- return SORD_BLANK;
- case SERD_LITERAL:
- return SORD_LITERAL;
case SERD_URI:
return SORD_URI;
+ case SERD_BLANK:
+ return SORD_BLANK;
default:
- fprintf(stderr, "error: invalid node type\n");
- return (SordNodeType)0;
+ return SORD_LITERAL;
}
+ SORD_UNREACHABLE();
}
const uint8_t*
diff --git a/src/sord_internal.h b/src/sord_internal.h
index 5a7236d..71c2f6d 100644
--- a/src/sord_internal.h
+++ b/src/sord_internal.h
@@ -22,6 +22,12 @@
#include "sord/sord.h"
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+# define SORD_UNREACHABLE() __builtin_unreachable()
+#else
+# define SORD_UNREACHABLE() assert(false)
+#endif
+
/** Resource node metadata */
typedef struct {
size_t refs_as_obj; ///< References as a quad object
diff --git a/src/sord_test.c b/src/sord_test.c
index fc37f06..438a393 100644
--- a/src/sord_test.c
+++ b/src/sord_test.c
@@ -22,7 +22,6 @@
#include "sord/sord.h"
static const int DIGITS = 3;
-static const int MAX_NUM = 999;
static const unsigned n_objects_per = 2;
static int n_expected_errors = 0;
@@ -89,7 +88,7 @@ generate(SordWorld* world,
// Add some literals
// (98 4 "hello") and (98 4 "hello"^^<5>)
- SordQuad tup = { 0, 0, 0, 0};
+ SordQuad tup = { 0, 0, 0, 0 };
tup[0] = uri(world, 98);
tup[1] = uri(world, 4);
tup[2] = sord_new_literal(world, 0, USTR("hello"), NULL);
@@ -381,17 +380,20 @@ main(int argc, char** argv)
SordWorld* world = sord_world_new();
- sord_world_set_error_sink(world, unexpected_error, NULL);
// Attempt to create invalid URI
+ fprintf(stderr, "expected ");
SordNode* bad_uri = sord_new_uri(world, USTR("noscheme"));
if (bad_uri) {
return test_fail("Successfully created invalid URI \"noscheme\"\n");
}
sord_node_free(world, bad_uri);
+ sord_world_set_error_sink(world, expected_error, NULL);
+
// Attempt to create invalid CURIE
- SerdEnv* env = serd_env_new(NULL);
+ SerdNode base = serd_node_from_string(SERD_URI, USTR("http://example.org/"));
+ SerdEnv* env = serd_env_new(&base);
SerdNode sbadns = serd_node_from_string(SERD_CURIE, USTR("badns:"));
SordNode* badns = sord_node_from_serd_node(world, env, &sbadns, NULL, NULL);
if (badns) {
@@ -414,10 +416,12 @@ main(int argc, char** argv)
sord_world_set_error_sink(world, expected_error, NULL);
sord_node_free(world, garbage);
sord_world_set_error_sink(world, unexpected_error, NULL);
- if (n_expected_errors != 1) {
+ if (n_expected_errors != 2) {
return test_fail("Successfully freed node twice\n");
}
+ sord_world_set_error_sink(world, unexpected_error, NULL);
+
// Check node flags are set properly
SordNode* with_newline = sord_new_literal(world, NULL, USTR("a\nb"), NULL);
if (!(sord_node_get_flags(with_newline) & SERD_HAS_NEWLINE)) {
@@ -664,10 +668,50 @@ main(int argc, char** argv)
}
sord_iter_free(iter);
+ // Load file into two separate graphs
sord_free(sord);
+ sord = sord_new(world, SORD_SPO, true);
+ env = serd_env_new(&base);
+ SordNode* graph1 = sord_new_uri(world, USTR("http://example.org/graph1"));
+ SordNode* graph2 = sord_new_uri(world, USTR("http://example.org/graph2"));
+ SerdReader* reader = sord_new_reader(sord, env, SERD_TURTLE, graph1);
+ if ((st = serd_reader_read_string(reader, USTR("<s> <p> <o> .")))) {
+ fprintf(stderr, "Failed to read string (%s)\n", serd_strerror(st));
+ goto fail;
+ }
+ serd_reader_free(reader);
+ reader = sord_new_reader(sord, env, SERD_TURTLE, graph2);
+ if ((st = serd_reader_read_string(reader, USTR("<s> <p> <o> .")))) {
+ fprintf(stderr, "Failed to re-read string (%s)\n", serd_strerror(st));
+ goto fail;
+ }
- sord_world_free(world);
+ // Ensure we only see triple once
+ size_t n_triples = 0;
+ for (iter = sord_begin(sord); !sord_iter_end(iter); sord_iter_next(iter)) {
+ fprintf(stderr, "%s %s %s %s\n",
+ sord_node_get_string(sord_iter_get_node(iter, SORD_SUBJECT)),
+ sord_node_get_string(sord_iter_get_node(iter, SORD_PREDICATE)),
+ sord_node_get_string(sord_iter_get_node(iter, SORD_OBJECT)),
+ sord_node_get_string(sord_iter_get_node(iter, SORD_GRAPH)));
+
+ ++n_triples;
+ }
+ if (n_triples != 1) {
+ fprintf(stderr, "Found duplicate triple\n");
+ goto fail;
+ }
+
+ // Test SPO iteration on an SOP indexed store
+ sord_free(sord);
+ sord = sord_new(world, SORD_SOP, false);
+ generate(world, sord, 1, graph42);
+ for (iter = sord_begin(sord); !sord_iter_end(iter); sord_iter_next(iter)) {
+ ++n_triples;
+ }
+ sord_free(sord);
+ sord_world_free(world);
return EXIT_SUCCESS;
fail:
diff --git a/src/syntax.c b/src/syntax.c
index 9c7fa74..f17312f 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -112,7 +112,7 @@ sord_new_reader(SordModel* model,
return reader;
}
-static void
+static SerdStatus
write_statement(SordModel* sord,
SerdWriter* writer,
SordQuad tup,
@@ -140,7 +140,7 @@ write_statement(SordModel* sord,
// TODO: Subject abbreviation
if (sord_node_is_inline_object(s) && !(flags & SERD_ANON_CONT)) {
- return;
+ return SERD_SUCCESS;
}
SerdStatus st = SERD_SUCCESS;
@@ -156,10 +156,10 @@ write_statement(SordModel* sord,
if (!st && sub_iter) {
flags |= SERD_ANON_CONT;
- for (; !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) {
+ for (; !st && !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) {
SordQuad sub_tup;
sord_iter_get(sub_iter, sub_tup);
- write_statement(sord, writer, sub_tup, flags);
+ st = write_statement(sord, writer, sub_tup, flags);
}
sord_iter_free(sub_iter);
serd_writer_end_anon(writer, so);
@@ -169,11 +169,7 @@ write_statement(SordModel* sord,
writer, flags, NULL, ss, sp, so, sd, &language);
}
- if (st) {
- fprintf(stderr, "Failed to write statement (%s)\n",
- serd_strerror(st));
- return;
- }
+ return st;
}
bool
@@ -195,11 +191,13 @@ sord_write_iter(SordIter* iter,
}
SordModel* model = (SordModel*)sord_iter_get_model(iter);
- for (; !sord_iter_end(iter); sord_iter_next(iter)) {
+ SerdStatus st = SERD_SUCCESS;
+ for (; !st && !sord_iter_end(iter); sord_iter_next(iter)) {
SordQuad tup;
sord_iter_get(iter, tup);
- write_statement(model, writer, tup, 0);
+ st = write_statement(model, writer, tup, 0);
}
sord_iter_free(iter);
- return true;
+
+ return !st;
}
diff --git a/src/zix/hash.h b/src/zix/hash.h
index e6f4028..e95b773 100644
--- a/src/zix/hash.h
+++ b/src/zix/hash.h
@@ -81,7 +81,7 @@ zix_hash_size(const ZixHash* hash);
If no matching value is found, ZIX_STATUS_SUCCESS will be returned, and @p
inserted will be pointed to the copy of `value` made in the new hash node.
-
+
If a matching value already exists, ZIX_STATUS_EXISTS will be returned, and
`inserted` will be pointed to the existing value.