From 3bf35cb9e72709fb417cff0d5a2dc9b681e5ecb1 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 6 Oct 2019 20:59:12 +0200 Subject: Add serd_new_float() and serd_new_double() --- NEWS | 1 + include/serd/serd.h | 32 +++++++++++++++++++++++++++++++- meson.build | 1 + src/node.c | 26 ++++++++++++++++++++++++++ src/static_nodes.h | 2 ++ src/string.c | 2 ++ 6 files changed, 63 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d900e544..2b792055 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ serd (1.0.1) unstable; * Add SerdBuffer for mutable buffers to keep SerdChunk const-correct + * Add support for xsd:float and xsd:double literals * Bring read/write interface closer to C standard * Make nodes opaque * Remove serd_uri_to_path() diff --git a/include/serd/serd.h b/include/serd/serd.h index fdae8ac7..e1a28fdf 100644 --- a/include/serd/serd.h +++ b/include/serd/serd.h @@ -627,7 +627,37 @@ SerdNode* SERD_ALLOCATED serd_new_decimal(double d, const SerdNode* SERD_NULLABLE datatype); /** - Create a new node by serialising `i` into an xsd:integer string. + Create a new node by serialising `d` into a normalised xsd:double string. + + The returned node will always be in normalised scientific notation, like + "1.23E4", except for NaN and negative/positive infinity, which are "NaN", + "-INF", and "INF", respectively. + + Uses the shortest possible representation that precisely describes `d`, + which has at most 17 significant digits (under 24 characters total). + + @param d Double value to serialise. + @return A literal node with datatype xsd:double. +*/ +SERD_API +SerdNode* SERD_ALLOCATED +serd_new_double(double d); + +/** + Create a new node by serialising `f` into a normalised xsd:float string. + + Uses identical formatting to serd_new_double(), except with at most 9 + significant digits (under 14 characters total). + + @param f Float value to serialise. + @return A literal node with datatype xsd:float. +*/ +SERD_API +SerdNode* SERD_ALLOCATED +serd_new_float(float f); + +/** + Create a new node by serialising `i` into an xsd:integer string @param i Integer value to serialise. @param datatype Datatype of node, or NULL for xsd:integer. diff --git a/meson.build b/meson.build index 98ae0d5e..4dd4b6e5 100644 --- a/meson.build +++ b/meson.build @@ -33,6 +33,7 @@ if get_option('strict') '-Wno-covered-switch-default', '-Wno-disabled-macro-expansion', '-Wno-double-promotion', + '-Wno-float-equal', '-Wno-format-nonliteral', '-Wno-implicit-fallthrough', '-Wno-nullability-extension', diff --git a/src/node.c b/src/node.c index 0d6eb19a..db183fc0 100644 --- a/src/node.c +++ b/src/node.c @@ -507,6 +507,32 @@ serd_new_custom_literal(const void* const user_data, return node; } +SerdNode* +serd_new_double(const double d) +{ + char buf[EXESS_MAX_DOUBLE_LENGTH + 1] = {0}; + + const ExessResult r = exess_write_double(d, sizeof(buf), buf); + + return r.status + ? NULL + : serd_new_typed_literal(SERD_STRING_VIEW(buf, r.count), + SERD_STATIC_STRING(EXESS_XSD_URI "double")); +} + +SerdNode* +serd_new_float(const float f) +{ + char buf[EXESS_MAX_FLOAT_LENGTH + 1] = {0}; + + const ExessResult r = exess_write_float(f, sizeof(buf), buf); + + return r.status + ? NULL + : serd_new_typed_literal(SERD_STRING_VIEW(buf, r.count), + SERD_STATIC_STRING(EXESS_XSD_URI "float")); +} + static size_t write_variant_literal(const void* const user_data, const size_t buf_size, diff --git a/src/static_nodes.h b/src/static_nodes.h index 952c0634..adbb5849 100644 --- a/src/static_nodes.h +++ b/src/static_nodes.h @@ -34,6 +34,8 @@ typedef struct StaticNode { DEFINE_XSD_NODE(base64Binary) DEFINE_XSD_NODE(boolean) DEFINE_XSD_NODE(decimal) +DEFINE_XSD_NODE(double) +DEFINE_XSD_NODE(float) DEFINE_XSD_NODE(integer) #endif // SERD_STATIC_NODES_H diff --git a/src/string.c b/src/string.c index 00b1e91a..6e28778b 100644 --- a/src/string.c +++ b/src/string.c @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include -- cgit v1.2.1