summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-02-03 04:43:37 +0000
committerDavid Robillard <d@drobilla.net>2011-02-03 04:43:37 +0000
commit5bc02bf31c689fe4a3758c8b484d220d4de33992 (patch)
treea9a425b59562908e09aa4cc202677115dabda860
parentc548e35abaf65266f2d806e375cb8e38adf705c4 (diff)
downloadsord-5bc02bf31c689fe4a3758c8b484d220d4de33992.tar.gz
sord-5bc02bf31c689fe4a3758c8b484d220d4de33992.tar.bz2
sord-5bc02bf31c689fe4a3758c8b484d220d4de33992.zip
Add SordTupleIndex enumeration for more readable Tuple code.
Add sord_node_equals. Add sord_read_file_handle and add graph URI parameter to sord_read_file. Resolve relative URIs when parsing into a model. Read literal datatype or language when parsing into a model. Bettern debug printing. Add GOPS index by default. Add export_indluces to library in wscript for building against sord locally. git-svn-id: http://svn.drobilla.net/sord/trunk@15 3d64ff67-21c5-427c-a301-fe4f08042e5a
-rw-r--r--sord/sord.h21
-rw-r--r--src/sord.c40
-rw-r--r--src/sord_internal.h34
-rw-r--r--src/sordi.c2
-rw-r--r--src/syntax.c74
-rw-r--r--wscript26
6 files changed, 149 insertions, 48 deletions
diff --git a/sord/sord.h b/sord/sord.h
index 4720e76..5b05587 100644
--- a/sord/sord.h
+++ b/sord/sord.h
@@ -64,6 +64,13 @@ typedef int SordCount; ///< Count of nodes or triples
*/
typedef SordID SordTuple[4];
+typedef enum {
+ SORD_SUBJECT = 0,
+ SORD_PREDICATE = 1,
+ SORD_OBJECT = 2,
+ SORD_GRAPH = 3
+} SordTupleIndex;
+
/** Type of a node */
typedef enum {
SORD_URI = 1, ///< URI
@@ -231,6 +238,9 @@ SORD_API
SordNode
sord_literal_get_datatype(SordNode node);
+SORD_API
+bool
+sord_node_equals(const SordNode a, const SordNode b);
/** @} */
/** @name Read Operations
@@ -348,7 +358,16 @@ sord_tuple_match(const SordTuple x, const SordTuple y);
SORD_API
bool
-sord_read_file(Sord sord, const uint8_t* uri);
+sord_read_file(Sord sord,
+ const uint8_t* uri,
+ const SordNode graph);
+
+SORD_API
+bool
+sord_read_file_handle(Sord sord,
+ FILE* fd,
+ const uint8_t* base_uri,
+ const SordNode graph);
/** @} */
diff --git a/src/sord.c b/src/sord.c
index 7f050e2..15d535a 100644
--- a/src/sord.c
+++ b/src/sord.c
@@ -37,7 +37,7 @@
#include <glib.h>
#include "sord-config.h"
-#include "sord/sord.h"
+#include "sord_internal.h"
#define SORD_LOG(prefix, ...) fprintf(stderr, "[Sord::" prefix "] " __VA_ARGS__)
@@ -63,8 +63,13 @@
#define DEFAULT_ORDER SPO
#define DEFAULT_GRAPH_ORDER GSPO
-#define TUP_FMT "(%d %d %d %d)"
-#define TUP_FMT_ARGS(t) ((t)[0]), ((t)[1]), ((t)[2]), ((t)[3])
+#define TUP_FMT "(%s %s %s %s)"
+#define TUP_FMT_ELEM(e) ((e) ? sord_node_get_string(e) : "*")
+#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_S 0
#define TUP_P 1
@@ -139,17 +144,6 @@ struct _SordIter {
bool skip_graphs; ///< True iff iteration should ignore graphs
};
-/** Node */
-struct _SordNode {
- SordNodeType type; ///< SordNodeType
- size_t n_bytes; ///< Length of data in bytes (including terminator)
- SordCount refs; ///< Reference count (i.e. number of containing tuples)
- void* user_data; ///< Opaque user data
- SordNode datatype; ///< Literal data type (ID of a URI node, or 0)
- const char* lang; ///< Literal language (interned string)
- char* buf; ///< Value (string)
-};
-
static unsigned
sord_literal_hash(const void* n)
{
@@ -168,7 +162,7 @@ sord_literal_equal(const void* a, const void* b)
}
static inline int
-sord_node_compare(Sord sord, const SordNode a, const SordNode b)
+sord_node_compare(const SordNode a, const SordNode b)
{
if (a->type != b->type)
return a->type - b->type;
@@ -185,6 +179,13 @@ sord_node_compare(Sord sord, const SordNode a, const SordNode b)
return 0;
}
+bool
+sord_node_equals(const SordNode a, const SordNode b)
+{
+ // FIXME: nodes are interned, this can be much faster
+ return sord_node_compare(a, b) == 0;
+}
+
/** Compare two IDs (dereferencing if necessary).
* The null ID, 0, is treated as a minimum (it is less than every other
* possible ID, except itself). This allows it to be used as a wildcard
@@ -200,7 +201,7 @@ sord_id_compare(Sord sord, const SordID a, const SordID b)
} else {
SordNode a_node = sord_node_load(sord, a);
SordNode b_node = sord_node_load(sord, b);
- const int ret = sord_node_compare(sord, a_node, b_node);
+ const int ret = sord_node_compare(a_node, b_node);
return ret;
}
}
@@ -601,8 +602,9 @@ sord_open(Sord sord)
// Use default indexing, avoids O(n) in all cases
sord->indices[SPO] = g_sequence_new(NULL);
sord->indices[OPS] = g_sequence_new(NULL);
- sord->indices[PSO] = g_sequence_new(NULL);
+ //sord->indices[PSO] = g_sequence_new(NULL);
sord->indices[GSPO] = g_sequence_new(NULL); // XXX: default? do on demand?
+ sord->indices[GOPS] = g_sequence_new(NULL); // XXX: default? do on demand?
}
if (!sord->indices[DEFAULT_ORDER])
@@ -734,6 +736,10 @@ sord_find(Sord sord, const SordTuple pat)
SordTuple search_key = { a, b, c, d };
GSequence* const db = sord->indices[index_order];
GSequenceIter* const cur = index_lower_bound(sord, db, search_key);
+ if (g_sequence_iter_is_end(cur)) {
+ SORD_FIND_LOG("No match found\n");
+ return NULL;
+ }
const SordID* const key = (const SordID*)g_sequence_get(cur);
if (!key || ( (mode == RANGE || mode == SINGLE)
&& !sord_tuple_match_inline(search_key, key) )) {
diff --git a/src/sord_internal.h b/src/sord_internal.h
new file mode 100644
index 0000000..b7a3398
--- /dev/null
+++ b/src/sord_internal.h
@@ -0,0 +1,34 @@
+/* Sord, a lightweight RDF model library.
+ * Copyright 2010-2011 David Robillard <d@drobilla.net>
+ *
+ * Sord is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Sord is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SORD_INTERNAL_H
+#define SORD_INTERNAL_H
+
+#include "sord/sord.h"
+
+/** Node */
+struct _SordNode {
+ SordNodeType type; ///< SordNodeType
+ size_t n_bytes; ///< Length of data in bytes (including terminator)
+ SordCount refs; ///< Reference count (i.e. number of containing tuples)
+ void* user_data; ///< Opaque user data
+ SordNode datatype; ///< Literal data type (ID of a URI node, or 0)
+ const char* lang; ///< Literal language (interned string)
+ char* buf; ///< Value (string)
+};
+
+#endif // SORD_INTERNAL_H
diff --git a/src/sordi.c b/src/sordi.c
index 6260879..ac05a2a 100644
--- a/src/sordi.c
+++ b/src/sordi.c
@@ -121,7 +121,7 @@ main(int argc, char** argv)
Sord sord = sord_new();
sord_open(sord);
- bool success = sord_read_file(sord, input);
+ bool success = sord_read_file(sord, input, NULL);
printf("loaded %u statements\n", sord_num_nodes(sord));
diff --git a/src/syntax.c b/src/syntax.c
index b18052a..4a6567d 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -18,14 +18,17 @@
#include <stdlib.h>
#include <string.h>
+#include <glib.h>
+
#include "serd/serd.h"
#include "sord-config.h"
-#include "sord/sord.h"
+#include "sord_internal.h"
typedef struct {
SerdReader reader;
SerdEnv env;
+ SordNode graph_uri_node;
SerdNode base_uri_node;
SerdURI base_uri;
Sord sord;
@@ -99,13 +102,24 @@ sord_node_from_serd_node(ReadState* state, const SerdNode* sn)
case SERD_LITERAL:
return sord_get_literal(state->sord, true, NULL,
(const char*)sn->buf, NULL);
- case SERD_URI:
- return sord_get_uri_counted(state->sord, true,
- (const char*)sn->buf, sn->n_chars);
+ case SERD_URI: {
+ SerdURI uri;
+ if (!serd_uri_parse(sn->buf, &uri)) {
+ return NULL;
+ }
+ SerdURI abs_uri;
+ if (!serd_uri_resolve(&uri, &state->base_uri, &abs_uri)) {
+ return false;
+ }
+ SerdURI ignored;
+ SerdNode abs_uri_node = serd_node_new_uri(&abs_uri, &ignored);
+ return sord_get_uri(state->sord, true, (const char*)abs_uri_node.buf);
+ }
case SERD_CURIE: {
SerdChunk uri_prefix;
SerdChunk uri_suffix;
if (!serd_env_expand(state->env, sn, &uri_prefix, &uri_suffix)) {
+ fprintf(stderr, "ERROR: failed to expand qname `%s'\n", sn->buf);
return NULL;
}
const size_t uri_len = uri_prefix.len + uri_suffix.len;
@@ -138,11 +152,25 @@ event_statement(void* handle,
SordTuple tup;
tup[0] = sord_node_from_serd_node(state, subject);
tup[1] = sord_node_from_serd_node(state, predicate);
- tup[2] = sord_node_from_serd_node(state, object);
- tup[3] = (graph && graph->buf)
- ? sord_node_from_serd_node(state, graph)
- : NULL;
-
+
+ SordNode object_node = sord_node_from_serd_node(state, object);
+
+ if (object_datatype) {
+ object_node->datatype = sord_node_from_serd_node(state, object_datatype);
+ }
+ if (object_lang) {
+ object_node->lang = g_intern_string((const char*)object_lang->buf);
+ }
+ tup[2] = object_node;
+
+ if (state->graph_uri_node) {
+ tup[3] = state->graph_uri_node;
+ } else {
+ tup[3] = (graph && graph->buf)
+ ? sord_node_from_serd_node(state, graph)
+ : NULL;
+ }
+
sord_add(state->sord, tup);
return true;
@@ -150,7 +178,9 @@ event_statement(void* handle,
SORD_API
bool
-sord_read_file(Sord sord, const uint8_t* input)
+sord_read_file(Sord sord,
+ const uint8_t* input,
+ const SordNode graph)
{
const uint8_t* filename = NULL;
if (serd_uri_string_has_scheme(input)) {
@@ -167,14 +197,27 @@ sord_read_file(Sord sord, const uint8_t* input)
filename = input;
}
- FILE* in_fd = fopen((const char*)input, "r");
+ FILE* in_fd = fopen((const char*)filename, "r");
if (!in_fd) {
- fprintf(stderr, "failed to open file %s\n", input);
+ fprintf(stderr, "failed to open file %s\n", filename);
return 1;
}
+ const bool success = sord_read_file_handle(sord, in_fd, input, graph);
+
+ fclose(in_fd);
+ return success;
+}
+
+SORD_API
+bool
+sord_read_file_handle(Sord sord,
+ FILE* fd,
+ const uint8_t* base_uri_str_in,
+ const SordNode graph)
+{
size_t base_uri_n_bytes = 0;
- uint8_t* base_uri_str = copy_string(input, &base_uri_n_bytes);
+ uint8_t* base_uri_str = copy_string(base_uri_str_in, &base_uri_n_bytes);
SerdURI base_uri;
if (!serd_uri_parse(base_uri_str, &base_uri)) {
fprintf(stderr, "invalid base URI `%s'\n", base_uri_str);
@@ -187,18 +230,17 @@ sord_read_file(Sord sord, const uint8_t* input)
base_uri_n_bytes - 1, // FIXME: UTF-8
base_uri_str };
- ReadState state = { NULL, env, base_uri_node, base_uri, sord };
+ ReadState state = { NULL, env, graph, base_uri_node, base_uri, sord };
state.reader = serd_reader_new(
SERD_TURTLE, &state,
event_base, event_prefix, event_statement, NULL);
- const bool success = serd_reader_read_file(state.reader, in_fd, input);
+ const bool success = serd_reader_read_file(state.reader, fd, base_uri_str);
serd_reader_free(state.reader);
serd_env_free(state.env);
serd_node_free(&state.base_uri_node);
- fclose(in_fd);
return success;
}
diff --git a/wscript b/wscript
index 828176f..89da079 100644
--- a/wscript
+++ b/wscript
@@ -41,7 +41,7 @@ def configure(conf):
atleast_version='0.1.0', mandatory=False)
conf.env['BUILD_TESTS'] = Options.options.build_tests
- conf.env['BUILD_UTILS'] = conf.env['HAVE_SERD'] != 0
+ conf.env['BUILD_UTILS'] = True
dump = Options.options.dump.split(',')
all = 'all' in dump
@@ -69,15 +69,16 @@ def build(bld):
# Library
obj = bld(features = 'c cshlib')
- obj.source = 'src/sord.c src/syntax.c'
- obj.includes = ['.', './src']
- obj.name = 'libsord'
- obj.target = 'sord'
- obj.vnum = SORD_LIB_VERSION
- obj.install_path = '${LIBDIR}'
- obj.cflags = [ '-fvisibility=hidden', '-DSORD_SHARED', '-DSORD_INTERNAL' ]
- obj.libs = [ 'm' ]
- autowaf.use_lib(bld, obj, 'GLIB')
+ obj.source = 'src/sord.c src/syntax.c'
+ obj.includes = ['.', './src']
+ obj.export_includes = ['.']
+ obj.name = 'libsord'
+ obj.target = 'sord'
+ obj.vnum = SORD_LIB_VERSION
+ obj.install_path = '${LIBDIR}'
+ obj.cflags = [ '-fvisibility=hidden', '-DSORD_SHARED', '-DSORD_INTERNAL' ]
+ obj.libs = [ 'm' ]
+ autowaf.use_lib(bld, obj, 'GLIB SERD')
if bld.env['BUILD_TESTS']:
# Static library (for unit test code coverage)
@@ -89,7 +90,7 @@ def build(bld):
obj.install_path = ''
obj.cflags = [ '-fprofile-arcs', '-ftest-coverage' ]
obj.libs = [ 'm' ]
- autowaf.use_lib(bld, obj, 'GLIB')
+ autowaf.use_lib(bld, obj, 'GLIB SERD')
# Unit test program
obj = bld(features = 'c cprogram')
@@ -100,7 +101,7 @@ def build(bld):
obj.target = 'sord_test'
obj.install_path = ''
obj.cflags = [ '-fprofile-arcs', '-ftest-coverage' ]
- autowaf.use_lib(bld, obj, 'GLIB')
+ autowaf.use_lib(bld, obj, 'GLIB SERD')
# Unit test programa
if bld.env['BUILD_UTILS']:
@@ -112,7 +113,6 @@ def build(bld):
obj.target = 'sordi_static'
obj.install_path = ''
obj.cflags = [ '-fprofile-arcs', '-ftest-coverage' ]
- autowaf.use_lib(bld, obj, 'SERD')
# Documentation
autowaf.build_dox(bld, 'SORD', SORD_VERSION, top, out)