summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-12-26 19:23:44 +0100
committerDavid Robillard <d@drobilla.net>2020-12-26 19:23:44 +0100
commit87aca493cd6ad0ffc49a896c9f8342d52ad6aa96 (patch)
tree25d222a5f8db03780cd1836dbca28ab5051cc173 /src
parentc05ab9add46d84e39bea5ee59258564ba35a9582 (diff)
downloadsord-87aca493cd6ad0ffc49a896c9f8342d52ad6aa96.tar.gz
sord-87aca493cd6ad0ffc49a896c9f8342d52ad6aa96.tar.bz2
sord-87aca493cd6ad0ffc49a896c9f8342d52ad6aa96.zip
Format all code with clang-format
Diffstat (limited to 'src')
-rw-r--r--src/sord.c1661
-rw-r--r--src/sord_internal.h24
-rw-r--r--src/sord_test.c1356
-rw-r--r--src/sord_validate.c1272
-rw-r--r--src/sordi.c326
-rw-r--r--src/sordmm_test.cpp6
-rw-r--r--src/syntax.c233
7 files changed, 2446 insertions, 2432 deletions
diff --git a/src/sord.c b/src/sord.c
index b870e1a..45881a3 100644
--- a/src/sord.c
+++ b/src/sord.c
@@ -37,67 +37,73 @@
#include <string.h>
#ifdef __GNUC__
-# define SORD_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
+# define SORD_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
#else
-# define SORD_LOG_FUNC(fmt, arg1)
+# define SORD_LOG_FUNC(fmt, arg1)
#endif
#define SORD_LOG(prefix, ...) fprintf(stderr, "[Sord::" prefix "] " __VA_ARGS__)
#ifdef SORD_DEBUG_ITER
-# define SORD_ITER_LOG(...) SORD_LOG("iter", __VA_ARGS__)
+# define SORD_ITER_LOG(...) SORD_LOG("iter", __VA_ARGS__)
#else
-# define SORD_ITER_LOG(...)
+# define SORD_ITER_LOG(...)
#endif
#ifdef SORD_DEBUG_SEARCH
-# define SORD_FIND_LOG(...) SORD_LOG("search", __VA_ARGS__)
+# define SORD_FIND_LOG(...) SORD_LOG("search", __VA_ARGS__)
#else
-# define SORD_FIND_LOG(...)
+# define SORD_FIND_LOG(...)
#endif
#ifdef SORD_DEBUG_WRITE
-# define SORD_WRITE_LOG(...) SORD_LOG("write", __VA_ARGS__)
+# define SORD_WRITE_LOG(...) SORD_LOG("write", __VA_ARGS__)
#else
-# define SORD_WRITE_LOG(...)
+# define SORD_WRITE_LOG(...)
#endif
-#define NUM_ORDERS 12
-#define STATEMENT_LEN 3
-#define TUP_LEN (STATEMENT_LEN + 1)
-#define DEFAULT_ORDER SPO
+#define NUM_ORDERS 12
+#define STATEMENT_LEN 3
+#define TUP_LEN (STATEMENT_LEN + 1)
+#define DEFAULT_ORDER SPO
#define DEFAULT_GRAPH_ORDER GSPO
-#define TUP_FMT "(%s %s %s %s)"
+#define TUP_FMT "(%s %s %s %s)"
#define TUP_FMT_ELEM(e) ((e) ? sord_node_get_string(e) : (const uint8_t*)"*")
-#define TUP_FMT_ARGS(t) \
- TUP_FMT_ELEM((t)[0]), \
- TUP_FMT_ELEM((t)[1]), \
- TUP_FMT_ELEM((t)[2]), \
- TUP_FMT_ELEM((t)[3])
+#define TUP_FMT_ARGS(t) \
+ TUP_FMT_ELEM((t)[0]), TUP_FMT_ELEM((t)[1]), TUP_FMT_ELEM((t)[2]), \
+ TUP_FMT_ELEM((t)[3])
#define TUP_G 3
/** Triple ordering */
typedef enum {
- SPO, ///< Subject, Predicate, Object
- SOP, ///< Subject, Object, Predicate
- OPS, ///< Object, Predicate, Subject
- OSP, ///< Object, Subject, Predicate
- PSO, ///< Predicate, Subject, Object
- POS, ///< Predicate, Object, Subject
- GSPO, ///< Graph, Subject, Predicate, Object
- GSOP, ///< Graph, Subject, Object, Predicate
- GOPS, ///< Graph, Object, Predicate, Subject
- GOSP, ///< Graph, Object, Subject, Predicate
- GPSO, ///< Graph, Predicate, Subject, Object
- GPOS ///< Graph, Predicate, Object, Subject
+ SPO, ///< Subject, Predicate, Object
+ SOP, ///< Subject, Object, Predicate
+ OPS, ///< Object, Predicate, Subject
+ OSP, ///< Object, Subject, Predicate
+ PSO, ///< Predicate, Subject, Object
+ POS, ///< Predicate, Object, Subject
+ GSPO, ///< Graph, Subject, Predicate, Object
+ GSOP, ///< Graph, Subject, Object, Predicate
+ GOPS, ///< Graph, Object, Predicate, Subject
+ GOSP, ///< Graph, Object, Subject, Predicate
+ GPSO, ///< Graph, Predicate, Subject, Object
+ 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"
-};
+static const char* const order_names[NUM_ORDERS] = {"spo",
+ "sop",
+ "ops",
+ "osp",
+ "pso",
+ "pos",
+ "gspo",
+ "gsop",
+ "gops",
+ "gosp",
+ "gpso",
+ "gpos"};
#endif
/**
@@ -105,128 +111,134 @@ static const char* const order_names[NUM_ORDERS] = {
(array indexed by SordOrder)
*/
static const int orderings[NUM_ORDERS][TUP_LEN] = {
- { 0, 1, 2, 3 }, { 0, 2, 1, 3 }, // SPO, SOP
- { 2, 1, 0, 3 }, { 2, 0, 1, 3 }, // OPS, OSP
- { 1, 0, 2, 3 }, { 1, 2, 0, 3 }, // PSO, POS
- { 3, 0, 1, 2 }, { 3, 0, 2, 1 }, // GSPO, GSOP
- { 3, 2, 1, 0 }, { 3, 2, 0, 1 }, // GOPS, GOSP
- { 3, 1, 0, 2 }, { 3, 1, 2, 0 } // GPSO, GPOS
+ {0, 1, 2, 3}, // SPO
+ {0, 2, 1, 3}, // SOP
+ {2, 1, 0, 3}, // OPS
+ {2, 0, 1, 3}, // OSP
+ {1, 0, 2, 3}, // PSO
+ {1, 2, 0, 3}, // POS
+ {3, 0, 1, 2}, // GSPO
+ {3, 0, 2, 1}, // GSOP
+ {3, 2, 1, 0}, // GOPS
+ {3, 2, 0, 1}, // GOSP
+ {3, 1, 0, 2}, // GPSO
+ {3, 1, 2, 0} // GPOS
};
/** World */
struct SordWorldImpl {
- ZixHash* nodes;
- SerdErrorSink error_sink;
- void* error_handle;
+ ZixHash* nodes;
+ SerdErrorSink error_sink;
+ void* error_handle;
};
/** Store */
struct SordModelImpl {
- SordWorld* world;
+ SordWorld* world;
- /** Index for each possible triple ordering (may or may not exist).
- * Each index is a tree of SordQuad with the appropriate ordering.
- */
- ZixBTree* indices[NUM_ORDERS];
+ /** Index for each possible triple ordering (may or may not exist).
+ * Each index is a tree of SordQuad with the appropriate ordering.
+ */
+ ZixBTree* indices[NUM_ORDERS];
- size_t n_quads;
- size_t n_iters;
+ size_t n_quads;
+ size_t n_iters;
};
/** Mode for searching or iteration */
typedef enum {
- ALL, ///< Iterate over entire store
- SINGLE, ///< Iteration over a single element (exact search)
- RANGE, ///< Iterate over range with equal prefix
- FILTER_RANGE, ///< Iterate over range with equal prefix, filtering
- FILTER_ALL ///< Iterate to end of store, filtering
+ ALL, ///< Iterate over entire store
+ SINGLE, ///< Iteration over a single element (exact search)
+ RANGE, ///< Iterate over range with equal prefix
+ FILTER_RANGE, ///< Iterate over range with equal prefix, filtering
+ FILTER_ALL ///< Iterate to end of store, filtering
} SearchMode;
/** Iterator over some range of a store */
struct SordIterImpl {
- const SordModel* sord; ///< Model being iterated over
- ZixBTreeIter* cur; ///< Current DB cursor
- SordQuad pat; ///< Pattern (in ordering order)
- SordOrder order; ///< Store order (which index)
- SearchMode mode; ///< Iteration mode
- int n_prefix; ///< Prefix for RANGE and FILTER_RANGE
- bool end; ///< True iff reached end
- bool skip_graphs; ///< Iteration should ignore graphs
+ const SordModel* sord; ///< Model being iterated over
+ ZixBTreeIter* cur; ///< Current DB cursor
+ SordQuad pat; ///< Pattern (in ordering order)
+ SordOrder order; ///< Store order (which index)
+ SearchMode mode; ///< Iteration mode
+ int n_prefix; ///< Prefix for RANGE and FILTER_RANGE
+ bool end; ///< True iff reached end
+ bool skip_graphs; ///< Iteration should ignore graphs
};
static uint32_t
sord_node_hash(const void* n)
{
- const SordNode* node = (const SordNode*)n;
- uint32_t hash = zix_digest_start();
- hash = zix_digest_add(hash, node->node.buf, node->node.n_bytes);
- hash = zix_digest_add(hash, &node->node.type, sizeof(node->node.type));
- if (node->node.type == SERD_LITERAL) {
- hash = zix_digest_add(hash, &node->meta.lit, sizeof(node->meta.lit));
- }
- return hash;
+ const SordNode* node = (const SordNode*)n;
+ uint32_t hash = zix_digest_start();
+ hash = zix_digest_add(hash, node->node.buf, node->node.n_bytes);
+ hash = zix_digest_add(hash, &node->node.type, sizeof(node->node.type));
+ if (node->node.type == SERD_LITERAL) {
+ hash = zix_digest_add(hash, &node->meta.lit, sizeof(node->meta.lit));
+ }
+ return hash;
}
static bool
sord_node_hash_equal(const void* a, const void* b)
{
- const SordNode* a_node = (const SordNode*)a;
- const SordNode* b_node = (const SordNode*)b;
- return (a_node == b_node)
- || ((a_node->node.type == b_node->node.type) &&
- (a_node->node.type != SERD_LITERAL ||
- (a_node->meta.lit.datatype == b_node->meta.lit.datatype &&
- !strncmp(a_node->meta.lit.lang,
- b_node->meta.lit.lang,
- sizeof(a_node->meta.lit.lang)))) &&
- (serd_node_equals(&a_node->node, &b_node->node)));
+ const SordNode* a_node = (const SordNode*)a;
+ const SordNode* b_node = (const SordNode*)b;
+ return (a_node == b_node) ||
+ ((a_node->node.type == b_node->node.type) &&
+ (a_node->node.type != SERD_LITERAL ||
+ (a_node->meta.lit.datatype == b_node->meta.lit.datatype &&
+ !strncmp(a_node->meta.lit.lang,
+ b_node->meta.lit.lang,
+ sizeof(a_node->meta.lit.lang)))) &&
+ (serd_node_equals(&a_node->node, &b_node->node)));
}
SORD_LOG_FUNC(3, 4)
static void
error(SordWorld* world, SerdStatus st, const char* fmt, ...)
{
- va_list args;
- va_start(args, fmt);
- const SerdError e = { st, NULL, 0, 0, fmt, &args };
- if (world->error_sink) {
- world->error_sink(world->error_handle, &e);
- } else {
- fprintf(stderr, "error: ");
- vfprintf(stderr, fmt, args);
- }
- va_end(args);
+ va_list args;
+ va_start(args, fmt);
+ const SerdError e = {st, NULL, 0, 0, fmt, &args};
+ if (world->error_sink) {
+ world->error_sink(world->error_handle, &e);
+ } else {
+ fprintf(stderr, "error: ");
+ vfprintf(stderr, fmt, args);
+ }
+ va_end(args);
}
SordWorld*
sord_world_new(void)
{
- SordWorld* world = (SordWorld*)malloc(sizeof(SordWorld));
- world->error_sink = NULL;
- world->error_handle = NULL;
+ SordWorld* world = (SordWorld*)malloc(sizeof(SordWorld));
+ world->error_sink = NULL;
+ world->error_handle = NULL;
- world->nodes = zix_hash_new(
- sord_node_hash, sord_node_hash_equal, sizeof(SordNode));
+ world->nodes =
+ zix_hash_new(sord_node_hash, sord_node_hash_equal, sizeof(SordNode));
- return world;
+ return world;
}
static void
free_node_entry(void* value, void* user_data)
{
- SordNode* node = (SordNode*)value;
- if (node->node.type == SERD_LITERAL) {
- sord_node_free((SordWorld*)user_data, node->meta.lit.datatype);
- }
- free((uint8_t*)node->node.buf);
+ SordNode* node = (SordNode*)value;
+ if (node->node.type == SERD_LITERAL) {
+ sord_node_free((SordWorld*)user_data, node->meta.lit.datatype);
+ }
+ free((uint8_t*)node->node.buf);
}
void
sord_world_free(SordWorld* world)
{
- zix_hash_foreach(world->nodes, free_node_entry, world);
- zix_hash_free(world->nodes);
- free(world);
+ zix_hash_foreach(world->nodes, free_node_entry, world);
+ zix_hash_free(world->nodes);
+ free(world);
}
void
@@ -234,96 +246,94 @@ sord_world_set_error_sink(SordWorld* world,
SerdErrorSink error_sink,
void* handle)
{
- world->error_sink = error_sink;
- world->error_handle = handle;
+ world->error_sink = error_sink;
+ world->error_handle = handle;
}
static inline int
sord_node_compare_literal(const SordNode* a, const SordNode* b)
{
- const int cmp = strcmp((const char*)sord_node_get_string(a),
- (const char*)sord_node_get_string(b));
- if (cmp != 0) {
- return cmp;
- }
-
- const bool a_has_lang = a->meta.lit.lang[0];
- const bool b_has_lang = b->meta.lit.lang[0];
- const bool a_has_datatype = a->meta.lit.datatype;
- const bool b_has_datatype = b->meta.lit.datatype;
- const bool a_has_meta = a_has_lang || a_has_datatype;
- const bool b_has_meta = b_has_lang || b_has_datatype;
-
- assert(!(a_has_lang && a_has_datatype));
- assert(!(b_has_lang && b_has_datatype));
-
- if (!a_has_meta && !b_has_meta) {
- return 0;
- } else if (!a_has_meta || (a_has_lang && b_has_datatype)) {
- return -1;
- } else if (!b_has_meta || (a_has_datatype && b_has_lang)) {
- return 1;
- } else if (a_has_lang) {
- assert(b_has_lang);
- return strcmp(a->meta.lit.lang, b->meta.lit.lang);
- }
-
- assert(a_has_datatype);
- assert(b_has_datatype);
- return strcmp((const char*)a->meta.lit.datatype->node.buf,
- (const char*)b->meta.lit.datatype->node.buf);
+ const int cmp = strcmp((const char*)sord_node_get_string(a),
+ (const char*)sord_node_get_string(b));
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ const bool a_has_lang = a->meta.lit.lang[0];
+ const bool b_has_lang = b->meta.lit.lang[0];
+ const bool a_has_datatype = a->meta.lit.datatype;
+ const bool b_has_datatype = b->meta.lit.datatype;
+ const bool a_has_meta = a_has_lang || a_has_datatype;
+ const bool b_has_meta = b_has_lang || b_has_datatype;
+
+ assert(!(a_has_lang && a_has_datatype));
+ assert(!(b_has_lang && b_has_datatype));
+
+ if (!a_has_meta && !b_has_meta) {
+ return 0;
+ } else if (!a_has_meta || (a_has_lang && b_has_datatype)) {
+ return -1;
+ } else if (!b_has_meta || (a_has_datatype && b_has_lang)) {
+ return 1;
+ } else if (a_has_lang) {
+ assert(b_has_lang);
+ return strcmp(a->meta.lit.lang, b->meta.lit.lang);
+ }
+
+ assert(a_has_datatype);
+ assert(b_has_datatype);
+ return strcmp((const char*)a->meta.lit.datatype->node.buf,
+ (const char*)b->meta.lit.datatype->node.buf);
}
/** Compare nodes, considering NULL a wildcard match. */
static inline int
sord_node_compare(const SordNode* a, const SordNode* b)
{
- if (a == b || !a || !b) {
- return 0; // Exact or wildcard match
- } else if (a->node.type != b->node.type) {
- return (a->node.type < b->node.type) ? -1 : 1;
- }
-
- int cmp = 0;
- switch (a->node.type) {
- case SERD_URI:
- case SERD_BLANK:
- return strcmp((const char*)a->node.buf, (const char*)b->node.buf);
- case SERD_LITERAL:
- cmp = sord_node_compare_literal(a, b);
- break;
- default:
- break;
- }
- return cmp;
+ if (a == b || !a || !b) {
+ return 0; // Exact or wildcard match
+ } else if (a->node.type != b->node.type) {
+ return (a->node.type < b->node.type) ? -1 : 1;
+ }
+
+ int cmp = 0;
+ switch (a->node.type) {
+ case SERD_URI:
+ case SERD_BLANK:
+ return strcmp((const char*)a->node.buf, (const char*)b->node.buf);
+ case SERD_LITERAL:
+ cmp = sord_node_compare_literal(a, b);
+ break;
+ default:
+ break;
+ }
+ return cmp;
}
bool
sord_node_equals(const SordNode* a, const SordNode* b)
{
- return a == b; // Nodes are interned
+ return a == b; // Nodes are interned
}
/** Return true iff IDs are equivalent, or one is a wildcard */
static inline bool
sord_id_match(const SordNode* a, const SordNode* b)
{
- return !a || !b || (a == b);
+ return !a || !b || (a == b);
}
static inline bool
sord_quad_match_inline(const SordQuad x, const SordQuad y)
{
- return sord_id_match(x[0], y[0])
- && sord_id_match(x[1], y[1])
- && sord_id_match(x[2], y[2])
- && sord_id_match(x[3], y[3]);
+ return sord_id_match(x[0], y[0]) && sord_id_match(x[1], y[1]) &&
+ sord_id_match(x[2], y[2]) && sord_id_match(x[3], y[3]);
}
bool
sord_quad_match(const SordQuad x, const SordQuad y)
{
- return sord_quad_match_inline(x, y);
+ return sord_quad_match_inline(x, y);
}
/**
@@ -334,44 +344,44 @@ sord_quad_match(const SordQuad x, const SordQuad y)
static int
sord_quad_compare(const void* x_ptr, const void* y_ptr, const void* user_data)
{
- const int* const ordering = (const int*)user_data;
- const SordNode*const*const x = (const SordNode*const*)x_ptr;
- const SordNode*const*const y = (const SordNode*const*)y_ptr;
+ const int* const ordering = (const int*)user_data;
+ const SordNode* const* const x = (const SordNode* const*)x_ptr;
+ const SordNode* const* const y = (const SordNode* const*)y_ptr;
- for (int i = 0; i < TUP_LEN; ++i) {
- const int idx = ordering[i];
- const int cmp = sord_node_compare(x[idx], y[idx]);
- if (cmp) {
- return cmp;
- }
- }
+ for (int i = 0; i < TUP_LEN; ++i) {
+ const int idx = ordering[i];
+ const int cmp = sord_node_compare(x[idx], y[idx]);
+ if (cmp) {
+ return cmp;
+ }
+ }
- return 0;
+ return 0;
}
static inline bool
sord_iter_forward(SordIter* iter)
{
- if (!iter->skip_graphs) {
- zix_btree_iter_increment(iter->cur);
- return zix_btree_iter_is_end(iter->cur);
- }
+ if (!iter->skip_graphs) {
+ zix_btree_iter_increment(iter->cur);
+ return zix_btree_iter_is_end(iter->cur);
+ }
- SordNode** key = (SordNode**)zix_btree_get(iter->cur);
- const SordQuad initial = { key[0], key[1], key[2], key[3] };
- 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;
- }
- }
+ SordNode** key = (SordNode**)zix_btree_get(iter->cur);
+ const SordQuad initial = {key[0], key[1], key[2], key[3]};
+ 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);
- }
+ zix_btree_iter_increment(iter->cur);
+ }
- return true;
+ return true;
}
/**
@@ -381,15 +391,14 @@ sord_iter_forward(SordIter* iter)
static inline bool
sord_iter_seek_match(SordIter* iter)
{
- for (iter->end = true;
- !zix_btree_iter_is_end(iter->cur);
- sord_iter_forward(iter)) {
- const SordNode** const key = (const SordNode**)zix_btree_get(iter->cur);
- if (sord_quad_match_inline(key, iter->pat)) {
- return (iter->end = false);
- }
- }
- return true;
+ for (iter->end = true; !zix_btree_iter_is_end(iter->cur);
+ sord_iter_forward(iter)) {
+ const SordNode** const key = (const SordNode**)zix_btree_get(iter->cur);
+ if (sord_quad_match_inline(key, iter->pat)) {
+ return (iter->end = false);
+ }
+ }
+ return true;
}
/**
@@ -400,178 +409,183 @@ sord_iter_seek_match(SordIter* iter)
static inline bool
sord_iter_seek_match_range(SordIter* iter)
{
- assert(!iter->end);
+ assert(!iter->end);
- do {
- const SordNode** key = (const SordNode**)zix_btree_get(iter->cur);
+ do {
+ const SordNode** key = (const SordNode**)zix_btree_get(iter->cur);
- if (sord_quad_match_inline(key, iter->pat)) {
- return false; // Found match
- }
+ if (sord_quad_match_inline(key, iter->pat)) {
+ return false; // Found match
+ }
- for (int i = 0; i < iter->n_prefix; ++i) {
- const int idx = orderings[iter->order][i];
- if (!sord_id_match(key[idx], iter->pat[idx])) {
- iter->end = true; // Reached end of valid range
- return true;
- }
- }
- } while (!sord_iter_forward(iter));
+ for (int i = 0; i < iter->n_prefix; ++i) {
+ const int idx = orderings[iter->order][i];
+ if (!sord_id_match(key[idx], iter->pat[idx])) {
+ iter->end = true; // Reached end of valid range
+ return true;
+ }
+ }
+ } while (!sord_iter_forward(iter));
- return (iter->end = true); // Reached end
+ return (iter->end = true); // Reached end
}
static SordIter*
-sord_iter_new(const SordModel* sord, ZixBTreeIter* cur, const SordQuad pat,
- SordOrder order, SearchMode mode, int n_prefix)
-{
- SordIter* iter = (SordIter*)malloc(sizeof(SordIter));
- iter->sord = sord;
- iter->cur = cur;
- iter->order = order;
- iter->mode = mode;
- iter->n_prefix = n_prefix;
- iter->end = false;
- iter->skip_graphs = order < GSPO;
- for (int i = 0; i < TUP_LEN; ++i) {
- iter->pat[i] = pat[i];
- }
-
- switch (iter->mode) {
- case ALL:
- case SINGLE:
- case RANGE:
- assert(
- sord_quad_match_inline((const SordNode**)zix_btree_get(iter->cur),
- iter->pat));
- break;
- case FILTER_RANGE:
- sord_iter_seek_match_range(iter);
- break;
- case FILTER_ALL:
- sord_iter_seek_match(iter);
- break;
- }
+sord_iter_new(const SordModel* sord,
+ ZixBTreeIter* cur,
+ const SordQuad pat,
+ SordOrder order,
+ SearchMode mode,
+ int n_prefix)
+{
+ SordIter* iter = (SordIter*)malloc(sizeof(SordIter));
+ iter->sord = sord;
+ iter->cur = cur;
+ iter->order = order;
+ iter->mode = mode;
+ iter->n_prefix = n_prefix;
+ iter->end = false;
+ iter->skip_graphs = order < GSPO;
+ for (int i = 0; i < TUP_LEN; ++i) {
+ iter->pat[i] = pat[i];
+ }
+
+ switch (iter->mode) {
+ case ALL:
+ case SINGLE:
+ case RANGE:
+ assert(sord_quad_match_inline((const SordNode**)zix_btree_get(iter->cur),
+ iter->pat));
+ break;
+ case FILTER_RANGE:
+ sord_iter_seek_match_range(iter);
+ break;
+ case FILTER_ALL:
+ sord_iter_seek_match(iter);
+ break;
+ }
#ifdef SORD_DEBUG_ITER
- SordQuad value;
- sord_iter_get(iter, value);
- SORD_ITER_LOG("New %p pat=" TUP_FMT " cur=" TUP_FMT " end=%d skip=%d\n",
- (void*)iter, TUP_FMT_ARGS(pat), TUP_FMT_ARGS(value),
- iter->end, iter->skip_graphs);
+ SordQuad value;
+ sord_iter_get(iter, value);
+ SORD_ITER_LOG("New %p pat=" TUP_FMT " cur=" TUP_FMT " end=%d skip=%d\n",
+ (void*)iter,
+ TUP_FMT_ARGS(pat),
+ TUP_FMT_ARGS(value),
+ iter->end,
+ iter->skip_graphs);
#endif
- ++((SordModel*)sord)->n_iters;
- return iter;
+ ++((SordModel*)sord)->n_iters;
+ return iter;
}
const SordModel*
sord_iter_get_model(SordIter* iter)
{
- return iter->sord;
+ return iter->sord;
}
void
sord_iter_get(const SordIter* iter, SordQuad tup)
{
- SordNode** key = (SordNode**)zix_btree_get(iter->cur);
- for (int i = 0; i < TUP_LEN; ++i) {
- tup[i] = key[i];
- }
+ SordNode** key = (SordNode**)zix_btree_get(iter->cur);
+ for (int i = 0; i < TUP_LEN; ++i) {
+ tup[i] = key[i];
+ }
}
const SordNode*
sord_iter_get_node(const SordIter* iter, SordQuadIndex index)
{
- return (!sord_iter_end(iter)
- ? ((SordNode**)zix_btree_get(iter->cur))[index]
- : NULL);
+ return (!sord_iter_end(iter) ? ((SordNode**)zix_btree_get(iter->cur))[index]
+ : NULL);
}
static bool
sord_iter_scan_next(SordIter* iter)
{
- if (iter->end) {
- return true;
- }
-
- const SordNode** key;
- if (!iter->end) {
- switch (iter->mode) {
- case ALL:
- // At the end if the cursor is (assigned above)
- break;
- case SINGLE:
- iter->end = true;
- SORD_ITER_LOG("%p reached single end\n", (void*)iter);
- break;
- case RANGE:
- SORD_ITER_LOG("%p range next\n", (void*)iter);
- // At the end if the MSNs no longer match
- key = (const SordNode**)zix_btree_get(iter->cur);
- assert(key);
- for (int i = 0; i < iter->n_prefix; ++i) {
- const int idx = orderings[iter->order][i];
- if (!sord_id_match(key[idx], iter->pat[idx])) {
- iter->end = true;
- SORD_ITER_LOG("%p reached non-match end\n", (void*)iter);
- break;
- }
- }
- break;
- case FILTER_RANGE:
- // Seek forward to next match, stopping if prefix changes
- sord_iter_seek_match_range(iter);
- break;
- case FILTER_ALL:
- // Seek forward to next match
- sord_iter_seek_match(iter);
- break;
- }
- } else {
- SORD_ITER_LOG("%p reached index end\n", (void*)iter);
- }
-
- if (iter->end) {
- SORD_ITER_LOG("%p Reached end\n", (void*)iter);
- return true;
- } else {
+ if (iter->end) {
+ return true;
+ }
+
+ const SordNode** key;
+ if (!iter->end) {
+ switch (iter->mode) {
+ case ALL:
+ // At the end if the cursor is (assigned above)
+ break;
+ case SINGLE:
+ iter->end = true;
+ SORD_ITER_LOG("%p reached single end\n", (void*)iter);
+ break;
+ case RANGE:
+ SORD_ITER_LOG("%p range next\n", (void*)iter);
+ // At the end if the MSNs no longer match
+ key = (const SordNode**)zix_btree_get(iter->cur);
+ assert(key);
+ for (int i = 0; i < iter->n_prefix; ++i) {
+ const int idx = orderings[iter->order][i];
+ if (!sord_id_match(key[idx], iter->pat[idx])) {
+ iter->end = true;
+ SORD_ITER_LOG("%p reached non-match end\n", (void*)iter);
+ break;
+ }
+ }
+ break;
+ case FILTER_RANGE:
+ // Seek forward to next match, stopping if prefix changes
+ sord_iter_seek_match_range(iter);
+ break;
+ case FILTER_ALL:
+ // Seek forward to next match
+ sord_iter_seek_match(iter);
+ break;
+ }
+ } else {
+ SORD_ITER_LOG("%p reached index end\n", (void*)iter);
+ }
+
+ if (iter->end) {
+ SORD_ITER_LOG("%p Reached end\n", (void*)iter);
+ return true;
+ } else {
#ifdef SORD_DEBUG_ITER
- SordQuad tup;
- sord_iter_get(iter, tup);
- SORD_ITER_LOG("%p Increment to " TUP_FMT "\n",
- (void*)iter, TUP_FMT_ARGS(tup));
+ SordQuad tup;
+ sord_iter_get(iter, tup);
+ SORD_ITER_LOG(
+ "%p Increment to " TUP_FMT "\n", (void*)iter, TUP_FMT_ARGS(tup));
#endif
- return false;
- }
+ return false;
+ }
}
bool
sord_iter_next(SordIter* iter)
{
- if (iter->end) {
- return true;
- }
+ if (iter->end) {
+ return true;
+ }
- iter->end = sord_iter_forward(iter);
- return sord_iter_scan_next(iter);
+ iter->end = sord_iter_forward(iter);
+ return sord_iter_scan_next(iter);
}
bool
sord_iter_end(const SordIter* iter)
{
- return !iter || iter->end;
+ return !iter || iter->end;
}
void
sord_iter_free(SordIter* iter)
{
- SORD_ITER_LOG("%p Free\n", (void*)iter);
- if (iter) {
- --((SordModel*)iter->sord)->n_iters;
- zix_btree_iter_free(iter->cur);
- free(iter);
- }
+ SORD_ITER_LOG("%p Free\n", (void*)iter);
+ if (iter) {
+ --((SordModel*)iter->sord)->n_iters;
+ zix_btree_iter_free(iter->cur);
+ free(iter);
+ }
}
/**
@@ -582,12 +596,12 @@ sord_iter_free(SordIter* iter)
static inline bool
sord_has_index(SordModel* model, SordOrder* order, int* n_prefix, bool graphs)
{
- if (graphs) {
- *order = (SordOrder)(*order + GSPO);
- *n_prefix += 1;
- }
+ if (graphs) {
+ *order = (SordOrder)(*order + GSPO);
+ *n_prefix += 1;
+ }
- return model->indices[*order];
+ return model->indices[*order];
}
/**
@@ -603,284 +617,286 @@ sord_best_index(SordModel* sord,
SearchMode* mode,
int* n_prefix)
{
- const bool graph_search = (pat[TUP_G] != 0);
+ const bool graph_search = (pat[TUP_G] != 0);
- const unsigned sig
- = (pat[0] ? 1 : 0) * 0x100
- + (pat[1] ? 1 : 0) * 0x010
- + (pat[2] ? 1 : 0) * 0x001;
+ const unsigned sig = (pat[0] ? 1 : 0) * 0x100 + (pat[1] ? 1 : 0) * 0x010 +
+ (pat[2] ? 1 : 0) * 0x001;
- SordOrder good[2] = { (SordOrder)-1, (SordOrder)-1 };
+ SordOrder good[2] = {(SordOrder)-1, (SordOrder)-1};
#define PAT_CASE(sig, m, g0, g1, np) \
- case sig: \
- *mode = m; \
- good[0] = g0; \
- good[1] = g1; \
- *n_prefix = np; \
- break
-
- // Good orderings that don't require filtering
- *mode = RANGE;
- *n_prefix = 0;
- switch (sig) {
- case 0x000:
- assert(graph_search);
- *mode = RANGE;
- *n_prefix = 1;
- return DEFAULT_GRAPH_ORDER;
- case 0x111:
- *mode = SINGLE;
- return graph_search ? DEFAULT_GRAPH_ORDER : DEFAULT_ORDER;
-
- PAT_CASE(0x001, RANGE, OPS, OSP, 1);
- PAT_CASE(0x010, RANGE, POS, PSO, 1);
- PAT_CASE(0x011, RANGE, OPS, POS, 2);
- PAT_CASE(0x100, RANGE, SPO, SOP, 1);
- PAT_CASE(0x101, RANGE, SOP, OSP, 2);
- PAT_CASE(0x110, RANGE, SPO, PSO, 2);
- }
-
- if (*mode == RANGE) {
- if (sord_has_index(sord, &good[0], n_prefix, graph_search)) {
- return good[0];
- } else if (sord_has_index(sord, &good[1], n_prefix, graph_search)) {
- return good[1];
- }
- }
-
- // Not so good orderings that require filtering, but can
- // still be constrained to a range
- switch (sig) {
- PAT_CASE(0x011, FILTER_RANGE, OSP, PSO, 1);
- PAT_CASE(0x101, FILTER_RANGE, SPO, OPS, 1);
- // SPO is always present, so 0x110 is never reached here
- default: break;
- }
-
- if (*mode == FILTER_RANGE) {
- if (sord_has_index(sord, &good[0], n_prefix, graph_search)) {
- return good[0];
- } else if (sord_has_index(sord, &good[1], n_prefix, graph_search)) {
- return good[1];
- }
- }
-
- if (graph_search) {
- *mode = FILTER_RANGE;
- *n_prefix = 1;
- return DEFAULT_GRAPH_ORDER;
- } else {
- *mode = FILTER_ALL;
- return DEFAULT_ORDER;
- }
+ case sig: \
+ *mode = m; \
+ good[0] = g0; \
+ good[1] = g1; \
+ *n_prefix = np; \
+ break
+
+ // Good orderings that don't require filtering
+ *mode = RANGE;
+ *n_prefix = 0;
+ switch (sig) {
+ case 0x000:
+ assert(graph_search);
+ *mode = RANGE;
+ *n_prefix = 1;
+ return DEFAULT_GRAPH_ORDER;
+ case 0x111:
+ *mode = SINGLE;
+ return graph_search ? DEFAULT_GRAPH_ORDER : DEFAULT_ORDER;
+
+ PAT_CASE(0x001, RANGE, OPS, OSP, 1);
+ PAT_CASE(0x010, RANGE, POS, PSO, 1);
+ PAT_CASE(0x011, RANGE, OPS, POS, 2);
+ PAT_CASE(0x100, RANGE, SPO, SOP, 1);
+ PAT_CASE(0x101, RANGE, SOP, OSP, 2);
+ PAT_CASE(0x110, RANGE, SPO, PSO, 2);
+ }
+
+ if (*mode == RANGE) {
+ if (sord_has_index(sord, &good[0], n_prefix, graph_search)) {
+ return good[0];
+ } else if (sord_has_index(sord, &good[1], n_prefix, graph_search)) {
+ return good[1];
+ }
+ }
+
+ // Not so good orderings that require filtering, but can
+ // still be constrained to a range
+ switch (sig) {
+ PAT_CASE(0x011, FILTER_RANGE, OSP, PSO, 1);
+ PAT_CASE(0x101, FILTER_RANGE, SPO, OPS, 1);
+ // SPO is always present, so 0x110 is never reached here
+ default:
+ break;
+ }
+
+ if (*mode == FILTER_RANGE) {
+ if (sord_has_index(sord, &good[0], n_prefix, graph_search)) {
+ return good[0];
+ } else if (sord_has_index(sord, &good[1], n_prefix, graph_search)) {
+ return good[1];
+ }
+ }
+
+ if (graph_search) {
+ *mode = FILTER_RANGE;
+ *n_prefix = 1;
+ return DEFAULT_GRAPH_ORDER;
+ } else {
+ *mode = FILTER_ALL;
+ return DEFAULT_ORDER;
+ }
}
SordModel*
sord_new(SordWorld* world, unsigned indices, bool graphs)
{
- SordModel* model = (SordModel*)malloc(sizeof(struct SordModelImpl));
- model->world = world;
- model->n_quads = 0;
- model->n_iters = 0;
-
- for (unsigned i = 0; i < (NUM_ORDERS / 2); ++i) {
- const int* const ordering = orderings[i];
- const int* const g_ordering = orderings[i + (NUM_ORDERS / 2)];
-
- if (indices & (1 << i)) {
- model->indices[i] = zix_btree_new(
- sord_quad_compare, (void*)ordering, NULL);
- if (graphs) {
- model->indices[i + (NUM_ORDERS / 2)] = zix_btree_new(
- sord_quad_compare, (void*)g_ordering, NULL);
- } else {
- model->indices[i + (NUM_ORDERS / 2)] = NULL;
- }
- } else {
- model->indices[i] = NULL;
- model->indices[i + (NUM_ORDERS / 2)] = NULL;
- }
- }
-
- if (!model->indices[DEFAULT_ORDER]) {
- model->indices[DEFAULT_ORDER] = zix_btree_new(
- sord_quad_compare, (void*)orderings[DEFAULT_ORDER], NULL);
- }
- if (graphs && !model->indices[DEFAULT_GRAPH_ORDER]) {
- model->indices[DEFAULT_GRAPH_ORDER] = zix_btree_new(
- sord_quad_compare, (void*)orderings[DEFAULT_GRAPH_ORDER], NULL);
- }
-
- return model;
+ SordModel* model = (SordModel*)malloc(sizeof(struct SordModelImpl));
+ model->world = world;
+ model->n_quads = 0;
+ model->n_iters = 0;
+
+ for (unsigned i = 0; i < (NUM_ORDERS / 2); ++i) {
+ const int* const ordering = orderings[i];
+ const int* const g_ordering = orderings[i + (NUM_ORDERS / 2)];
+
+ if (indices & (1 << i)) {
+ model->indices[i] =
+ zix_btree_new(sord_quad_compare, (void*)ordering, NULL);
+ if (graphs) {
+ model->indices[i + (NUM_ORDERS / 2)] =
+ zix_btree_new(sord_quad_compare, (void*)g_ordering, NULL);
+ } else {
+ model->indices[i + (NUM_ORDERS / 2)] = NULL;
+ }
+ } else {
+ model->indices[i] = NULL;
+ model->indices[i + (NUM_ORDERS / 2)] = NULL;
+ }
+ }
+
+ if (!model->indices[DEFAULT_ORDER]) {
+ model->indices[DEFAULT_ORDER] =
+ zix_btree_new(sord_quad_compare, (void*)orderings[DEFAULT_ORDER], NULL);
+ }
+ if (graphs && !model->indices[DEFAULT_GRAPH_ORDER]) {
+ model->indices[DEFAULT_GRAPH_ORDER] = zix_btree_new(
+ sord_quad_compare, (void*)orderings[DEFAULT_GRAPH_ORDER], NULL);
+ }
+
+ return model;
}
static void
sord_node_free_internal(SordWorld* world, SordNode* node)
{
- assert(node->refs == 0);
+ assert(node->refs == 0);
- // If you hit this, the world has probably been destroyed too early
- assert(world);
+ // If you hit this, the world has probably been destroyed too early
+ assert(world);
- // Cache pointer to buffer to free after node removal and destruction
- const uint8_t* const buf = node->node.buf;
+ // Cache pointer to buffer to free after node removal and destruction
+ const uint8_t* const buf = node->node.buf;
- // Remove node from hash (which frees the node)
- if (zix_hash_remove(world->nodes, node)) {
- error(world, SERD_ERR_INTERNAL, "failed to remove node from hash\n");
- }
+ // Remove node from hash (which frees the node)
+ if (zix_hash_remove(world->nodes, node)) {
+ error(world, SERD_ERR_INTERNAL, "failed to remove node from hash\n");
+ }
- // Free buffer
- free((uint8_t*)buf);
+ // Free buffer
+ free((uint8_t*)buf);
}
static void
sord_add_quad_ref(SordModel* model, const SordNode* node, SordQuadIndex i)
{
- if (node) {
- assert(node->refs > 0);
- ++((SordNode*)node)->refs;
- if (node->node.type != SERD_LITERAL && i == SORD_OBJECT) {
- ++((SordNode*)node)->meta.res.refs_as_obj;
- }
- }
+ if (node) {
+ assert(node->refs > 0);
+ ++((SordNode*)node)->refs;
+ if (node->node.type != SERD_LITERAL && i == SORD_OBJECT) {
+ ++((SordNode*)node)->meta.res.refs_as_obj;
+ }
+ }
}
static void
sord_drop_quad_ref(SordModel* model, const SordNode* node, SordQuadIndex i)
{
- if (!node) {
- return;
- }
+ if (!node) {
+ return;
+ }
- assert(node->refs > 0);
- if (node->node.type != SERD_LITERAL && i == SORD_OBJECT) {
- assert(node->meta.res.refs_as_obj > 0);
- --((SordNode*)node)->meta.res.refs_as_obj;
- }
- if (--((SordNode*)node)->refs == 0) {
- sord_node_free_internal(sord_get_world(model), (SordNode*)node);
- }
+ assert(node->refs > 0);
+ if (node->node.type != SERD_LITERAL && i == SORD_OBJECT) {
+ assert(node->meta.res.refs_as_obj > 0);
+ --((SordNode*)node)->meta.res.refs_as_obj;
+ }
+ if (--((SordNode*)node)->refs == 0) {
+ sord_node_free_internal(sord_get_world(model), (SordNode*)node);
+ }
}
void
sord_free(SordModel* model)
{
- if (!model) {
- return;
- }
-
- // Free nodes
- SordQuad tup;
- SordIter* i = sord_begin(model);
- for (; !sord_iter_end(i); sord_iter_next(i)) {
- sord_iter_get(i, tup);
- for (int t = 0; t < TUP_LEN; ++t) {
- sord_drop_quad_ref(model, tup[t], (SordQuadIndex)t);
- }
- }
- sord_iter_free(i);
-
- // Free quads
- ZixBTreeIter* t = zix_btree_begin(model->indices[DEFAULT_ORDER]);
- for (; !zix_btree_iter_is_end(t); zix_btree_iter_increment(t)) {
- free(zix_btree_get(t));
- }
- zix_btree_iter_free(t);
-
- // Free indices
- for (unsigned o = 0; o < NUM_ORDERS; ++o) {
- if (model->indices[o]) {
- zix_btree_free(model->indices[o]);
- }
- }
-
- free(model);
+ if (!model) {
+ return;
+ }
+
+ // Free nodes
+ SordQuad tup;
+ SordIter* i = sord_begin(model);
+ for (; !sord_iter_end(i); sord_iter_next(i)) {
+ sord_iter_get(i, tup);
+ for (int t = 0; t < TUP_LEN; ++t) {
+ sord_drop_quad_ref(model, tup[t], (SordQuadIndex)t);
+ }
+ }
+ sord_iter_free(i);
+
+ // Free quads
+ ZixBTreeIter* t = zix_btree_begin(model->indices[DEFAULT_ORDER]);
+ for (; !zix_btree_iter_is_end(t); zix_btree_iter_increment(t)) {
+ free(zix_btree_get(t));
+ }
+ zix_btree_iter_free(t);
+
+ // Free indices
+ for (unsigned o = 0; o < NUM_ORDERS; ++o) {
+ if (model->indices[o]) {
+ zix_btree_free(model->indices[o]);
+ }
+ }
+
+ free(model);
}
SordWorld*
sord_get_world(SordModel* model)
{
- return model->world;
+ return model->world;
}
size_t
sord_num_quads(const SordModel* model)
{
- return model->n_quads;
+ return model->n_quads;
}
size_t
sord_num_nodes(const SordWorld* world)
{
- return zix_hash_size(world->nodes);
+ return zix_hash_size(world->nodes);
}
SordIter*
sord_begin(const SordModel* model)
{
- if (sord_num_quads(model) == 0) {
- return NULL;
- } else {
- ZixBTreeIter* cur = zix_btree_begin(model->indices[DEFAULT_ORDER]);
- SordQuad pat = { 0, 0, 0, 0 };
- return sord_iter_new(model, cur, pat, DEFAULT_ORDER, ALL, 0);
- }
+ if (sord_num_quads(model) == 0) {
+ return NULL;
+ } else {
+ ZixBTreeIter* cur = zix_btree_begin(model->indices[DEFAULT_ORDER]);
+ SordQuad pat = {0, 0, 0, 0};
+ return sord_iter_new(model, cur, pat, DEFAULT_ORDER, ALL, 0);
+ }
}
SordIter*
sord_find(SordModel* model, const SordQuad pat)
{
- if (!pat[0] && !pat[1] && !pat[2] && !pat[3]) {
- return sord_begin(model);
- }
-
- SearchMode mode;
- int n_prefix;
- const SordOrder index_order = sord_best_index(model, pat, &mode, &n_prefix);
-
- SORD_FIND_LOG("Find " TUP_FMT " index=%s mode=%u n_prefix=%d\n",
- TUP_FMT_ARGS(pat), order_names[index_order], mode, n_prefix);
-
- if (pat[0] && pat[1] && pat[2] && pat[3]) {
- mode = SINGLE; // No duplicate quads (Sord is a set)
- }
-
- ZixBTree* const db = model->indices[index_order];
- ZixBTreeIter* cur = NULL;
-
- if (mode == FILTER_ALL) {
- // No prefix shared with an index at all, linear search (worst case)
- cur = zix_btree_begin(db);
- } else if (mode == FILTER_RANGE) {
- /* Some prefix, but filtering still required. Build a search pattern
- with only the prefix to find the lower bound in log time. */
- SordQuad prefix_pat = { NULL, NULL, NULL, NULL };
- const int* const ordering = orderings[index_order];
- for (int i = 0; i < n_prefix; ++i) {
- prefix_pat[ordering[i]] = pat[ordering[i]];
- }
- zix_btree_lower_bound(db, prefix_pat, &cur);
- } else {
- // Ideal case, pattern matches an index with no filtering required
- zix_btree_lower_bound(db, pat, &cur);
- }
-
- if (zix_btree_iter_is_end(cur)) {
- SORD_FIND_LOG("No match found\n");
- zix_btree_iter_free(cur);
- return NULL;
- }
- const SordNode** const key = (const SordNode**)zix_btree_get(cur);
- if (!key || ( (mode == RANGE || mode == SINGLE)
- && !sord_quad_match_inline(pat, key) )) {
- SORD_FIND_LOG("No match found\n");
- zix_btree_iter_free(cur);
- return NULL;
- }
-
- return sord_iter_new(model, cur, pat, index_order, mode, n_prefix);
+ if (!pat[0] && !pat[1] && !pat[2] && !pat[3]) {
+ return sord_begin(model);
+ }
+
+ SearchMode mode;
+ int n_prefix;
+ const SordOrder index_order = sord_best_index(model, pat, &mode, &n_prefix);
+
+ SORD_FIND_LOG("Find " TUP_FMT " index=%s mode=%u n_prefix=%d\n",
+ TUP_FMT_ARGS(pat),
+ order_names[index_order],
+ mode,
+ n_prefix);
+
+ if (pat[0] && pat[1] && pat[2] && pat[3]) {
+ mode = SINGLE; // No duplicate quads (Sord is a set)
+ }
+
+ ZixBTree* const db = model->indices[index_order];
+ ZixBTreeIter* cur = NULL;
+
+ if (mode == FILTER_ALL) {
+ // No prefix shared with an index at all, linear search (worst case)
+ cur = zix_btree_begin(db);
+ } else if (mode == FILTER_RANGE) {
+ /* Some prefix, but filtering still required. Build a search pattern
+ with only the prefix to find the lower bound in log time. */
+ SordQuad prefix_pat = {NULL, NULL, NULL, NULL};
+ const int* const ordering = orderings[index_order];
+ for (int i = 0; i < n_prefix; ++i) {
+ prefix_pat[ordering[i]] = pat[ordering[i]];
+ }
+ zix_btree_lower_bound(db, prefix_pat, &cur);
+ } else {
+ // Ideal case, pattern matches an index with no filtering required
+ zix_btree_lower_bound(db, pat, &cur);
+ }
+
+ if (zix_btree_iter_is_end(cur)) {
+ SORD_FIND_LOG("No match found\n");
+ zix_btree_iter_free(cur);
+ return NULL;
+ }
+ const SordNode** const key = (const SordNode**)zix_btree_get(cur);
+ if (!key || ((mode == RANGE || mode == SINGLE) &&
+ !sord_quad_match_inline(pat, key))) {
+ SORD_FIND_LOG("No match found\n");
+ zix_btree_iter_free(cur);
+ return NULL;
+ }
+
+ return sord_iter_new(model, cur, pat, index_order, mode, n_prefix);
}
SordIter*
@@ -890,8 +906,8 @@ sord_search(SordModel* model,
const SordNode* o,
const SordNode* g)
{
- SordQuad pat = { s, p, o, g };
- return sord_find(model, pat);
+ SordQuad pat = {s, p, o, g};
+ return sord_find(model, pat);
}
SordNode*
@@ -901,22 +917,22 @@ sord_get(SordModel* model,
const SordNode* o,
const SordNode* g)
{
- if ((bool)s + (bool)p + (bool)o != 2) {
- return NULL;
- }
+ if ((bool)s + (bool)p + (bool)o != 2) {
+ return NULL;
+ }
- SordIter* i = sord_search(model, s, p, o, g);
- SordNode* ret = NULL;
- if (!s) {
- ret = sord_node_copy(sord_iter_get_node(i, SORD_SUBJECT));
- } else if (!p) {
- ret = sord_node_copy(sord_iter_get_node(i, SORD_PREDICATE));
- } else if (!o) {
- ret = sord_node_copy(sord_iter_get_node(i, SORD_OBJECT));
- }
+ SordIter* i = sord_search(model, s, p, o, g);
+ SordNode* ret = NULL;
+ if (!s) {
+ ret = sord_node_copy(sord_iter_get_node(i, SORD_SUBJECT));
+ } else if (!p) {
+ ret = sord_node_copy(sord_iter_get_node(i, SORD_PREDICATE));
+ } else if (!o) {
+ ret = sord_node_copy(sord_iter_get_node(i, SORD_OBJECT));
+ }
- sord_iter_free(i);
- return ret;
+ sord_iter_free(i);
+ return ret;
}
bool
@@ -926,8 +942,8 @@ sord_ask(SordModel* model,
const SordNode* o,
const SordNode* g)
{
- SordQuad pat = { s, p, o, g };
- return sord_contains(model, pat);
+ SordQuad pat = {s, p, o, g};
+ return sord_contains(model, pat);
}
uint64_t
@@ -937,57 +953,57 @@ sord_count(SordModel* model,
const SordNode* o,
const SordNode* g)
{
- SordIter* i = sord_search(model, s, p, o, g);
- uint64_t n = 0;
- for (; !sord_iter_end(i); sord_iter_next(i)) {
- ++n;
- }
- sord_iter_free(i);
- return n;
+ SordIter* i = sord_search(model, s, p, o, g);
+ uint64_t n = 0;
+ for (; !sord_iter_end(i); sord_iter_next(i)) {
+ ++n;
+ }
+ sord_iter_free(i);
+ return n;
}
bool
sord_contains(SordModel* model, const SordQuad pat)
{
- SordIter* iter = sord_find(model, pat);
- bool ret = (iter != NULL);
- sord_iter_free(iter);
- return ret;
+ SordIter* iter = sord_find(model, pat);
+ bool ret = (iter != NULL);
+ sord_iter_free(iter);
+ return ret;
}
static uint8_t*
sord_strndup(const uint8_t* str, size_t len)
{
- uint8_t* dup = (uint8_t*)malloc(len + 1);
- memcpy(dup, str, len + 1);
- return dup;
+ uint8_t* dup = (uint8_t*)malloc(len + 1);
+ memcpy(dup, str, len + 1);
+ return dup;
}
SordNodeType
sord_node_get_type(const SordNode* node)
{
- switch (node->node.type) {
- case SERD_URI:
- return SORD_URI;
- case SERD_BLANK:
- return SORD_BLANK;
- default:
- return SORD_LITERAL;
- }
- SORD_UNREACHABLE();
+ switch (node->node.type) {
+ case SERD_URI:
+ return SORD_URI;
+ case SERD_BLANK:
+ return SORD_BLANK;
+ default:
+ return SORD_LITERAL;
+ }
+ SORD_UNREACHABLE();
}
const uint8_t*
sord_node_get_string(const SordNode* node)
{
- return node->node.buf;
+ return node->node.buf;
}
const uint8_t*
sord_node_get_string_counted(const SordNode* node, size_t* bytes)
{
- *bytes = node->node.n_bytes;
- return node->node.buf;
+ *bytes = node->node.n_bytes;
+ return node->node.buf;
}
const uint8_t*
@@ -995,91 +1011,91 @@ sord_node_get_string_measured(const SordNode* node,
size_t* bytes,
size_t* chars)
{
- *bytes = node->node.n_bytes;
- *chars = node->node.n_chars;
- return node->node.buf;
+ *bytes = node->node.n_bytes;
+ *chars = node->node.n_chars;
+ return node->node.buf;
}
const char*
sord_node_get_language(const SordNode* node)
{
- if (node->node.type != SERD_LITERAL || !node->meta.lit.lang[0]) {
- return NULL;
- }
- return node->meta.lit.lang;
+ if (node->node.type != SERD_LITERAL || !node->meta.lit.lang[0]) {
+ return NULL;
+ }
+ return node->meta.lit.lang;
}
SordNode*
sord_node_get_datatype(const SordNode* node)
{
- return (node->node.type == SERD_LITERAL) ? node->meta.lit.datatype : NULL;
+ return (node->node.type == SERD_LITERAL) ? node->meta.lit.datatype : NULL;
}
SerdNodeFlags
sord_node_get_flags(const SordNode* node)
{
- return node->node.flags;
+ return node->node.flags;
}
bool
sord_node_is_inline_object(const SordNode* node)
{
- return (node->node.type == SERD_BLANK) && (node->meta.res.refs_as_obj == 1);
+ return (node->node.type == SERD_BLANK) && (node->meta.res.refs_as_obj == 1);
}
static SordNode*
sord_insert_node(SordWorld* world, const SordNode* key, bool copy)
{
- SordNode* node = NULL;
- ZixStatus st = zix_hash_insert(world->nodes, key, (void**)&node);
- switch (st) {
- case ZIX_STATUS_EXISTS:
- ++node->refs;
- break;
- case ZIX_STATUS_SUCCESS:
- assert(node->refs == 1);
- if (copy) {
- node->node.buf = sord_strndup(node->node.buf, node->node.n_bytes);
- }
- if (node->node.type == SERD_LITERAL) {
- node->meta.lit.datatype = sord_node_copy(node->meta.lit.datatype);
- }
- return node;
- default:
- error(world, SERD_ERR_INTERNAL,
- "error inserting node `%s'\n", key->node.buf);
- }
-
- if (!copy) {
- // Free the buffer we would have copied if a new node was created
- free((uint8_t*)key->node.buf);
- }
-
- return node;
+ SordNode* node = NULL;
+ ZixStatus st = zix_hash_insert(world->nodes, key, (void**)&node);
+ switch (st) {
+ case ZIX_STATUS_EXISTS:
+ ++node->refs;
+ break;
+ case ZIX_STATUS_SUCCESS:
+ assert(node->refs == 1);
+ if (copy) {
+ node->node.buf = sord_strndup(node->node.buf, node->node.n_bytes);
+ }
+ if (node->node.type == SERD_LITERAL) {
+ node->meta.lit.datatype = sord_node_copy(node->meta.lit.datatype);
+ }
+ return node;
+ default:
+ error(
+ world, SERD_ERR_INTERNAL, "error inserting node `%s'\n", key->node.buf);
+ }
+
+ if (!copy) {
+ // Free the buffer we would have copied if a new node was created
+ free((uint8_t*)key->node.buf);
+ }
+
+ return node;
}
static SordNode*
-sord_new_uri_counted(SordWorld* world, const uint8_t* str,
- size_t n_bytes, size_t n_chars, bool copy)
+sord_new_uri_counted(SordWorld* world,
+ const uint8_t* str,
+ size_t n_bytes,
+ size_t n_chars,
+ bool copy)
{
- if (!serd_uri_string_has_scheme(str)) {
- error(world, SERD_ERR_BAD_ARG,
- "attempt to map invalid URI `%s'\n", str);
- return NULL; // Can't intern relative URIs
- }
+ if (!serd_uri_string_has_scheme(str)) {
+ error(world, SERD_ERR_BAD_ARG, "attempt to map invalid URI `%s'\n", str);
+ return NULL; // Can't intern relative URIs
+ }
- const SordNode key = {
- { str, n_bytes, n_chars, 0, SERD_URI }, 1, { { 0 } }
- };
+ const SordNode key = {{str, n_bytes, n_chars, 0, SERD_URI}, 1, {{0}}};
- return sord_insert_node(world, &key, copy);
+ return sord_insert_node(world, &key, copy);
}
SordNode*
sord_new_uri(SordWorld* world, const uint8_t* uri)
{
- const SerdNode node = serd_node_from_string(SERD_URI, uri);
- return sord_new_uri_counted(world, uri, node.n_bytes, node.n_chars, true);
+ const SerdNode node = serd_node_from_string(SERD_URI, uri);
+ return sord_new_uri_counted(world, uri, node.n_bytes, node.n_chars, true);
}
SordNode*
@@ -1087,36 +1103,36 @@ sord_new_relative_uri(SordWorld* world,
const uint8_t* uri,
const uint8_t* base_uri)
{
- if (serd_uri_string_has_scheme(uri)) {
- return sord_new_uri(world, uri);
- }
- SerdURI buri = SERD_URI_NULL;
- SerdNode base = serd_node_new_uri_from_string(base_uri, NULL, &buri);
- SerdNode node = serd_node_new_uri_from_string(uri, &buri, NULL);
+ if (serd_uri_string_has_scheme(uri)) {
+ return sord_new_uri(world, uri);
+ }
+ SerdURI buri = SERD_URI_NULL;
+ SerdNode base = serd_node_new_uri_from_string(base_uri, NULL, &buri);
+ SerdNode node = serd_node_new_uri_from_string(uri, &buri, NULL);
- SordNode* ret = sord_new_uri_counted(
- world, node.buf, node.n_bytes, node.n_chars, false);
+ SordNode* ret =
+ sord_new_uri_counted(world, node.buf, node.n_bytes, node.n_chars, false);
- serd_node_free(&base);
- return ret;
+ serd_node_free(&base);
+ return ret;
}
static SordNode*
-sord_new_blank_counted(SordWorld* world, const uint8_t* str,
- size_t n_bytes, size_t n_chars)
+sord_new_blank_counted(SordWorld* world,
+ const uint8_t* str,
+ size_t n_bytes,
+ size_t n_chars)
{
- const SordNode key = {
- { str, n_bytes, n_chars, 0, SERD_BLANK }, 1, { { 0 } }
- };
+ const SordNode key = {{str, n_bytes, n_chars, 0, SERD_BLANK}, 1, {{0}}};
- return sord_insert_node(world, &key, true);
+ return sord_insert_node(world, &key, true);
}
SordNode*
sord_new_blank(SordWorld* world, const uint8_t* str)
{
- const SerdNode node = serd_node_from_string(SERD_URI, str);
- return sord_new_blank_counted(world, str, node.n_bytes, node.n_chars);
+ const SerdNode node = serd_node_from_string(SERD_URI, str);
+ return sord_new_blank_counted(world, str, node.n_bytes, node.n_chars);
}
static SordNode*
@@ -1128,28 +1144,27 @@ sord_new_literal_counted(SordWorld* world,
SerdNodeFlags flags,
const char* lang)
{
- SordNode key = {
- { str, n_bytes, n_chars, flags, SERD_LITERAL }, 1, { { 0 } }
- };
- key.meta.lit.datatype = sord_node_copy(datatype);
- memset(key.meta.lit.lang, 0, sizeof(key.meta.lit.lang));
- if (lang) {
- strncpy(key.meta.lit.lang, lang, sizeof(key.meta.lit.lang) - 1);
- }
+ SordNode key = {{str, n_bytes, n_chars, flags, SERD_LITERAL}, 1, {{0}}};
+ key.meta.lit.datatype = sord_node_copy(datatype);
+ memset(key.meta.lit.lang, 0, sizeof(key.meta.lit.lang));
+ if (lang) {
+ strncpy(key.meta.lit.lang, lang, sizeof(key.meta.lit.lang) - 1);
+ }
- return sord_insert_node(world, &key, true);
+ return sord_insert_node(world, &key, true);
}
SordNode*
-sord_new_literal(SordWorld* world, SordNode* datatype,
- const uint8_t* str, const char* lang)
+sord_new_literal(SordWorld* world,
+ SordNode* datatype,
+ const uint8_t* str,
+ const char* lang)
{
- SerdNodeFlags flags = 0;
- size_t n_bytes = 0;
- size_t n_chars = serd_strlen(str, &n_bytes, &flags);
- return sord_new_literal_counted(world, datatype,
- str, n_bytes, n_chars, flags,
- lang);
+ SerdNodeFlags flags = 0;
+ size_t n_bytes = 0;
+ size_t n_chars = serd_strlen(str, &n_bytes, &flags);
+ return sord_new_literal_counted(
+ world, datatype, str, n_bytes, n_chars, flags, lang);
}
SordNode*
@@ -1159,195 +1174,195 @@ sord_node_from_serd_node(SordWorld* world,
const SerdNode* datatype,
const SerdNode* lang)
{
- if (!node) {
- return NULL;
- }
-
- SordNode* datatype_node = NULL;
- SordNode* ret = NULL;
- switch (node->type) {
- case SERD_NOTHING:
- return NULL;
- case SERD_LITERAL:
- datatype_node = sord_node_from_serd_node(
- world, env, datatype, NULL, NULL);
- ret = sord_new_literal_counted(
- world,
- datatype_node,
- node->buf,
- node->n_bytes,
- node->n_chars,
- node->flags,
- lang ? (const char*)lang->buf : NULL);
- sord_node_free(world, datatype_node);
- return ret;
- case SERD_URI:
- if (serd_uri_string_has_scheme(node->buf)) {
- return sord_new_uri_counted(
- world, node->buf, node->n_bytes, node->n_chars, true);
- } else {
- SerdURI base_uri;
- serd_env_get_base_uri(env, &base_uri);
- SerdURI abs_uri;
- SerdNode abs_uri_node = serd_node_new_uri_from_node(
- node, &base_uri, &abs_uri);
- ret = sord_new_uri_counted(world,
- abs_uri_node.buf,
- abs_uri_node.n_bytes,
- abs_uri_node.n_chars,
- true);
- serd_node_free(&abs_uri_node);
- return ret;
- }
- case SERD_CURIE: {
- SerdChunk uri_prefix;
- SerdChunk uri_suffix;
- if (serd_env_expand(env, node, &uri_prefix, &uri_suffix)) {
- error(world, SERD_ERR_BAD_CURIE,
- "failed to expand CURIE `%s'\n", node->buf);
- return NULL;
- }
- const size_t uri_len = uri_prefix.len + uri_suffix.len;
- uint8_t* buf = (uint8_t*)malloc(uri_len + 1);
- memcpy(buf, uri_prefix.buf, uri_prefix.len);
- memcpy(buf + uri_prefix.len, uri_suffix.buf, uri_suffix.len);
- buf[uri_len] = '\0';
- ret = sord_new_uri_counted(
- world, buf, uri_len, serd_strlen(buf, NULL, NULL), false);
- return ret;
- }
- case SERD_BLANK:
- return sord_new_blank_counted(
- world, node->buf, node->n_bytes, node->n_chars);
- }
- return NULL;
+ if (!node) {
+ return NULL;
+ }
+
+ SordNode* datatype_node = NULL;
+ SordNode* ret = NULL;
+ switch (node->type) {
+ case SERD_NOTHING:
+ return NULL;
+ case SERD_LITERAL:
+ datatype_node = sord_node_from_serd_node(world, env, datatype, NULL, NULL);
+ ret = sord_new_literal_counted(world,
+ datatype_node,
+ node->buf,
+ node->n_bytes,
+ node->n_chars,
+ node->flags,
+ lang ? (const char*)lang->buf : NULL);
+ sord_node_free(world, datatype_node);
+ return ret;
+ case SERD_URI:
+ if (serd_uri_string_has_scheme(node->buf)) {
+ return sord_new_uri_counted(
+ world, node->buf, node->n_bytes, node->n_chars, true);
+ } else {
+ SerdURI base_uri;
+ serd_env_get_base_uri(env, &base_uri);
+ SerdURI abs_uri;
+ SerdNode abs_uri_node =
+ serd_node_new_uri_from_node(node, &base_uri, &abs_uri);
+ ret = sord_new_uri_counted(world,
+ abs_uri_node.buf,
+ abs_uri_node.n_bytes,
+ abs_uri_node.n_chars,
+ true);
+ serd_node_free(&abs_uri_node);
+ return ret;
+ }
+ case SERD_CURIE: {
+ SerdChunk uri_prefix;
+ SerdChunk uri_suffix;
+ if (serd_env_expand(env, node, &uri_prefix, &uri_suffix)) {
+ error(
+ world, SERD_ERR_BAD_CURIE, "failed to expand CURIE `%s'\n", node->buf);
+ return NULL;
+ }
+ const size_t uri_len = uri_prefix.len + uri_suffix.len;
+ uint8_t* buf = (uint8_t*)malloc(uri_len + 1);
+ memcpy(buf, uri_prefix.buf, uri_prefix.len);
+ memcpy(buf + uri_prefix.len, uri_suffix.buf, uri_suffix.len);
+ buf[uri_len] = '\0';
+ ret = sord_new_uri_counted(
+ world, buf, uri_len, serd_strlen(buf, NULL, NULL), false);
+ return ret;
+ }
+ case SERD_BLANK:
+ return sord_new_blank_counted(
+ world, node->buf, node->n_bytes, node->n_chars);
+ }
+ return NULL;
}
const SerdNode*
sord_node_to_serd_node(const SordNode* node)
{
- return node ? &node->node : &SERD_NODE_NULL;
+ return node ? &node->node : &SERD_NODE_NULL;
}
void
sord_node_free(SordWorld* world, SordNode* node)
{
- if (!node) {
- return;
- } else if (node->refs == 0) {
- error(world, SERD_ERR_BAD_ARG, "attempt to free garbage node\n");
- } else if (--node->refs == 0) {
- sord_node_free_internal(world, node);
- }
+ if (!node) {
+ return;
+ } else if (node->refs == 0) {
+ error(world, SERD_ERR_BAD_ARG, "attempt to free garbage node\n");
+ } else if (--node->refs == 0) {
+ sord_node_free_internal(world, node);
+ }
}
SordNode*
sord_node_copy(const SordNode* node)
{
- SordNode* copy = (SordNode*)node;
- if (copy) {
- ++copy->refs;
- }
- return copy;
+ SordNode* copy = (SordNode*)node;
+ if (copy) {
+ ++copy->refs;
+ }
+ return copy;
}
static inline bool
sord_add_to_index(SordModel* model, const SordNode** tup, SordOrder order)
{
- return !zix_btree_insert(model->indices[order], tup);
+ return !zix_btree_insert(model->indices[order], tup);
}
bool
sord_add(SordModel* model, const SordQuad tup)
{
- SORD_WRITE_LOG("Add " TUP_FMT "\n", TUP_FMT_ARGS(tup));
- if (!tup[0] || !tup[1] || !tup[2]) {
- error(model->world, SERD_ERR_BAD_ARG,
- "attempt to add quad with NULL field\n");
- return false;
- } else if (model->n_iters > 0) {
- error(model->world, SERD_ERR_BAD_ARG, "added tuple during iteration\n");
- }
+ SORD_WRITE_LOG("Add " TUP_FMT "\n", TUP_FMT_ARGS(tup));
+ if (!tup[0] || !tup[1] || !tup[2]) {
+ error(
+ model->world, SERD_ERR_BAD_ARG, "attempt to add quad with NULL field\n");
+ return false;
+ } else if (model->n_iters > 0) {
+ error(model->world, SERD_ERR_BAD_ARG, "added tuple during iteration\n");
+ }
- const SordNode** quad = (const SordNode**)malloc(sizeof(SordQuad));
- memcpy(quad, tup, sizeof(SordQuad));
+ const SordNode** quad = (const SordNode**)malloc(sizeof(SordQuad));
+ memcpy(quad, tup, sizeof(SordQuad));
- for (unsigned i = 0; i < NUM_ORDERS; ++i) {
- if (model->indices[i] && (i < GSPO || tup[3])) {
- if (!sord_add_to_index(model, quad, (SordOrder)i)) {
- assert(i == 0); // Assuming index coherency
- free(quad);
- return false; // Quad already stored, do nothing
- }
- }
- }
+ for (unsigned i = 0; i < NUM_ORDERS; ++i) {
+ if (model->indices[i] && (i < GSPO || tup[3])) {
+ if (!sord_add_to_index(model, quad, (SordOrder)i)) {
+ assert(i == 0); // Assuming index coherency
+ free(quad);
+ return false; // Quad already stored, do nothing
+ }
+ }
+ }
- for (int i = 0; i < TUP_LEN; ++i) {
- sord_add_quad_ref(model, tup[i], (SordQuadIndex)i);
- }
+ for (int i = 0; i < TUP_LEN; ++i) {
+ sord_add_quad_ref(model, tup[i], (SordQuadIndex)i);
+ }
- ++model->n_quads;
- return true;
+ ++model->n_quads;
+ return true;
}
void
sord_remove(SordModel* model, const SordQuad tup)
{
- SORD_WRITE_LOG("Remove " TUP_FMT "\n", TUP_FMT_ARGS(tup));
- if (model->n_iters > 0) {
- error(model->world, SERD_ERR_BAD_ARG, "remove with iterator\n");
- }
+ SORD_WRITE_LOG("Remove " TUP_FMT "\n", TUP_FMT_ARGS(tup));
+ if (model->n_iters > 0) {
+ error(model->world, SERD_ERR_BAD_ARG, "remove with iterator\n");
+ }
- SordNode* quad = NULL;
- for (unsigned i = 0; i < NUM_ORDERS; ++i) {
- if (model->indices[i] && (i < GSPO || tup[3])) {
- if (zix_btree_remove(model->indices[i], tup, (void**)&quad, NULL)) {
- assert(i == 0); // Assuming index coherency
- return; // Quad not found, do nothing
- }
- }
- }
+ SordNode* quad = NULL;
+ for (unsigned i = 0; i < NUM_ORDERS; ++i) {
+ if (model->indices[i] && (i < GSPO || tup[3])) {
+ if (zix_btree_remove(model->indices[i], tup, (void**)&quad, NULL)) {
+ assert(i == 0); // Assuming index coherency
+ return; // Quad not found, do nothing
+ }
+ }
+ }
- free(quad);
+ free(quad);
- for (int i = 0; i < TUP_LEN; ++i) {
- sord_drop_quad_ref(model, tup[i], (SordQuadIndex)i);
- }
+ for (int i = 0; i < TUP_LEN; ++i) {
+ sord_drop_quad_ref(model, tup[i], (SordQuadIndex)i);
+ }
- --model->n_quads;
+ --model->n_quads;
}
SerdStatus
sord_erase(SordModel* model, SordIter* iter)
{
- if (model->n_iters > 1) {
- error(model->world, SERD_ERR_BAD_ARG, "erased with many iterators\n");
- return SERD_ERR_BAD_ARG;
- }
-
- SordQuad tup;
- sord_iter_get(iter, tup);
-
- SORD_WRITE_LOG("Remove " TUP_FMT "\n", TUP_FMT_ARGS(tup));
-
- SordNode* quad = NULL;
- for (unsigned i = 0; i < NUM_ORDERS; ++i) {
- if (model->indices[i] && (i < GSPO || tup[3])) {
- if (zix_btree_remove(model->indices[i], tup, (void**)&quad,
- i == iter->order ? &iter->cur : NULL)) {
- return (i == 0) ? SERD_ERR_NOT_FOUND : SERD_ERR_INTERNAL;
- }
- }
- }
- iter->end = zix_btree_iter_is_end(iter->cur);
- sord_iter_scan_next(iter);
-
- free(quad);
-
- for (int i = 0; i < TUP_LEN; ++i) {
- sord_drop_quad_ref(model, tup[i], (SordQuadIndex)i);
- }
-
- --model->n_quads;
- return SERD_SUCCESS;
+ if (model->n_iters > 1) {
+ error(model->world, SERD_ERR_BAD_ARG, "erased with many iterators\n");
+ return SERD_ERR_BAD_ARG;
+ }
+
+ SordQuad tup;
+ sord_iter_get(iter, tup);
+
+ SORD_WRITE_LOG("Remove " TUP_FMT "\n", TUP_FMT_ARGS(tup));
+
+ SordNode* quad = NULL;
+ for (unsigned i = 0; i < NUM_ORDERS; ++i) {
+ if (model->indices[i] && (i < GSPO || tup[3])) {
+ if (zix_btree_remove(model->indices[i],
+ tup,
+ (void**)&quad,
+ i == iter->order ? &iter->cur : NULL)) {
+ return (i == 0) ? SERD_ERR_NOT_FOUND : SERD_ERR_INTERNAL;
+ }
+ }
+ }
+ iter->end = zix_btree_iter_is_end(iter->cur);
+ sord_iter_scan_next(iter);
+
+ free(quad);
+
+ for (int i = 0; i < TUP_LEN; ++i) {
+ sord_drop_quad_ref(model, tup[i], (SordQuadIndex)i);
+ }
+
+ --model->n_quads;
+ return SERD_SUCCESS;
}
diff --git a/src/sord_internal.h b/src/sord_internal.h
index 872b1c1..0b74bcd 100644
--- a/src/sord_internal.h
+++ b/src/sord_internal.h
@@ -23,31 +23,31 @@
#include <stddef.h>
#if defined(__GNUC__) && __GNUC__ > 4
-# define SORD_UNREACHABLE() __builtin_unreachable()
+# define SORD_UNREACHABLE() __builtin_unreachable()
#else
-# include <assert.h>
-# define SORD_UNREACHABLE() assert(0)
+# include <assert.h>
+# define SORD_UNREACHABLE() assert(0)
#endif
/** Resource node metadata */
typedef struct {
- size_t refs_as_obj; ///< References as a quad object
+ size_t refs_as_obj; ///< References as a quad object
} SordResourceMetadata;
/** Literal node metadata */
typedef struct {
- SordNode* datatype; ///< Optional literal data type URI
- char lang[16]; ///< Optional language tag
+ SordNode* datatype; ///< Optional literal data type URI
+ char lang[16]; ///< Optional language tag
} SordLiteralMetadata;
/** Node */
struct SordNodeImpl {
- SerdNode node; ///< Serd node
- size_t refs; ///< Reference count (# of containing quads)
- union {
- SordResourceMetadata res;
- SordLiteralMetadata lit;
- } meta;
+ SerdNode node; ///< Serd node
+ size_t refs; ///< Reference count (# of containing quads)
+ union {
+ SordResourceMetadata res;
+ SordLiteralMetadata lit;
+ } meta;
};
#endif /* SORD_SORD_INTERNAL_H */
diff --git a/src/sord_test.c b/src/sord_test.c
index 828acf8..d8a0d6c 100644
--- a/src/sord_test.c
+++ b/src/sord_test.c
@@ -26,9 +26,9 @@
#include <string.h>
#ifdef __GNUC__
-# define SORD_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
+# define SORD_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
#else
-# define SORD_LOG_FUNC(fmt, arg1)
+# define SORD_LOG_FUNC(fmt, arg1)
#endif
static const int DIGITS = 3;
@@ -37,8 +37,8 @@ static const unsigned n_objects_per = 2;
static int n_expected_errors = 0;
typedef struct {
- SordQuad query;
- int expected_num_results;
+ SordQuad query;
+ int expected_num_results;
} QueryTest;
#define USTR(s) ((const uint8_t*)(s))
@@ -46,724 +46,722 @@ typedef struct {
static SordNode*
uri(SordWorld* world, int num)
{
- if (num == 0) {
- return 0;
- }
-
- char str[] = "eg:000";
- char* uri_num = str + 3; // First `0'
- snprintf(uri_num, DIGITS + 1, "%0*d", DIGITS, num);
- return sord_new_uri(world, (const uint8_t*)str);
+ if (num == 0) {
+ return 0;
+ }
+
+ char str[] = "eg:000";
+ char* uri_num = str + 3; // First `0'
+ snprintf(uri_num, DIGITS + 1, "%0*d", DIGITS, num);
+ return sord_new_uri(world, (const uint8_t*)str);
}
SORD_LOG_FUNC(1, 2)
static int
test_fail(const char* fmt, ...)
{
- va_list args;
- va_start(args, fmt);
- fprintf(stderr, "error: ");
- vfprintf(stderr, fmt, args);
- va_end(args);
- return 1;
+ va_list args;
+ va_start(args, fmt);
+ fprintf(stderr, "error: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ return 1;
}
static int
-generate(SordWorld* world,
- SordModel* sord,
- size_t n_quads,
- SordNode* graph)
+generate(SordWorld* world, SordModel* sord, size_t n_quads, SordNode* graph)
{
- fprintf(stderr, "Generating %zu (S P *) quads with %u objects each\n",
- n_quads, n_objects_per);
-
- for (size_t i = 0; i < n_quads; ++i) {
- int num = (i * n_objects_per) + 1;
-
- SordNode* ids[2 + n_objects_per];
- for (unsigned j = 0; j < 2 + n_objects_per; ++j) {
- ids[j] = uri(world, num++);
- }
-
- for (unsigned j = 0; j < n_objects_per; ++j) {
- SordQuad tup = { ids[0], ids[1], ids[2 + j], graph };
- if (!sord_add(sord, tup)) {
- return test_fail("Fail: Failed to add quad\n");
- }
- }
-
- for (unsigned j = 0; j < 2 + n_objects_per; ++j) {
- sord_node_free(world, ids[j]);
- }
- }
-
- // Add some literals
-
- // (98 4 "hello") and (98 4 "hello"^^<5>)
- 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);
- tup[3] = graph;
- sord_add(sord, tup);
- sord_node_free(world, (SordNode*)tup[2]);
- tup[2] = sord_new_literal(world, uri(world, 5), USTR("hello"), NULL);
- if (!sord_add(sord, tup)) {
- return test_fail("Failed to add typed literal\n");
- }
-
- // (96 4 "hello"^^<4>) and (96 4 "hello"^^<5>)
- tup[0] = uri(world, 96);
- tup[1] = uri(world, 4);
- tup[2] = sord_new_literal(world, uri(world, 4), USTR("hello"), NULL);
- tup[3] = graph;
- sord_add(sord, tup);
- sord_node_free(world, (SordNode*)tup[2]);
- tup[2] = sord_new_literal(world, uri(world, 5), USTR("hello"), NULL);
- if (!sord_add(sord, tup)) {
- return test_fail("Failed to add typed literal\n");
- }
-
- // (94 5 "hello") and (94 5 "hello"@en-gb)
- tup[0] = uri(world, 94);
- tup[1] = uri(world, 5);
- tup[2] = sord_new_literal(world, 0, USTR("hello"), NULL);
- tup[3] = graph;
- sord_add(sord, tup);
- sord_node_free(world, (SordNode*)tup[2]);
- tup[2] = sord_new_literal(world, NULL, USTR("hello"), "en-gb");
- if (!sord_add(sord, tup)) {
- return test_fail("Failed to add literal with language\n");
- }
-
- // (92 6 "hello"@en-us) and (92 5 "hello"@en-gb)
- tup[0] = uri(world, 92);
- tup[1] = uri(world, 6);
- tup[2] = sord_new_literal(world, 0, USTR("hello"), "en-us");
- tup[3] = graph;
- sord_add(sord, tup);
- sord_node_free(world, (SordNode*)tup[2]);
- tup[2] = sord_new_literal(world, NULL, USTR("hello"), "en-gb");
- if (!sord_add(sord, tup)) {
- return test_fail("Failed to add literal with language\n");
- }
-
- sord_node_free(world, (SordNode*)tup[0]);
- sord_node_free(world, (SordNode*)tup[2]);
- tup[0] = uri(world, 14);
- tup[2] = sord_new_literal(world, 0, USTR("bonjour"), "fr");
- sord_add(sord, tup);
- sord_node_free(world, (SordNode*)tup[2]);
- tup[2] = sord_new_literal(world, 0, USTR("salut"), "fr");
- sord_add(sord, tup);
-
- // Attempt to add some duplicates
- if (sord_add(sord, tup)) {
- return test_fail("Fail: Successfully added duplicate quad\n");
- }
- if (sord_add(sord, tup)) {
- return test_fail("Fail: Successfully added duplicate quad\n");
- }
-
- // Add a blank node subject
- sord_node_free(world, (SordNode*)tup[0]);
- tup[0] = sord_new_blank(world, USTR("ablank"));
- sord_add(sord, tup);
-
- sord_node_free(world, (SordNode*)tup[1]);
- sord_node_free(world, (SordNode*)tup[2]);
- tup[1] = uri(world, 6);
- tup[2] = uri(world, 7);
- sord_add(sord, tup);
- sord_node_free(world, (SordNode*)tup[0]);
- sord_node_free(world, (SordNode*)tup[1]);
- sord_node_free(world, (SordNode*)tup[2]);
-
- return EXIT_SUCCESS;
+ fprintf(stderr,
+ "Generating %zu (S P *) quads with %u objects each\n",
+ n_quads,
+ n_objects_per);
+
+ for (size_t i = 0; i < n_quads; ++i) {
+ int num = (i * n_objects_per) + 1;
+
+ SordNode* ids[2 + n_objects_per];
+ for (unsigned j = 0; j < 2 + n_objects_per; ++j) {
+ ids[j] = uri(world, num++);
+ }
+
+ for (unsigned j = 0; j < n_objects_per; ++j) {
+ SordQuad tup = {ids[0], ids[1], ids[2 + j], graph};
+ if (!sord_add(sord, tup)) {
+ return test_fail("Fail: Failed to add quad\n");
+ }
+ }
+
+ for (unsigned j = 0; j < 2 + n_objects_per; ++j) {
+ sord_node_free(world, ids[j]);
+ }
+ }
+
+ // Add some literals
+
+ // (98 4 "hello") and (98 4 "hello"^^<5>)
+ 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);
+ tup[3] = graph;
+ sord_add(sord, tup);
+ sord_node_free(world, (SordNode*)tup[2]);
+ tup[2] = sord_new_literal(world, uri(world, 5), USTR("hello"), NULL);
+ if (!sord_add(sord, tup)) {
+ return test_fail("Failed to add typed literal\n");
+ }
+
+ // (96 4 "hello"^^<4>) and (96 4 "hello"^^<5>)
+ tup[0] = uri(world, 96);
+ tup[1] = uri(world, 4);
+ tup[2] = sord_new_literal(world, uri(world, 4), USTR("hello"), NULL);
+ tup[3] = graph;
+ sord_add(sord, tup);
+ sord_node_free(world, (SordNode*)tup[2]);
+ tup[2] = sord_new_literal(world, uri(world, 5), USTR("hello"), NULL);
+ if (!sord_add(sord, tup)) {
+ return test_fail("Failed to add typed literal\n");
+ }
+
+ // (94 5 "hello") and (94 5 "hello"@en-gb)
+ tup[0] = uri(world, 94);
+ tup[1] = uri(world, 5);
+ tup[2] = sord_new_literal(world, 0, USTR("hello"), NULL);
+ tup[3] = graph;
+ sord_add(sord, tup);
+ sord_node_free(world, (SordNode*)tup[2]);
+ tup[2] = sord_new_literal(world, NULL, USTR("hello"), "en-gb");
+ if (!sord_add(sord, tup)) {
+ return test_fail("Failed to add literal with language\n");
+ }
+
+ // (92 6 "hello"@en-us) and (92 5 "hello"@en-gb)
+ tup[0] = uri(world, 92);
+ tup[1] = uri(world, 6);
+ tup[2] = sord_new_literal(world, 0, USTR("hello"), "en-us");
+ tup[3] = graph;
+ sord_add(sord, tup);
+ sord_node_free(world, (SordNode*)tup[2]);
+ tup[2] = sord_new_literal(world, NULL, USTR("hello"), "en-gb");
+ if (!sord_add(sord, tup)) {
+ return test_fail("Failed to add literal with language\n");
+ }
+
+ sord_node_free(world, (SordNode*)tup[0]);
+ sord_node_free(world, (SordNode*)tup[2]);
+ tup[0] = uri(world, 14);
+ tup[2] = sord_new_literal(world, 0, USTR("bonjour"), "fr");
+ sord_add(sord, tup);
+ sord_node_free(world, (SordNode*)tup[2]);
+ tup[2] = sord_new_literal(world, 0, USTR("salut"), "fr");
+ sord_add(sord, tup);
+
+ // Attempt to add some duplicates
+ if (sord_add(sord, tup)) {
+ return test_fail("Fail: Successfully added duplicate quad\n");
+ }
+ if (sord_add(sord, tup)) {
+ return test_fail("Fail: Successfully added duplicate quad\n");
+ }
+
+ // Add a blank node subject
+ sord_node_free(world, (SordNode*)tup[0]);
+ tup[0] = sord_new_blank(world, USTR("ablank"));
+ sord_add(sord, tup);
+
+ sord_node_free(world, (SordNode*)tup[1]);
+ sord_node_free(world, (SordNode*)tup[2]);
+ tup[1] = uri(world, 6);
+ tup[2] = uri(world, 7);
+ sord_add(sord, tup);
+ sord_node_free(world, (SordNode*)tup[0]);
+ sord_node_free(world, (SordNode*)tup[1]);
+ sord_node_free(world, (SordNode*)tup[2]);
+
+ return EXIT_SUCCESS;
}
#define TUP_FMT "(%6s %6s %6s)"
-#define TUP_FMT_ARGS(t) \
- ((t)[0] ? sord_node_get_string((t)[0]) : USTR("*")), \
- ((t)[1] ? sord_node_get_string((t)[1]) : USTR("*")), \
- ((t)[2] ? sord_node_get_string((t)[2]) : USTR("*"))
+#define TUP_FMT_ARGS(t) \
+ ((t)[0] ? sord_node_get_string((t)[0]) : USTR("*")), \
+ ((t)[1] ? sord_node_get_string((t)[1]) : USTR("*")), \
+ ((t)[2] ? sord_node_get_string((t)[2]) : USTR("*"))
static int
-test_read(SordWorld* world, SordModel* sord, SordNode* g,
- const size_t n_quads)
+test_read(SordWorld* world, SordModel* sord, SordNode* g, const size_t n_quads)
{
- int ret = EXIT_SUCCESS;
+ int ret = EXIT_SUCCESS;
- SordQuad id;
+ SordQuad id;
- SordIter* iter = sord_begin(sord);
- if (sord_iter_get_model(iter) != sord) {
- return test_fail("Fail: Iterator has incorrect sord pointer\n");
- }
+ SordIter* iter = sord_begin(sord);
+ if (sord_iter_get_model(iter) != sord) {
+ return test_fail("Fail: Iterator has incorrect sord pointer\n");
+ }
- for (; !sord_iter_end(iter); sord_iter_next(iter)) {
- sord_iter_get(iter, id);
- }
+ for (; !sord_iter_end(iter); sord_iter_next(iter)) {
+ sord_iter_get(iter, id);
+ }
- // Attempt to increment past end
- if (!sord_iter_next(iter)) {
- return test_fail("Fail: Successfully incremented past end\n");
- }
+ // Attempt to increment past end
+ if (!sord_iter_next(iter)) {
+ return test_fail("Fail: Successfully incremented past end\n");
+ }
- sord_iter_free(iter);
+ sord_iter_free(iter);
- const uint8_t* s = USTR("hello");
- SordNode* plain_hello = sord_new_literal(world, 0, s, NULL);
- SordNode* type4_hello = sord_new_literal(world, uri(world, 4), s, NULL);
- SordNode* type5_hello = sord_new_literal(world, uri(world, 5), s, NULL);
- SordNode* gb_hello = sord_new_literal(world, NULL, s, "en-gb");
- SordNode* us_hello = sord_new_literal(world, NULL, s, "en-us");
+ const uint8_t* s = USTR("hello");
+ SordNode* plain_hello = sord_new_literal(world, 0, s, NULL);
+ SordNode* type4_hello = sord_new_literal(world, uri(world, 4), s, NULL);
+ SordNode* type5_hello = sord_new_literal(world, uri(world, 5), s, NULL);
+ SordNode* gb_hello = sord_new_literal(world, NULL, s, "en-gb");
+ SordNode* us_hello = sord_new_literal(world, NULL, s, "en-us");
#define NUM_PATTERNS 18
- QueryTest patterns[NUM_PATTERNS] = {
- { { 0, 0, 0 }, (int)(n_quads * n_objects_per) + 12 },
- { { uri(world, 1), 0, 0 }, 2 },
- { { uri(world, 9), uri(world, 9), uri(world, 9) }, 0 },
- { { uri(world, 1), uri(world, 2), uri(world, 4) }, 1 },
- { { uri(world, 3), uri(world, 4), uri(world, 0) }, 2 },
- { { uri(world, 0), uri(world, 2), uri(world, 4) }, 1 },
- { { uri(world, 0), uri(world, 0), uri(world, 4) }, 1 },
- { { uri(world, 1), uri(world, 0), uri(world, 0) }, 2 },
- { { uri(world, 1), uri(world, 0), uri(world, 4) }, 1 },
- { { uri(world, 0), uri(world, 2), uri(world, 0) }, 2 },
- { { uri(world, 98), uri(world, 4), plain_hello }, 1 },
- { { uri(world, 98), uri(world, 4), type5_hello }, 1 },
- { { uri(world, 96), uri(world, 4), type4_hello }, 1 },
- { { uri(world, 96), uri(world, 4), type5_hello }, 1 },
- { { uri(world, 94), uri(world, 5), plain_hello }, 1 },
- { { uri(world, 94), uri(world, 5), gb_hello }, 1 },
- { { uri(world, 92), uri(world, 6), gb_hello }, 1 },
- { { uri(world, 92), uri(world, 6), us_hello }, 1 } };
-
- SordQuad match = { uri(world, 1), uri(world, 2), uri(world, 4), g };
- if (!sord_contains(sord, match)) {
- return test_fail("Fail: No match for " TUP_FMT "\n",
- TUP_FMT_ARGS(match));
- }
-
- SordQuad nomatch = { uri(world, 1), uri(world, 2), uri(world, 9), g };
- if (sord_contains(sord, nomatch)) {
- return test_fail("Fail: False match for " TUP_FMT "\n",
- TUP_FMT_ARGS(nomatch));
- }
-
- if (sord_get(sord, NULL, NULL, uri(world, 3), g)) {
- return test_fail("Fail: Get *,*,3 succeeded\n");
- } else if (!sord_node_equals(
- sord_get(sord, uri(world, 1), uri(world, 2), NULL, g),
- uri(world, 3))) {
- return test_fail("Fail: Get 1,2,* != 3\n");
- } else if (!sord_node_equals(
- sord_get(sord, uri(world, 1), NULL, uri(world, 3), g),
- uri(world, 2))) {
- return test_fail("Fail: Get 1,*,3 != 2\n");
- } else if (!sord_node_equals(
- sord_get(sord, NULL, uri(world, 2), uri(world, 3), g),
- uri(world, 1))) {
- return test_fail("Fail: Get *,2,3 != 1\n");
- }
-
- for (unsigned i = 0; i < NUM_PATTERNS; ++i) {
- QueryTest test = patterns[i];
- SordQuad pat = { test.query[0], test.query[1], test.query[2], g };
- fprintf(stderr, "Query " TUP_FMT "... ", TUP_FMT_ARGS(pat));
-
- iter = sord_find(sord, pat);
- int num_results = 0;
- for (; !sord_iter_end(iter); sord_iter_next(iter)) {
- sord_iter_get(iter, id);
- ++num_results;
- if (!sord_quad_match(pat, id)) {
- sord_iter_free(iter);
- return test_fail(
- "Fail: Query result " TUP_FMT " does not match pattern\n",
- TUP_FMT_ARGS(id));
- }
- }
- sord_iter_free(iter);
- if (num_results != test.expected_num_results) {
- return test_fail("Fail: Expected %d results, got %d\n",
- test.expected_num_results, num_results);
- }
- fprintf(stderr, "OK (%i matches)\n", test.expected_num_results);
- }
-
- // Query blank node subject
- SordQuad pat = { sord_new_blank(world, USTR("ablank")), 0, 0 };
- if (!pat[0]) {
- return test_fail("Blank node subject lost\n");
- }
- fprintf(stderr, "Query " TUP_FMT "... ", TUP_FMT_ARGS(pat));
- iter = sord_find(sord, pat);
- int num_results = 0;
- for (; !sord_iter_end(iter); sord_iter_next(iter)) {
- sord_iter_get(iter, id);
- ++num_results;
- if (!sord_quad_match(pat, id)) {
- sord_iter_free(iter);
- return test_fail(
- "Fail: Query result " TUP_FMT " does not match pattern\n",
- TUP_FMT_ARGS(id));
- }
- }
- fprintf(stderr, "OK\n");
- sord_node_free(world, (SordNode*)pat[0]);
- sord_iter_free(iter);
- if (num_results != 2) {
- return test_fail("Blank node subject query failed\n");
- }
-
- // Test nested queries
- fprintf(stderr, "Nested Queries... ");
- const SordNode* last_subject = 0;
- iter = sord_search(sord, NULL, NULL, NULL, NULL);
- for (; !sord_iter_end(iter); sord_iter_next(iter)) {
- sord_iter_get(iter, id);
- if (id[0] == last_subject) {
- continue;
- }
-
- SordQuad subpat = { id[0], 0, 0 };
- SordIter* subiter = sord_find(sord, subpat);
- unsigned num_sub_results = 0;
- if (sord_iter_get_node(subiter, SORD_SUBJECT) != id[0]) {
- return test_fail("Fail: Incorrect initial submatch\n");
- }
- for (; !sord_iter_end(subiter); sord_iter_next(subiter)) {
- SordQuad subid;
- sord_iter_get(subiter, subid);
- if (!sord_quad_match(subpat, subid)) {
- sord_iter_free(iter);
- sord_iter_free(subiter);
- return test_fail(
- "Fail: Nested query result does not match pattern\n");
- }
- ++num_sub_results;
- }
- sord_iter_free(subiter);
- if (num_sub_results != n_objects_per) {
- return test_fail(
- "Fail: Nested query " TUP_FMT " failed"
- " (%u results, expected %u)\n",
- TUP_FMT_ARGS(subpat), num_sub_results, n_objects_per);
- }
-
- uint64_t count = sord_count(sord, id[0], 0, 0, 0);
- if (count != num_sub_results) {
- return test_fail("Fail: Query " TUP_FMT " sord_count() %" PRIu64
- "does not match result count %u\n",
- TUP_FMT_ARGS(subpat), count, num_sub_results);
- }
-
- last_subject = id[0];
- }
- fprintf(stderr, "OK\n\n");
- sord_iter_free(iter);
-
- return ret;
+ QueryTest patterns[NUM_PATTERNS] = {
+ {{0, 0, 0}, (int)(n_quads * n_objects_per) + 12},
+ {{uri(world, 1), 0, 0}, 2},
+ {{uri(world, 9), uri(world, 9), uri(world, 9)}, 0},
+ {{uri(world, 1), uri(world, 2), uri(world, 4)}, 1},
+ {{uri(world, 3), uri(world, 4), uri(world, 0)}, 2},
+ {{uri(world, 0), uri(world, 2), uri(world, 4)}, 1},
+ {{uri(world, 0), uri(world, 0), uri(world, 4)}, 1},
+ {{uri(world, 1), uri(world, 0), uri(world, 0)}, 2},
+ {{uri(world, 1), uri(world, 0), uri(world, 4)}, 1},
+ {{uri(world, 0), uri(world, 2), uri(world, 0)}, 2},
+ {{uri(world, 98), uri(world, 4), plain_hello}, 1},
+ {{uri(world, 98), uri(world, 4), type5_hello}, 1},
+ {{uri(world, 96), uri(world, 4), type4_hello}, 1},
+ {{uri(world, 96), uri(world, 4), type5_hello}, 1},
+ {{uri(world, 94), uri(world, 5), plain_hello}, 1},
+ {{uri(world, 94), uri(world, 5), gb_hello}, 1},
+ {{uri(world, 92), uri(world, 6), gb_hello}, 1},
+ {{uri(world, 92), uri(world, 6), us_hello}, 1}};
+
+ SordQuad match = {uri(world, 1), uri(world, 2), uri(world, 4), g};
+ if (!sord_contains(sord, match)) {
+ return test_fail("Fail: No match for " TUP_FMT "\n", TUP_FMT_ARGS(match));
+ }
+
+ SordQuad nomatch = {uri(world, 1), uri(world, 2), uri(world, 9), g};
+ if (sord_contains(sord, nomatch)) {
+ return test_fail("Fail: False match for " TUP_FMT "\n",
+ TUP_FMT_ARGS(nomatch));
+ }
+
+ if (sord_get(sord, NULL, NULL, uri(world, 3), g)) {
+ return test_fail("Fail: Get *,*,3 succeeded\n");
+ } else if (!sord_node_equals(
+ sord_get(sord, uri(world, 1), uri(world, 2), NULL, g),
+ uri(world, 3))) {
+ return test_fail("Fail: Get 1,2,* != 3\n");
+ } else if (!sord_node_equals(
+ sord_get(sord, uri(world, 1), NULL, uri(world, 3), g),
+ uri(world, 2))) {
+ return test_fail("Fail: Get 1,*,3 != 2\n");
+ } else if (!sord_node_equals(
+ sord_get(sord, NULL, uri(world, 2), uri(world, 3), g),
+ uri(world, 1))) {
+ return test_fail("Fail: Get *,2,3 != 1\n");
+ }
+
+ for (unsigned i = 0; i < NUM_PATTERNS; ++i) {
+ QueryTest test = patterns[i];
+ SordQuad pat = {test.query[0], test.query[1], test.query[2], g};
+ fprintf(stderr, "Query " TUP_FMT "... ", TUP_FMT_ARGS(pat));
+
+ iter = sord_find(sord, pat);
+ int num_results = 0;
+ for (; !sord_iter_end(iter); sord_iter_next(iter)) {
+ sord_iter_get(iter, id);
+ ++num_results;
+ if (!sord_quad_match(pat, id)) {
+ sord_iter_free(iter);
+ return test_fail("Fail: Query result " TUP_FMT
+ " does not match pattern\n",
+ TUP_FMT_ARGS(id));
+ }
+ }
+ sord_iter_free(iter);
+ if (num_results != test.expected_num_results) {
+ return test_fail("Fail: Expected %d results, got %d\n",
+ test.expected_num_results,
+ num_results);
+ }
+ fprintf(stderr, "OK (%i matches)\n", test.expected_num_results);
+ }
+
+ // Query blank node subject
+ SordQuad pat = {sord_new_blank(world, USTR("ablank")), 0, 0};
+ if (!pat[0]) {
+ return test_fail("Blank node subject lost\n");
+ }
+ fprintf(stderr, "Query " TUP_FMT "... ", TUP_FMT_ARGS(pat));
+ iter = sord_find(sord, pat);
+ int num_results = 0;
+ for (; !sord_iter_end(iter); sord_iter_next(iter)) {
+ sord_iter_get(iter, id);
+ ++num_results;
+ if (!sord_quad_match(pat, id)) {
+ sord_iter_free(iter);
+ return test_fail("Fail: Query result " TUP_FMT
+ " does not match pattern\n",
+ TUP_FMT_ARGS(id));
+ }
+ }
+ fprintf(stderr, "OK\n");
+ sord_node_free(world, (SordNode*)pat[0]);
+ sord_iter_free(iter);
+ if (num_results != 2) {
+ return test_fail("Blank node subject query failed\n");
+ }
+
+ // Test nested queries
+ fprintf(stderr, "Nested Queries... ");
+ const SordNode* last_subject = 0;
+ iter = sord_search(sord, NULL, NULL, NULL, NULL);
+ for (; !sord_iter_end(iter); sord_iter_next(iter)) {
+ sord_iter_get(iter, id);
+ if (id[0] == last_subject) {
+ continue;
+ }
+
+ SordQuad subpat = {id[0], 0, 0};
+ SordIter* subiter = sord_find(sord, subpat);
+ unsigned num_sub_results = 0;
+ if (sord_iter_get_node(subiter, SORD_SUBJECT) != id[0]) {
+ return test_fail("Fail: Incorrect initial submatch\n");
+ }
+ for (; !sord_iter_end(subiter); sord_iter_next(subiter)) {
+ SordQuad subid;
+ sord_iter_get(subiter, subid);
+ if (!sord_quad_match(subpat, subid)) {
+ sord_iter_free(iter);
+ sord_iter_free(subiter);
+ return test_fail("Fail: Nested query result does not match pattern\n");
+ }
+ ++num_sub_results;
+ }
+ sord_iter_free(subiter);
+ if (num_sub_results != n_objects_per) {
+ return test_fail("Fail: Nested query " TUP_FMT " failed"
+ " (%u results, expected %u)\n",
+ TUP_FMT_ARGS(subpat),
+ num_sub_results,
+ n_objects_per);
+ }
+
+ uint64_t count = sord_count(sord, id[0], 0, 0, 0);
+ if (count != num_sub_results) {
+ return test_fail("Fail: Query " TUP_FMT " sord_count() %" PRIu64
+ "does not match result count %u\n",
+ TUP_FMT_ARGS(subpat),
+ count,
+ num_sub_results);
+ }
+
+ last_subject = id[0];
+ }
+ fprintf(stderr, "OK\n\n");
+ sord_iter_free(iter);
+
+ return ret;
}
static SerdStatus
unexpected_error(void* handle, const SerdError* error)
{
- fprintf(stderr, "unexpected error: ");
- vfprintf(stderr, error->fmt, *error->args);
- return SERD_SUCCESS;
+ fprintf(stderr, "unexpected error: ");
+ vfprintf(stderr, error->fmt, *error->args);
+ return SERD_SUCCESS;
}
static SerdStatus
expected_error(void* handle, const SerdError* error)
{
- fprintf(stderr, "expected error: ");
- vfprintf(stderr, error->fmt, *error->args);
- ++n_expected_errors;
- return SERD_SUCCESS;
+ fprintf(stderr, "expected error: ");
+ vfprintf(stderr, error->fmt, *error->args);
+ ++n_expected_errors;
+ return SERD_SUCCESS;
}
static int
finished(SordWorld* world, SordModel* sord, int status)
{
- sord_free(sord);
- sord_world_free(world);
- return status;
+ sord_free(sord);
+ sord_world_free(world);
+ return status;
}
int
main(int argc, char** argv)
{
- static const size_t n_quads = 300;
-
- sord_free(NULL); // Shouldn't crash
-
- SordWorld* world = sord_world_new();
-
-
- // 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
- SerdNode base = serd_node_from_string(SERD_URI, USTR("http://example.org/"));
- SerdEnv* env = serd_env_new(&base);
- SerdNode sbad = serd_node_from_string(SERD_CURIE, USTR("bad:"));
- SordNode* bad = sord_node_from_serd_node(world, env, &sbad, NULL, NULL);
- if (bad) {
- return test_fail("Successfully created CURIE with bad namespace\n");
- }
- sord_node_free(world, bad);
- serd_env_free(env);
-
- // Attempt to create node from garbage
- SerdNode junk = SERD_NODE_NULL;
- junk.type = (SerdType)1234;
- if (sord_node_from_serd_node(world, env, &junk, NULL, NULL)) {
- return test_fail("Successfully created node from garbage serd node\n");
- }
-
- // Attempt to create NULL node
- SordNode* nil_node = sord_node_from_serd_node(
- world, NULL, &SERD_NODE_NULL, NULL, NULL);
- if (nil_node) {
- return test_fail("Successfully created NULL node\n");
- }
- sord_node_free(world, nil_node);
-
- // 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)) {
- return test_fail("Newline flag not set\n");
- }
- SordNode* with_quote = sord_new_literal(world, NULL, USTR("a\"b"), NULL);
- if (!(sord_node_get_flags(with_quote) & SERD_HAS_QUOTE)) {
- return test_fail("Quote flag not set\n");
- }
-
- // Create with minimal indexing
- SordModel* sord = sord_new(world, SORD_SPO, false);
- generate(world, sord, n_quads, NULL);
-
- if (test_read(world, sord, NULL, n_quads)) {
- sord_free(sord);
- sord_world_free(world);
- return EXIT_FAILURE;
- }
-
- // Check adding tuples with NULL fields fails
- sord_world_set_error_sink(world, expected_error, NULL);
- const size_t initial_num_quads = sord_num_quads(sord);
- SordQuad tup = { 0, 0, 0, 0};
- if (sord_add(sord, tup)) {
- return test_fail("Added NULL tuple\n");
- }
- tup[0] = uri(world, 1);
- if (sord_add(sord, tup)) {
- return test_fail("Added tuple with NULL P and O\n");
- }
- tup[1] = uri(world, 2);
- if (sord_add(sord, tup)) {
- return test_fail("Added tuple with NULL O\n");
- }
-
- if (sord_num_quads(sord) != initial_num_quads) {
- return test_fail("Num quads %zu != %zu\n",
- sord_num_quads(sord), initial_num_quads);
- }
-
- // Check adding tuples with an active iterator fails
- SordIter* iter = sord_begin(sord);
- tup[2] = uri(world, 3);
- if (sord_add(sord, tup)) {
- return test_fail("Added tuple with active iterator\n");
- }
-
- // Check removing tuples with several active iterator fails
- SordIter* iter2 = sord_begin(sord);
- if (!sord_erase(sord, iter)) {
- return test_fail("Erased tuple with several active iterators\n");
- }
- n_expected_errors = 0;
- sord_remove(sord, tup);
- if (n_expected_errors != 1) {
- return test_fail("Removed tuple with several active iterators\n");
- }
- sord_iter_free(iter);
- sord_iter_free(iter2);
-
- sord_world_set_error_sink(world, unexpected_error, NULL);
-
- // Check interning merges equivalent values
- SordNode* uri_id = sord_new_uri(world, USTR("http://example.org"));
- SordNode* blank_id = sord_new_blank(world, USTR("testblank"));
- SordNode* lit_id = sord_new_literal(world, uri_id, USTR("hello"), NULL);
- if (sord_node_get_type(uri_id) != SORD_URI) {
- return test_fail("URI node has incorrect type\n");
- } else if (sord_node_get_type(blank_id) != SORD_BLANK) {
- return test_fail("Blank node has incorrect type\n");
- } else if (sord_node_get_type(lit_id) != SORD_LITERAL) {
- return test_fail("Literal node has incorrect type\n");
- }
-
- const size_t initial_num_nodes = sord_num_nodes(world);
-
- SordNode* uri_id2 = sord_new_uri(world, USTR("http://example.org"));
- SordNode* blank_id2 = sord_new_blank(world, USTR("testblank"));
- SordNode* lit_id2 = sord_new_literal(world, uri_id, USTR("hello"), NULL);
- if (uri_id2 != uri_id || !sord_node_equals(uri_id2, uri_id)) {
- fprintf(stderr, "Fail: URI interning failed (duplicates)\n");
- return finished(world, sord, EXIT_FAILURE);
- } else if (blank_id2 != blank_id
- || !sord_node_equals(blank_id2, blank_id)) {
- fprintf(stderr, "Fail: Blank node interning failed (duplicates)\n");
- return finished(world, sord, EXIT_FAILURE);
- } else if (lit_id2 != lit_id || !sord_node_equals(lit_id2, lit_id)) {
- fprintf(stderr, "Fail: Literal interning failed (duplicates)\n");
- return finished(world, sord, EXIT_FAILURE);
- }
-
- if (sord_num_nodes(world) != initial_num_nodes) {
- return test_fail("Num nodes %zu != %zu\n",
- sord_num_nodes(world), initial_num_nodes);
- }
-
- const uint8_t ni_hao[] = { 0xE4, 0xBD, 0xA0, 0xE5, 0xA5, 0xBD, 0 };
- SordNode* chello = sord_new_literal(world, NULL, ni_hao, "cmn");
-
- // Test literal length
- size_t n_bytes;
- size_t n_chars;
- const uint8_t* str = sord_node_get_string_counted(lit_id2, &n_bytes);
- if (strcmp((const char*)str, "hello")) {
- return test_fail("Literal node corrupt\n");
- } else if (n_bytes != strlen("hello")) {
- return test_fail("ASCII literal byte count incorrect\n");
- }
-
- str = sord_node_get_string_measured(lit_id2, &n_bytes, &n_chars);
- if (n_bytes != strlen("hello") || n_chars != strlen("hello")) {
- return test_fail("ASCII literal measured length incorrect\n");
- } else if (strcmp((const char*)str, "hello")) {
- return test_fail("ASCII literal string incorrect\n");
- }
-
- str = sord_node_get_string_measured(chello, &n_bytes, &n_chars);
- if (n_bytes != 6) {
- return test_fail("Multi-byte literal byte count incorrect\n");
- } else if (n_chars != 2) {
- return test_fail("Multi-byte literal character count incorrect\n");
- } else if (strcmp((const char*)str, (const char*)ni_hao)) {
- return test_fail("Multi-byte literal string incorrect\n");
- }
-
- // Check interning doesn't clash non-equivalent values
- SordNode* uri_id3 = sord_new_uri(world, USTR("http://example.orgX"));
- SordNode* blank_id3 = sord_new_blank(world, USTR("testblankX"));
- SordNode* lit_id3 = sord_new_literal(world, uri_id, USTR("helloX"), NULL);
- if (uri_id3 == uri_id || sord_node_equals(uri_id3, uri_id)) {
- fprintf(stderr, "Fail: URI interning failed (clash)\n");
- return finished(world, sord, EXIT_FAILURE);
- } else if (blank_id3 == blank_id || sord_node_equals(blank_id3, blank_id)) {
- fprintf(stderr, "Fail: Blank node interning failed (clash)\n");
- return finished(world, sord, EXIT_FAILURE);
- } else if (lit_id3 == lit_id || sord_node_equals(lit_id3, lit_id)) {
- fprintf(stderr, "Fail: Literal interning failed (clash)\n");
- return finished(world, sord, EXIT_FAILURE);
- }
-
- // Check literal interning
- SordNode* lit4 = sord_new_literal(world, NULL, USTR("hello"), NULL);
- SordNode* lit5 = sord_new_literal(world, uri_id2, USTR("hello"), NULL);
- SordNode* lit6 = sord_new_literal(world, NULL, USTR("hello"), "en-ca");
- if (lit4 == lit5 || sord_node_equals(lit4, lit5)
- || lit4 == lit6 || sord_node_equals(lit4, lit6)
- || lit5 == lit6 || sord_node_equals(lit5, lit6)) {
- fprintf(stderr, "Fail: Literal interning failed (type/lang clash)\n");
- return finished(world, sord, EXIT_FAILURE);
- }
-
- // Check relative URI construction
- SordNode* reluri = sord_new_relative_uri(
- world, USTR("a/b"), USTR("http://example.org/"));
- if (strcmp((const char*)sord_node_get_string(reluri),
- "http://example.org/a/b")) {
- fprintf(stderr, "Fail: Bad relative URI constructed: <%s>\n",
- sord_node_get_string(reluri));
- return finished(world, sord, EXIT_FAILURE);
- }
- SordNode* reluri2 = sord_new_relative_uri(
- world, USTR("http://drobilla.net/"), USTR("http://example.org/"));
- if (strcmp((const char*)sord_node_get_string(reluri2),
- "http://drobilla.net/")) {
- fprintf(stderr, "Fail: Bad relative URI constructed: <%s>\n",
- sord_node_get_string(reluri));
- return finished(world, sord, EXIT_FAILURE);
- }
-
- // Check comparison with NULL
- sord_node_free(world, uri_id);
- sord_node_free(world, blank_id);
- sord_node_free(world, lit_id);
- sord_node_free(world, uri_id2);
- sord_node_free(world, blank_id2);
- sord_node_free(world, lit_id2);
- sord_node_free(world, uri_id3);
- sord_node_free(world, blank_id3);
- sord_node_free(world, lit_id3);
- sord_free(sord);
-
- static const char* const index_names[6] = {
- "spo", "sop", "ops", "osp", "pso", "pos"
- };
-
- for (int i = 0; i < 6; ++i) {
- sord = sord_new(world, (1 << i), false);
- printf("Testing Index `%s'\n", index_names[i]);
- generate(world, sord, n_quads, 0);
- if (test_read(world, sord, 0, n_quads)) {
- return finished(world, sord, EXIT_FAILURE);
- }
- sord_free(sord);
- }
-
- static const char* const graph_index_names[6] = {
- "gspo", "gsop", "gops", "gosp", "gpso", "gpos"
- };
-
- for (int i = 0; i < 6; ++i) {
- sord = sord_new(world, (1 << i), true);
- printf("Testing Index `%s'\n", graph_index_names[i]);
- SordNode* graph = uri(world, 42);
- generate(world, sord, n_quads, graph);
- if (test_read(world, sord, graph, n_quads)) {
- return finished(world, sord, EXIT_FAILURE);
- }
- sord_free(sord);
- }
-
- // Test removing
- sord = sord_new(world, SORD_SPO, true);
- tup[0] = uri(world, 1);
- tup[1] = uri(world, 2);
- tup[2] = sord_new_literal(world, 0, USTR("hello"), NULL);
- tup[3] = 0;
- sord_add(sord, tup);
- if (!sord_ask(sord, tup[0], tup[1], tup[2], tup[3])) {
- fprintf(stderr, "Failed to add tuple\n");
- return finished(world, sord, EXIT_FAILURE);
- }
- sord_node_free(world, (SordNode*)tup[2]);
- tup[2] = sord_new_literal(world, 0, USTR("hi"), NULL);
- sord_add(sord, tup);
- sord_remove(sord, tup);
- if (sord_num_quads(sord) != 1) {
- fprintf(stderr, "Remove failed (%zu quads, expected 1)\n",
- sord_num_quads(sord));
- return finished(world, sord, EXIT_FAILURE);
- }
-
- iter = sord_find(sord, tup);
- if (!sord_iter_end(iter)) {
- fprintf(stderr, "Found removed tuple\n");
- return finished(world, sord, EXIT_FAILURE);
- }
- sord_iter_free(iter);
-
- // Test double remove (silent success)
- sord_remove(sord, tup);
-
- // Load a couple graphs
- SordNode* graph42 = uri(world, 42);
- SordNode* graph43 = uri(world, 43);
- generate(world, sord, 1, graph42);
- generate(world, sord, 1, graph43);
-
- // Remove one graph via iterator
- SerdStatus st;
- iter = sord_search(sord, NULL, NULL, NULL, graph43);
- while (!sord_iter_end(iter)) {
- if ((st = sord_erase(sord, iter))) {
- fprintf(stderr, "Remove by iterator failed (%s)\n",
- serd_strerror(st));
- return finished(world, sord, EXIT_FAILURE);
- }
- }
- sord_iter_free(iter);
-
- // Erase the first tuple (an element in the default graph)
- iter = sord_begin(sord);
- if (sord_erase(sord, iter)) {
- return test_fail("Failed to erase begin iterator on non-empty model\n");
- }
- sord_iter_free(iter);
-
- // Ensure only the other graph is left
- SordQuad quad;
- SordQuad pat = { 0, 0, 0, graph42 };
- for (iter = sord_begin(sord); !sord_iter_end(iter); sord_iter_next(iter)) {
- sord_iter_get(iter, quad);
- if (!sord_quad_match(quad, pat)) {
- fprintf(stderr, "Graph removal via iteration failed\n");
- return finished(world, sord, EXIT_FAILURE);
- }
- }
- 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));
- return finished(world, sord, EXIT_FAILURE);
- }
- 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));
- return finished(world, sord, EXIT_FAILURE);
- }
- serd_reader_free(reader);
- serd_env_free(env);
-
- // 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;
- }
- sord_iter_free(iter);
- if (n_triples != 1) {
- fprintf(stderr, "Found duplicate triple\n");
- return finished(world, sord, EXIT_FAILURE);
- }
-
- // 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_iter_free(iter);
-
- return finished(world, sord, EXIT_SUCCESS);
+ static const size_t n_quads = 300;
+
+ sord_free(NULL); // Shouldn't crash
+
+ SordWorld* world = sord_world_new();
+
+ // 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
+ SerdNode base = serd_node_from_string(SERD_URI, USTR("http://example.org/"));
+ SerdEnv* env = serd_env_new(&base);
+ SerdNode sbad = serd_node_from_string(SERD_CURIE, USTR("bad:"));
+ SordNode* bad = sord_node_from_serd_node(world, env, &sbad, NULL, NULL);
+ if (bad) {
+ return test_fail("Successfully created CURIE with bad namespace\n");
+ }
+ sord_node_free(world, bad);
+ serd_env_free(env);
+
+ // Attempt to create node from garbage
+ SerdNode junk = SERD_NODE_NULL;
+ junk.type = (SerdType)1234;
+ if (sord_node_from_serd_node(world, env, &junk, NULL, NULL)) {
+ return test_fail("Successfully created node from garbage serd node\n");
+ }
+
+ // Attempt to create NULL node
+ SordNode* nil_node =
+ sord_node_from_serd_node(world, NULL, &SERD_NODE_NULL, NULL, NULL);
+ if (nil_node) {
+ return test_fail("Successfully created NULL node\n");
+ }
+ sord_node_free(world, nil_node);
+
+ // 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)) {
+ return test_fail("Newline flag not set\n");
+ }
+ SordNode* with_quote = sord_new_literal(world, NULL, USTR("a\"b"), NULL);
+ if (!(sord_node_get_flags(with_quote) & SERD_HAS_QUOTE)) {
+ return test_fail("Quote flag not set\n");
+ }
+
+ // Create with minimal indexing
+ SordModel* sord = sord_new(world, SORD_SPO, false);
+ generate(world, sord, n_quads, NULL);
+
+ if (test_read(world, sord, NULL, n_quads)) {
+ sord_free(sord);
+ sord_world_free(world);
+ return EXIT_FAILURE;
+ }
+
+ // Check adding tuples with NULL fields fails
+ sord_world_set_error_sink(world, expected_error, NULL);
+ const size_t initial_num_quads = sord_num_quads(sord);
+ SordQuad tup = {0, 0, 0, 0};
+ if (sord_add(sord, tup)) {
+ return test_fail("Added NULL tuple\n");
+ }
+ tup[0] = uri(world, 1);
+ if (sord_add(sord, tup)) {
+ return test_fail("Added tuple with NULL P and O\n");
+ }
+ tup[1] = uri(world, 2);
+ if (sord_add(sord, tup)) {
+ return test_fail("Added tuple with NULL O\n");
+ }
+
+ if (sord_num_quads(sord) != initial_num_quads) {
+ return test_fail(
+ "Num quads %zu != %zu\n", sord_num_quads(sord), initial_num_quads);
+ }
+
+ // Check adding tuples with an active iterator fails
+ SordIter* iter = sord_begin(sord);
+ tup[2] = uri(world, 3);
+ if (sord_add(sord, tup)) {
+ return test_fail("Added tuple with active iterator\n");
+ }
+
+ // Check removing tuples with several active iterator fails
+ SordIter* iter2 = sord_begin(sord);
+ if (!sord_erase(sord, iter)) {
+ return test_fail("Erased tuple with several active iterators\n");
+ }
+ n_expected_errors = 0;
+ sord_remove(sord, tup);
+ if (n_expected_errors != 1) {
+ return test_fail("Removed tuple with several active iterators\n");
+ }
+ sord_iter_free(iter);
+ sord_iter_free(iter2);
+
+ sord_world_set_error_sink(world, unexpected_error, NULL);
+
+ // Check interning merges equivalent values
+ SordNode* uri_id = sord_new_uri(world, USTR("http://example.org"));
+ SordNode* blank_id = sord_new_blank(world, USTR("testblank"));
+ SordNode* lit_id = sord_new_literal(world, uri_id, USTR("hello"), NULL);
+ if (sord_node_get_type(uri_id) != SORD_URI) {
+ return test_fail("URI node has incorrect type\n");
+ } else if (sord_node_get_type(blank_id) != SORD_BLANK) {
+ return test_fail("Blank node has incorrect type\n");
+ } else if (sord_node_get_type(lit_id) != SORD_LITERAL) {
+ return test_fail("Literal node has incorrect type\n");
+ }
+
+ const size_t initial_num_nodes = sord_num_nodes(world);
+
+ SordNode* uri_id2 = sord_new_uri(world, USTR("http://example.org"));
+ SordNode* blank_id2 = sord_new_blank(world, USTR("testblank"));
+ SordNode* lit_id2 = sord_new_literal(world, uri_id, USTR("hello"), NULL);
+ if (uri_id2 != uri_id || !sord_node_equals(uri_id2, uri_id)) {
+ fprintf(stderr, "Fail: URI interning failed (duplicates)\n");
+ return finished(world, sord, EXIT_FAILURE);
+ } else if (blank_id2 != blank_id || !sord_node_equals(blank_id2, blank_id)) {
+ fprintf(stderr, "Fail: Blank node interning failed (duplicates)\n");
+ return finished(world, sord, EXIT_FAILURE);
+ } else if (lit_id2 != lit_id || !sord_node_equals(lit_id2, lit_id)) {
+ fprintf(stderr, "Fail: Literal interning failed (duplicates)\n");
+ return finished(world, sord, EXIT_FAILURE);
+ }
+
+ if (sord_num_nodes(world) != initial_num_nodes) {
+ return test_fail(
+ "Num nodes %zu != %zu\n", sord_num_nodes(world), initial_num_nodes);
+ }
+
+ const uint8_t ni_hao[] = {0xE4, 0xBD, 0xA0, 0xE5, 0xA5, 0xBD, 0};
+ SordNode* chello = sord_new_literal(world, NULL, ni_hao, "cmn");
+
+ // Test literal length
+ size_t n_bytes;
+ size_t n_chars;
+ const uint8_t* str = sord_node_get_string_counted(lit_id2, &n_bytes);
+ if (strcmp((const char*)str, "hello")) {
+ return test_fail("Literal node corrupt\n");
+ } else if (n_bytes != strlen("hello")) {
+ return test_fail("ASCII literal byte count incorrect\n");
+ }
+
+ str = sord_node_get_string_measured(lit_id2, &n_bytes, &n_chars);
+ if (n_bytes != strlen("hello") || n_chars != strlen("hello")) {
+ return test_fail("ASCII literal measured length incorrect\n");
+ } else if (strcmp((const char*)str, "hello")) {
+ return test_fail("ASCII literal string incorrect\n");
+ }
+
+ str = sord_node_get_string_measured(chello, &n_bytes, &n_chars);
+ if (n_bytes != 6) {
+ return test_fail("Multi-byte literal byte count incorrect\n");
+ } else if (n_chars != 2) {
+ return test_fail("Multi-byte literal character count incorrect\n");
+ } else if (strcmp((const char*)str, (const char*)ni_hao)) {
+ return test_fail("Multi-byte literal string incorrect\n");
+ }
+
+ // Check interning doesn't clash non-equivalent values
+ SordNode* uri_id3 = sord_new_uri(world, USTR("http://example.orgX"));
+ SordNode* blank_id3 = sord_new_blank(world, USTR("testblankX"));
+ SordNode* lit_id3 = sord_new_literal(world, uri_id, USTR("helloX"), NULL);
+ if (uri_id3 == uri_id || sord_node_equals(uri_id3, uri_id)) {
+ fprintf(stderr, "Fail: URI interning failed (clash)\n");
+ return finished(world, sord, EXIT_FAILURE);
+ } else if (blank_id3 == blank_id || sord_node_equals(blank_id3, blank_id)) {
+ fprintf(stderr, "Fail: Blank node interning failed (clash)\n");
+ return finished(world, sord, EXIT_FAILURE);
+ } else if (lit_id3 == lit_id || sord_node_equals(lit_id3, lit_id)) {
+ fprintf(stderr, "Fail: Literal interning failed (clash)\n");
+ return finished(world, sord, EXIT_FAILURE);
+ }
+
+ // Check literal interning
+ SordNode* lit4 = sord_new_literal(world, NULL, USTR("hello"), NULL);
+ SordNode* lit5 = sord_new_literal(world, uri_id2, USTR("hello"), NULL);
+ SordNode* lit6 = sord_new_literal(world, NULL, USTR("hello"), "en-ca");
+ if (lit4 == lit5 || sord_node_equals(lit4, lit5) || lit4 == lit6 ||
+ sord_node_equals(lit4, lit6) || lit5 == lit6 ||
+ sord_node_equals(lit5, lit6)) {
+ fprintf(stderr, "Fail: Literal interning failed (type/lang clash)\n");
+ return finished(world, sord, EXIT_FAILURE);
+ }
+
+ // Check relative URI construction
+ SordNode* reluri =
+ sord_new_relative_uri(world, USTR("a/b"), USTR("http://example.org/"));
+ if (strcmp((const char*)sord_node_get_string(reluri),
+ "http://example.org/a/b")) {
+ fprintf(stderr,
+ "Fail: Bad relative URI constructed: <%s>\n",
+ sord_node_get_string(reluri));
+ return finished(world, sord, EXIT_FAILURE);
+ }
+ SordNode* reluri2 = sord_new_relative_uri(
+ world, USTR("http://drobilla.net/"), USTR("http://example.org/"));
+ if (strcmp((const char*)sord_node_get_string(reluri2),
+ "http://drobilla.net/")) {
+ fprintf(stderr,
+ "Fail: Bad relative URI constructed: <%s>\n",
+ sord_node_get_string(reluri));
+ return finished(world, sord, EXIT_FAILURE);
+ }
+
+ // Check comparison with NULL
+ sord_node_free(world, uri_id);
+ sord_node_free(world, blank_id);
+ sord_node_free(world, lit_id);
+ sord_node_free(world, uri_id2);
+ sord_node_free(world, blank_id2);
+ sord_node_free(world, lit_id2);
+ sord_node_free(world, uri_id3);
+ sord_node_free(world, blank_id3);
+ sord_node_free(world, lit_id3);
+ sord_free(sord);
+
+ static const char* const index_names[6] = {
+ "spo", "sop", "ops", "osp", "pso", "pos"};
+
+ for (int i = 0; i < 6; ++i) {
+ sord = sord_new(world, (1 << i), false);
+ printf("Testing Index `%s'\n", index_names[i]);
+ generate(world, sord, n_quads, 0);
+ if (test_read(world, sord, 0, n_quads)) {
+ return finished(world, sord, EXIT_FAILURE);
+ }
+ sord_free(sord);
+ }
+
+ static const char* const graph_index_names[6] = {
+ "gspo", "gsop", "gops", "gosp", "gpso", "gpos"};
+
+ for (int i = 0; i < 6; ++i) {
+ sord = sord_new(world, (1 << i), true);
+ printf("Testing Index `%s'\n", graph_index_names[i]);
+ SordNode* graph = uri(world, 42);
+ generate(world, sord, n_quads, graph);
+ if (test_read(world, sord, graph, n_quads)) {
+ return finished(world, sord, EXIT_FAILURE);
+ }
+ sord_free(sord);
+ }
+
+ // Test removing
+ sord = sord_new(world, SORD_SPO, true);
+ tup[0] = uri(world, 1);
+ tup[1] = uri(world, 2);
+ tup[2] = sord_new_literal(world, 0, USTR("hello"), NULL);
+ tup[3] = 0;
+ sord_add(sord, tup);
+ if (!sord_ask(sord, tup[0], tup[1], tup[2], tup[3])) {
+ fprintf(stderr, "Failed to add tuple\n");
+ return finished(world, sord, EXIT_FAILURE);
+ }
+ sord_node_free(world, (SordNode*)tup[2]);
+ tup[2] = sord_new_literal(world, 0, USTR("hi"), NULL);
+ sord_add(sord, tup);
+ sord_remove(sord, tup);
+ if (sord_num_quads(sord) != 1) {
+ fprintf(
+ stderr, "Remove failed (%zu quads, expected 1)\n", sord_num_quads(sord));
+ return finished(world, sord, EXIT_FAILURE);
+ }
+
+ iter = sord_find(sord, tup);
+ if (!sord_iter_end(iter)) {
+ fprintf(stderr, "Found removed tuple\n");
+ return finished(world, sord, EXIT_FAILURE);
+ }
+ sord_iter_free(iter);
+
+ // Test double remove (silent success)
+ sord_remove(sord, tup);
+
+ // Load a couple graphs
+ SordNode* graph42 = uri(world, 42);
+ SordNode* graph43 = uri(world, 43);
+ generate(world, sord, 1, graph42);
+ generate(world, sord, 1, graph43);
+
+ // Remove one graph via iterator
+ SerdStatus st;
+ iter = sord_search(sord, NULL, NULL, NULL, graph43);
+ while (!sord_iter_end(iter)) {
+ if ((st = sord_erase(sord, iter))) {
+ fprintf(stderr, "Remove by iterator failed (%s)\n", serd_strerror(st));
+ return finished(world, sord, EXIT_FAILURE);
+ }
+ }
+ sord_iter_free(iter);
+
+ // Erase the first tuple (an element in the default graph)
+ iter = sord_begin(sord);
+ if (sord_erase(sord, iter)) {
+ return test_fail("Failed to erase begin iterator on non-empty model\n");
+ }
+ sord_iter_free(iter);
+
+ // Ensure only the other graph is left
+ SordQuad quad;
+ SordQuad pat = {0, 0, 0, graph42};
+ for (iter = sord_begin(sord); !sord_iter_end(iter); sord_iter_next(iter)) {
+ sord_iter_get(iter, quad);
+ if (!sord_quad_match(quad, pat)) {
+ fprintf(stderr, "Graph removal via iteration failed\n");
+ return finished(world, sord, EXIT_FAILURE);
+ }
+ }
+ 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));
+ return finished(world, sord, EXIT_FAILURE);
+ }
+ 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));
+ return finished(world, sord, EXIT_FAILURE);
+ }
+ serd_reader_free(reader);
+ serd_env_free(env);
+
+ // 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;
+ }
+ sord_iter_free(iter);
+ if (n_triples != 1) {
+ fprintf(stderr, "Found duplicate triple\n");
+ return finished(world, sord, EXIT_FAILURE);
+ }
+
+ // 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_iter_free(iter);
+
+ return finished(world, sord, EXIT_SUCCESS);
}
diff --git a/src/sord_validate.c b/src/sord_validate.c
index 193dc06..0acb0a4 100644
--- a/src/sord_validate.c
+++ b/src/sord_validate.c
@@ -14,18 +14,18 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define _BSD_SOURCE 1 // for realpath
-#define _DEFAULT_SOURCE 1 // for realpath
+#define _BSD_SOURCE 1 // for realpath
+#define _DEFAULT_SOURCE 1 // for realpath
#include "serd/serd.h"
#include "sord/sord.h"
#include "sord_config.h"
#ifdef HAVE_PCRE
-# include <pcre.h>
+# include <pcre.h>
#endif
#ifdef _WIN32
-# include <windows.h>
+# include <windows.h>
#endif
#include <stdarg.h>
@@ -36,55 +36,55 @@
#include <string.h>
#ifdef __GNUC__
-# define SORD_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
+# define SORD_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
#else
-# define SORD_LOG_FUNC(fmt, arg1)
+# define SORD_LOG_FUNC(fmt, arg1)
#endif
#define NS_foaf (const uint8_t*)"http://xmlns.com/foaf/0.1/"
-#define NS_owl (const uint8_t*)"http://www.w3.org/2002/07/owl#"
-#define NS_rdf (const uint8_t*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+#define NS_owl (const uint8_t*)"http://www.w3.org/2002/07/owl#"
+#define NS_rdf (const uint8_t*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
#define NS_rdfs (const uint8_t*)"http://www.w3.org/2000/01/rdf-schema#"
-#define NS_xsd (const uint8_t*)"http://www.w3.org/2001/XMLSchema#"
+#define NS_xsd (const uint8_t*)"http://www.w3.org/2001/XMLSchema#"
typedef struct {
- SordNode* foaf_Document;
- SordNode* owl_AnnotationProperty;
- SordNode* owl_Class;
- SordNode* owl_DatatypeProperty;
- SordNode* owl_FunctionalProperty;
- SordNode* owl_InverseFunctionalProperty;
- SordNode* owl_ObjectProperty;
- SordNode* owl_OntologyProperty;
- SordNode* owl_Restriction;
- SordNode* owl_Thing;
- SordNode* owl_cardinality;
- SordNode* owl_equivalentClass;
- SordNode* owl_maxCardinality;
- SordNode* owl_minCardinality;
- SordNode* owl_onDatatype;
- SordNode* owl_onProperty;
- SordNode* owl_someValuesFrom;
- SordNode* owl_withRestrictions;
- SordNode* rdf_PlainLiteral;
- SordNode* rdf_Property;
- SordNode* rdf_first;
- SordNode* rdf_rest;
- SordNode* rdf_type;
- SordNode* rdfs_Class;
- SordNode* rdfs_Literal;
- SordNode* rdfs_Resource;
- SordNode* rdfs_domain;
- SordNode* rdfs_label;
- SordNode* rdfs_range;
- SordNode* rdfs_subClassOf;
- SordNode* xsd_anyURI;
- SordNode* xsd_decimal;
- SordNode* xsd_double;
- SordNode* xsd_maxInclusive;
- SordNode* xsd_minInclusive;
- SordNode* xsd_pattern;
- SordNode* xsd_string;
+ SordNode* foaf_Document;
+ SordNode* owl_AnnotationProperty;
+ SordNode* owl_Class;
+ SordNode* owl_DatatypeProperty;
+ SordNode* owl_FunctionalProperty;
+ SordNode* owl_InverseFunctionalProperty;
+ SordNode* owl_ObjectProperty;
+ SordNode* owl_OntologyProperty;
+ SordNode* owl_Restriction;
+ SordNode* owl_Thing;
+ SordNode* owl_cardinality;
+ SordNode* owl_equivalentClass;
+ SordNode* owl_maxCardinality;
+ SordNode* owl_minCardinality;
+ SordNode* owl_onDatatype;
+ SordNode* owl_onProperty;
+ SordNode* owl_someValuesFrom;
+ SordNode* owl_withRestrictions;
+ SordNode* rdf_PlainLiteral;
+ SordNode* rdf_Property;
+ SordNode* rdf_first;
+ SordNode* rdf_rest;
+ SordNode* rdf_type;
+ SordNode* rdfs_Class;
+ SordNode* rdfs_Literal;
+ SordNode* rdfs_Resource;
+ SordNode* rdfs_domain;
+ SordNode* rdfs_label;
+ SordNode* rdfs_range;
+ SordNode* rdfs_subClassOf;
+ SordNode* xsd_anyURI;
+ SordNode* xsd_decimal;
+ SordNode* xsd_double;
+ SordNode* xsd_maxInclusive;
+ SordNode* xsd_minInclusive;
+ SordNode* xsd_pattern;
+ SordNode* xsd_string;
} URIs;
static int n_errors = 0;
@@ -94,42 +94,42 @@ static bool one_line_errors = false;
static int
print_version(void)
{
- printf("sord_validate " SORD_VERSION
- " <http://drobilla.net/software/sord>\n");
- printf("Copyright 2012-2017 David Robillard <http://drobilla.net>.\n"
- "License: <http://www.opensource.org/licenses/isc>\n"
- "This is free software; you are free to change and redistribute it."
- "\nThere is NO WARRANTY, to the extent permitted by law.\n");
- return 0;
+ printf("sord_validate " SORD_VERSION
+ " <http://drobilla.net/software/sord>\n");
+ printf("Copyright 2012-2017 David Robillard <http://drobilla.net>.\n"
+ "License: <http://www.opensource.org/licenses/isc>\n"
+ "This is free software; you are free to change and redistribute it."
+ "\nThere is NO WARRANTY, to the extent permitted by law.\n");
+ return 0;
}
static int
print_usage(const char* name, bool error)
{
- FILE* const os = error ? stderr : stdout;
- fprintf(os, "Usage: %s [OPTION]... INPUT...\n", name);
- fprintf(os, "Validate RDF data\n\n");
- fprintf(os, " -h Display this help and exit\n");
- fprintf(os, " -l Print errors on a single line.\n");
- fprintf(os, " -v Display version information and exit\n");
- fprintf(os,
- "Validate RDF data. This is a simple validator which checks\n"
- "that all used properties are actually defined. It does not do\n"
- "any fancy file retrieval, the files passed on the command line\n"
- "are the only data that is read. In other words, you must pass\n"
- "the definition of all vocabularies used on the command line.\n");
- return error ? 1 : 0;
+ FILE* const os = error ? stderr : stdout;
+ fprintf(os, "Usage: %s [OPTION]... INPUT...\n", name);
+ fprintf(os, "Validate RDF data\n\n");
+ fprintf(os, " -h Display this help and exit\n");
+ fprintf(os, " -l Print errors on a single line.\n");
+ fprintf(os, " -v Display version information and exit\n");
+ fprintf(os,
+ "Validate RDF data. This is a simple validator which checks\n"
+ "that all used properties are actually defined. It does not do\n"
+ "any fancy file retrieval, the files passed on the command line\n"
+ "are the only data that is read. In other words, you must pass\n"
+ "the definition of all vocabularies used on the command line.\n");
+ return error ? 1 : 0;
}
static uint8_t*
absolute_path(const uint8_t* path)
{
#ifdef _WIN32
- char* out = (char*)malloc(MAX_PATH);
- GetFullPathName((const char*)path, MAX_PATH, out, NULL);
- return (uint8_t*)out;
+ char* out = (char*)malloc(MAX_PATH);
+ GetFullPathName((const char*)path, MAX_PATH, out, NULL);
+ return (uint8_t*)out;
#else
- return (uint8_t*)realpath((const char*)path, NULL);
+ return (uint8_t*)realpath((const char*)path, NULL);
#endif
}
@@ -137,20 +137,24 @@ SORD_LOG_FUNC(2, 3)
static int
errorf(const SordQuad quad, const char* fmt, ...)
{
- va_list args;
- va_start(args, fmt);
- fprintf(stderr, "error: ");
- vfprintf(stderr, fmt, args);
- va_end(args);
-
- const char* sep = one_line_errors ? "\t" : "\n ";
- fprintf(stderr, "%s%s%s%s%s%s\n",
- sep, (const char*)sord_node_get_string(quad[SORD_SUBJECT]),
- sep, (const char*)sord_node_get_string(quad[SORD_PREDICATE]),
- sep, (const char*)sord_node_get_string(quad[SORD_OBJECT]));
-
- ++n_errors;
- return 1;
+ va_list args;
+ va_start(args, fmt);
+ fprintf(stderr, "error: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+
+ const char* sep = one_line_errors ? "\t" : "\n ";
+ fprintf(stderr,
+ "%s%s%s%s%s%s\n",
+ sep,
+ (const char*)sord_node_get_string(quad[SORD_SUBJECT]),
+ sep,
+ (const char*)sord_node_get_string(quad[SORD_PREDICATE]),
+ sep,
+ (const char*)sord_node_get_string(quad[SORD_OBJECT]));
+
+ ++n_errors;
+ return 1;
}
static bool
@@ -160,56 +164,55 @@ is_descendant_of(SordModel* model,
const SordNode* parent,
const SordNode* pred)
{
- if (!child) {
- return false;
- } else if (
- sord_node_equals(child, parent) ||
- sord_ask(model, child, uris->owl_equivalentClass, parent, NULL)) {
- return true;
- }
-
- SordIter* i = sord_search(model, child, pred, NULL, NULL);
- for (; !sord_iter_end(i); sord_iter_next(i)) {
- const SordNode* o = sord_iter_get_node(i, SORD_OBJECT);
- if (sord_node_equals(child, o)) {
- continue; // Weird class is explicitly a descendent of itself
- }
- if (is_descendant_of(model, uris, o, parent, pred)) {
- sord_iter_free(i);
- return true;
- }
- }
- sord_iter_free(i);
-
- return false;
+ if (!child) {
+ return false;
+ } else if (sord_node_equals(child, parent) ||
+ sord_ask(model, child, uris->owl_equivalentClass, parent, NULL)) {
+ return true;
+ }
+
+ SordIter* i = sord_search(model, child, pred, NULL, NULL);
+ for (; !sord_iter_end(i); sord_iter_next(i)) {
+ const SordNode* o = sord_iter_get_node(i, SORD_OBJECT);
+ if (sord_node_equals(child, o)) {
+ continue; // Weird class is explicitly a descendent of itself
+ }
+ if (is_descendant_of(model, uris, o, parent, pred)) {
+ sord_iter_free(i);
+ return true;
+ }
+ }
+ sord_iter_free(i);
+
+ return false;
}
static bool
regexp_match(const uint8_t* pat, const char* str)
{
#ifdef HAVE_PCRE
- // Append a $ to the pattern so we only match if the entire string matches
- const size_t len = strlen((const char*)pat);
- char* const regx = (char*)malloc(len + 2);
- memcpy(regx, pat, len);
- regx[len] = '$';
- regx[len + 1] = '\0';
-
- const char* err;
- int erroffset;
- pcre* re = pcre_compile(regx, PCRE_ANCHORED, &err, &erroffset, NULL);
- free(regx);
- if (!re) {
- fprintf(stderr, "Error in pattern `%s' at offset %d (%s)\n",
- pat, erroffset, err);
- return false;
- }
-
- const bool ret = pcre_exec(re, NULL, str, strlen(str), 0, 0, NULL, 0) >= 0;
- pcre_free(re);
- return ret;
-#endif // HAVE_PCRE
- return true;
+ // Append a $ to the pattern so we only match if the entire string matches
+ const size_t len = strlen((const char*)pat);
+ char* const regx = (char*)malloc(len + 2);
+ memcpy(regx, pat, len);
+ regx[len] = '$';
+ regx[len + 1] = '\0';
+
+ const char* err;
+ int erroffset;
+ pcre* re = pcre_compile(regx, PCRE_ANCHORED, &err, &erroffset, NULL);
+ free(regx);
+ if (!re) {
+ fprintf(
+ stderr, "Error in pattern `%s' at offset %d (%s)\n", pat, erroffset, err);
+ return false;
+ }
+
+ const bool ret = pcre_exec(re, NULL, str, strlen(str), 0, 0, NULL, 0) >= 0;
+ pcre_free(re);
+ return ret;
+#endif // HAVE_PCRE
+ return true;
}
static int
@@ -219,22 +222,20 @@ bound_cmp(SordModel* model,
const SordNode* type,
const SordNode* bound)
{
- const char* str = (const char*)sord_node_get_string(literal);
- const char* bound_str = (const char*)sord_node_get_string(bound);
- const SordNode* pred = uris->owl_onDatatype;
- const bool is_numeric =
- is_descendant_of(model, uris, type, uris->xsd_decimal, pred) ||
- is_descendant_of(model, uris, type, uris->xsd_double, pred);
-
- if (is_numeric) {
- const double fbound = serd_strtod(bound_str, NULL);
- const double fliteral = serd_strtod(str, NULL);
- return ((fliteral < fbound) ? -1 :
- (fliteral > fbound) ? 1 :
- 0);
- } else {
- return strcmp(str, bound_str);
- }
+ const char* str = (const char*)sord_node_get_string(literal);
+ const char* bound_str = (const char*)sord_node_get_string(bound);
+ const SordNode* pred = uris->owl_onDatatype;
+ const bool is_numeric =
+ is_descendant_of(model, uris, type, uris->xsd_decimal, pred) ||
+ is_descendant_of(model, uris, type, uris->xsd_double, pred);
+
+ if (is_numeric) {
+ const double fbound = serd_strtod(bound_str, NULL);
+ const double fliteral = serd_strtod(str, NULL);
+ return ((fliteral < fbound) ? -1 : (fliteral > fbound) ? 1 : 0);
+ } else {
+ return strcmp(str, bound_str);
+ }
}
static bool
@@ -244,58 +245,61 @@ check_restriction(SordModel* model,
const SordNode* type,
const SordNode* restriction)
{
- size_t len = 0;
- const char* str = (const char*)sord_node_get_string_counted(literal, &len);
-
- // Check xsd:pattern
- SordIter* p = sord_search(model, restriction, uris->xsd_pattern, 0, 0);
- if (p) {
- const SordNode* pat = sord_iter_get_node(p, SORD_OBJECT);
- if (!regexp_match(sord_node_get_string(pat), str)) {
- fprintf(stderr, "`%s' does not match <%s> pattern `%s'\n",
- sord_node_get_string(literal),
- sord_node_get_string(type),
- sord_node_get_string(pat));
- sord_iter_free(p);
- return false;
- }
- sord_iter_free(p);
- ++n_restrictions;
- }
-
- // Check xsd:minInclusive
- SordIter* l = sord_search(model, restriction, uris->xsd_minInclusive, 0, 0);
- if (l) {
- const SordNode* lower = sord_iter_get_node(l, SORD_OBJECT);
- if (bound_cmp(model, uris, literal, type, lower) < 0) {
- fprintf(stderr, "`%s' is not >= <%s> minimum `%s'\n",
- sord_node_get_string(literal),
- sord_node_get_string(type),
- sord_node_get_string(lower));
- sord_iter_free(l);
- return false;
- }
- sord_iter_free(l);
- ++n_restrictions;
- }
-
- // Check xsd:maxInclusive
- SordIter* u = sord_search(model, restriction, uris->xsd_maxInclusive, 0, 0);
- if (u) {
- const SordNode* upper = sord_iter_get_node(u, SORD_OBJECT);
- if (bound_cmp(model, uris, literal, type, upper) > 0) {
- fprintf(stderr, "`%s' is not <= <%s> maximum `%s'\n",
- sord_node_get_string(literal),
- sord_node_get_string(type),
- sord_node_get_string(upper));
- sord_iter_free(u);
- return false;
- }
- sord_iter_free(u);
- ++n_restrictions;
- }
-
- return true; // Unknown restriction, be quietly tolerant
+ size_t len = 0;
+ const char* str = (const char*)sord_node_get_string_counted(literal, &len);
+
+ // Check xsd:pattern
+ SordIter* p = sord_search(model, restriction, uris->xsd_pattern, 0, 0);
+ if (p) {
+ const SordNode* pat = sord_iter_get_node(p, SORD_OBJECT);
+ if (!regexp_match(sord_node_get_string(pat), str)) {
+ fprintf(stderr,
+ "`%s' does not match <%s> pattern `%s'\n",
+ sord_node_get_string(literal),
+ sord_node_get_string(type),
+ sord_node_get_string(pat));
+ sord_iter_free(p);
+ return false;
+ }
+ sord_iter_free(p);
+ ++n_restrictions;
+ }
+
+ // Check xsd:minInclusive
+ SordIter* l = sord_search(model, restriction, uris->xsd_minInclusive, 0, 0);
+ if (l) {
+ const SordNode* lower = sord_iter_get_node(l, SORD_OBJECT);
+ if (bound_cmp(model, uris, literal, type, lower) < 0) {
+ fprintf(stderr,
+ "`%s' is not >= <%s> minimum `%s'\n",
+ sord_node_get_string(literal),
+ sord_node_get_string(type),
+ sord_node_get_string(lower));
+ sord_iter_free(l);
+ return false;
+ }
+ sord_iter_free(l);
+ ++n_restrictions;
+ }
+
+ // Check xsd:maxInclusive
+ SordIter* u = sord_search(model, restriction, uris->xsd_maxInclusive, 0, 0);
+ if (u) {
+ const SordNode* upper = sord_iter_get_node(u, SORD_OBJECT);
+ if (bound_cmp(model, uris, literal, type, upper) > 0) {
+ fprintf(stderr,
+ "`%s' is not <= <%s> maximum `%s'\n",
+ sord_node_get_string(literal),
+ sord_node_get_string(type),
+ sord_node_get_string(upper));
+ sord_iter_free(u);
+ return false;
+ }
+ sord_iter_free(u);
+ ++n_restrictions;
+ }
+
+ return true; // Unknown restriction, be quietly tolerant
}
static bool
@@ -305,78 +309,72 @@ literal_is_valid(SordModel* model,
const SordNode* literal,
const SordNode* type)
{
- if (!type) {
- return true;
- }
-
- /* Check that literal data is related to required type. We don't do a
- strict subtype check here because e.g. an xsd:decimal might be a valid
- xsd:unsignedInt, which the pattern checks will verify, but if the
- literal type is not related to the required type at all
- (e.g. xsd:decimal and xsd:string) there is a problem. */
- const SordNode* datatype = sord_node_get_datatype(literal);
- if (datatype && datatype != type) {
- if (!is_descendant_of(
- model, uris,
- datatype, type, uris->owl_onDatatype) &&
- !is_descendant_of(
- model, uris,
- type, datatype, uris->owl_onDatatype) &&
- !(sord_node_equals(datatype, uris->xsd_decimal) &&
- is_descendant_of(
- model, uris,
- type, uris->xsd_double, uris->owl_onDatatype))) {
- errorf(quad,
- "Literal `%s' datatype <%s> is not compatible with <%s>\n",
- sord_node_get_string(literal),
- sord_node_get_string(datatype),
- sord_node_get_string(type));
- return false;
- }
- }
-
- // Find restrictions list
- SordIter* rs = sord_search(model, type, uris->owl_withRestrictions, 0, 0);
- if (sord_iter_end(rs)) {
- return true; // No restrictions
- }
-
- // Walk list, checking each restriction
- const SordNode* head = sord_iter_get_node(rs, SORD_OBJECT);
- while (head) {
- SordIter* f = sord_search(model, head, uris->rdf_first, 0, 0);
- if (!f) {
- break; // Reached end of restrictions list without failure
- }
-
- // Check this restriction
- const bool good = check_restriction(
- model, uris, literal, type, sord_iter_get_node(f, SORD_OBJECT));
- sord_iter_free(f);
-
- if (!good) {
- sord_iter_free(rs);
- return false; // Failed, literal is invalid
- }
-
- // Seek to next list node
- SordIter* n = sord_search(model, head, uris->rdf_rest, 0, 0);
- head = n ? sord_iter_get_node(n, SORD_OBJECT) : NULL;
- sord_iter_free(n);
- }
-
- sord_iter_free(rs);
-
- SordIter* s = sord_search(model, type, uris->owl_onDatatype, 0, 0);
- if (s) {
- const SordNode* super = sord_iter_get_node(s, SORD_OBJECT);
- const bool good = literal_is_valid(
- model, uris, quad, literal, super);
- sord_iter_free(s);
- return good; // Match iff literal also matches supertype
- }
-
- return true; // Matches top level type
+ if (!type) {
+ return true;
+ }
+
+ /* Check that literal data is related to required type. We don't do a
+ strict subtype check here because e.g. an xsd:decimal might be a valid
+ xsd:unsignedInt, which the pattern checks will verify, but if the
+ literal type is not related to the required type at all
+ (e.g. xsd:decimal and xsd:string) there is a problem. */
+ const SordNode* datatype = sord_node_get_datatype(literal);
+ if (datatype && datatype != type) {
+ if (!is_descendant_of(model, uris, datatype, type, uris->owl_onDatatype) &&
+ !is_descendant_of(model, uris, type, datatype, uris->owl_onDatatype) &&
+ !(sord_node_equals(datatype, uris->xsd_decimal) &&
+ is_descendant_of(
+ model, uris, type, uris->xsd_double, uris->owl_onDatatype))) {
+ errorf(quad,
+ "Literal `%s' datatype <%s> is not compatible with <%s>\n",
+ sord_node_get_string(literal),
+ sord_node_get_string(datatype),
+ sord_node_get_string(type));
+ return false;
+ }
+ }
+
+ // Find restrictions list
+ SordIter* rs = sord_search(model, type, uris->owl_withRestrictions, 0, 0);
+ if (sord_iter_end(rs)) {
+ return true; // No restrictions
+ }
+
+ // Walk list, checking each restriction
+ const SordNode* head = sord_iter_get_node(rs, SORD_OBJECT);
+ while (head) {
+ SordIter* f = sord_search(model, head, uris->rdf_first, 0, 0);
+ if (!f) {
+ break; // Reached end of restrictions list without failure
+ }
+
+ // Check this restriction
+ const bool good = check_restriction(
+ model, uris, literal, type, sord_iter_get_node(f, SORD_OBJECT));
+ sord_iter_free(f);
+
+ if (!good) {
+ sord_iter_free(rs);
+ return false; // Failed, literal is invalid
+ }
+
+ // Seek to next list node
+ SordIter* n = sord_search(model, head, uris->rdf_rest, 0, 0);
+ head = n ? sord_iter_get_node(n, SORD_OBJECT) : NULL;
+ sord_iter_free(n);
+ }
+
+ sord_iter_free(rs);
+
+ SordIter* s = sord_search(model, type, uris->owl_onDatatype, 0, 0);
+ if (s) {
+ const SordNode* super = sord_iter_get_node(s, SORD_OBJECT);
+ const bool good = literal_is_valid(model, uris, quad, literal, super);
+ sord_iter_free(s);
+ return good; // Match iff literal also matches supertype
+ }
+
+ return true; // Matches top level type
}
static bool
@@ -386,170 +384,168 @@ check_type(SordModel* model,
const SordNode* node,
const SordNode* type)
{
- if (sord_node_equals(type, uris->rdfs_Resource) ||
- sord_node_equals(type, uris->owl_Thing)) {
- return true;
- }
-
- if (sord_node_get_type(node) == SORD_LITERAL) {
- if (sord_node_equals(type, uris->rdfs_Literal)) {
- return true;
- } else if (sord_node_equals(type, uris->rdf_PlainLiteral)) {
- return !sord_node_get_language(node);
- } else {
- return literal_is_valid(model, uris, quad, node, type);
- }
- } else if (sord_node_get_type(node) == SORD_URI) {
- if (sord_node_equals(type, uris->foaf_Document)) {
- return true; // Questionable...
- } else if (is_descendant_of(
- model, uris,
- type, uris->xsd_anyURI, uris->owl_onDatatype)) {
- /* Type is any URI and this is a URI, so pass. Restrictions on
- anyURI subtypes are not currently checked (very uncommon). */
- return true; // Type is anyURI, and this is a URI
- } else {
- SordIter* t = sord_search(model, node, uris->rdf_type, NULL, NULL);
- for (; !sord_iter_end(t); sord_iter_next(t)) {
- if (is_descendant_of(model, uris,
- sord_iter_get_node(t, SORD_OBJECT),
- type,
- uris->rdfs_subClassOf)) {
- sord_iter_free(t);
- return true;
- }
- }
- sord_iter_free(t);
- return false;
- }
- } else {
- return true; // Blanks often lack explicit types, ignore
- }
-
- return false;
+ if (sord_node_equals(type, uris->rdfs_Resource) ||
+ sord_node_equals(type, uris->owl_Thing)) {
+ return true;
+ }
+
+ if (sord_node_get_type(node) == SORD_LITERAL) {
+ if (sord_node_equals(type, uris->rdfs_Literal)) {
+ return true;
+ } else if (sord_node_equals(type, uris->rdf_PlainLiteral)) {
+ return !sord_node_get_language(node);
+ } else {
+ return literal_is_valid(model, uris, quad, node, type);
+ }
+ } else if (sord_node_get_type(node) == SORD_URI) {
+ if (sord_node_equals(type, uris->foaf_Document)) {
+ return true; // Questionable...
+ } else if (is_descendant_of(
+ model, uris, type, uris->xsd_anyURI, uris->owl_onDatatype)) {
+ /* Type is any URI and this is a URI, so pass. Restrictions on
+ anyURI subtypes are not currently checked (very uncommon). */
+ return true; // Type is anyURI, and this is a URI
+ } else {
+ SordIter* t = sord_search(model, node, uris->rdf_type, NULL, NULL);
+ for (; !sord_iter_end(t); sord_iter_next(t)) {
+ if (is_descendant_of(model,
+ uris,
+ sord_iter_get_node(t, SORD_OBJECT),
+ type,
+ uris->rdfs_subClassOf)) {
+ sord_iter_free(t);
+ return true;
+ }
+ }
+ sord_iter_free(t);
+ return false;
+ }
+ } else {
+ return true; // Blanks often lack explicit types, ignore
+ }
+
+ return false;
}
static uint64_t
count_non_blanks(SordIter* i, SordQuadIndex field)
{
- uint64_t n = 0;
- for (; !sord_iter_end(i); sord_iter_next(i)) {
- const SordNode* node = sord_iter_get_node(i, field);
- if (sord_node_get_type(node) != SORD_BLANK) {
- ++n;
- }
- }
- return n;
+ uint64_t n = 0;
+ for (; !sord_iter_end(i); sord_iter_next(i)) {
+ const SordNode* node = sord_iter_get_node(i, field);
+ if (sord_node_get_type(node) != SORD_BLANK) {
+ ++n;
+ }
+ }
+ return n;
}
static int
check_properties(SordModel* model, URIs* uris)
{
- int st = 0;
- SordIter* i = sord_begin(model);
- for (; !sord_iter_end(i); sord_iter_next(i)) {
- SordQuad quad;
- sord_iter_get(i, quad);
-
- const SordNode* subj = quad[SORD_SUBJECT];
- const SordNode* pred = quad[SORD_PREDICATE];
- const SordNode* obj = quad[SORD_OBJECT];
-
- bool is_any_property = false;
- SordIter* t = sord_search(model, pred, uris->rdf_type, NULL, NULL);
- for (; !sord_iter_end(t); sord_iter_next(t)) {
- if (is_descendant_of(model, uris,
- sord_iter_get_node(t, SORD_OBJECT),
- uris->rdf_Property,
- uris->rdfs_subClassOf)) {
- is_any_property = true;
- break;
- }
- }
- sord_iter_free(t);
-
- const bool is_ObjectProperty = sord_ask(
- model, pred, uris->rdf_type, uris->owl_ObjectProperty, 0);
- const bool is_FunctionalProperty = sord_ask(
- model, pred, uris->rdf_type, uris->owl_FunctionalProperty, 0);
- const bool is_InverseFunctionalProperty = sord_ask(
- model, pred, uris->rdf_type, uris->owl_InverseFunctionalProperty, 0);
- const bool is_DatatypeProperty = sord_ask(
- model, pred, uris->rdf_type, uris->owl_DatatypeProperty, 0);
-
- if (!is_any_property) {
- st = errorf(quad, "Use of undefined property");
- }
-
- if (!sord_ask(model, pred, uris->rdfs_label, NULL, NULL)) {
- st = errorf(quad, "Property <%s> has no label",
- sord_node_get_string(pred));
- }
-
- if (is_DatatypeProperty &&
- sord_node_get_type(obj) != SORD_LITERAL) {
- st = errorf(quad, "Datatype property with non-literal value");
- }
-
- if (is_ObjectProperty &&
- sord_node_get_type(obj) == SORD_LITERAL) {
- st = errorf(quad, "Object property with literal value");
- }
-
- if (is_FunctionalProperty) {
- SordIter* o = sord_search(model, subj, pred, NULL, NULL);
- const unsigned n = count_non_blanks(o, SORD_OBJECT);
- if (n > 1) {
- st = errorf(quad, "Functional property with %u objects", n);
- }
- sord_iter_free(o);
- }
-
- if (is_InverseFunctionalProperty) {
- SordIter* s = sord_search(model, NULL, pred, obj, NULL);
- const unsigned n = count_non_blanks(s, SORD_SUBJECT);
- if (n > 1) {
- st = errorf(
- quad, "Inverse functional property with %u subjects", n);
- }
- sord_iter_free(s);
- }
-
- if (sord_node_equals(pred, uris->rdf_type) &&
- !sord_ask(model, obj, uris->rdf_type, uris->rdfs_Class, NULL) &&
- !sord_ask(model, obj, uris->rdf_type, uris->owl_Class, NULL)) {
- st = errorf(quad, "Type is not a rdfs:Class or owl:Class");
- }
-
- if (sord_node_get_type(obj) == SORD_LITERAL &&
- !literal_is_valid(model, uris, quad,
- obj, sord_node_get_datatype(obj))) {
- st = errorf(quad, "Literal does not match datatype");
- }
-
- SordIter* r = sord_search(model, pred, uris->rdfs_range, NULL, NULL);
- for (; !sord_iter_end(r); sord_iter_next(r)) {
- const SordNode* range = sord_iter_get_node(r, SORD_OBJECT);
- if (!check_type(model, uris, quad, obj, range)) {
- st = errorf(quad, "Object not in range <%s>\n",
- sord_node_get_string(range));
- }
- }
- sord_iter_free(r);
-
- SordIter* d = sord_search(model, pred, uris->rdfs_domain, NULL, NULL);
- if (d) {
- const SordNode* domain = sord_iter_get_node(d, SORD_OBJECT);
- if (!check_type(model, uris, quad, subj, domain)) {
- st = errorf(quad, "Subject not in domain <%s>",
- sord_node_get_string(domain));
- }
- sord_iter_free(d);
- }
- }
- sord_iter_free(i);
-
- return st;
+ int st = 0;
+ SordIter* i = sord_begin(model);
+ for (; !sord_iter_end(i); sord_iter_next(i)) {
+ SordQuad quad;
+ sord_iter_get(i, quad);
+
+ const SordNode* subj = quad[SORD_SUBJECT];
+ const SordNode* pred = quad[SORD_PREDICATE];
+ const SordNode* obj = quad[SORD_OBJECT];
+
+ bool is_any_property = false;
+ SordIter* t = sord_search(model, pred, uris->rdf_type, NULL, NULL);
+ for (; !sord_iter_end(t); sord_iter_next(t)) {
+ if (is_descendant_of(model,
+ uris,
+ sord_iter_get_node(t, SORD_OBJECT),
+ uris->rdf_Property,
+ uris->rdfs_subClassOf)) {
+ is_any_property = true;
+ break;
+ }
+ }
+ sord_iter_free(t);
+
+ const bool is_ObjectProperty =
+ sord_ask(model, pred, uris->rdf_type, uris->owl_ObjectProperty, 0);
+ const bool is_FunctionalProperty =
+ sord_ask(model, pred, uris->rdf_type, uris->owl_FunctionalProperty, 0);
+ const bool is_InverseFunctionalProperty = sord_ask(
+ model, pred, uris->rdf_type, uris->owl_InverseFunctionalProperty, 0);
+ const bool is_DatatypeProperty =
+ sord_ask(model, pred, uris->rdf_type, uris->owl_DatatypeProperty, 0);
+
+ if (!is_any_property) {
+ st = errorf(quad, "Use of undefined property");
+ }
+
+ if (!sord_ask(model, pred, uris->rdfs_label, NULL, NULL)) {
+ st =
+ errorf(quad, "Property <%s> has no label", sord_node_get_string(pred));
+ }
+
+ if (is_DatatypeProperty && sord_node_get_type(obj) != SORD_LITERAL) {
+ st = errorf(quad, "Datatype property with non-literal value");
+ }
+
+ if (is_ObjectProperty && sord_node_get_type(obj) == SORD_LITERAL) {
+ st = errorf(quad, "Object property with literal value");
+ }
+
+ if (is_FunctionalProperty) {
+ SordIter* o = sord_search(model, subj, pred, NULL, NULL);
+ const unsigned n = count_non_blanks(o, SORD_OBJECT);
+ if (n > 1) {
+ st = errorf(quad, "Functional property with %u objects", n);
+ }
+ sord_iter_free(o);
+ }
+
+ if (is_InverseFunctionalProperty) {
+ SordIter* s = sord_search(model, NULL, pred, obj, NULL);
+ const unsigned n = count_non_blanks(s, SORD_SUBJECT);
+ if (n > 1) {
+ st = errorf(quad, "Inverse functional property with %u subjects", n);
+ }
+ sord_iter_free(s);
+ }
+
+ if (sord_node_equals(pred, uris->rdf_type) &&
+ !sord_ask(model, obj, uris->rdf_type, uris->rdfs_Class, NULL) &&
+ !sord_ask(model, obj, uris->rdf_type, uris->owl_Class, NULL)) {
+ st = errorf(quad, "Type is not a rdfs:Class or owl:Class");
+ }
+
+ if (sord_node_get_type(obj) == SORD_LITERAL &&
+ !literal_is_valid(
+ model, uris, quad, obj, sord_node_get_datatype(obj))) {
+ st = errorf(quad, "Literal does not match datatype");
+ }
+
+ SordIter* r = sord_search(model, pred, uris->rdfs_range, NULL, NULL);
+ for (; !sord_iter_end(r); sord_iter_next(r)) {
+ const SordNode* range = sord_iter_get_node(r, SORD_OBJECT);
+ if (!check_type(model, uris, quad, obj, range)) {
+ st = errorf(
+ quad, "Object not in range <%s>\n", sord_node_get_string(range));
+ }
+ }
+ sord_iter_free(r);
+
+ SordIter* d = sord_search(model, pred, uris->rdfs_domain, NULL, NULL);
+ if (d) {
+ const SordNode* domain = sord_iter_get_node(d, SORD_OBJECT);
+ if (!check_type(model, uris, quad, subj, domain)) {
+ st = errorf(
+ quad, "Subject not in domain <%s>", sord_node_get_string(domain));
+ }
+ sord_iter_free(d);
+ }
+ }
+ sord_iter_free(i);
+
+ return st;
}
static int
@@ -558,82 +554,89 @@ check_instance(SordModel* model,
const SordNode* restriction,
const SordQuad quad)
{
- const SordNode* instance = quad[SORD_SUBJECT];
- int st = 0;
-
- const SordNode* prop = sord_get(
- model, restriction, uris->owl_onProperty, NULL, NULL);
- if (!prop) {
- return 0;
- }
-
- const unsigned values = sord_count(model, instance, prop, NULL, NULL);
-
- // Check exact cardinality
- const SordNode* card = sord_get(
- model, restriction, uris->owl_cardinality, NULL, NULL);
- if (card) {
- const unsigned c = atoi((const char*)sord_node_get_string(card));
- if (values != c) {
- st = errorf(quad, "Property %s on %s has %u != %u values",
- sord_node_get_string(prop),
- sord_node_get_string(instance),
- values, c);
- }
- }
-
- // Check minimum cardinality
- const SordNode* minCard = sord_get(
- model, restriction, uris->owl_minCardinality, NULL, NULL);
- if (minCard) {
- const unsigned m = atoi((const char*)sord_node_get_string(minCard));
- if (values < m) {
- st = errorf(quad, "Property %s on %s has %u < %u values",
- sord_node_get_string(prop),
- sord_node_get_string(instance),
- values, m);
- }
- }
-
- // Check maximum cardinality
- const SordNode* maxCard = sord_get(
- model, restriction, uris->owl_maxCardinality, NULL, NULL);
- if (maxCard) {
- const unsigned m = atoi((const char*)sord_node_get_string(maxCard));
- if (values < m) {
- st = errorf(quad, "Property %s on %s has %u > %u values",
- sord_node_get_string(prop),
- sord_node_get_string(instance),
- values, m);
- }
- }
-
- // Check someValuesFrom
- SordIter* sf = sord_search(
- model, restriction, uris->owl_someValuesFrom, NULL, NULL);
- if (sf) {
- const SordNode* type = sord_iter_get_node(sf, SORD_OBJECT);
-
- SordIter* v = sord_search(model, instance, prop, NULL, NULL);
- bool found = false;
- for (; !sord_iter_end(v); sord_iter_next(v)) {
- const SordNode* value = sord_iter_get_node(v, SORD_OBJECT);
- if (check_type(model, uris, quad, value, type)) {
- found = true;
- break;
- }
- }
- if (!found) {
- st = errorf(quad, "%s has no <%s> values of type <%s>\n",
- sord_node_get_string(instance),
- sord_node_get_string(prop),
- sord_node_get_string(type));
- }
- sord_iter_free(v);
- }
- sord_iter_free(sf);
-
- return st;
+ const SordNode* instance = quad[SORD_SUBJECT];
+ int st = 0;
+
+ const SordNode* prop =
+ sord_get(model, restriction, uris->owl_onProperty, NULL, NULL);
+ if (!prop) {
+ return 0;
+ }
+
+ const unsigned values = sord_count(model, instance, prop, NULL, NULL);
+
+ // Check exact cardinality
+ const SordNode* card =
+ sord_get(model, restriction, uris->owl_cardinality, NULL, NULL);
+ if (card) {
+ const unsigned c = atoi((const char*)sord_node_get_string(card));
+ if (values != c) {
+ st = errorf(quad,
+ "Property %s on %s has %u != %u values",
+ sord_node_get_string(prop),
+ sord_node_get_string(instance),
+ values,
+ c);
+ }
+ }
+
+ // Check minimum cardinality
+ const SordNode* minCard =
+ sord_get(model, restriction, uris->owl_minCardinality, NULL, NULL);
+ if (minCard) {
+ const unsigned m = atoi((const char*)sord_node_get_string(minCard));
+ if (values < m) {
+ st = errorf(quad,
+ "Property %s on %s has %u < %u values",
+ sord_node_get_string(prop),
+ sord_node_get_string(instance),
+ values,
+ m);
+ }
+ }
+
+ // Check maximum cardinality
+ const SordNode* maxCard =
+ sord_get(model, restriction, uris->owl_maxCardinality, NULL, NULL);
+ if (maxCard) {
+ const unsigned m = atoi((const char*)sord_node_get_string(maxCard));
+ if (values < m) {
+ st = errorf(quad,
+ "Property %s on %s has %u > %u values",
+ sord_node_get_string(prop),
+ sord_node_get_string(instance),
+ values,
+ m);
+ }
+ }
+
+ // Check someValuesFrom
+ SordIter* sf =
+ sord_search(model, restriction, uris->owl_someValuesFrom, NULL, NULL);
+ if (sf) {
+ const SordNode* type = sord_iter_get_node(sf, SORD_OBJECT);
+
+ SordIter* v = sord_search(model, instance, prop, NULL, NULL);
+ bool found = false;
+ for (; !sord_iter_end(v); sord_iter_next(v)) {
+ const SordNode* value = sord_iter_get_node(v, SORD_OBJECT);
+ if (check_type(model, uris, quad, value, type)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ st = errorf(quad,
+ "%s has no <%s> values of type <%s>\n",
+ sord_node_get_string(instance),
+ sord_node_get_string(prop),
+ sord_node_get_string(type));
+ }
+ sord_iter_free(v);
+ }
+ sord_iter_free(sf);
+
+ return st;
}
static int
@@ -642,158 +645,159 @@ check_class_instances(SordModel* model,
const SordNode* restriction,
const SordNode* klass)
{
- // Check immediate instances of this class
- SordIter* i = sord_search(model, NULL, uris->rdf_type, klass, NULL);
- for (; !sord_iter_end(i); sord_iter_next(i)) {
- SordQuad quad;
- sord_iter_get(i, quad);
- check_instance(model, uris, restriction, quad);
- }
- sord_iter_free(i);
-
- // Check instances of all subclasses recursively
- SordIter* s = sord_search(model, NULL, uris->rdfs_subClassOf, klass, NULL);
- for (; !sord_iter_end(s); sord_iter_next(s)) {
- const SordNode* subklass = sord_iter_get_node(s, SORD_SUBJECT);
- check_class_instances(model, uris, restriction, subklass);
- }
- sord_iter_free(s);
-
- return 0;
+ // Check immediate instances of this class
+ SordIter* i = sord_search(model, NULL, uris->rdf_type, klass, NULL);
+ for (; !sord_iter_end(i); sord_iter_next(i)) {
+ SordQuad quad;
+ sord_iter_get(i, quad);
+ check_instance(model, uris, restriction, quad);
+ }
+ sord_iter_free(i);
+
+ // Check instances of all subclasses recursively
+ SordIter* s = sord_search(model, NULL, uris->rdfs_subClassOf, klass, NULL);
+ for (; !sord_iter_end(s); sord_iter_next(s)) {
+ const SordNode* subklass = sord_iter_get_node(s, SORD_SUBJECT);
+ check_class_instances(model, uris, restriction, subklass);
+ }
+ sord_iter_free(s);
+
+ return 0;
}
static int
check_instances(SordModel* model, const URIs* uris)
{
- int st = 0;
- SordIter* r = sord_search(
- model, NULL, uris->rdf_type, uris->owl_Restriction, NULL);
- for (; !sord_iter_end(r); sord_iter_next(r)) {
- const SordNode* restriction = sord_iter_get_node(r, SORD_SUBJECT);
- const SordNode* prop = sord_get(
- model, restriction, uris->owl_onProperty, NULL, NULL);
- if (!prop) {
- continue;
- }
-
- SordIter* c = sord_search(
- model, NULL, uris->rdfs_subClassOf, restriction, NULL);
- for (; !sord_iter_end(c); sord_iter_next(c)) {
- const SordNode* klass = sord_iter_get_node(c, SORD_SUBJECT);
- check_class_instances(model, uris, restriction, klass);
- }
- sord_iter_free(c);
- }
- sord_iter_free(r);
-
- return st;
+ int st = 0;
+ SordIter* r =
+ sord_search(model, NULL, uris->rdf_type, uris->owl_Restriction, NULL);
+ for (; !sord_iter_end(r); sord_iter_next(r)) {
+ const SordNode* restriction = sord_iter_get_node(r, SORD_SUBJECT);
+ const SordNode* prop =
+ sord_get(model, restriction, uris->owl_onProperty, NULL, NULL);
+ if (!prop) {
+ continue;
+ }
+
+ SordIter* c =
+ sord_search(model, NULL, uris->rdfs_subClassOf, restriction, NULL);
+ for (; !sord_iter_end(c); sord_iter_next(c)) {
+ const SordNode* klass = sord_iter_get_node(c, SORD_SUBJECT);
+ check_class_instances(model, uris, restriction, klass);
+ }
+ sord_iter_free(c);
+ }
+ sord_iter_free(r);
+
+ return st;
}
int
main(int argc, char** argv)
{
- if (argc < 2) {
- return print_usage(argv[0], true);
- }
-
- int a = 1;
- for (; a < argc && argv[a][0] == '-'; ++a) {
- if (argv[a][1] == 'l') {
- one_line_errors = true;
- } else if (argv[a][1] == 'v') {
- return print_version();
- } else {
- fprintf(stderr, "%s: Unknown option `%s'\n", argv[0], argv[a]);
- return print_usage(argv[0], true);
- }
- }
-
- SordWorld* world = sord_world_new();
- SordModel* model = sord_new(world, SORD_SPO|SORD_OPS, false);
- SerdEnv* env = serd_env_new(&SERD_NODE_NULL);
- SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
-
- for (; a < argc; ++a) {
- const uint8_t* input = (const uint8_t*)argv[a];
- uint8_t* rel_in_path = serd_file_uri_parse(input, NULL);
- uint8_t* in_path = absolute_path(rel_in_path);
-
- free(rel_in_path);
- if (!in_path) {
- fprintf(stderr, "Skipping file %s\n", input);
- continue;
- }
-
- SerdURI base_uri;
- SerdNode base_uri_node = serd_node_new_file_uri(
- in_path, NULL, &base_uri, true);
-
- serd_env_set_base_uri(env, &base_uri_node);
- const SerdStatus st = serd_reader_read_file(reader, in_path);
- if (st) {
- fprintf(stderr, "error reading %s: %s\n",
- in_path, serd_strerror(st));
- }
-
- serd_node_free(&base_uri_node);
- free(in_path);
- }
- serd_reader_free(reader);
- serd_env_free(env);
+ if (argc < 2) {
+ return print_usage(argv[0], true);
+ }
+
+ int a = 1;
+ for (; a < argc && argv[a][0] == '-'; ++a) {
+ if (argv[a][1] == 'l') {
+ one_line_errors = true;
+ } else if (argv[a][1] == 'v') {
+ return print_version();
+ } else {
+ fprintf(stderr, "%s: Unknown option `%s'\n", argv[0], argv[a]);
+ return print_usage(argv[0], true);
+ }
+ }
+
+ SordWorld* world = sord_world_new();
+ SordModel* model = sord_new(world, SORD_SPO | SORD_OPS, false);
+ SerdEnv* env = serd_env_new(&SERD_NODE_NULL);
+ SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL);
+
+ for (; a < argc; ++a) {
+ const uint8_t* input = (const uint8_t*)argv[a];
+ uint8_t* rel_in_path = serd_file_uri_parse(input, NULL);
+ uint8_t* in_path = absolute_path(rel_in_path);
+
+ free(rel_in_path);
+ if (!in_path) {
+ fprintf(stderr, "Skipping file %s\n", input);
+ continue;
+ }
+
+ SerdURI base_uri;
+ SerdNode base_uri_node =
+ serd_node_new_file_uri(in_path, NULL, &base_uri, true);
+
+ serd_env_set_base_uri(env, &base_uri_node);
+ const SerdStatus st = serd_reader_read_file(reader, in_path);
+ if (st) {
+ fprintf(stderr, "error reading %s: %s\n", in_path, serd_strerror(st));
+ }
+
+ serd_node_free(&base_uri_node);
+ free(in_path);
+ }
+ serd_reader_free(reader);
+ serd_env_free(env);
#define URI(prefix, suffix) \
- uris.prefix##_##suffix = sord_new_uri(world, NS_##prefix #suffix)
-
- URIs uris;
- URI(foaf, Document);
- URI(owl, AnnotationProperty);
- URI(owl, Class);
- URI(owl, DatatypeProperty);
- URI(owl, FunctionalProperty);
- URI(owl, InverseFunctionalProperty);
- URI(owl, ObjectProperty);
- URI(owl, OntologyProperty);
- URI(owl, Restriction);
- URI(owl, Thing);
- URI(owl, cardinality);
- URI(owl, equivalentClass);
- URI(owl, maxCardinality);
- URI(owl, minCardinality);
- URI(owl, onDatatype);
- URI(owl, onProperty);
- URI(owl, someValuesFrom);
- URI(owl, withRestrictions);
- URI(rdf, PlainLiteral);
- URI(rdf, Property);
- URI(rdf, first);
- URI(rdf, rest);
- URI(rdf, type);
- URI(rdfs, Class);
- URI(rdfs, Literal);
- URI(rdfs, Resource);
- URI(rdfs, domain);
- URI(rdfs, label);
- URI(rdfs, range);
- URI(rdfs, subClassOf);
- URI(xsd, anyURI);
- URI(xsd, decimal);
- URI(xsd, double);
- URI(xsd, maxInclusive);
- URI(xsd, minInclusive);
- URI(xsd, pattern);
- URI(xsd, string);
+ uris.prefix##_##suffix = sord_new_uri(world, NS_##prefix #suffix)
+
+ URIs uris;
+ URI(foaf, Document);
+ URI(owl, AnnotationProperty);
+ URI(owl, Class);
+ URI(owl, DatatypeProperty);
+ URI(owl, FunctionalProperty);
+ URI(owl, InverseFunctionalProperty);
+ URI(owl, ObjectProperty);
+ URI(owl, OntologyProperty);
+ URI(owl, Restriction);
+ URI(owl, Thing);
+ URI(owl, cardinality);
+ URI(owl, equivalentClass);
+ URI(owl, maxCardinality);
+ URI(owl, minCardinality);
+ URI(owl, onDatatype);
+ URI(owl, onProperty);
+ URI(owl, someValuesFrom);
+ URI(owl, withRestrictions);
+ URI(rdf, PlainLiteral);
+ URI(rdf, Property);
+ URI(rdf, first);
+ URI(rdf, rest);
+ URI(rdf, type);
+ URI(rdfs, Class);
+ URI(rdfs, Literal);
+ URI(rdfs, Resource);
+ URI(rdfs, domain);
+ URI(rdfs, label);
+ URI(rdfs, range);
+ URI(rdfs, subClassOf);
+ URI(xsd, anyURI);
+ URI(xsd, decimal);
+ URI(xsd, double);
+ URI(xsd, maxInclusive);
+ URI(xsd, minInclusive);
+ URI(xsd, pattern);
+ URI(xsd, string);
#ifndef HAVE_PCRE
- fprintf(stderr, "warning: Built without PCRE, datatypes not checked.\n");
+ fprintf(stderr, "warning: Built without PCRE, datatypes not checked.\n");
#endif
- const int prop_st = check_properties(model, &uris);
- const int inst_st = check_instances(model, &uris);
+ const int prop_st = check_properties(model, &uris);
+ const int inst_st = check_instances(model, &uris);
- printf("Found %d errors among %d files (checked %d restrictions)\n",
- n_errors, argc - 1, n_restrictions);
+ printf("Found %d errors among %d files (checked %d restrictions)\n",
+ n_errors,
+ argc - 1,
+ n_restrictions);
- sord_free(model);
- sord_world_free(world);
- return prop_st || inst_st;
+ sord_free(model);
+ sord_world_free(world);
+ return prop_st || inst_st;
}
diff --git a/src/sordi.c b/src/sordi.c
index 3a68fa7..c038dbb 100644
--- a/src/sordi.c
+++ b/src/sordi.c
@@ -19,7 +19,7 @@
#include "sord_config.h"
#ifdef _WIN32
-# include <windows.h>
+# include <windows.h>
#endif
#include <stdbool.h>
@@ -28,189 +28,189 @@
#include <stdlib.h>
#include <string.h>
-#define SORDI_ERROR(msg) fprintf(stderr, "sordi: " msg)
+#define SORDI_ERROR(msg) fprintf(stderr, "sordi: " msg)
#define SORDI_ERRORF(fmt, ...) fprintf(stderr, "sordi: " fmt, __VA_ARGS__)
typedef struct {
- SerdWriter* writer;
- SerdEnv* env;
- SerdNode base_uri_node;
- SerdURI base_uri;
- SordModel* sord;
+ SerdWriter* writer;
+ SerdEnv* env;
+ SerdNode base_uri_node;
+ SerdURI base_uri;
+ SordModel* sord;
} State;
static int
print_version(void)
{
- printf("sordi " SORD_VERSION " <http://drobilla.net/software/sord>\n");
- printf("Copyright 2011-2016 David Robillard <http://drobilla.net>.\n"
- "License: <http://www.opensource.org/licenses/isc>\n"
- "This is free software; you are free to change and redistribute it."
- "\nThere is NO WARRANTY, to the extent permitted by law.\n");
- return 0;
+ printf("sordi " SORD_VERSION " <http://drobilla.net/software/sord>\n");
+ printf("Copyright 2011-2016 David Robillard <http://drobilla.net>.\n"
+ "License: <http://www.opensource.org/licenses/isc>\n"
+ "This is free software; you are free to change and redistribute it."
+ "\nThere is NO WARRANTY, to the extent permitted by law.\n");
+ return 0;
}
static int
print_usage(const char* name, bool error)
{
- FILE* const os = error ? stderr : stdout;
- fprintf(os, "%s", error ? "\n" : "");
- fprintf(os, "Usage: %s [OPTION]... INPUT [BASE_URI]\n", name);
- fprintf(os, "Load and re-serialise RDF data.\n");
- fprintf(os, "Use - for INPUT to read from standard input.\n\n");
- fprintf(os, " -h Display this help and exit\n");
- fprintf(os, " -i SYNTAX Input syntax (`turtle' or `ntriples')\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;
+ FILE* const os = error ? stderr : stdout;
+ fprintf(os, "%s", error ? "\n" : "");
+ fprintf(os, "Usage: %s [OPTION]... INPUT [BASE_URI]\n", name);
+ fprintf(os, "Load and re-serialise RDF data.\n");
+ fprintf(os, "Use - for INPUT to read from standard input.\n\n");
+ fprintf(os, " -h Display this help and exit\n");
+ fprintf(os, " -i SYNTAX Input syntax (`turtle' or `ntriples')\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;
}
static bool
set_syntax(SerdSyntax* syntax, const char* name)
{
- if (!strcmp(name, "turtle")) {
- *syntax = SERD_TURTLE;
- } else if (!strcmp(name, "ntriples")) {
- *syntax = SERD_NTRIPLES;
- } else {
- SORDI_ERRORF("unknown syntax `%s'\n", name);
- return false;
- }
- return true;
+ if (!strcmp(name, "turtle")) {
+ *syntax = SERD_TURTLE;
+ } else if (!strcmp(name, "ntriples")) {
+ *syntax = SERD_NTRIPLES;
+ } else {
+ SORDI_ERRORF("unknown syntax `%s'\n", name);
+ return false;
+ }
+ return true;
}
int
main(int argc, char** argv)
{
- if (argc < 2) {
- return print_usage(argv[0], true);
- }
-
- FILE* in_fd = NULL;
- SerdSyntax input_syntax = SERD_TURTLE;
- SerdSyntax output_syntax = SERD_NTRIPLES;
- bool from_file = true;
- const uint8_t* in_name = NULL;
- int a = 1;
- for (; a < argc && argv[a][0] == '-'; ++a) {
- if (argv[a][1] == '\0') {
- in_name = (const uint8_t*)"(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 = (const uint8_t*)"(string)";
- from_file = false;
- ++a;
- break;
- } else if (argv[a][1] == 'i') {
- if (++a == argc) {
- SORDI_ERROR("option requires an argument -- 'i'\n\n");
- return print_usage(argv[0], true);
- }
- if (!set_syntax(&input_syntax, argv[a])) {
- return print_usage(argv[0], true);
- }
- } else if (argv[a][1] == 'o') {
- if (++a == argc) {
- SORDI_ERROR("option requires an argument -- 'o'\n\n");
- return print_usage(argv[0], true);
- }
- if (!set_syntax(&output_syntax, argv[a])) {
- return print_usage(argv[0], true);
- }
- } else {
- SORDI_ERRORF("invalid option -- '%s'\n", argv[a] + 1);
- return print_usage(argv[0], true);
- }
- }
-
- if (a == argc) {
- SORDI_ERROR("missing input\n");
- return print_usage(argv[0], true);
- }
-
- uint8_t* input_path = NULL;
- const uint8_t* input = (const uint8_t*)argv[a++];
- if (from_file) {
- in_name = in_name ? in_name : input;
- if (!in_fd) {
- if (!strncmp((const char*)input, "file:", 5)) {
- input_path = serd_file_uri_parse(input, NULL);
- input = input_path;
- }
- if (!input || !(in_fd = fopen((const char*)input, "rb"))) {
- return 1;
- }
- }
- }
-
- SerdURI base_uri = SERD_URI_NULL;
- SerdNode base = SERD_NODE_NULL;
- if (a < argc) { // Base URI given on command line
- base = serd_node_new_uri_from_string(
- (const uint8_t*)argv[a], NULL, &base_uri);
- } else if (from_file && in_fd != stdin) { // Use input file URI
- base = serd_node_new_file_uri(input, NULL, &base_uri, true);
- }
-
- SordWorld* world = sord_world_new();
- SordModel* sord = sord_new(world, SORD_SPO|SORD_OPS, false);
- SerdEnv* env = serd_env_new(&base);
- SerdReader* reader = sord_new_reader(sord, env, input_syntax, NULL);
-
- SerdStatus status = (from_file)
- ? serd_reader_read_file_handle(reader, in_fd, in_name)
- : serd_reader_read_string(reader, input);
-
- serd_reader_free(reader);
-
- FILE* out_fd = stdout;
- SerdEnv* write_env = serd_env_new(&base);
-
- int output_style = SERD_STYLE_RESOLVED;
- if (output_syntax == SERD_NTRIPLES) {
- output_style |= SERD_STYLE_ASCII;
- } else {
- output_style |= SERD_STYLE_CURIED | SERD_STYLE_ABBREVIATED;
- }
-
- SerdWriter* writer = serd_writer_new(
- output_syntax,
- (SerdStyle)output_style,
- write_env, &base_uri, serd_file_sink, stdout);
-
- // Write @prefix directives
- serd_env_foreach(env,
- (SerdPrefixSink)serd_writer_set_prefix,
- writer);
-
- // Write statements
- sord_write(sord, writer, NULL);
-
- serd_writer_finish(writer);
- serd_writer_free(writer);
-
- serd_env_free(env);
- serd_env_free(write_env);
- serd_node_free(&base);
- free(input_path);
-
- sord_free(sord);
- sord_world_free(world);
-
- if (from_file) {
- fclose(in_fd);
- }
-
- if (fclose(out_fd)) {
- perror("sordi: write error");
- status = SERD_ERR_UNKNOWN;
- }
-
- return (status > SERD_FAILURE) ? 1 : 0;
+ if (argc < 2) {
+ return print_usage(argv[0], true);
+ }
+
+ FILE* in_fd = NULL;
+ SerdSyntax input_syntax = SERD_TURTLE;
+ SerdSyntax output_syntax = SERD_NTRIPLES;
+ bool from_file = true;
+ const uint8_t* in_name = NULL;
+ int a = 1;
+ for (; a < argc && argv[a][0] == '-'; ++a) {
+ if (argv[a][1] == '\0') {
+ in_name = (const uint8_t*)"(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 = (const uint8_t*)"(string)";
+ from_file = false;
+ ++a;
+ break;
+ } else if (argv[a][1] == 'i') {
+ if (++a == argc) {
+ SORDI_ERROR("option requires an argument -- 'i'\n\n");
+ return print_usage(argv[0], true);
+ }
+ if (!set_syntax(&input_syntax, argv[a])) {
+ return print_usage(argv[0], true);
+ }
+ } else if (argv[a][1] == 'o') {
+ if (++a == argc) {
+ SORDI_ERROR("option requires an argument -- 'o'\n\n");
+ return print_usage(argv[0], true);
+ }
+ if (!set_syntax(&output_syntax, argv[a])) {
+ return print_usage(argv[0], true);
+ }
+ } else {
+ SORDI_ERRORF("invalid option -- '%s'\n", argv[a] + 1);
+ return print_usage(argv[0], true);
+ }
+ }
+
+ if (a == argc) {
+ SORDI_ERROR("missing input\n");
+ return print_usage(argv[0], true);
+ }
+
+ uint8_t* input_path = NULL;
+ const uint8_t* input = (const uint8_t*)argv[a++];
+ if (from_file) {
+ in_name = in_name ? in_name : input;
+ if (!in_fd) {
+ if (!strncmp((const char*)input, "file:", 5)) {
+ input_path = serd_file_uri_parse(input, NULL);
+ input = input_path;
+ }
+ if (!input || !(in_fd = fopen((const char*)input, "rb"))) {
+ return 1;
+ }
+ }
+ }
+
+ SerdURI base_uri = SERD_URI_NULL;
+ SerdNode base = SERD_NODE_NULL;
+ if (a < argc) { // Base URI given on command line
+ base =
+ serd_node_new_uri_from_string((const uint8_t*)argv[a], NULL, &base_uri);
+ } else if (from_file && in_fd != stdin) { // Use input file URI
+ base = serd_node_new_file_uri(input, NULL, &base_uri, true);
+ }
+
+ SordWorld* world = sord_world_new();
+ SordModel* sord = sord_new(world, SORD_SPO | SORD_OPS, false);
+ SerdEnv* env = serd_env_new(&base);
+ SerdReader* reader = sord_new_reader(sord, env, input_syntax, NULL);
+
+ SerdStatus status = (from_file)
+ ? serd_reader_read_file_handle(reader, in_fd, in_name)
+ : serd_reader_read_string(reader, input);
+
+ serd_reader_free(reader);
+
+ FILE* out_fd = stdout;
+ SerdEnv* write_env = serd_env_new(&base);
+
+ int output_style = SERD_STYLE_RESOLVED;
+ if (output_syntax == SERD_NTRIPLES) {
+ output_style |= SERD_STYLE_ASCII;
+ } else {
+ output_style |= SERD_STYLE_CURIED | SERD_STYLE_ABBREVIATED;
+ }
+
+ SerdWriter* writer = serd_writer_new(output_syntax,
+ (SerdStyle)output_style,
+ write_env,
+ &base_uri,
+ serd_file_sink,
+ stdout);
+
+ // Write @prefix directives
+ serd_env_foreach(env, (SerdPrefixSink)serd_writer_set_prefix, writer);
+
+ // Write statements
+ sord_write(sord, writer, NULL);
+
+ serd_writer_finish(writer);
+ serd_writer_free(writer);
+
+ serd_env_free(env);
+ serd_env_free(write_env);
+ serd_node_free(&base);
+ free(input_path);
+
+ sord_free(sord);
+ sord_world_free(world);
+
+ if (from_file) {
+ fclose(in_fd);
+ }
+
+ if (fclose(out_fd)) {
+ perror("sordi: write error");
+ status = SERD_ERR_UNKNOWN;
+ }
+
+ return (status > SERD_FAILURE) ? 1 : 0;
}
diff --git a/src/sordmm_test.cpp b/src/sordmm_test.cpp
index 8dc1386..3d09b9d 100644
--- a/src/sordmm_test.cpp
+++ b/src/sordmm_test.cpp
@@ -19,7 +19,7 @@
int
main()
{
- Sord::World world;
- Sord::Model model(world, "http://example.org/");
- return 0;
+ Sord::World world;
+ Sord::Model model(world, "http://example.org/");
+ return 0;
}
diff --git a/src/syntax.c b/src/syntax.c
index 1561c1d..6ed868f 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -23,31 +23,29 @@
#include <string.h>
struct SordInserterImpl {
- SordModel* model;
- SerdEnv* env;
+ SordModel* model;
+ SerdEnv* env;
};
SordInserter*
-sord_inserter_new(SordModel* model,
- SerdEnv* env)
+sord_inserter_new(SordModel* model, SerdEnv* env)
{
- SordInserter* inserter = (SordInserter*)malloc(sizeof(SordInserter));
- inserter->model = model;
- inserter->env = env;
- return inserter;
+ SordInserter* inserter = (SordInserter*)malloc(sizeof(SordInserter));
+ inserter->model = model;
+ inserter->env = env;
+ return inserter;
}
void
sord_inserter_free(SordInserter* inserter)
{
- free(inserter);
+ free(inserter);
}
SerdStatus
-sord_inserter_set_base_uri(SordInserter* inserter,
- const SerdNode* uri)
+sord_inserter_set_base_uri(SordInserter* inserter, const SerdNode* uri)
{
- return serd_env_set_base_uri(inserter->env, uri);
+ return serd_env_set_base_uri(inserter->env, uri);
}
SerdStatus
@@ -55,7 +53,7 @@ sord_inserter_set_prefix(SordInserter* inserter,
const SerdNode* name,
const SerdNode* uri)
{
- return serd_env_set_prefix(inserter->env, name, uri);
+ return serd_env_set_prefix(inserter->env, name, uri);
}
SerdStatus
@@ -68,28 +66,28 @@ sord_inserter_write_statement(SordInserter* inserter,
const SerdNode* object_datatype,
const SerdNode* object_lang)
{
- SordWorld* world = sord_get_world(inserter->model);
- SerdEnv* env = inserter->env;
+ SordWorld* world = sord_get_world(inserter->model);
+ SerdEnv* env = inserter->env;
- SordNode* g = sord_node_from_serd_node(world, env, graph, NULL, NULL);
- SordNode* s = sord_node_from_serd_node(world, env, subject, NULL, NULL);
- SordNode* p = sord_node_from_serd_node(world, env, predicate, NULL, NULL);
- SordNode* o = sord_node_from_serd_node(world, env, object,
- object_datatype, object_lang);
+ SordNode* g = sord_node_from_serd_node(world, env, graph, NULL, NULL);
+ SordNode* s = sord_node_from_serd_node(world, env, subject, NULL, NULL);
+ SordNode* p = sord_node_from_serd_node(world, env, predicate, NULL, NULL);
+ SordNode* o =
+ sord_node_from_serd_node(world, env, object, object_datatype, object_lang);
- if (!s || !p || !o) {
- return SERD_ERR_BAD_ARG;
- }
+ if (!s || !p || !o) {
+ return SERD_ERR_BAD_ARG;
+ }
- const SordQuad tup = { s, p, o, g };
- sord_add(inserter->model, tup);
+ const SordQuad tup = {s, p, o, g};
+ sord_add(inserter->model, tup);
- sord_node_free(world, o);
- sord_node_free(world, p);
- sord_node_free(world, s);
- sord_node_free(world, g);
+ sord_node_free(world, o);
+ sord_node_free(world, p);
+ sord_node_free(world, s);
+ sord_node_free(world, g);
- return SERD_SUCCESS;
+ return SERD_SUCCESS;
}
SORD_API
@@ -99,20 +97,22 @@ sord_new_reader(SordModel* model,
SerdSyntax syntax,
SordNode* graph)
{
- SordInserter* inserter = sord_inserter_new(model, env);
-
- SerdReader* reader = serd_reader_new(
- syntax, inserter, (void (*)(void* ptr))sord_inserter_free,
- (SerdBaseSink)sord_inserter_set_base_uri,
- (SerdPrefixSink)sord_inserter_set_prefix,
- (SerdStatementSink)sord_inserter_write_statement,
- NULL);
-
- if (graph) {
- serd_reader_set_default_graph(reader, sord_node_to_serd_node(graph));
- }
-
- return reader;
+ SordInserter* inserter = sord_inserter_new(model, env);
+
+ SerdReader* reader =
+ serd_reader_new(syntax,
+ inserter,
+ (void (*)(void* ptr))sord_inserter_free,
+ (SerdBaseSink)sord_inserter_set_base_uri,
+ (SerdPrefixSink)sord_inserter_set_prefix,
+ (SerdStatementSink)sord_inserter_write_statement,
+ NULL);
+
+ if (graph) {
+ serd_reader_set_default_graph(reader, sord_node_to_serd_node(graph));
+ }
+
+ return reader;
}
static SerdStatus
@@ -121,86 +121,83 @@ write_statement(SordModel* sord,
SordQuad tup,
SerdStatementFlags flags)
{
- const SordNode* s = tup[SORD_SUBJECT];
- const SordNode* p = tup[SORD_PREDICATE];
- const SordNode* o = tup[SORD_OBJECT];
- const SordNode* d = sord_node_get_datatype(o);
- const SerdNode* ss = sord_node_to_serd_node(s);
- const SerdNode* sp = sord_node_to_serd_node(p);
- const SerdNode* so = sord_node_to_serd_node(o);
- const SerdNode* sd = sord_node_to_serd_node(d);
-
- const char* lang_str = sord_node_get_language(o);
- size_t lang_len = lang_str ? strlen(lang_str) : 0;
- SerdNode language = SERD_NODE_NULL;
- if (lang_str) {
- language.type = SERD_LITERAL;
- language.n_bytes = lang_len;
- language.n_chars = lang_len;
- language.buf = (const uint8_t*)lang_str;
- }
-
- // TODO: Subject abbreviation
-
- if (sord_node_is_inline_object(s) && !(flags & SERD_ANON_CONT)) {
- return SERD_SUCCESS;
- }
-
- SerdStatus st = SERD_SUCCESS;
- if (sord_node_is_inline_object(o)) {
- SordQuad sub_pat = { o, 0, 0, 0 };
- SordIter* sub_iter = sord_find(sord, sub_pat);
-
- SerdStatementFlags start_flags = flags
- | ((sub_iter) ? SERD_ANON_O_BEGIN : SERD_EMPTY_O);
-
- st = serd_writer_write_statement(
- writer, start_flags, NULL, ss, sp, so, sd, &language);
-
- if (!st && sub_iter) {
- flags |= SERD_ANON_CONT;
- for (; !st && !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) {
- SordQuad sub_tup;
- sord_iter_get(sub_iter, sub_tup);
- st = write_statement(sord, writer, sub_tup, flags);
- }
- sord_iter_free(sub_iter);
- serd_writer_end_anon(writer, so);
- }
- } else {
- st = serd_writer_write_statement(
- writer, flags, NULL, ss, sp, so, sd, &language);
- }
-
- return st;
+ const SordNode* s = tup[SORD_SUBJECT];
+ const SordNode* p = tup[SORD_PREDICATE];
+ const SordNode* o = tup[SORD_OBJECT];
+ const SordNode* d = sord_node_get_datatype(o);
+ const SerdNode* ss = sord_node_to_serd_node(s);
+ const SerdNode* sp = sord_node_to_serd_node(p);
+ const SerdNode* so = sord_node_to_serd_node(o);
+ const SerdNode* sd = sord_node_to_serd_node(d);
+
+ const char* lang_str = sord_node_get_language(o);
+ size_t lang_len = lang_str ? strlen(lang_str) : 0;
+ SerdNode language = SERD_NODE_NULL;
+ if (lang_str) {
+ language.type = SERD_LITERAL;
+ language.n_bytes = lang_len;
+ language.n_chars = lang_len;
+ language.buf = (const uint8_t*)lang_str;
+ }
+
+ // TODO: Subject abbreviation
+
+ if (sord_node_is_inline_object(s) && !(flags & SERD_ANON_CONT)) {
+ return SERD_SUCCESS;
+ }
+
+ SerdStatus st = SERD_SUCCESS;
+ if (sord_node_is_inline_object(o)) {
+ SordQuad sub_pat = {o, 0, 0, 0};
+ SordIter* sub_iter = sord_find(sord, sub_pat);
+
+ SerdStatementFlags start_flags =
+ flags | ((sub_iter) ? SERD_ANON_O_BEGIN : SERD_EMPTY_O);
+
+ st = serd_writer_write_statement(
+ writer, start_flags, NULL, ss, sp, so, sd, &language);
+
+ if (!st && sub_iter) {
+ flags |= SERD_ANON_CONT;
+ for (; !st && !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) {
+ SordQuad sub_tup;
+ sord_iter_get(sub_iter, sub_tup);
+ st = write_statement(sord, writer, sub_tup, flags);
+ }
+ sord_iter_free(sub_iter);
+ serd_writer_end_anon(writer, so);
+ }
+ } else {
+ st = serd_writer_write_statement(
+ writer, flags, NULL, ss, sp, so, sd, &language);
+ }
+
+ return st;
}
bool
-sord_write(SordModel* model,
- SerdWriter* writer,
- SordNode* graph)
+sord_write(SordModel* model, SerdWriter* writer, SordNode* graph)
{
- SordQuad pat = { 0, 0, 0, graph };
- SordIter* iter = sord_find(model, pat);
- return sord_write_iter(iter, writer);
+ SordQuad pat = {0, 0, 0, graph};
+ SordIter* iter = sord_find(model, pat);
+ return sord_write_iter(iter, writer);
}
bool
-sord_write_iter(SordIter* iter,
- SerdWriter* writer)
+sord_write_iter(SordIter* iter, SerdWriter* writer)
{
- if (!iter) {
- return false;
- }
-
- SordModel* model = (SordModel*)sord_iter_get_model(iter);
- SerdStatus st = SERD_SUCCESS;
- for (; !st && !sord_iter_end(iter); sord_iter_next(iter)) {
- SordQuad tup;
- sord_iter_get(iter, tup);
- st = write_statement(model, writer, tup, 0);
- }
- sord_iter_free(iter);
-
- return !st;
+ if (!iter) {
+ return false;
+ }
+
+ SordModel* model = (SordModel*)sord_iter_get_model(iter);
+ SerdStatus st = SERD_SUCCESS;
+ for (; !st && !sord_iter_end(iter); sord_iter_next(iter)) {
+ SordQuad tup;
+ sord_iter_get(iter, tup);
+ st = write_statement(model, writer, tup, 0);
+ }
+ sord_iter_free(iter);
+
+ return !st;
}