summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sord/sord.h11
-rw-r--r--src/sord.c86
-rw-r--r--src/sord_internal.h15
-rw-r--r--src/sordi.c28
4 files changed, 101 insertions, 39 deletions
diff --git a/sord/sord.h b/sord/sord.h
index 8174f55..29e4299 100644
--- a/sord/sord.h
+++ b/sord/sord.h
@@ -272,6 +272,17 @@ SerdNodeFlags
sord_node_get_flags(const SordNode* node);
/**
+ Return true iff node can be serialised as an inline object.
+
+ More specifically, this returns true iff the node is the object field
+ of exactly one statement, and therefore can be inlined since it needn't
+ be referred to by name.
+*/
+SORD_API
+bool
+sord_node_is_inline_object(const SordNode* node);
+
+/**
Return true iff @c a is equal to @c b.
Note this is much faster than comparing the node's strings.
diff --git a/src/sord.c b/src/sord.c
index ad7c791..397f1bc 100644
--- a/src/sord.c
+++ b/src/sord.c
@@ -588,18 +588,52 @@ sord_new(SordWorld* world, unsigned indices, bool graphs)
}
static void
-sord_add_quad_ref(SordModel* sord, const SordNode* node)
+sord_node_free_internal(SordWorld* world, SordNode* node)
+{
+ assert(node->refs == 0);
+ if (node->type == SORD_LITERAL) {
+ if (!g_hash_table_remove(world->literals, node)) {
+ fprintf(stderr, "Failed to remove literal from hash.\n");
+ return;
+ }
+ sord_node_free(world, node->datatype);
+ } else {
+ if (!g_hash_table_remove(world->names, node->buf)) {
+ fprintf(stderr, "Failed to remove resource from hash.\n");
+ return;
+ }
+ }
+ g_free(node->buf);
+ free(node);
+}
+
+static void
+sord_add_quad_ref(SordModel* sord, const SordNode* node, SordQuadIndex i)
{
if (node) {
assert(node->refs > 0);
++((SordNode*)node)->refs;
+ if (i == SORD_OBJECT) {
+ ++((SordNode*)node)->refs_as_obj;
+ }
}
}
static void
-sord_drop_quad_ref(SordModel* sord, const SordNode* node)
+sord_drop_quad_ref(SordModel* sord, const SordNode* node, SordQuadIndex i)
{
- sord_node_free(sord_get_world(sord), (SordNode*)node);
+ if (!node) {
+ return;
+ }
+
+ assert(node->refs > 0);
+ if (i == SORD_OBJECT) {
+ assert(node->refs_as_obj > 0);
+ --((SordNode*)node)->refs_as_obj;
+ }
+ if (--((SordNode*)node)->refs == 0) {
+ sord_node_free_internal(sord_get_world(sord), (SordNode*)node);
+ }
}
void
@@ -614,7 +648,7 @@ sord_free(SordModel* sord)
for (; !sord_iter_end(i); sord_iter_next(i)) {
sord_iter_get(i, tup);
for (int i = 0; i < TUP_LEN; ++i) {
- sord_drop_quad_ref(sord, (SordNode*)tup[i]);
+ sord_drop_quad_ref(sord, (SordNode*)tup[i], i);
}
}
sord_iter_free(i);
@@ -767,13 +801,14 @@ sord_new_node(SordNodeType type, const uint8_t* data,
size_t n_bytes, SerdNodeFlags flags)
{
SordNode* node = malloc(sizeof(struct SordNodeImpl));
- node->type = type;
- node->n_bytes = n_bytes;
- node->refs = 1;
- node->datatype = 0;
- node->lang = 0;
- node->flags = flags;
- node->buf = (uint8_t*)g_strdup((const char*)data); // TODO: no-copy
+ node->type = type;
+ node->n_bytes = n_bytes;
+ node->refs = 1;
+ node->refs_as_obj = 0;
+ node->datatype = 0;
+ node->lang = 0;
+ node->flags = flags;
+ node->buf = (uint8_t*)g_strdup((const char*)data); // TODO: no-copy
return node;
}
@@ -863,6 +898,12 @@ sord_node_get_flags(const SordNode* node)
return node->flags;
}
+bool
+sord_node_is_inline_object(const SordNode* node)
+{
+ return (node->type == SORD_BLANK) && (node->refs_as_obj == 1);
+}
+
static void
sord_add_node(SordWorld* world, SordNode* node)
{
@@ -951,20 +992,7 @@ sord_node_free(SordWorld* world, SordNode* node)
assert(node->refs > 0);
if (--node->refs == 0) {
- if (node->type == SORD_LITERAL) {
- if (!g_hash_table_remove(world->literals, node)) {
- fprintf(stderr, "Failed to remove literal from hash.\n");
- return;
- }
- sord_node_free(world, node->datatype);
- } else {
- if (!g_hash_table_remove(world->names, node->buf)) {
- fprintf(stderr, "Failed to remove resource from hash.\n");
- return;
- }
- }
- g_free(node->buf);
- free(node);
+ sord_node_free_internal(world, node);
}
}
@@ -1019,8 +1047,8 @@ sord_add(SordModel* sord, const SordQuad tup)
}
}
- for (int i = 0; i < TUP_LEN; ++i)
- sord_add_quad_ref(sord, tup[i]);
+ for (SordQuadIndex i = 0; i < TUP_LEN; ++i)
+ sord_add_quad_ref(sord, tup[i], i);
++sord->n_quads;
assert(sord->n_quads == (size_t)g_sequence_get_length(sord->indices[SPO]));
@@ -1048,8 +1076,8 @@ sord_remove(SordModel* sord, const SordQuad tup)
}
}
- for (int i = 0; i < TUP_LEN; ++i)
- sord_drop_quad_ref(sord, tup[i]);
+ for (SordQuadIndex i = 0; i < TUP_LEN; ++i)
+ sord_drop_quad_ref(sord, tup[i], i);
--sord->n_quads;
}
diff --git a/src/sord_internal.h b/src/sord_internal.h
index 6935de8..6a5daf8 100644
--- a/src/sord_internal.h
+++ b/src/sord_internal.h
@@ -24,13 +24,14 @@
/** Node */
struct SordNodeImpl {
- uint8_t* buf; ///< Value (string)
- const char* lang; ///< Literal language (interned string)
- SordNode* datatype; ///< Literal data type (ID of a URI node, or 0)
- size_t n_bytes; ///< Length of data in bytes (including NULL)
- size_t refs; ///< Reference count (# of containing quads)
- SerdNodeFlags flags; ///< String properties
- SordNodeType type; ///< SordNodeType
+ uint8_t* buf; ///< Value (string)
+ const char* lang; ///< Literal language (interned string)
+ SordNode* datatype; ///< Literal data type (ID of a URI node, or 0)
+ size_t n_bytes; ///< Length of data in bytes (including NULL)
+ size_t refs; ///< Reference count (# of containing quads)
+ size_t refs_as_obj; ///< References as a quad object
+ SerdNodeFlags flags; ///< String properties
+ SordNodeType type; ///< SordNodeType
};
const char*
diff --git a/src/sordi.c b/src/sordi.c
index 235c67a..5410beb 100644
--- a/src/sordi.c
+++ b/src/sordi.c
@@ -124,7 +124,7 @@ main(int argc, char** argv)
bool success = sord_read_file(sord, env, input, NULL, NULL);
- printf("Loaded %zu statements\n", sord_num_nodes(world));
+ fprintf(stderr, "Loaded %zu statements\n", sord_num_nodes(world));
SerdURI base_uri;
if (serd_uri_parse(input, &base_uri)) {
@@ -156,9 +156,31 @@ main(int argc, char** argv)
SerdNode ss = serd_node_from_sord_node(s);
SerdNode sp = serd_node_from_sord_node(p);
SerdNode so = serd_node_from_sord_node(o);
- serd_writer_write_statement(
- writer, NULL, &ss, &sp, &so, NULL, NULL);
+ if (sord_node_is_inline_object(o)) {
+ so.type = SERD_ANON_BEGIN;
+ serd_writer_write_statement(
+ writer, NULL, &ss, &sp, &so, NULL, NULL);
+ so.type = SERD_ANON;
+ SordQuad sub_pat = { o, 0, 0, 0 };
+ SordIter* sub_iter = sord_find(sord, sub_pat);
+ for (; !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) {
+ SordQuad sub_tup;
+ sord_iter_get(sub_iter, sub_tup);
+ const SordNode* sub_p = sub_tup[SORD_PREDICATE];
+ const SordNode* sub_o = sub_tup[SORD_OBJECT];
+ SerdNode sub_sp = serd_node_from_sord_node(sub_p);
+ SerdNode sub_so = serd_node_from_sord_node(sub_o);
+ serd_writer_write_statement(
+ writer, NULL, &so, &sub_sp, &sub_so, NULL, NULL);
+ }
+ sord_iter_free(sub_iter);
+ serd_writer_end_anon(writer, &so);
+ } else if (!sord_node_is_inline_object(s)) {
+ serd_writer_write_statement(
+ writer, NULL, &ss, &sp, &so, NULL, NULL);
+ }
}
+ sord_iter_free(iter);
serd_writer_finish(writer);
serd_writer_free(writer);