diff options
-rw-r--r-- | include/serd/node.h | 13 | ||||
-rw-r--r-- | src/node.c | 27 | ||||
-rw-r--r-- | src/node.h | 6 | ||||
-rw-r--r-- | test/test_node.c | 60 |
4 files changed, 106 insertions, 0 deletions
diff --git a/include/serd/node.h b/include/serd/node.h index 50108f57..95638c68 100644 --- a/include/serd/node.h +++ b/include/serd/node.h @@ -410,6 +410,19 @@ serd_node_equals(const SerdNode* SERD_NULLABLE a, const SerdNode* SERD_NULLABLE b); /** + Compare two nodes. + + Returns less than, equal to, or greater than zero if `a` is less than, equal + to, or greater than `b`, respectively. + + Nodes are ordered first by type, then by string, then by language or + datatype, if present. +*/ +SERD_PURE_API int +serd_node_compare(const SerdNode* SERD_NONNULL a, + const SerdNode* SERD_NONNULL b); + +/** @} @} */ @@ -458,6 +458,33 @@ serd_node_equals(const SerdNode* const a, const SerdNode* const b) return true; } +int +serd_node_compare(const SerdNode* const a, const SerdNode* const b) +{ + assert(a); + assert(b); + + int cmp = 0; + + if ((cmp = ((int)a->type - (int)b->type)) || + (cmp = strcmp(serd_node_string_i(a), serd_node_string_i(b))) || + (cmp = ((int)a->flags - (int)b->flags)) || + !(a->flags & (SERD_HAS_LANGUAGE | SERD_HAS_DATATYPE))) { + return cmp; + } + + assert(a->flags == b->flags); + assert(a->flags & (SERD_HAS_LANGUAGE | SERD_HAS_DATATYPE)); + assert(b->flags & (SERD_HAS_LANGUAGE | SERD_HAS_DATATYPE)); + const SerdNode* const ma = serd_node_meta_c(a); + const SerdNode* const mb = serd_node_meta_c(b); + + assert(ma->type == mb->type); + assert(ma->flags == mb->flags); + + return strcmp(serd_node_string_i(ma), serd_node_string_i(mb)); +} + SerdNode* serd_new_uri(const SerdStringView string) { @@ -33,6 +33,12 @@ serd_node_buffer_c(const SerdNode* SERD_NONNULL node) return (const char*)(node + 1); } +static inline const char* SERD_NONNULL +serd_node_string_i(const SerdNode* const SERD_NONNULL node) +{ + return (const char*)(node + 1); +} + SerdNode* SERD_ALLOCATED serd_node_malloc(size_t length, SerdNodeFlags flags, SerdNodeType type); diff --git a/test/test_node.c b/test/test_node.c index ab0ceca8..3db0a46f 100644 --- a/test/test_node.c +++ b/test/test_node.c @@ -531,6 +531,65 @@ test_blank(void) serd_node_free(blank); } +static void +test_compare(void) +{ + SerdNode* xsd_short = + serd_new_uri(serd_string("http://www.w3.org/2001/XMLSchema#short")); + + SerdNode* angst = + serd_new_plain_literal(serd_string("angst"), serd_empty_string()); + + SerdNode* angst_de = + serd_new_plain_literal(serd_string("angst"), serd_string("de")); + + SerdNode* angst_en = + serd_new_plain_literal(serd_string("angst"), serd_string("en")); + + SerdNode* hallo = + serd_new_plain_literal(serd_string("Hallo"), serd_string("de")); + + SerdNode* hello = serd_new_string(serd_string("Hello")); + SerdNode* universe = serd_new_string(serd_string("Universe")); + SerdNode* integer = serd_new_integer(4, NULL); + SerdNode* short_int = serd_new_integer(4, xsd_short); + SerdNode* blank = serd_new_blank(serd_string("b1")); + SerdNode* uri = serd_new_uri(serd_string("http://example.org/")); + + SerdNode* aardvark = serd_new_typed_literal( + serd_string("alex"), serd_string("http://example.org/Aardvark")); + + SerdNode* badger = serd_new_typed_literal( + serd_string("bobby"), serd_string("http://example.org/Badger")); + + // Types are ordered according to their SerdNodeType (more or less arbitrary) + assert(serd_node_compare(hello, uri) < 0); + assert(serd_node_compare(uri, blank) < 0); + + // If the types are the same, then strings are compared + assert(serd_node_compare(hello, universe) < 0); + + // If literal strings are the same, languages or datatypes are compared + assert(serd_node_compare(angst, angst_de) < 0); + assert(serd_node_compare(angst_de, angst_en) < 0); + assert(serd_node_compare(integer, short_int) < 0); + assert(serd_node_compare(aardvark, badger) < 0); + + serd_node_free(uri); + serd_node_free(blank); + serd_node_free(short_int); + serd_node_free(integer); + serd_node_free(badger); + serd_node_free(aardvark); + serd_node_free(universe); + serd_node_free(hello); + serd_node_free(hallo); + serd_node_free(angst_en); + serd_node_free(angst_de); + serd_node_free(angst); + serd_node_free(xsd_short); +} + int main(void) { @@ -550,6 +609,7 @@ main(void) test_node_from_substring(); test_literal(); test_blank(); + test_compare(); printf("Success\n"); return 0; |