diff options
-rw-r--r-- | sord/sord.h | 11 | ||||
-rw-r--r-- | src/sord.c | 86 | ||||
-rw-r--r-- | src/sord_internal.h | 15 | ||||
-rw-r--r-- | src/sordi.c | 28 |
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. @@ -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); |