aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2018-10-28 14:15:28 +0100
committerDavid Robillard <d@drobilla.net>2023-12-02 18:49:08 -0500
commitc8594c69b612005c7507ad00f7274ca7791197d7 (patch)
tree74a33b550deb1a953a6a9d53872c626878194206
parente750f4b6734d086e433e3c9c05b2252f43f4be8f (diff)
downloadserd-c8594c69b612005c7507ad00f7274ca7791197d7.tar.gz
serd-c8594c69b612005c7507ad00f7274ca7791197d7.tar.bz2
serd-c8594c69b612005c7507ad00f7274ca7791197d7.zip
Cache commonly used nodes in the world
-rw-r--r--include/serd/world.h11
-rw-r--r--src/world.c37
-rw-r--r--src/world.h24
-rw-r--r--src/writer.c22
-rw-r--r--test/test_writer.c3
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"
@@ -68,6 +69,16 @@ 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.
The returned node is valid only until the next time serd_world_get_blank()
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 <assert.h>
@@ -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 <stdbool.h>
#include <stdint.h>
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);
}