summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2011-03-07 17:54:31 +0000
committerDavid Robillard <d@drobilla.net>2011-03-07 17:54:31 +0000
commit8298adea47c3ac90ad43e92387404a7d9381f638 (patch)
treeb506808bb234321b1accc7d84435e8553ff918f0
parentaf05f9f74e39baa6669b7e5799479a63e4f218aa (diff)
downloadsord-8298adea47c3ac90ad43e92387404a7d9381f638.tar.gz
sord-8298adea47c3ac90ad43e92387404a7d9381f638.tar.bz2
sord-8298adea47c3ac90ad43e92387404a7d9381f638.zip
Fix literal comparison and memory leaks.
git-svn-id: http://svn.drobilla.net/sord/trunk@47 3d64ff67-21c5-427c-a301-fe4f08042e5a
-rw-r--r--sord/sord.h2
-rw-r--r--src/sord.c109
-rw-r--r--src/sord_test.c8
3 files changed, 74 insertions, 45 deletions
diff --git a/sord/sord.h b/sord/sord.h
index c2c69a4..e68f86d 100644
--- a/sord/sord.h
+++ b/sord/sord.h
@@ -204,7 +204,7 @@ sord_node_copy(SordNode node);
*/
SORD_API
void
-sord_node_free(SordNode node);
+sord_node_free(SordWorld world, SordNode node);
/**
Return the type of a node (SORD_URI, SORD_BLANK, or SORD_LITERAL).
diff --git a/src/sord.c b/src/sord.c
index 94c4bde..f375711 100644
--- a/src/sord.c
+++ b/src/sord.c
@@ -158,9 +158,10 @@ sord_literal_equal(const void* a, const void* b)
{
SordNode a_node = (SordNode)a;
SordNode b_node = (SordNode)b;
- // FIXME: type, lang
return g_str_equal(sord_node_get_string(a_node),
- sord_node_get_string(b_node));
+ sord_node_get_string(b_node))
+ && (a_node->lang == b_node->lang)
+ && sord_node_equals(a_node->datatype, b_node->datatype);
}
SordWorld
@@ -184,17 +185,31 @@ sord_world_free(SordWorld world)
static inline int
sord_node_compare(const SordNode a, const SordNode b)
{
- if (a->type != b->type)
+ if (!a || !b) {
+ return a - b;
+ } else if (a->type != b->type) {
return a->type - b->type;
+ }
+ int cmp;
switch ((SordNodeType)a->type) {
case SORD_URI:
case SORD_BLANK:
return strcmp((const char*)a->buf, (const char*)b->buf);
case SORD_LITERAL:
- // TODO: lang, type
- return strcmp((const char*)sord_node_get_string(a),
- (const char*)sord_node_get_string(b));
+ cmp = strcmp((const char*)sord_node_get_string(a),
+ (const char*)sord_node_get_string(b));
+ if (cmp == 0) {
+ cmp = sord_node_compare(a->datatype, b->datatype);
+ }
+ if (cmp == 0) {
+ if (!a->lang || !b->lang) {
+ cmp = a->lang - b->lang;
+ } else {
+ cmp = strcmp(a->lang, b->lang);
+ }
+ }
+ return cmp;
}
assert(false);
return 0;
@@ -203,8 +218,12 @@ sord_node_compare(const SordNode a, const SordNode b)
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;
+ if (!a || !b) {
+ return (a == b);
+ } else {
+ // FIXME: nodes are interned, this can be much faster
+ return (a == b) || (sord_node_compare(a, b) == 0);
+ }
}
/** Compare two IDs (dereferencing if necessary).
@@ -580,32 +599,9 @@ sord_add_quad_ref(SordModel sord, const SordNode node)
}
static void
-sord_drop_node(SordModel sord, SordNode node)
-{
- SordWorld world = sord_get_world(sord);
- if (node->type == SORD_LITERAL) {
- if (!g_hash_table_remove(world->literals, node)) {
- fprintf(stderr, "Failed to remove literal from hash, leak!\n");
- return;
- }
- } else {
- if (!g_hash_table_remove(world->names, node->buf)) {
- fprintf(stderr, "Failed to remove resource from hash, leak!\n");
- return;
- }
- }
- free(node->buf);
- free(node);
-}
-
-static void
-sord_drop_quad_ref(SordModel sord, const SordNode node)
+sord_drop_quad_ref(SordModel sord, SordNode node)
{
- if (node) {
- if (--node->refs == 0) {
- sord_drop_node(sord, node);
- }
- }
+ sord_node_free(sord_get_world(sord), node);
}
void
@@ -773,12 +769,12 @@ static SordNode
sord_new_node(SordNodeType type, const uint8_t* data, size_t n_bytes)
{
SordNode node = malloc(sizeof(struct _SordNode));
- node->type = type;
- node->n_bytes = n_bytes;
- node->refs = 0;
- node->datatype = 0;
- node->lang = 0;
- node->buf = (uint8_t*)g_strdup((const char*)data); // TODO: no-copy
+ node->type = type;
+ node->n_bytes = n_bytes;
+ node->refs = 0;
+ node->datatype = 0;
+ node->lang = 0;
+ node->buf = (uint8_t*)g_strdup((const char*)data); // TODO: no-copy
return node;
}
@@ -798,10 +794,16 @@ sord_lookup_literal(SordWorld world, SordNode type,
const uint8_t* str, int str_len,
const char* lang, uint8_t lang_len)
{
- // FIXME: double alloc, ick
- SordNode node = sord_new_literal_node(type, str, str_len, lang, lang_len);
- SordNode id = g_hash_table_lookup(world->literals, node);
- free(node);
+ // Make search key (FIXME: ick)
+ struct _SordNode key;
+ key.type = SORD_LITERAL;
+ key.n_bytes = str_len;
+ key.refs = 0;
+ key.datatype = type;
+ key.lang = lang ? g_intern_string(lang) : NULL;
+ key.buf = (uint8_t*)str;
+
+ SordNode id = g_hash_table_lookup(world->literals, &key);
if (id) {
return id;
} else {
@@ -913,8 +915,27 @@ sord_new_literal(SordWorld world, SordNode type,
}
void
-sord_node_free(SordNode node)
+sord_node_free(SordWorld world, SordNode node)
{
+ if (!node) {
+ return;
+ }
+
+ if (node->refs == 0 || (--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;
+ }
+ } else {
+ if (!g_hash_table_remove(world->names, node->buf)) {
+ fprintf(stderr, "Failed to remove resource from hash.\n");
+ return;
+ }
+ }
+ free(node->buf);
+ free(node);
+ }
}
SordNode
diff --git a/src/sord_test.c b/src/sord_test.c
index fa2b952..840b1e7 100644
--- a/src/sord_test.c
+++ b/src/sord_test.c
@@ -317,6 +317,12 @@ main(int argc, char** argv)
goto fail;
}
+ sord_node_free(world, uri_id);
+ sord_node_free(world, blank_id);
+ sord_node_free(world, lit_id);
+ sord_node_free(world, uri_id3);
+ sord_node_free(world, blank_id3);
+ sord_node_free(world, lit_id3);
sord_free(sord);
static const char* const index_names[6] = {
@@ -338,6 +344,8 @@ main(int argc, char** argv)
sord_free(sord);
+ sord_world_free(world);
+
return EXIT_SUCCESS;
fail: