summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-11-11 21:03:53 +0100
committerDavid Robillard <d@drobilla.net>2020-11-11 21:03:53 +0100
commit5e3efed788f4b184ed02d147588ff53c20c244f5 (patch)
tree4d95d39e9d7a9412ab067f83bcac179faf53f353 /src
parent701a598c2f214dc0fe93cdd1b341200ded954880 (diff)
downloadsord-5e3efed788f4b184ed02d147588ff53c20c244f5.tar.gz
sord-5e3efed788f4b184ed02d147588ff53c20c244f5.tar.bz2
sord-5e3efed788f4b184ed02d147588ff53c20c244f5.zip
Fix flaky literal comparison
Diffstat (limited to 'src')
-rw-r--r--src/sord.c51
1 files changed, 37 insertions, 14 deletions
diff --git a/src/sord.c b/src/sord.c
index 958a6db..5a759c0 100644
--- a/src/sord.c
+++ b/src/sord.c
@@ -232,6 +232,42 @@ sord_world_set_error_sink(SordWorld* world,
world->error_handle = handle;
}
+static inline int
+sord_node_compare_literal(const SordNode* a, const SordNode* b)
+{
+ const int cmp = strcmp((const char*)sord_node_get_string(a),
+ (const char*)sord_node_get_string(b));
+ if (cmp != 0) {
+ return cmp;
+ }
+
+ const bool a_has_lang = a->meta.lit.lang[0];
+ const bool b_has_lang = b->meta.lit.lang[0];
+ const bool a_has_datatype = a->meta.lit.datatype;
+ const bool b_has_datatype = b->meta.lit.datatype;
+ const bool a_has_meta = a_has_lang || a_has_datatype;
+ const bool b_has_meta = b_has_lang || b_has_datatype;
+
+ assert(!(a_has_lang && a_has_datatype));
+ assert(!(b_has_lang && b_has_datatype));
+
+ if (!a_has_meta && !b_has_meta) {
+ return 0;
+ } else if (!a_has_meta || (a_has_lang && b_has_datatype)) {
+ return -1;
+ } else if (!b_has_meta || (a_has_datatype && b_has_lang)) {
+ return 1;
+ } else if (a_has_lang) {
+ assert(b_has_lang);
+ return strcmp(a->meta.lit.lang, b->meta.lit.lang);
+ }
+
+ assert(a_has_datatype);
+ assert(b_has_datatype);
+ return strcmp((const char*)a->meta.lit.datatype->node.buf,
+ (const char*)b->meta.lit.datatype->node.buf);
+}
+
/** Compare nodes, considering NULL a wildcard match. */
static inline int
sord_node_compare(const SordNode* a, const SordNode* b)
@@ -248,20 +284,7 @@ sord_node_compare(const SordNode* a, const SordNode* b)
case SERD_BLANK:
return strcmp((const char*)a->node.buf, (const char*)b->node.buf);
case SERD_LITERAL:
- cmp = strcmp((const char*)sord_node_get_string(a),
- (const char*)sord_node_get_string(b));
- if (cmp == 0) {
- // Note: Can't use sord_node_compare here since it does wildcards
- if (!a->meta.lit.datatype || !b->meta.lit.datatype) {
- cmp = (a->meta.lit.datatype < b->meta.lit.datatype) ? -1 : 1;
- } else {
- cmp = strcmp((const char*)a->meta.lit.datatype->node.buf,
- (const char*)b->meta.lit.datatype->node.buf);
- }
- }
- if (cmp == 0) {
- cmp = strcmp(a->meta.lit.lang, b->meta.lit.lang);
- }
+ cmp = sord_node_compare_literal(a, b);
break;
default:
break;