From c8594c69b612005c7507ad00f7274ca7791197d7 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 28 Oct 2018 14:15:28 +0100 Subject: Cache commonly used nodes in the world --- include/serd/world.h | 11 +++++++++++ src/world.c | 37 ++++++++++++++++++++++++++++++++++++- src/world.h | 24 +++++++++++++++--------- src/writer.c | 22 ++++++++++------------ test/test_writer.c | 3 +-- 5 files changed, 73 insertions(+), 24 deletions(-) diff --git a/include/serd/world.h b/include/serd/world.h index dc2b3b83..fb0930aa 100644 --- a/include/serd/world.h +++ b/include/serd/world.h @@ -7,6 +7,7 @@ #include "serd/attributes.h" #include "serd/memory.h" #include "serd/node.h" +#include "serd/nodes.h" #include "serd/status.h" #include "zix/attributes.h" @@ -67,6 +68,16 @@ serd_world_limits(const SerdWorld* ZIX_NONNULL world); SERD_API SerdStatus serd_world_set_limits(SerdWorld* ZIX_NONNULL world, SerdLimits limits); +/** + Return the nodes cache in `world`. + + The returned cache is owned by the world and contains various nodes used + frequently by the implementation. For convenience, it may be used to store + additional nodes which will be freed when the world is freed. +*/ +SERD_PURE_API SerdNodes* ZIX_NONNULL +serd_world_nodes(SerdWorld* ZIX_NONNULL world); + /** Return a unique blank node. diff --git a/src/world.c b/src/world.c index 406956b1..c4787aba 100644 --- a/src/world.c +++ b/src/world.c @@ -5,10 +5,12 @@ #include "log.h" #include "memory.h" +#include "namespaces.h" #include "node.h" #include "serd/node.h" #include "serd/status.h" +#include "serd/string_view.h" #include "serd/world.h" #include @@ -25,19 +27,44 @@ serd_world_new(SerdAllocator* const allocator) SerdNode* blank_node = serd_node_new(actual, serd_a_blank_string("b00000000000")); - if (!world || !blank_node) { + SerdNodes* const nodes = serd_nodes_new(actual); + + if (!world || !blank_node || !nodes) { + serd_nodes_free(nodes); serd_node_free(actual, blank_node); serd_afree(actual, world); return NULL; } + const SerdStringView rdf_first = serd_string(NS_RDF "first"); + const SerdStringView rdf_nil = serd_string(NS_RDF "nil"); + const SerdStringView rdf_rest = serd_string(NS_RDF "rest"); + const SerdStringView rdf_type = serd_string(NS_RDF "type"); + const SerdStringView xsd_boolean = serd_string(NS_XSD "boolean"); + const SerdStringView xsd_decimal = serd_string(NS_XSD "decimal"); + const SerdStringView xsd_integer = serd_string(NS_XSD "integer"); + world->limits.reader_stack_size = 1048576U; world->limits.writer_max_depth = 128U; world->allocator = actual; + world->nodes = nodes; world->blank_node = blank_node; serd_log_init(&world->log); + if (!(world->rdf_first = serd_nodes_get(nodes, serd_a_uri(rdf_first))) || + !(world->rdf_nil = serd_nodes_get(nodes, serd_a_uri(rdf_nil))) || + !(world->rdf_rest = serd_nodes_get(nodes, serd_a_uri(rdf_rest))) || + !(world->rdf_type = serd_nodes_get(nodes, serd_a_uri(rdf_type))) || + !(world->xsd_boolean = serd_nodes_get(nodes, serd_a_uri(xsd_boolean))) || + !(world->xsd_decimal = serd_nodes_get(nodes, serd_a_uri(xsd_decimal))) || + !(world->xsd_integer = serd_nodes_get(nodes, serd_a_uri(xsd_integer)))) { + serd_nodes_free(nodes); + serd_node_free(actual, blank_node); + serd_afree(actual, world); + return NULL; + } + return world; } @@ -46,6 +73,7 @@ serd_world_free(SerdWorld* const world) { if (world) { serd_node_free(world->allocator, world->blank_node); + serd_nodes_free(world->nodes); serd_afree(world->allocator, world); } } @@ -90,3 +118,10 @@ serd_world_allocator(const SerdWorld* const world) assert(world->allocator); return world->allocator; } + +SerdNodes* +serd_world_nodes(SerdWorld* const world) +{ + assert(world); + return world->nodes; +} diff --git a/src/world.h b/src/world.h index f615868a..0888b480 100644 --- a/src/world.h +++ b/src/world.h @@ -8,20 +8,26 @@ #include "serd/memory.h" #include "serd/node.h" +#include "serd/nodes.h" #include "serd/world.h" -#include #include struct SerdWorldImpl { - SerdAllocator* allocator; - SerdLog log; - SerdLimits limits; - uint32_t next_blank_id; - uint32_t next_document_id; - SerdNode* blank_node; - - bool stderr_color; + SerdAllocator* allocator; + SerdLog log; + SerdLimits limits; + SerdNodes* nodes; + const SerdNode* rdf_first; + const SerdNode* rdf_nil; + const SerdNode* rdf_rest; + const SerdNode* rdf_type; + const SerdNode* xsd_boolean; + const SerdNode* xsd_decimal; + const SerdNode* xsd_integer; + SerdNode* blank_node; + uint32_t next_blank_id; + uint32_t next_document_id; }; #endif // SERD_SRC_WORLD_H diff --git a/src/writer.c b/src/writer.c index 7afeb1c4..88c544d4 100644 --- a/src/writer.c +++ b/src/writer.c @@ -4,7 +4,6 @@ #include "block_dumper.h" #include "env.h" #include "memory.h" -#include "namespaces.h" #include "node.h" #include "sink.h" #include "string_utils.h" @@ -758,14 +757,12 @@ write_literal(SerdWriter* const writer, const char* const type_uri = datatype ? serd_node_string(datatype) : NULL; if (supports_abbrev(writer) && type_uri) { - if (!strncmp(type_uri, NS_XSD, sizeof(NS_XSD) - 1) && - (!strcmp(type_uri + sizeof(NS_XSD) - 1, "boolean") || - !strcmp(type_uri + sizeof(NS_XSD) - 1, "integer"))) { + if (serd_node_equals(datatype, writer->world->xsd_boolean) || + serd_node_equals(datatype, writer->world->xsd_integer)) { return esink(node_str, node->length, writer); } - if (!strncmp(type_uri, NS_XSD, sizeof(NS_XSD) - 1) && - !strcmp(type_uri + sizeof(NS_XSD) - 1, "decimal") && + if (serd_node_equals(datatype, writer->world->xsd_decimal) && strchr(node_str, '.') && node_str[node->length - 1] != '.') { /* xsd:decimal literals without trailing digits, e.g. "5.", can not be written bare in Turtle. We could add a 0 which is @@ -842,11 +839,12 @@ write_uri_node(SerdWriter* const writer, const bool has_scheme = serd_uri_string_has_scheme(string.data); if (supports_abbrev(writer)) { - if (field == SERD_PREDICATE && !strcmp(string.data, NS_RDF "type")) { + if (field == SERD_PREDICATE && + serd_node_equals(node, writer->world->rdf_type)) { return esink("a", 1, writer); } - if (!strcmp(string.data, NS_RDF "nil")) { + if (serd_node_equals(node, writer->world->rdf_nil)) { return esink("()", 2, writer); } @@ -972,12 +970,12 @@ write_list_next(SerdWriter* const writer, { SerdStatus st = SERD_SUCCESS; - if (!strcmp(serd_node_string(object), NS_RDF "nil")) { + if (serd_node_equals(object, writer->world->rdf_nil)) { TRY(st, write_sep(writer, writer->context.flags, SEP_LIST_END)); return SERD_FAILURE; } - if (!strcmp(serd_node_string(predicate), NS_RDF "first")) { + if (serd_node_equals(predicate, writer->world->rdf_first)) { TRY(st, write_node(writer, object, SERD_OBJECT, flags)); } else { TRY(st, write_sep(writer, writer->context.flags, SEP_LIST_SEP)); @@ -1084,8 +1082,8 @@ write_list_statement(SerdWriter* const writer, { SerdStatus st = SERD_SUCCESS; - if (!strcmp(serd_node_string(predicate), NS_RDF "first") && - !strcmp(serd_node_string(object), NS_RDF "nil")) { + if (serd_node_equals(predicate, writer->world->rdf_first) && + serd_node_equals(object, writer->world->rdf_nil)) { return esink("()", 2, writer); } diff --git a/test/test_writer.c b/test/test_writer.c index 8b0d31c6..7e72ec5c 100644 --- a/test/test_writer.c +++ b/test/test_writer.c @@ -75,7 +75,7 @@ test_write_failed_alloc(void) SerdFailingAllocator allocator = serd_failing_allocator(); SerdWorld* world = serd_world_new(&allocator.base); - SerdNodes* nodes = serd_nodes_new(&allocator.base); + SerdNodes* nodes = serd_world_nodes(world); SerdEnv* env = serd_env_new(NULL, serd_empty_string()); SerdBuffer buffer = {&allocator.base, NULL, 0}; SerdOutputStream output = serd_open_output_buffer(&buffer); @@ -128,7 +128,6 @@ test_write_failed_alloc(void) serd_buffer_close(&buffer); serd_free(NULL, buffer.buf); - serd_nodes_free(nodes); serd_world_free(world); } -- cgit v1.2.1