aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2023-05-05 09:43:57 -0400
committerDavid Robillard <d@drobilla.net>2023-12-02 18:49:08 -0500
commit4711fdf527f416faee8ff19e15f050d4b48dcfb2 (patch)
tree6b18712ec44cce5713ddef1a21aec5f12651d901
parent248a874d7425749d29cf900a1c3783c624ea8d8c (diff)
downloadserd-4711fdf527f416faee8ff19e15f050d4b48dcfb2.tar.gz
serd-4711fdf527f416faee8ff19e15f050d4b48dcfb2.tar.bz2
serd-4711fdf527f416faee8ff19e15f050d4b48dcfb2.zip
[WIP] Generalize node construction API
-rw-r--r--.clang-tidy1
-rw-r--r--doc/conf.py.in5
-rw-r--r--include/serd/node.h432
-rw-r--r--include/serd/serd.h1
-rw-r--r--include/serd/string.h18
-rw-r--r--include/serd/value.h118
-rw-r--r--meson.build2
-rw-r--r--src/base64.c27
-rw-r--r--src/base64.h35
-rw-r--r--src/byte_source.c3
-rw-r--r--src/env.c37
-rw-r--r--src/node.c967
-rw-r--r--src/node.h66
-rw-r--r--src/read_turtle.c2
-rw-r--r--src/value.c101
-rw-r--r--src/world.c4
-rw-r--r--src/writer.c7
-rw-r--r--test/test_caret.c12
-rw-r--r--test/test_env.c16
-rw-r--r--test/test_log.c3
-rw-r--r--test/test_node.c608
-rw-r--r--test/test_overflow.c2
-rw-r--r--test/test_reader.c2
-rw-r--r--test/test_reader_writer.c23
-rw-r--r--test/test_sink.c9
-rw-r--r--test/test_statement.c27
-rw-r--r--test/test_terse_write.c20
-rw-r--r--test/test_uri.c35
-rw-r--r--test/test_writer.c71
-rw-r--r--tools/console.c4
-rw-r--r--tools/serd-pipe.c7
31 files changed, 1741 insertions, 924 deletions
diff --git a/.clang-tidy b/.clang-tidy
index a283cc08..ba762f8a 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -5,7 +5,6 @@ Checks: >
*,
-altera-*,
-bugprone-assignment-in-if-condition,
- -bugprone-suspicious-realloc-usage,
-clang-diagnostic-unused-macros,
-llvmlibc-*,
-modernize-macro-to-enum,
diff --git a/doc/conf.py.in b/doc/conf.py.in
index 51a09d4e..c6e146f2 100644
--- a/doc/conf.py.in
+++ b/doc/conf.py.in
@@ -36,9 +36,14 @@ _opaque = [
"SerdStatementImpl",
"SerdWorldImpl",
"SerdWriterImpl",
+ "int16_t",
+ "int32_t",
"int64_t",
+ "int8_t",
"size_t",
+ "uint16_t",
"uint32_t",
+ "uint64_t",
"uint8_t",
"va_list",
]
diff --git a/include/serd/node.h b/include/serd/node.h
index f42f07f1..d140e4c0 100644
--- a/include/serd/node.h
+++ b/include/serd/node.h
@@ -8,6 +8,7 @@
#include "serd/memory.h"
#include "serd/string_view.h"
#include "serd/uri.h"
+#include "serd/value.h"
#include "serd/write_result.h"
#include "zix/attributes.h"
@@ -107,168 +108,324 @@ typedef uint32_t SerdNodeFlags;
/**
@}
- @defgroup serd_node_dynamic_allocation Dynamic Allocation
- @{
-*/
+ @defgroup serd_node_construction_arguments Arguments
-/**
- Create a new simple "token" node.
+ A unified representation of the arguments needed to specify any node.
+
+ Since there are several types of node, and a node can be constructed in
+ memory in several ways, the API for specifying node arguments is separate
+ from the APIs for actually creating nodes. This prevents a combinatorial
+ API explosion by allowing functions that create or access nodes to have a
+ single parameter that describes the node.
- A "token" is a node that isn't a typed or tagged literal. This can be used
- to create URIs, blank nodes, CURIEs, and simple string literals.
+ Arguments constructors like #serd_a_file_uri return a temporary view of
+ their arguments, which can be passed (usually inline) to node construction
+ functions like #serd_node_new, or #serd_node_construct.
+
+ @{
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_token(SerdAllocator* ZIX_NULLABLE allocator,
- SerdNodeType type,
- SerdStringView string);
-/**
- Create a new string literal node.
+/// The type of a #SerdNodeArgs
+typedef enum {
+ SERD_NODE_ARGS_TOKEN, ///< A token @see #serd_a_token
+ SERD_NODE_ARGS_PARSED_URI, ///< A parsed URI @see #serd_a_parsed_uri
+ SERD_NODE_ARGS_FILE_URI, ///< A file URI @see #serd_a_file_uri
+ SERD_NODE_ARGS_LITERAL, ///< A literal @see #serd_a_literal
+ SERD_NODE_ARGS_PRIMITIVE, ///< A "native" primitive @see #serd_a_primitive
+ SERD_NODE_ARGS_DECIMAL, ///< A decimal number @see #serd_a_decimal
+ SERD_NODE_ARGS_INTEGER, ///< An integer number @see #serd_a_integer
+ SERD_NODE_ARGS_HEX, ///< A hex-encoded blob @see #serd_a_hex
+ SERD_NODE_ARGS_BASE64, ///< A base64-encoded blob @see #serd_a_base64
+} SerdNodeArgsType;
+
+/// The data for #SERD_NODE_ARGS_TOKEN
+typedef struct {
+ SerdNodeType type;
+ SerdStringView string;
+} SerdNodeTokenArgs;
+
+/// The data for #SERD_NODE_ARGS_PARSED_URI
+typedef struct {
+ SerdURIView uri;
+} SerdNodeParsedURIArgs;
+
+/// The data for #SERD_NODE_ARGS_FILE_URI
+typedef struct {
+ SerdStringView path;
+ SerdStringView hostname;
+} SerdNodeFileURIArgs;
+
+/// The data for #SERD_NODE_ARGS_LITERAL
+typedef struct {
+ SerdStringView string;
+ SerdNodeFlags flags;
+ SerdStringView meta;
+} SerdNodeLiteralArgs;
+
+/// The data for #SERD_NODE_ARGS_PRIMITIVE
+typedef struct {
+ SerdValue value;
+} SerdNodePrimitiveArgs;
+
+/// The data for #SERD_NODE_ARGS_DECIMAL
+typedef struct {
+ double value;
+} SerdNodeDecimalArgs;
+
+/// The data for #SERD_NODE_ARGS_INTEGER
+typedef struct {
+ int64_t value;
+} SerdNodeIntegerArgs;
+
+/// The data for #SERD_NODE_ARGS_HEX or #SERD_NODE_ARGS_BASE64
+typedef struct {
+ size_t size;
+ const void* ZIX_NONNULL data;
+} SerdNodeBlobArgs;
+
+/// The data of a #SerdNodeArgs
+typedef union {
+ SerdNodeTokenArgs as_token;
+ SerdNodeParsedURIArgs as_parsed_uri;
+ SerdNodeFileURIArgs as_file_uri;
+ SerdNodeLiteralArgs as_literal;
+ SerdNodePrimitiveArgs as_primitive;
+ SerdNodeDecimalArgs as_decimal;
+ SerdNodeIntegerArgs as_integer;
+ SerdNodeBlobArgs as_blob;
+} SerdNodeArgsData;
+
+/// Arguments for constructing a node
+typedef struct {
+ SerdNodeArgsType type; ///< Type of node described and valid field of `data`
+ SerdNodeArgsData data; ///< Data union
+} SerdNodeArgs;
+
+/**
+ A simple "token" node.
+
+ "Token" is just a shorthand used in this API to refer to a node that is not
+ a typed or tagged literal, that is, a node that is just one string. This
+ can be used to create URIs, blank nodes, variables, and simple string
+ literals.
+
+ Note that string literals constructed with this function will have no flags
+ set, and so will be written as "short" literals (not triple-quoted). To
+ construct long literals, use the more advanced serd_a_literal() with the
+ #SERD_IS_LONG flag.
+*/
+SERD_CONST_API SerdNodeArgs
+serd_a_token(SerdNodeType type, SerdStringView string);
+
+/// A URI node from a parsed URI
+SERD_CONST_API SerdNodeArgs
+serd_a_parsed_uri(SerdURIView uri);
+
+/// A file URI node from a path and optional hostname
+SERD_CONST_API SerdNodeArgs
+serd_a_file_uri(SerdStringView path, SerdStringView hostname);
+
+/**
+ A literal node with an optional datatype or language.
+
+ Either a datatype (which must be an absolute URI) or a language (which must
+ be an RFC5646 language tag) may be given, but not both.
+
+ This is the most general literal constructor, which can be used to construct
+ any literal node.
+
+ @param string The string body of the node.
+
+ @param flags Flags that describe the details of the node.
+
+ @param meta The string value of the literal's metadata. If
+ #SERD_HAS_DATATYPE is set, then this must be an absolute datatype URI. If
+ #SERD_HAS_LANGUAGE is set, then this must be a language tag like "en-ca".
+ Otherwise, it is ignored.
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_string(SerdAllocator* ZIX_NULLABLE allocator, SerdStringView string);
+SERD_CONST_API SerdNodeArgs
+serd_a_literal(SerdStringView string, SerdNodeFlags flags, SerdStringView meta);
-/**
- Create a new literal node with optional datatype or language.
+/// A simple string literal node from a string view
+ZIX_CONST_FUNC static inline SerdNodeArgs
+serd_a_string_view(SerdStringView string)
+{
+ return serd_a_token(SERD_LITERAL, string);
+}
- This can create more complex literals than serd_new_string() with an
- associated datatype URI or language tag, as well as control whether a
- literal should be written as a short or long (triple-quoted) string.
+/// A simple string literal node from a C string
+ZIX_CONST_FUNC static inline SerdNodeArgs
+serd_a_string(const char* ZIX_NONNULL string)
+{
+ return serd_a_string_view(serd_string(string));
+}
- @param allocator Allocator for the returned node.
+/// A blank node from a string view
+ZIX_CONST_FUNC static inline SerdNodeArgs
+serd_a_blank(SerdStringView name)
+{
+ return serd_a_token(SERD_BLANK, name);
+}
- @param string The string value of the literal.
+/// A blank node from a string
+ZIX_CONST_FUNC static inline SerdNodeArgs
+serd_a_blank_string(const char* ZIX_NONNULL name)
+{
+ return serd_a_blank(serd_string(name));
+}
- @param flags Flags to describe the literal and its metadata. This must be a
- valid combination of flags, in particular, at most one of #SERD_HAS_DATATYPE
- and #SERD_HAS_LANGUAGE may be set.
+/// A URI node from a string view
+ZIX_CONST_FUNC static inline SerdNodeArgs
+serd_a_uri(SerdStringView uri)
+{
+ return serd_a_token(SERD_URI, uri);
+}
- @param meta The string value of the literal's metadata. If
- #SERD_HAS_DATATYPE is set, then this must be an absolute datatype URI. If
- #SERD_HAS_LANGUAGE is set, then this must be a language tag like "en-ca".
- Otherwise, it is ignored.
+/**
+ A URI node from a string.
- @return A newly allocated literal node that must be freed with
- serd_node_free(), or null if the arguments are invalid or allocation failed.
+ @param uri The URI string.
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_literal(SerdAllocator* ZIX_NULLABLE allocator,
- SerdStringView string,
- SerdNodeFlags flags,
- SerdStringView meta);
+ZIX_CONST_FUNC static inline SerdNodeArgs
+serd_a_uri_string(const char* ZIX_NONNULL uri)
+{
+ return serd_a_uri(serd_string(uri));
+}
/**
- Create a new node from a blank node label.
+ A literal node with a datatype.
+
+ @param string The string body of the node.
+ @param datatype The absolute URI of the datatype.
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_blank(SerdAllocator* ZIX_NULLABLE allocator, SerdStringView string);
+ZIX_CONST_FUNC static inline SerdNodeArgs
+serd_a_typed_literal(const SerdStringView string, const SerdStringView datatype)
+{
+ return serd_a_literal(string, SERD_HAS_DATATYPE, datatype);
+}
/**
- Create a new URI node from a parsed URI.
+ A literal node with a language.
+
+ @param string The string body of the node.
+ @param language A language tag like "en-ca".
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_parsed_uri(SerdAllocator* ZIX_NULLABLE allocator, SerdURIView uri);
+ZIX_CONST_FUNC static inline SerdNodeArgs
+serd_a_plain_literal(const SerdStringView string, const SerdStringView language)
+{
+ return serd_a_literal(string, SERD_HAS_LANGUAGE, language);
+}
/**
- Create a new URI node from a string.
+ A canonical literal for a primitive value.
+
+ The node will be a typed literal in canonical form for the xsd datatype
+ corresponding to the value.
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_uri(SerdAllocator* ZIX_NULLABLE allocator, SerdStringView string);
+SERD_CONST_API SerdNodeArgs
+serd_a_primitive(SerdValue value);
/**
- Create a new file URI node from a file system path and optional hostname.
+ A canonical xsd:decimal literal.
- Backslashes in Windows paths will be converted, and other characters will be
- percent encoded as necessary.
+ The node will be an xsd:decimal literal, like "12.34", with datatype
+ xsd:decimal.
- If `path` is relative, `hostname` is ignored.
+ The node will always contain a '.', start with a digit, and end with a digit
+ (a leading and/or trailing '0' will be added if necessary), for example,
+ "1.0". It will never be in scientific notation.
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_file_uri(SerdAllocator* ZIX_NULLABLE allocator,
- SerdStringView path,
- SerdStringView hostname);
+SERD_CONST_API SerdNodeArgs
+serd_a_decimal(double value);
/**
- Create a new canonical xsd:boolean node.
+ A canonical xsd:integer literal.
+
+ The node will be an xsd:integer literal like "1234", with datatype
+ xsd:integer.
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_boolean(SerdAllocator* ZIX_NULLABLE allocator, bool b);
+SERD_CONST_API SerdNodeArgs
+serd_a_integer(int64_t value);
/**
- Create a new canonical xsd:decimal literal.
+ A canonical xsd:hexBinary literal.
- The node will be an xsd:decimal literal, like "12.34", with
- datatype xsd:decimal by default, or a custom datatype.
+ The node will be an xsd:hexBinary literal like "534D", with datatype
+ xsd:hexBinary.
+*/
+SERD_CONST_API SerdNodeArgs
+serd_a_hex(size_t size, const void* ZIX_NONNULL data);
- The node will always contain a '.', start with a digit, and end with a digit
- (a leading and/or trailing '0' will be added if necessary), for example,
- "1.0". It will never be in scientific notation.
+/**
+ A canonical xsd:base64Binary literal.
- @param allocator Allocator for the returned node.
- @param d The value for the new node.
- @param datatype Datatype of node, or NULL for xsd:decimal.
+ The node will be an xsd:base64Binary literal like "Zm9vYmFy", with datatype
+ xsd:base64Binary.
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_decimal(SerdAllocator* ZIX_NULLABLE allocator,
- double d,
- const SerdNode* ZIX_NULLABLE datatype);
+SERD_CONST_API SerdNodeArgs
+serd_a_base64(size_t size, const void* ZIX_NONNULL data);
/**
- Create a new canonical xsd:double literal.
+ @}
+ @defgroup serd_node_construction Construction
- The node will be in scientific notation, like "1.23E4", except for NaN and
- negative/positive infinity, which are "NaN", "-INF", and "INF",
- respectively.
+ This is the low-level node construction API, which can be used to construct
+ nodes into existing buffers. Advanced applications can use this to
+ specially manage node memory, for example by allocating nodes on the stack,
+ or with a special allocator.
- Uses the shortest possible representation that precisely describes the
- value, which has at most 17 significant digits (under 24 characters total).
+ Note that nodes are "plain old data", so there is no need to destroy a
+ constructed node, and nodes may be trivially copied, for example with
+ memcpy().
- @param allocator Allocator for the returned node.
- @param d Double value to write.
- @return A literal node with datatype xsd:double.
+ @{
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_double(SerdAllocator* ZIX_NULLABLE allocator, double d);
/**
- Create a new canonical xsd:float literal.
+ Construct a node into an existing buffer.
- Uses identical formatting to serd_new_double(), except with at most 9
- significant digits (under 14 characters total).
+ This is the universal node constructor which can construct any node. The
+ type of node is specified in a #SerdNodeArgs tagged union, to avoid API
+ bloat and allow this function to be used with data-based dispatch.
- @param allocator Allocator for the returned node.
- @param f Float value of literal.
- @return A literal node with datatype xsd:float.
+ This function may also be used to determine the size of buffer required by
+ passing a null buffer with zero size.
+
+ @param buf_size The size of `buf` in bytes, or zero to only measure.
+
+ @param buf Buffer where the node will be written, or null to only measure.
+
+ @param args Arguments describing the node to construct.
+
+ @return A result with a `status` and a `count` of bytes written. If the
+ buffer is too small for the node, then `status` will be #SERD_OVERFLOW, and
+ `count` will be set to the number of bytes required to successfully
+ construct the node.
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_float(SerdAllocator* ZIX_NULLABLE allocator, float f);
+SERD_API SerdWriteResult
+serd_node_construct(size_t buf_size, void* ZIX_NULLABLE buf, SerdNodeArgs args);
/**
- Create a new canonical xsd:integer literal.
+ @}
+ @defgroup serd_node_dynamic_allocation Dynamic Allocation
- The node will be an xsd:integer literal like "1234", with datatype
- xsd:integer.
+ This is a convenient higher-level node construction API which allocates
+ nodes with an allocator. The returned nodes must be freed with
+ serd_node_free() using the same allocator.
- @param allocator Allocator for the returned node.
- @param i Integer value of literal.
+ @{
*/
-SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_integer(SerdAllocator* ZIX_NULLABLE allocator, int64_t i);
/**
- Create a new canonical xsd:base64Binary literal.
+ Create a new node.
- This function can be used to make a node out of arbitrary binary data, which
- can be decoded using serd_base64_decode().
+ This allocates and constructs a new node of any type.
- @param allocator Allocator for the returned node.
- @param buf Raw binary data to encode in node.
- @param size Size of `buf` in bytes.
+ @return A newly allocated node that must be freed with serd_node_free(), or
+ null.
*/
SERD_API SerdNode* ZIX_ALLOCATED
-serd_new_base64(SerdAllocator* ZIX_NULLABLE allocator,
- const void* ZIX_NONNULL buf,
- size_t size);
+serd_node_new(SerdAllocator* ZIX_NULLABLE allocator, SerdNodeArgs args);
/**
Return a deep copy of `node`.
@@ -353,45 +510,37 @@ SERD_PURE_API const SerdNode* ZIX_NULLABLE
serd_node_language(const SerdNode* ZIX_NONNULL node);
/**
- Return the value of `node` as a boolean.
+ Return the primitive value of a literal node.
- This will work for booleans, and numbers of any datatype if they are 0 or
- 1.
+ This will return a typed numeric value if the node can be read as one, or
+ nothing otherwise.
- @return The value of `node` as a `bool`, or `false` on error.
+ @return The primitive value of `node`, if possible and supported.
*/
-SERD_API bool
-serd_get_boolean(const SerdNode* ZIX_NONNULL node);
+SERD_API SerdValue
+serd_node_value(const SerdNode* ZIX_NONNULL node);
/**
- Return the value of `node` as a double.
+ Return the primitive value of a node as a specific type of number.
- This will coerce numbers of any datatype to double, if the value fits.
+ This is like serd_node_value(), but will coerce the value of the node to the
+ requested type if possible.
- @return The value of `node` as a `double`, or NaN on error.
-*/
-SERD_API double
-serd_get_double(const SerdNode* ZIX_NONNULL node);
+ @param node The node to interpret as a number.
-/**
- Return the value of `node` as a float.
+ @param type The desired numeric datatype of the result.
- This will coerce numbers of any datatype to float, if the value fits.
+ @param lossy Whether lossy conversions can be used. If this is false, then
+ this function only succeeds if the value could be converted back to the
+ original datatype of the node without loss. Otherwise, precision may be
+ reduced or values may be truncated to fit the result.
- @return The value of `node` as a `float`, or NaN on error.
+ @return The value of `node` as a #SerdValue, or nothing.
*/
-SERD_API float
-serd_get_float(const SerdNode* ZIX_NONNULL node);
-
-/**
- Return the value of `node` as a long (signed 64-bit integer).
-
- This will coerce numbers of any datatype to long, if the value fits.
-
- @return The value of `node` as a `int64_t`, or 0 on error.
-*/
-SERD_API int64_t
-serd_get_integer(const SerdNode* ZIX_NONNULL node);
+SERD_API SerdValue
+serd_node_value_as(const SerdNode* ZIX_NONNULL node,
+ SerdValueType type,
+ bool lossy);
/**
Return the maximum size of a decoded binary node in bytes.
@@ -400,16 +549,21 @@ serd_get_integer(const SerdNode* ZIX_NONNULL node);
decode to. This is calculated as a simple constant-time arithmetic
expression based on the length of the encoded string, so may be larger than
the actual size of the data due to things like additional whitespace.
+
+ @return The size of the decoded hex or base64 blob `node`, or zero if it
+ does not have datatype <http://www.w3.org/2001/XMLSchema#hexBinary> or
+ <http://www.w3.org/2001/XMLSchema#base64Binary>.
*/
SERD_PURE_API size_t
-serd_get_base64_size(const SerdNode* ZIX_NONNULL node);
+serd_node_decoded_size(const SerdNode* ZIX_NONNULL node);
/**
- Decode a base64 node.
+ Decode a binary (base64 or hex) node.
- This function can be used to decode a node created with serd_new_base64().
+ This function can be used to decode a node created with serd_a_base64() or
+ serd_a_hex() and retrieve the original unencoded binary data.
- @param node A literal node which is an encoded base64 string.
+ @param node A literal node which is an encoded base64 or hex string.
@param buf_size The size of `buf` in bytes.
@@ -420,9 +574,9 @@ serd_get_base64_size(const SerdNode* ZIX_NONNULL node);
along with the number of bytes required for successful decoding.
*/
SERD_API SerdWriteResult
-serd_get_base64(const SerdNode* ZIX_NONNULL node,
- size_t buf_size,
- void* ZIX_NONNULL buf);
+serd_node_decode(const SerdNode* ZIX_NONNULL node,
+ size_t buf_size,
+ void* ZIX_NONNULL buf);
/**
@}
diff --git a/include/serd/serd.h b/include/serd/serd.h
index 6103c543..88be5daa 100644
--- a/include/serd/serd.h
+++ b/include/serd/serd.h
@@ -61,6 +61,7 @@
#include "serd/node.h"
#include "serd/statement.h"
#include "serd/uri.h"
+#include "serd/value.h"
/**
@}
diff --git a/include/serd/string.h b/include/serd/string.h
index 11e55e6e..028a1a29 100644
--- a/include/serd/string.h
+++ b/include/serd/string.h
@@ -18,19 +18,15 @@ SERD_BEGIN_DECLS
*/
/**
- Decode a base64 string.
+ Compare two strings ignoring case.
- This function can be used to decode a node created with serd_new_base64().
-
- @param str Base64 string to decode.
- @param len The length of `str`.
- @param size Set to the size of the returned blob in bytes.
- @return A newly allocated blob which must be freed with serd_free().
+ @return Less than, equal to, or greater than zero if `s1` is less than,
+ equal to, or greater than `s2`, respectively.
*/
-SERD_API void* ZIX_ALLOCATED
-serd_base64_decode(const char* ZIX_NONNULL str,
- size_t len,
- size_t* ZIX_NONNULL size);
+SERD_PURE_API int
+serd_strncasecmp(const char* ZIX_NONNULL s1,
+ const char* ZIX_NONNULL s2,
+ size_t n);
/**
@}
diff --git a/include/serd/value.h b/include/serd/value.h
new file mode 100644
index 00000000..a31268e0
--- /dev/null
+++ b/include/serd/value.h
@@ -0,0 +1,118 @@
+// Copyright 2011-2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#ifndef SERD_VALUE_H
+#define SERD_VALUE_H
+
+#include "serd/attributes.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+SERD_BEGIN_DECLS
+
+/**
+ @defgroup serd_node_value Values
+ @ingroup serd_data
+
+ Serd supports reading and writing machine-native numbers, called "values",
+ in a standards-conformant and portable way. The value structure is used in
+ the API to allow passing and returning a primitive value of any supported
+ type. Note that this is just an API convenience, literal nodes themselves
+ always store their values as strings.
+
+ @{
+*/
+
+/// The type of a #SerdValue
+typedef enum {
+ SERD_NOTHING, ///< Sentinel for unknown datatypes or errors
+ SERD_BOOL, ///< xsd:boolean (bool)
+ SERD_DOUBLE, ///< xsd:double (double)
+ SERD_FLOAT, ///< xsd:float (float)
+ SERD_LONG, ///< xsd:long (int64_t)
+ SERD_INT, ///< xsd:integer (int32_t)
+ SERD_SHORT, ///< xsd:short (int16_t)
+ SERD_BYTE, ///< xsd:byte (int8_t)
+ SERD_ULONG, ///< xsd:unsignedLong (uint64_t)
+ SERD_UINT, ///< xsd:unsignedInt (uint32_t)
+ SERD_USHORT, ///< xsd:unsignedShort (uint16_t)
+ SERD_UBYTE, ///< xsd:unsignedByte (uint8_t)
+} SerdValueType;
+
+/// The data of a #SerdValue (the actual machine-native primitive)
+typedef union {
+ bool as_bool;
+ double as_double;
+ float as_float;
+ int64_t as_long;
+ int32_t as_int;
+ int16_t as_short;
+ int8_t as_byte;
+ uint64_t as_ulong;
+ uint32_t as_uint;
+ uint16_t as_ushort;
+ uint8_t as_ubyte;
+} SerdValueData;
+
+/// A primitive value with a type tag
+typedef struct {
+ SerdValueType type;
+ SerdValueData data;
+} SerdValue;
+
+/// Convenience constructor to make a #SERD_NOTHING (non-)value
+SERD_CONST_API SerdValue
+serd_nothing(void);
+
+/// Convenience constructor to make a #SERD_BOOL value
+SERD_CONST_API SerdValue
+serd_bool(bool v);
+
+/// Convenience constructor to make a #SERD_DOUBLE value
+SERD_CONST_API SerdValue
+serd_double(double v);
+
+/// Convenience constructor to make a #SERD_FLOAT value
+SERD_CONST_API SerdValue
+serd_float(float v);
+
+/// Convenience constructor to make a #SERD_LONG value
+SERD_CONST_API SerdValue
+serd_long(int64_t v);
+
+/// Convenience constructor to make a #SERD_INT value
+SERD_CONST_API SerdValue
+serd_int(int32_t v);
+
+/// Convenience constructor to make a #SERD_SHORT value
+SERD_CONST_API SerdValue
+serd_short(int16_t v);
+
+/// Convenience constructor to make a #SERD_BYTE value
+SERD_CONST_API SerdValue
+serd_byte(int8_t v);
+
+/// Convenience constructor to make a #SERD_ULONG value
+SERD_CONST_API SerdValue
+serd_ulong(uint64_t v);
+
+/// Convenience constructor to make a #SERD_UINT value
+SERD_CONST_API SerdValue
+serd_uint(uint32_t v);
+
+/// Convenience constructor to make a #SERD_USHORT value
+SERD_CONST_API SerdValue
+serd_ushort(uint16_t v);
+
+/// Convenience constructor to make a #SERD_UBYTE value
+SERD_CONST_API SerdValue
+serd_ubyte(uint8_t v);
+
+/**
+ @}
+*/
+
+SERD_END_DECLS
+
+#endif // SERD_VALUE_H
diff --git a/meson.build b/meson.build
index ad745658..7bd2e560 100644
--- a/meson.build
+++ b/meson.build
@@ -147,6 +147,7 @@ c_headers = files(
'include/serd/string_view.h',
'include/serd/syntax.h',
'include/serd/uri.h',
+ 'include/serd/value.h',
'include/serd/version.h',
'include/serd/world.h',
'include/serd/write_result.h',
@@ -177,6 +178,7 @@ sources = files(
'src/syntax.c',
'src/system.c',
'src/uri.c',
+ 'src/value.c',
'src/world.c',
'src/writer.c',
)
diff --git a/src/base64.c b/src/base64.c
deleted file mode 100644
index 50ec3981..00000000
--- a/src/base64.c
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2011-2020 David Robillard <d@drobilla.net>
-// SPDX-License-Identifier: ISC
-
-#include "base64.h"
-
-#include "exess/exess.h"
-#include "serd/string.h"
-
-#include <stdlib.h>
-
-void*
-serd_base64_decode(const char* const str, const size_t len, size_t* const size)
-{
- const size_t max_size = exess_base64_decoded_size(len);
-
- void* const buf = malloc(max_size);
- const ExessVariableResult r = exess_read_base64(max_size, buf, str);
- if (r.status) {
- *size = 0;
- free(buf);
- return NULL;
- }
-
- *size = r.write_count;
-
- return buf;
-}
diff --git a/src/base64.h b/src/base64.h
deleted file mode 100644
index d3e2b6e1..00000000
--- a/src/base64.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2011-2023 David Robillard <d@drobilla.net>
-// SPDX-License-Identifier: ISC
-
-#ifndef SERD_SRC_BASE64_H
-#define SERD_SRC_BASE64_H
-
-#include "serd/attributes.h"
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-/**
- Return the number of bytes required to encode `size` bytes in base64.
-
- @param size The number of input (binary) bytes to encode.
- @param wrap_lines Wrap lines at 76 characters to conform to RFC 2045.
- @return The length of the base64 encoding, excluding null terminator.
-*/
-SERD_CONST_FUNC size_t
-serd_base64_get_length(size_t size, bool wrap_lines);
-
-/**
- Encode `size` bytes of `buf` into `str`, which must be large enough.
-
- @param str Output string buffer.
- @param buf Input binary data.
- @param size Number of bytes to encode from `buf`.
- @param wrap_lines Wrap lines at 76 characters to conform to RFC 2045.
- @return True iff `str` contains newlines.
-*/
-bool
-serd_base64_encode(uint8_t* str, const void* buf, size_t size, bool wrap_lines);
-
-#endif // SERD_SRC_BASE64_H
diff --git a/src/byte_source.c b/src/byte_source.c
index cf9a2466..249c0dde 100644
--- a/src/byte_source.c
+++ b/src/byte_source.c
@@ -7,7 +7,6 @@
#include "system.h"
#include "serd/node.h"
-#include "serd/string_view.h"
#include <assert.h>
#include <stdbool.h>
@@ -67,7 +66,7 @@ serd_byte_source_new_input(SerdAllocator* const allocator,
SerdNode* const source_name =
name ? serd_node_copy(allocator, name)
- : serd_new_string(allocator, serd_string("input"));
+ : serd_node_new(allocator, serd_a_string("input"));
if (!source_name) {
return NULL;
diff --git a/src/env.c b/src/env.c
index 90924cd2..dcffb98e 100644
--- a/src/env.c
+++ b/src/env.c
@@ -159,7 +159,7 @@ serd_env_set_base_uri(SerdEnv* const env, const SerdStringView uri)
// Replace the current base URI
if ((env->base_uri_node =
- serd_new_parsed_uri(env->allocator, new_base_uri))) {
+ serd_node_new(env->allocator, serd_a_parsed_uri(new_base_uri)))) {
env->base_uri = serd_node_uri_view(env->base_uri_node);
} else {
return SERD_BAD_ALLOC;
@@ -209,7 +209,7 @@ serd_env_add(SerdEnv* const env,
if (prefix) {
if (!!strcmp(serd_node_string(prefix->uri), uri.data)) {
serd_node_free(env->allocator, prefix->uri);
- prefix->uri = serd_new_uri(env->allocator, uri);
+ prefix->uri = serd_node_new(env->allocator, serd_a_uri(uri));
}
} else {
SerdPrefix* const new_prefixes =
@@ -222,8 +222,9 @@ serd_env_add(SerdEnv* const env,
env->prefixes = new_prefixes;
- SerdNode* const name_node = serd_new_string(env->allocator, name);
- SerdNode* const uri_node = serd_new_uri(env->allocator, uri);
+ SerdNode* const name_node =
+ serd_node_new(env->allocator, serd_a_string_view(name));
+ SerdNode* const uri_node = serd_node_new(env->allocator, serd_a_uri(uri));
if (!name_node || !uri_node) {
serd_node_free(env->allocator, uri_node);
serd_node_free(env->allocator, name_node);
@@ -260,7 +261,8 @@ serd_env_set_prefix(SerdEnv* const env,
assert(abs_uri_view.scheme.length);
// Create a new node for the absolute URI
- SerdNode* const abs_uri = serd_new_parsed_uri(env->allocator, abs_uri_view);
+ SerdNode* const abs_uri =
+ serd_node_new(env->allocator, serd_a_parsed_uri(abs_uri_view));
if (!abs_uri) {
return SERD_BAD_ALLOC;
}
@@ -317,7 +319,7 @@ serd_env_expand_in_place(const SerdEnv* const env,
return SERD_BAD_CURIE;
}
- uri_prefix->data = serd_node_string(prefix->uri);
+ uri_prefix->data = prefix->uri ? serd_node_string(prefix->uri) : "";
uri_prefix->length = prefix->uri ? prefix->uri->length : 0;
uri_suffix->data = colon + 1;
uri_suffix->length = curie.length - name_len - 1;
@@ -338,15 +340,23 @@ serd_env_expand_curie(const SerdEnv* const env, const SerdStringView curie)
return NULL;
}
- const size_t len = prefix.length + suffix.length;
- SerdNode* const ret = serd_node_malloc(env->allocator, len, 0U, SERD_URI);
- if (ret) {
- char* const string = serd_node_buffer(ret);
+ const size_t len = prefix.length + suffix.length;
+ const size_t real_length = serd_node_pad_length(len);
+ const size_t node_size = sizeof(SerdNode) + real_length;
+ SerdNode* node = serd_node_malloc(env->allocator, node_size);
+
+ if (node) {
+ node->length = len;
+ node->flags = 0U;
+ node->type = SERD_URI;
+
+ char* const string = (char*)(node + 1U);
+ assert(prefix.data);
memcpy(string, prefix.data, prefix.length);
memcpy(string + prefix.length, suffix.data, suffix.length);
}
- return ret;
+ return node;
}
SerdNode*
@@ -359,8 +369,9 @@ serd_env_expand_node(const SerdEnv* const env, const SerdNode* const node)
const SerdURIView uri = serd_node_uri_view(node);
const SerdURIView abs_uri = serd_resolve_uri(uri, env->base_uri);
- return abs_uri.scheme.length ? serd_new_parsed_uri(env->allocator, abs_uri)
- : NULL;
+ return abs_uri.scheme.length
+ ? serd_node_new(env->allocator, serd_a_parsed_uri(abs_uri))
+ : NULL;
}
SerdStatus
diff --git a/src/node.c b/src/node.c
index 135ccc22..b4cd14fa 100644
--- a/src/node.c
+++ b/src/node.c
@@ -8,81 +8,142 @@
#include "string_utils.h"
#include "exess/exess.h"
-#include "serd/buffer.h"
#include "serd/node.h"
#include "serd/status.h"
#include "serd/string_view.h"
#include "serd/uri.h"
+#include "serd/value.h"
#include "serd/write_result.h"
#include "zix/attributes.h"
#include <assert.h>
-#include <math.h>
#include <stdbool.h>
#include <stdint.h>
-#include <stdlib.h>
#include <string.h>
-typedef struct {
- const void* ZIX_NULLABLE buf;
- size_t len;
-} SerdConstBuffer;
+#ifndef NDEBUG
+# define MUST_SUCCEED(status) assert(!(status))
+#else
+# define MUST_SUCCEED(status) ((void)(status))
+#endif
#define NS_XSD "http://www.w3.org/2001/XMLSchema#"
-typedef struct StaticNode {
- SerdNode node;
- char buf[sizeof(NS_XSD "base64Binary")];
-} StaticNode;
+static const SerdNodeFlags meta_mask = (SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE);
-#define DEFINE_XSD_NODE(name) \
- static const StaticNode serd_xsd_##name = { \
- {sizeof(NS_XSD #name) - 1, 0, SERD_URI}, NS_XSD #name};
+static const ExessDatatype value_type_datatypes[] = {
+ EXESS_NOTHING,
+ EXESS_BOOLEAN,
+ EXESS_DOUBLE,
+ EXESS_FLOAT,
+ EXESS_LONG,
+ EXESS_INT,
+ EXESS_SHORT,
+ EXESS_BYTE,
+ EXESS_ULONG,
+ EXESS_UINT,
+ EXESS_USHORT,
+ EXESS_UBYTE,
+};
-DEFINE_XSD_NODE(base64Binary)
-DEFINE_XSD_NODE(boolean)
-DEFINE_XSD_NODE(decimal)
-DEFINE_XSD_NODE(integer)
+// Argument constructors
-static const SerdNodeFlags meta_mask = (SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE);
+SerdNodeArgs
+serd_a_token(const SerdNodeType type, const SerdStringView string)
+{
+ const SerdNodeArgs args = {SERD_NODE_ARGS_TOKEN, {{type, string}}};
+ return args;
+}
-static size_t
-string_sink(const void* const buf,
- const size_t size,
- const size_t nmemb,
- void* const stream)
+SerdNodeArgs
+serd_a_parsed_uri(const SerdURIView uri)
{
- char** ptr = (char**)stream;
- memcpy(*ptr, buf, size * nmemb);
- *ptr += size * nmemb;
- return nmemb;
+ SerdNodeArgs args;
+ args.type = SERD_NODE_ARGS_PARSED_URI;
+ args.data.as_parsed_uri.uri = uri;
+ return args;
+}
+
+SerdNodeArgs
+serd_a_file_uri(const SerdStringView path, const SerdStringView hostname)
+{
+ SerdNodeArgs args;
+ args.type = SERD_NODE_ARGS_FILE_URI;
+ args.data.as_file_uri.path = path;
+ args.data.as_file_uri.hostname = hostname;
+ return args;
}
-ZIX_PURE_FUNC static size_t
-serd_node_pad_length(const size_t n_bytes)
+SerdNodeArgs
+serd_a_literal(const SerdStringView string,
+ const SerdNodeFlags flags,
+ const SerdStringView meta)
{
- const size_t pad = sizeof(SerdNode) - (n_bytes + 2) % sizeof(SerdNode);
- const size_t size = n_bytes + 2 + pad;
- assert(size % sizeof(SerdNode) == 0);
- return size;
+ SerdNodeArgs args;
+ args.type = SERD_NODE_ARGS_LITERAL;
+ args.data.as_literal.string = string;
+ args.data.as_literal.flags = flags;
+ args.data.as_literal.meta = meta;
+ return args;
}
-static const SerdNode*
-serd_node_meta_c(const SerdNode* const node)
+SerdNodeArgs
+serd_a_primitive(const SerdValue value)
{
- return node + 1 + (serd_node_pad_length(node->length) / sizeof(SerdNode));
+ SerdNodeArgs args;
+ args.type = SERD_NODE_ARGS_PRIMITIVE;
+ args.data.as_primitive.value = value;
+ return args;
}
-static SerdNode*
-serd_node_meta(SerdNode* const node)
+SerdNodeArgs
+serd_a_decimal(const double value)
{
- return node + 1 + (serd_node_pad_length(node->length) / sizeof(SerdNode));
+ SerdNodeArgs args;
+ args.type = SERD_NODE_ARGS_DECIMAL;
+ args.data.as_decimal.value = value;
+ return args;
}
-ZIX_PURE_FUNC static const SerdNode*
-serd_node_maybe_get_meta_c(const SerdNode* const node)
+SerdNodeArgs
+serd_a_integer(const int64_t value)
+{
+ SerdNodeArgs args;
+ args.type = SERD_NODE_ARGS_INTEGER;
+ args.data.as_integer.value = value;
+ return args;
+}
+
+SerdNodeArgs
+serd_a_hex(const size_t size, const void* const data)
+{
+ SerdNodeArgs args;
+ args.type = SERD_NODE_ARGS_HEX;
+ args.data.as_blob.size = size;
+ args.data.as_blob.data = data;
+ return args;
+}
+
+SerdNodeArgs
+serd_a_base64(size_t size, const void* const data)
+{
+ SerdNodeArgs args;
+ args.type = SERD_NODE_ARGS_BASE64;
+ args.data.as_blob.size = size;
+ args.data.as_blob.data = data;
+ return args;
+}
+
+// Node functions
+
+// Round size up to an even multiple of the node alignment
+static size_t
+serd_node_pad_size(const size_t size)
{
- return (node->flags & meta_mask) ? serd_node_meta_c(node) : NULL;
+ const size_t n_trailing = size % serd_node_align;
+ const size_t n_pad = n_trailing ? (serd_node_align - n_trailing) : 0U;
+
+ return size + n_pad;
}
static void
@@ -96,7 +157,8 @@ serd_node_check_padding(const SerdNode* node)
assert(serd_node_buffer_c(node)[node->length + i] == '\0');
}
- serd_node_check_padding(serd_node_maybe_get_meta_c(node));
+ serd_node_check_padding(serd_node_datatype(node));
+ serd_node_check_padding(serd_node_language(node));
}
#endif
}
@@ -104,32 +166,37 @@ serd_node_check_padding(const SerdNode* node)
size_t
serd_node_total_size(const SerdNode* const node)
{
- return node ? (sizeof(SerdNode) + serd_node_pad_length(node->length) +
- serd_node_total_size(serd_node_maybe_get_meta_c(node)))
- : 0;
+ const size_t real_length = serd_node_pad_length(node->length);
+ const size_t base_size = sizeof(SerdNode) + real_length;
+
+ if (!(node->flags & meta_mask)) {
+ return base_size;
+ }
+
+ const SerdNode* const meta = serd_node_meta_c(node);
+ const size_t meta_real_length = serd_node_pad_length(meta->length);
+
+ return base_size + sizeof(SerdNode) + meta_real_length;
}
SerdNode*
-serd_node_malloc(SerdAllocator* const allocator,
- const size_t length,
- const SerdNodeFlags flags,
- const SerdNodeType type)
+serd_node_malloc(SerdAllocator* const allocator, const size_t size)
{
- const size_t size = sizeof(SerdNode) + serd_node_pad_length(length);
-
- SerdNode* const node =
- (SerdNode*)serd_aaligned_calloc(allocator, serd_node_align, size);
-
- if (node) {
- node->length = 0;
- node->flags = flags;
- node->type = type;
- }
+ SerdNode* const node = (SerdNode*)serd_aaligned_calloc(
+ allocator, serd_node_align, serd_node_pad_size(size));
assert((uintptr_t)node % serd_node_align == 0U);
return node;
}
+SerdNode*
+serd_node_try_malloc(SerdAllocator* const allocator, const SerdWriteResult r)
+{
+ return (r.status && r.status != SERD_OVERFLOW)
+ ? NULL
+ : serd_node_malloc(allocator, r.count);
+}
+
SerdStatus
serd_node_set(SerdAllocator* const allocator,
SerdNode** const dst,
@@ -179,44 +246,31 @@ result(const SerdStatus status, const size_t count)
return result;
}
-SerdNode*
-serd_new_token(SerdAllocator* const allocator,
- const SerdNodeType type,
- const SerdStringView str)
-{
- SerdNodeFlags flags = 0U;
- const size_t length = str.data ? str.length : 0U;
- SerdNode* node = serd_node_malloc(allocator, length, flags, type);
-
- if (node) {
- if (str.data) {
- memcpy(serd_node_buffer(node), str.data, length);
- }
-
- node->length = length;
+static SerdWriteResult
+serd_node_construct_simple(const size_t buf_size,
+ void* const buf,
+ const SerdNodeType type,
+ const SerdNodeFlags flags,
+ const SerdStringView string)
+{
+ const size_t total_size =
+ sizeof(SerdNode) + serd_node_pad_length(string.length);
+ if (!buf || total_size > buf_size) {
+ return result(SERD_OVERFLOW, total_size);
}
- serd_node_check_padding(node);
+ SerdNode* const node = (SerdNode*)buf;
- return node;
-}
-
-SerdNode*
-serd_new_string(SerdAllocator* const allocator, const SerdStringView str)
-{
- SerdNodeFlags flags = 0U;
- SerdNode* node = serd_node_malloc(allocator, str.length, flags, SERD_LITERAL);
-
- if (node) {
- if (str.data && str.length) {
- memcpy(serd_node_buffer(node), str.data, str.length);
- }
+ node->length = string.length;
+ node->flags = flags;
+ node->type = type;
- node->length = str.length;
- serd_node_check_padding(node);
+ if (string.data) {
+ memcpy(serd_node_buffer(node), string.data, string.length);
}
- return node;
+ serd_node_zero_pad(node);
+ return result(SERD_SUCCESS, total_size);
}
ZIX_PURE_FUNC static bool
@@ -248,165 +302,427 @@ is_langtag(const SerdStringView string)
return true;
}
-SerdNode*
-serd_new_literal(SerdAllocator* const allocator,
- const SerdStringView string,
- const SerdNodeFlags flags,
- const SerdStringView meta)
+static SerdWriteResult
+serd_node_construct_literal(const size_t buf_size,
+ void* const buf,
+ const SerdStringView string,
+ const SerdNodeFlags flags,
+ const SerdStringView meta)
{
if (!(flags & (SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE))) {
- SerdNode* node =
- serd_node_malloc(allocator, string.length, flags, SERD_LITERAL);
-
- memcpy(serd_node_buffer(node), string.data, string.length);
- node->length = string.length;
- serd_node_check_padding(node);
- return node;
+ return serd_node_construct_simple(
+ buf_size, buf, SERD_LITERAL, flags, string);
}
if ((flags & SERD_HAS_DATATYPE) && (flags & SERD_HAS_LANGUAGE)) {
- return NULL;
+ return result(SERD_BAD_ARG, 0);
}
if (!meta.length) {
- return NULL;
+ return result(SERD_BAD_ARG, 0);
}
if (((flags & SERD_HAS_DATATYPE) &&
(!serd_uri_string_has_scheme(meta.data) ||
!strcmp(meta.data, NS_RDF "langString"))) ||
((flags & SERD_HAS_LANGUAGE) && !is_langtag(meta))) {
- return NULL;
+ return result(SERD_BAD_ARG, 0);
+ }
+
+ // Calculate total node size
+ const size_t padded_len = serd_node_pad_length(string.length);
+ const size_t meta_size = sizeof(SerdNode) + serd_node_pad_length(meta.length);
+ const size_t total_size = sizeof(SerdNode) + padded_len + meta_size;
+ if (!buf || total_size > buf_size) {
+ return result(SERD_OVERFLOW, total_size);
}
- const size_t len = serd_node_pad_length(string.length);
- const size_t meta_len = serd_node_pad_length(meta.length);
- const size_t meta_size = sizeof(SerdNode) + meta_len;
+ // Write node header
+ SerdNode* const node = (SerdNode*)buf;
+ node->length = string.length;
+ node->flags = flags;
+ node->type = SERD_LITERAL;
- SerdNode* node =
- serd_node_malloc(allocator, len + meta_size, flags, SERD_LITERAL);
+ // Copy string to node body
memcpy(serd_node_buffer(node), string.data, string.length);
- node->length = string.length;
- SerdNode* meta_node = node + 1U + (len / sizeof(SerdNode));
- meta_node->length = meta.length;
+ // Append datatype or language
+ SerdNode* meta_node = node + 1 + (padded_len / sizeof(SerdNode));
meta_node->type = (flags & SERD_HAS_DATATYPE) ? SERD_URI : SERD_LITERAL;
+ meta_node->length = meta.length;
memcpy(serd_node_buffer(meta_node), meta.data, meta.length);
- serd_node_check_padding(meta_node);
- serd_node_check_padding(node);
- return node;
+ serd_node_zero_pad(node);
+ return result(SERD_SUCCESS, total_size);
+}
+
+static ExessDatatype
+value_type_datatype(const SerdValueType value_type)
+{
+ return (value_type > SERD_UBYTE) ? EXESS_NOTHING
+ : value_type_datatypes[value_type];
+}
+
+static const char*
+value_type_uri(const SerdValueType value_type)
+{
+ return exess_datatype_uri(value_type_datatype(value_type));
+}
+
+static inline SerdValueType
+datatype_value_type(const ExessDatatype datatype)
+{
+ switch (datatype) {
+ case EXESS_NOTHING:
+ return SERD_NOTHING;
+ case EXESS_BOOLEAN:
+ return SERD_BOOL;
+ case EXESS_DECIMAL:
+ case EXESS_DOUBLE:
+ return SERD_DOUBLE;
+ case EXESS_FLOAT:
+ return SERD_FLOAT;
+ case EXESS_INTEGER:
+ case EXESS_NON_POSITIVE_INTEGER:
+ case EXESS_NEGATIVE_INTEGER:
+ case EXESS_LONG:
+ return SERD_LONG;
+ case EXESS_INT:
+ return SERD_INT;
+ case EXESS_SHORT:
+ return SERD_SHORT;
+ case EXESS_BYTE:
+ return SERD_BYTE;
+ case EXESS_NON_NEGATIVE_INTEGER:
+ case EXESS_ULONG:
+ return SERD_ULONG;
+ case EXESS_UINT:
+ return SERD_UINT;
+ case EXESS_USHORT:
+ return SERD_USHORT;
+ case EXESS_UBYTE:
+ return SERD_UBYTE;
+ case EXESS_POSITIVE_INTEGER:
+ return SERD_ULONG;
+
+ case EXESS_DURATION:
+ case EXESS_DATETIME:
+ case EXESS_TIME:
+ case EXESS_DATE:
+ case EXESS_HEX:
+ case EXESS_BASE64:
+ break;
+ }
+
+ return SERD_NOTHING;
}
-SerdNode*
-serd_new_blank(SerdAllocator* const allocator, const SerdStringView str)
-{
- return serd_new_token(allocator, SERD_BLANK, str);
+static SerdWriteResult
+serd_node_construct_value(const size_t buf_size,
+ void* const buf,
+ const SerdValue value)
+{
+ char temp[EXESS_MAX_DOUBLE_LENGTH + 1] = {0};
+ ExessResult r = {EXESS_UNSUPPORTED, 0U};
+ switch (value.type) {
+ case SERD_NOTHING:
+ return result(SERD_BAD_ARG, 0U);
+ case SERD_BOOL:
+ r = exess_write_boolean(value.data.as_bool, sizeof(temp), temp);
+ break;
+ case SERD_DOUBLE:
+ r = exess_write_double(value.data.as_double, sizeof(temp), temp);
+ break;
+ case SERD_FLOAT:
+ r = exess_write_float(value.data.as_float, sizeof(temp), temp);
+ break;
+ case SERD_LONG:
+ r = exess_write_long(value.data.as_long, sizeof(temp), temp);
+ break;
+ case SERD_INT:
+ r = exess_write_int(value.data.as_int, sizeof(temp), temp);
+ break;
+ case SERD_SHORT:
+ r = exess_write_short(value.data.as_short, sizeof(temp), temp);
+ break;
+ case SERD_BYTE:
+ r = exess_write_byte(value.data.as_byte, sizeof(temp), temp);
+ break;
+ case SERD_ULONG:
+ r = exess_write_ulong(value.data.as_ulong, sizeof(temp), temp);
+ break;
+ case SERD_UINT:
+ r = exess_write_uint(value.data.as_uint, sizeof(temp), temp);
+ break;
+ case SERD_USHORT:
+ r = exess_write_ushort(value.data.as_ushort, sizeof(temp), temp);
+ break;
+ case SERD_UBYTE:
+ r = exess_write_ubyte(value.data.as_ubyte, sizeof(temp), temp);
+ break;
+ }
+
+ MUST_SUCCEED(r.status); // The only error is buffer overrun
+
+ const char* const datatype_uri = value_type_uri(value.type);
+ assert(datatype_uri);
+
+ return serd_node_construct_literal(buf_size,
+ buf,
+ serd_substring(temp, r.count),
+ SERD_HAS_DATATYPE,
+ serd_string(datatype_uri));
}
-ExessResult
-serd_node_get_value_as(const SerdNode* const node,
- const ExessDatatype value_type,
- const size_t value_size,
- void* const value)
+static SerdWriteResult
+serd_node_construct_decimal(const size_t buf_size,
+ void* const buf,
+ const double value)
{
- const SerdNode* const datatype_node = serd_node_datatype(node);
+ char temp[EXESS_MAX_DECIMAL_LENGTH + 1] = {0};
- const ExessDatatype node_type =
- datatype_node ? exess_datatype_from_uri(serd_node_string(datatype_node))
- : EXESS_NOTHING;
+ const ExessResult r = exess_write_decimal(value, sizeof(temp), temp);
+ MUST_SUCCEED(r.status); // The only error is buffer overrun
+
+ return serd_node_construct_literal(buf_size,
+ buf,
+ serd_substring(temp, r.count),
+ SERD_HAS_DATATYPE,
+ serd_string(EXESS_XSD_URI "decimal"));
+}
- if (node_type == EXESS_NOTHING ||
- (node_type == EXESS_HEX && value_type == EXESS_BASE64) ||
- (node_type == EXESS_BASE64 && value_type == EXESS_HEX)) {
- // Try to read the large or untyped node string directly into the result
- const ExessVariableResult vr =
- exess_read_value(value_type, value_size, value, serd_node_string(node));
+static SerdWriteResult
+serd_node_construct_integer(const size_t buf_size,
+ void* const buf,
+ const int64_t value)
+{
+ char temp[24] = {0};
+ const ExessResult r = exess_write_long(value, sizeof(temp), temp);
+ MUST_SUCCEED(r.status); // The only error is buffer overrun
- const ExessResult r = {vr.status, vr.write_count};
- return r;
+ return serd_node_construct_literal(buf_size,
+ buf,
+ serd_substring(temp, r.count),
+ SERD_HAS_DATATYPE,
+ serd_string(NS_XSD "integer"));
+}
+
+static SerdWriteResult
+serd_node_construct_binary(
+ const size_t buf_size,
+ void* const buf,
+ const size_t value_size,
+ const void* const value,
+ const SerdStringView datatype_uri,
+ ExessResult (*write_func)(size_t, const void*, size_t, char*))
+{
+ // Verify argument sanity
+ if (!value || !value_size) {
+ return result(SERD_BAD_ARG, 0);
}
- // Read the (smallish) value from the node
- ExessValue node_value = {false};
- const ExessVariableResult vr = exess_read_value(
- node_type, sizeof(node_value), &node_value, serd_node_string(node));
+ // Find the size required for the datatype
+ const size_t type_length = serd_node_pad_length(datatype_uri.length);
+ const size_t type_size = sizeof(SerdNode) + type_length;
- if (vr.status) {
- const ExessResult r = {vr.status, 0U};
- return r;
+ // Find the length of the encoded string (just an O(1) arithmetic expression)
+ ExessResult r = write_func(value_size, value, 0, NULL);
+
+ // Check that the provided buffer is large enough
+ const size_t padded_length = serd_node_pad_length(r.count);
+ const size_t total_size = sizeof(SerdNode) + padded_length + type_size;
+ if (!buf || total_size > buf_size) {
+ return result(SERD_OVERFLOW, total_size);
}
- // Coerce value to the desired type if possible
- return exess_value_coerce(EXESS_REDUCE_PRECISION,
- node_type,
- vr.write_count,
- &node_value,
- value_type,
- value_size,
- value);
+ // Write node header
+ SerdNode* const node = (SerdNode*)buf;
+ node->length = r.count;
+ node->flags = SERD_HAS_DATATYPE;
+ node->type = SERD_LITERAL;
+
+ // Write the encoded string into the node body
+ r = write_func(
+ value_size, value, total_size - sizeof(SerdNode), serd_node_buffer(node));
+
+ MUST_SUCCEED(r.status);
+ (void)r;
+
+ // Append datatype
+ SerdNode* meta_node = node + 1 + (padded_length / sizeof(SerdNode));
+ meta_node->length = datatype_uri.length;
+ meta_node->flags = 0U;
+ meta_node->type = SERD_URI;
+ memcpy(serd_node_buffer(meta_node), datatype_uri.data, datatype_uri.length);
+
+ return result(SERD_SUCCESS, total_size);
}
-bool
-serd_get_boolean(const SerdNode* const node)
+static size_t
+string_sink(const void* const buf,
+ const size_t size,
+ const size_t nmemb,
+ void* const stream)
{
- assert(node);
+ char** ptr = (char**)stream;
+ memcpy(*ptr, buf, size * nmemb);
+ *ptr += size * nmemb;
+ return nmemb;
+}
- bool value = false;
- serd_node_get_value_as(node, EXESS_BOOLEAN, sizeof(value), &value);
+static SerdWriteResult
+serd_node_construct_uri(const size_t buf_size,
+ void* const buf,
+ const SerdURIView uri)
+{
+ const size_t length = serd_uri_string_length(uri);
+ const size_t required_size = sizeof(SerdNode) + serd_node_pad_length(length);
+ if (!buf || buf_size < required_size) {
+ return result(SERD_OVERFLOW, required_size);
+ }
+
+ // Write node header
+ SerdNode* const node = (SerdNode*)buf;
+ node->length = length;
+ node->flags = 0U;
+ node->type = SERD_URI;
- return value;
+ // Serialise URI to node body
+ char* ptr = serd_node_buffer(node);
+ const size_t actual_length = serd_write_uri(uri, string_sink, &ptr);
+ assert(actual_length == length);
+
+ serd_node_buffer(node)[actual_length] = '\0';
+ serd_node_check_padding(node);
+ return result(SERD_SUCCESS, required_size);
}
-double
-serd_get_double(const SerdNode* const node)
+SerdNode*
+serd_node_new(SerdAllocator* const allocator, const SerdNodeArgs args)
{
- assert(node);
+ SerdWriteResult r = serd_node_construct(0, NULL, args);
+ if (r.status != SERD_OVERFLOW) {
+ return NULL;
+ }
- double value = (double)NAN; // NOLINT(google-readability-casting)
- serd_node_get_value_as(node, EXESS_DOUBLE, sizeof(value), &value);
+ assert(r.count % sizeof(SerdNode) == 0);
- return value;
+ SerdNode* const node =
+ serd_node_malloc(allocator, sizeof(SerdNode) + r.count + 1);
+
+ if (node) {
+ r = serd_node_construct(r.count, node, args);
+ MUST_SUCCEED(r.status); // Any error should have been reported above
+ }
+
+ return node;
}
-float
-serd_get_float(const SerdNode* const node)
+SerdValue
+serd_node_value(const SerdNode* const node)
{
assert(node);
- float value = (float)NAN; // NOLINT(google-readability-casting)
- serd_node_get_value_as(node, EXESS_FLOAT, sizeof(value), &value);
+ const SerdNode* const datatype_node = serd_node_datatype(node);
+
+ const ExessDatatype datatype =
+ datatype_node ? exess_datatype_from_uri(serd_node_string(datatype_node))
+ : EXESS_NOTHING;
+
+ const SerdValueType value_type = datatype_value_type(datatype);
+ if (value_type == SERD_NOTHING) {
+ return serd_nothing();
+ }
+
+ ExessValue value = {false};
+ const ExessVariableResult vr =
+ exess_read_value(datatype, sizeof(value), &value, serd_node_string(node));
- return value;
+ if (vr.status) {
+ return serd_nothing();
+ }
+
+ SerdValue result = {value_type, {false}};
+ memcpy(&result.data, &value, vr.write_count);
+
+ return result;
}
-int64_t
-serd_get_integer(const SerdNode* const node)
+SerdValue
+serd_node_value_as(const SerdNode* const node,
+ const SerdValueType type,
+ const bool lossy)
{
- assert(node);
+ // Get the value as it is
+ const SerdValue value = serd_node_value(node);
+ if (!value.type || value.type == type) {
+ return value;
+ }
- int64_t value = 0;
- serd_node_get_value_as(node, EXESS_LONG, sizeof(value), &value);
+ const ExessCoercions coercions =
+ lossy ? (EXESS_REDUCE_PRECISION | EXESS_ROUND | EXESS_TRUNCATE)
+ : EXESS_LOSSLESS;
+
+ const ExessDatatype node_datatype = value_type_datatype(value.type);
+ const ExessDatatype datatype = value_type_datatype(type);
+ SerdValue result = {type, {false}};
+
+ // Coerce to the desired type
+ const ExessResult r = exess_value_coerce(coercions,
+ node_datatype,
+ exess_value_size(node_datatype),
+ &value.data,
+ datatype,
+ exess_value_size(datatype),
+ &result.data);
+
+ if (r.status) {
+ result.type = SERD_NOTHING;
+ }
- return value;
+ return result;
}
size_t
-serd_get_base64_size(const SerdNode* const node)
+serd_node_decoded_size(const SerdNode* const node)
{
- return exess_base64_decoded_size(serd_node_length(node));
+ const SerdNode* const datatype = serd_node_datatype(node);
+ if (!datatype) {
+ return 0U;
+ }
+
+ if (!strcmp(serd_node_string(datatype), NS_XSD "hexBinary")) {
+ return exess_hex_decoded_size(serd_node_length(node));
+ }
+
+ if (!strcmp(serd_node_string(datatype), NS_XSD "base64Binary")) {
+ return exess_base64_decoded_size(serd_node_length(node));
+ }
+
+ return 0U;
}
SerdWriteResult
-serd_get_base64(const SerdNode* const node,
- const size_t buf_size,
- void* const buf)
+serd_node_decode(const SerdNode* const node,
+ const size_t buf_size,
+ void* const buf)
{
- const size_t max_size = serd_get_base64_size(node);
- const ExessVariableResult r =
- exess_read_base64(buf_size, buf, serd_node_string(node));
+ const SerdNode* const datatype = serd_node_datatype(node);
+ if (!datatype) {
+ return result(SERD_BAD_ARG, 0U);
+ }
+
+ ExessVariableResult r = {EXESS_UNSUPPORTED, 0U, 0U};
- return r.status == EXESS_NO_SPACE ? result(SERD_OVERFLOW, max_size)
+ if (!strcmp(serd_node_string(datatype), NS_XSD "hexBinary")) {
+ r = exess_read_hex(buf_size, buf, serd_node_string(node));
+ } else if (!strcmp(serd_node_string(datatype), NS_XSD "base64Binary")) {
+ r = exess_read_base64(buf_size, buf, serd_node_string(node));
+ } else {
+ return result(SERD_BAD_ARG, 0U);
+ }
+
+ return r.status == EXESS_NO_SPACE ? result(SERD_OVERFLOW, r.write_count)
: r.status ? result(SERD_BAD_SYNTAX, 0U)
: result(SERD_SUCCESS, r.write_count);
}
@@ -485,197 +801,120 @@ serd_node_compare(const SerdNode* const a, const SerdNode* const b)
return strcmp(serd_node_string_i(ma), serd_node_string_i(mb));
}
-SerdNode*
-serd_new_uri(SerdAllocator* const allocator, const SerdStringView string)
-{
- return serd_new_token(allocator, SERD_URI, string);
-}
+typedef struct {
+ char* buf;
+ size_t len;
+ size_t offset;
+} ConstructWriteHead;
-SerdNode*
-serd_new_parsed_uri(SerdAllocator* const allocator, const SerdURIView uri)
+static size_t
+construct_write(const void* const buf,
+ const size_t size,
+ const size_t nmemb,
+ void* const stream)
{
- const size_t len = serd_uri_string_length(uri);
- SerdNode* const node = serd_node_malloc(allocator, len, 0, SERD_URI);
-
- if (node) {
- char* ptr = serd_node_buffer(node);
- const size_t actual_len = serd_write_uri(uri, string_sink, &ptr);
-
- assert(actual_len == len);
+ const size_t n_bytes = size * nmemb;
+ ConstructWriteHead* const head = (ConstructWriteHead*)stream;
- serd_node_buffer(node)[actual_len] = '\0';
- node->length = actual_len;
+ if (head->buf && head->offset + n_bytes <= head->len) {
+ memcpy(head->buf + head->offset, buf, n_bytes);
}
- serd_node_check_padding(node);
- return node;
-}
-
-SerdNode*
-serd_new_file_uri(SerdAllocator* const allocator,
- const SerdStringView path,
- const SerdStringView hostname)
-{
- SerdBuffer buffer = {NULL, NULL, 0U};
-
- serd_write_file_uri(path, hostname, serd_buffer_write, &buffer);
- serd_buffer_close(&buffer);
-
- const size_t length = buffer.len;
- const char* const string = (char*)buffer.buf;
- SerdNode* const node =
- serd_new_string(allocator, serd_substring(string, length));
-
- free(buffer.buf);
- serd_node_check_padding(node);
- return node;
+ head->offset += n_bytes;
+ return n_bytes;
}
-typedef size_t (*SerdWriteLiteralFunc)(const void* user_data,
- size_t buf_size,
- char* buf);
-
-static SerdNode*
-serd_new_custom_literal(SerdAllocator* const allocator,
- const void* const user_data,
- const size_t len,
- const SerdWriteLiteralFunc write,
- const SerdNode* const datatype)
-{
- if (len == 0 || !write) {
- return NULL;
+static SerdWriteResult
+serd_node_construct_file_uri(const size_t buf_size,
+ void* const buf,
+ const SerdStringView path,
+ const SerdStringView hostname)
+{
+ SerdNode* const node = (SerdNode*)buf;
+ ConstructWriteHead head = {(char*)buf, buf_size, 0U};
+ size_t count = 0U;
+
+ // Write node header
+ SerdNode header = {0U, 0U, SERD_URI};
+ count += construct_write(&header, sizeof(header), 1, &head);
+
+ // Write URI string node body
+ const size_t length =
+ serd_write_file_uri(path, hostname, construct_write, &head);
+
+ // Terminate string and pad with at least 1 additional null byte
+ const size_t padded_length = serd_node_pad_length(length);
+ count += length;
+ for (size_t p = 0U; p < padded_length - length; ++p) {
+ count += construct_write("", 1, 1, &head);
}
- const size_t datatype_size = serd_node_total_size(datatype);
- const size_t total_size = serd_node_pad_length(len) + datatype_size;
-
- SerdNode* const node = serd_node_malloc(
- allocator, total_size, datatype ? SERD_HAS_DATATYPE : 0U, SERD_LITERAL);
-
- node->length = write(user_data, len + 1, serd_node_buffer(node));
-
- if (datatype) {
- memcpy(serd_node_meta(node), datatype, datatype_size);
+ if (!buf || count > buf_size) {
+ return result(SERD_OVERFLOW, count);
}
- return node;
-}
-
-SerdNode*
-serd_new_double(SerdAllocator* const allocator, 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_literal(allocator,
- serd_substring(buf, r.count),
- SERD_HAS_DATATYPE,
- serd_string(EXESS_XSD_URI "double"));
-}
-
-SerdNode*
-serd_new_float(SerdAllocator* const allocator, const float f)
-{
- char buf[EXESS_MAX_FLOAT_LENGTH + 1] = {0};
-
- const ExessResult r = exess_write_float(f, sizeof(buf), buf);
+ node->length = length;
+ assert(node->length == strlen(serd_node_string(node)));
- return r.status ? NULL
- : serd_new_literal(allocator,
- serd_substring(buf, r.count),
- SERD_HAS_DATATYPE,
- serd_string(EXESS_XSD_URI "float"));
+ return result(SERD_SUCCESS, count);
}
-SerdNode*
-serd_new_boolean(SerdAllocator* const allocator, bool b)
-{
- return serd_new_literal(allocator,
- b ? serd_string("true") : serd_string("false"),
- SERD_HAS_DATATYPE,
- serd_node_string_view(&serd_xsd_boolean.node));
-}
-
-SerdNode*
-serd_new_decimal(SerdAllocator* const allocator,
- const double d,
- const SerdNode* const datatype)
-{
- // Use given datatype, or xsd:decimal as a default if it is null
- const SerdNode* type = datatype ? datatype : &serd_xsd_decimal.node;
- const size_t type_size = serd_node_total_size(type);
-
- // Measure integer string to know how much space the node will need
- ExessResult r = exess_write_decimal(d, 0, NULL);
- assert(!r.status);
-
- // Allocate node with enough space for value and datatype URI
- SerdNode* const node =
- serd_node_malloc(allocator,
- serd_node_pad_length(r.count) + type_size,
- SERD_HAS_DATATYPE,
- SERD_LITERAL);
-
- // Write string directly into node
- r = exess_write_decimal(d, r.count + 1, serd_node_buffer(node));
- assert(!r.status);
-
- node->length = r.count;
- memcpy(serd_node_meta(node), type, type_size);
- serd_node_check_padding(node);
- return node;
-}
-
-SerdNode*
-serd_new_integer(SerdAllocator* const allocator, const int64_t i)
-{
- // Use given datatype, or xsd:integer as a default if it is null
- const SerdNode* datatype = &serd_xsd_integer.node;
- const size_t datatype_size = serd_node_total_size(datatype);
-
- // Measure integer string to know how much space the node will need
- ExessResult r = exess_write_long(i, 0, NULL);
- assert(!r.status);
-
- // Allocate node with enough space for value and datatype URI
- SerdNode* const node =
- serd_node_malloc(allocator,
- serd_node_pad_length(r.count) + datatype_size,
- SERD_HAS_DATATYPE,
- SERD_LITERAL);
-
- // Write string directly into node
- r = exess_write_long(i, r.count + 1U, serd_node_buffer(node));
- assert(!r.status);
-
- node->length = r.count;
- memcpy(serd_node_meta(node), datatype, datatype_size);
- serd_node_check_padding(node);
- return node;
-}
-
-static size_t
-write_base64_literal(const void* const user_data,
- const size_t buf_size,
- char* const buf)
-{
- const SerdConstBuffer blob = *(const SerdConstBuffer*)user_data;
-
- const ExessResult r = exess_write_base64(blob.len, blob.buf, buf_size, buf);
-
- return r.status ? 0 : r.count;
-}
-
-SerdNode*
-serd_new_base64(SerdAllocator* const allocator, const void* buf, size_t size)
-{
- const size_t len = exess_write_base64(size, buf, 0, NULL).count;
- SerdConstBuffer blob = {buf, size};
+SerdWriteResult
+serd_node_construct(const size_t buf_size,
+ void* const buf,
+ const SerdNodeArgs args)
+{
+ switch (args.type) {
+ case SERD_NODE_ARGS_TOKEN:
+ return serd_node_construct_simple(
+ buf_size, buf, args.data.as_token.type, 0U, args.data.as_token.string);
+
+ case SERD_NODE_ARGS_PARSED_URI:
+ return serd_node_construct_uri(buf_size, buf, args.data.as_parsed_uri.uri);
+
+ case SERD_NODE_ARGS_FILE_URI:
+ return serd_node_construct_file_uri(buf_size,
+ buf,
+ args.data.as_file_uri.path,
+ args.data.as_file_uri.hostname);
+
+ case SERD_NODE_ARGS_LITERAL:
+ return serd_node_construct_literal(buf_size,
+ buf,
+ args.data.as_literal.string,
+ args.data.as_literal.flags,
+ args.data.as_literal.meta);
+
+ case SERD_NODE_ARGS_PRIMITIVE:
+ return serd_node_construct_value(
+ buf_size, buf, args.data.as_primitive.value);
+
+ case SERD_NODE_ARGS_DECIMAL:
+ return serd_node_construct_decimal(
+ buf_size, buf, args.data.as_decimal.value);
+
+ case SERD_NODE_ARGS_INTEGER:
+ return serd_node_construct_integer(
+ buf_size, buf, args.data.as_integer.value);
+
+ case SERD_NODE_ARGS_HEX:
+ return serd_node_construct_binary(buf_size,
+ buf,
+ args.data.as_blob.size,
+ args.data.as_blob.data,
+ serd_string(NS_XSD "hexBinary"),
+ exess_write_hex);
+
+ case SERD_NODE_ARGS_BASE64:
+ return serd_node_construct_binary(buf_size,
+ buf,
+ args.data.as_blob.size,
+ args.data.as_blob.data,
+ serd_string(NS_XSD "base64Binary"),
+ exess_write_base64);
+ }
- return serd_new_custom_literal(
- allocator, &blob, len, write_base64_literal, &serd_xsd_base64Binary.node);
+ return result(SERD_BAD_ARG, 0U);
}
SerdNodeType
@@ -760,3 +999,5 @@ serd_node_free(SerdAllocator* const allocator, SerdNode* const node)
{
serd_aaligned_free(allocator, node);
}
+
+#undef MUST_SUCCEED
diff --git a/src/node.h b/src/node.h
index 43368367..0dd15d0c 100644
--- a/src/node.h
+++ b/src/node.h
@@ -4,12 +4,13 @@
#ifndef SERD_SRC_NODE_H
#define SERD_SRC_NODE_H
-#include "exess/exess.h"
#include "serd/memory.h"
#include "serd/node.h"
#include "serd/status.h"
+#include "serd/write_result.h"
#include "zix/attributes.h"
+#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -22,19 +23,57 @@ struct SerdNodeImpl {
static const size_t serd_node_align = 2 * sizeof(uint64_t);
-static inline char* ZIX_NONNULL
+#if SIZE_MAX == UINT64_MAX
+
+static inline size_t
+serd_node_pad_length(const size_t n_bytes)
+{
+ const size_t align = sizeof(SerdNode);
+
+ assert((align & (align - 1U)) == 0U);
+
+ return (n_bytes + align + 2U) & ~(align - 1U);
+}
+
+#else
+
+static inline size_t
+serd_node_pad_length(const size_t n_bytes)
+{
+ const size_t pad = sizeof(SerdNode) - (n_bytes + 2) % sizeof(SerdNode);
+ const size_t size = n_bytes + 2 + pad;
+ assert(size % sizeof(SerdNode) == 0);
+ return size;
+}
+
+#endif
+
+ZIX_CONST_FUNC static inline char* ZIX_NONNULL
serd_node_buffer(SerdNode* ZIX_NONNULL node)
{
return (char*)(node + 1);
}
-static inline const char* ZIX_NONNULL
+ZIX_PURE_FUNC static inline const char* ZIX_NONNULL
serd_node_buffer_c(const SerdNode* ZIX_NONNULL node)
{
return (const char*)(node + 1);
}
-static inline const char* ZIX_NONNULL
+ZIX_PURE_FUNC static inline SerdNode* ZIX_NONNULL
+serd_node_meta(SerdNode* const ZIX_NONNULL node)
+{
+ return node + 1 + (serd_node_pad_length(node->length) / sizeof(SerdNode));
+}
+
+ZIX_PURE_FUNC static inline const SerdNode* ZIX_NONNULL
+serd_node_meta_c(const SerdNode* const ZIX_NONNULL node)
+{
+ assert(node->flags & (SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE));
+ return node + 1 + (serd_node_pad_length(node->length) / sizeof(SerdNode));
+}
+
+ZIX_CONST_FUNC static inline const char* ZIX_NONNULL
serd_node_string_i(const SerdNode* const ZIX_NONNULL node)
{
return (const char*)(node + 1);
@@ -47,11 +86,12 @@ serd_node_pattern_match(const SerdNode* ZIX_NULLABLE a,
return !a || !b || serd_node_equals(a, b);
}
-SerdNode* ZIX_ALLOCATED
-serd_node_malloc(SerdAllocator* ZIX_NULLABLE allocator,
- size_t length,
- SerdNodeFlags flags,
- SerdNodeType type);
+ZIX_MALLOC_FUNC SerdNode* ZIX_ALLOCATED
+serd_node_malloc(SerdAllocator* ZIX_NULLABLE allocator, size_t size);
+
+ZIX_MALLOC_FUNC SerdNode* ZIX_ALLOCATED
+serd_node_try_malloc(SerdAllocator* ZIX_NULLABLE allocator,
+ SerdWriteResult result);
SerdStatus
serd_node_set(SerdAllocator* ZIX_NULLABLE allocator,
@@ -59,15 +99,9 @@ serd_node_set(SerdAllocator* ZIX_NULLABLE allocator,
const SerdNode* ZIX_NONNULL src);
ZIX_PURE_FUNC size_t
-serd_node_total_size(const SerdNode* ZIX_NULLABLE node);
+serd_node_total_size(const SerdNode* ZIX_NONNULL node);
void
serd_node_zero_pad(SerdNode* ZIX_NONNULL node);
-ExessResult
-serd_node_get_value_as(const SerdNode* ZIX_NONNULL node,
- ExessDatatype value_type,
- size_t value_size,
- void* ZIX_NONNULL value);
-
#endif // SERD_SRC_NODE_H
diff --git a/src/read_turtle.c b/src/read_turtle.c
index 613b33d2..f85c956a 100644
--- a/src/read_turtle.c
+++ b/src/read_turtle.c
@@ -348,7 +348,7 @@ resolve_IRIREF(SerdReader* const reader,
temp->length = serd_write_uri(uri, write_to_stack, &ctx);
if (!ctx.status) {
// Replace the destination with the new expanded node
- memmove(dest, temp, serd_node_total_size(temp));
+ memmove(dest, temp, sizeof(SerdNode) + serd_node_pad_length(temp->length));
serd_stack_pop_to(&reader->stack, string_start_offset + dest->length);
}
diff --git a/src/value.c b/src/value.c
new file mode 100644
index 00000000..ab6b1b43
--- /dev/null
+++ b/src/value.c
@@ -0,0 +1,101 @@
+// Copyright 2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include "serd/value.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+SerdValue
+serd_nothing(void)
+{
+ static const SerdValue value = {SERD_NOTHING, {0}};
+ return value;
+}
+
+SerdValue
+serd_bool(const bool v)
+{
+ const SerdValue value = {SERD_BOOL, {v}};
+ return value;
+}
+
+SerdValue
+serd_double(const double v)
+{
+ SerdValue value = {SERD_DOUBLE, {0}};
+ value.data.as_double = v;
+ return value;
+}
+
+SerdValue
+serd_float(const float v)
+{
+ SerdValue value = {SERD_FLOAT, {0}};
+ value.data.as_float = v;
+ return value;
+}
+
+SerdValue
+serd_long(const int64_t v)
+{
+ SerdValue value = {SERD_LONG, {0}};
+ value.data.as_long = v;
+ return value;
+}
+
+SerdValue
+serd_int(const int32_t v)
+{
+ SerdValue value = {SERD_INT, {0}};
+ value.data.as_int = v;
+ return value;
+}
+
+SerdValue
+serd_short(const int16_t v)
+{
+ SerdValue value = {SERD_SHORT, {0}};
+ value.data.as_short = v;
+ return value;
+}
+
+SerdValue
+serd_byte(const int8_t v)
+{
+ SerdValue value = {SERD_BYTE, {0}};
+ value.data.as_byte = v;
+ return value;
+}
+
+SerdValue
+serd_ulong(const uint64_t v)
+{
+ SerdValue value = {SERD_ULONG, {0}};
+ value.data.as_ulong = v;
+ return value;
+}
+
+SerdValue
+serd_uint(const uint32_t v)
+{
+ SerdValue value = {SERD_UINT, {0}};
+ value.data.as_uint = v;
+ return value;
+}
+
+SerdValue
+serd_ushort(const uint16_t v)
+{
+ SerdValue value = {SERD_USHORT, {0}};
+ value.data.as_ushort = v;
+ return value;
+}
+
+SerdValue
+serd_ubyte(const uint8_t v)
+{
+ SerdValue value = {SERD_UBYTE, {0}};
+ value.data.as_ubyte = v;
+ return value;
+}
diff --git a/src/world.c b/src/world.c
index 2c563f15..406956b1 100644
--- a/src/world.c
+++ b/src/world.c
@@ -9,7 +9,6 @@
#include "serd/node.h"
#include "serd/status.h"
-#include "serd/string_view.h"
#include "serd/world.h"
#include <assert.h>
@@ -23,7 +22,8 @@ serd_world_new(SerdAllocator* const allocator)
allocator ? allocator : serd_default_allocator();
SerdWorld* world = (SerdWorld*)serd_acalloc(actual, 1, sizeof(SerdWorld));
- SerdNode* blank_node = serd_new_blank(actual, serd_string("b00000000000"));
+ SerdNode* blank_node =
+ serd_node_new(actual, serd_a_blank_string("b00000000000"));
if (!world || !blank_node) {
serd_node_free(actual, blank_node);
diff --git a/src/writer.c b/src/writer.c
index 6d52b4e6..1de5e055 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -18,6 +18,7 @@
#include "serd/env.h"
#include "serd/event.h"
#include "serd/log.h"
+#include "serd/memory.h"
#include "serd/node.h"
#include "serd/output_stream.h"
#include "serd/sink.h"
@@ -1430,12 +1431,14 @@ serd_writer_set_root_uri(SerdWriter* writer, const SerdStringView uri)
{
assert(writer);
- serd_node_free(writer->world->allocator, writer->root_node);
+ SerdAllocator* const allocator = writer->world->allocator;
+
+ serd_node_free(allocator, writer->root_node);
writer->root_node = NULL;
writer->root_uri = SERD_URI_NULL;
if (uri.length) {
- writer->root_node = serd_new_uri(writer->world->allocator, uri);
+ writer->root_node = serd_node_new(allocator, serd_a_uri(uri));
writer->root_uri = serd_node_uri_view(writer->root_node);
}
diff --git a/test/test_caret.c b/test/test_caret.c
index a97b3d0f..9374f65b 100644
--- a/test/test_caret.c
+++ b/test/test_caret.c
@@ -7,7 +7,6 @@
#include "serd/caret.h"
#include "serd/node.h"
-#include "serd/string_view.h"
#include <assert.h>
#include <stddef.h>
@@ -16,7 +15,7 @@
static int
test_caret(void)
{
- SerdNode* const node = serd_new_string(NULL, serd_string("node"));
+ SerdNode* const node = serd_node_new(NULL, serd_a_string("node"));
SerdCaret* const caret = serd_caret_new(NULL, node, 46, 2);
assert(serd_caret_equals(caret, caret));
@@ -29,7 +28,7 @@ test_caret(void)
assert(serd_caret_equals(caret, copy));
assert(!serd_caret_copy(NULL, NULL));
- SerdNode* const other_node = serd_new_string(NULL, serd_string("other"));
+ SerdNode* const other_node = serd_node_new(NULL, serd_a_string("other"));
SerdCaret* const other_file = serd_caret_new(NULL, other_node, 46, 2);
SerdCaret* const other_line = serd_caret_new(NULL, node, 47, 2);
SerdCaret* const other_col = serd_caret_new(NULL, node, 46, 3);
@@ -54,8 +53,12 @@ test_caret(void)
static void
test_failed_alloc(void)
{
- SerdNode* node = serd_new_token(NULL, SERD_LITERAL, serd_string("node"));
+ char node_buf[32];
+ assert(!serd_node_construct(sizeof(node_buf), node_buf, serd_a_string("node"))
+ .status);
+
+ const SerdNode* node = (const SerdNode*)node_buf;
SerdFailingAllocator allocator = serd_failing_allocator();
// Successfully allocate a new caret to count the number of allocations
@@ -84,7 +87,6 @@ test_failed_alloc(void)
serd_caret_free(&allocator.base, copy);
serd_caret_free(&allocator.base, caret);
- serd_node_free(NULL, node);
}
int
diff --git a/test/test_env.c b/test/test_env.c
index 89947826..eec8a2ef 100644
--- a/test/test_env.c
+++ b/test/test_env.c
@@ -202,7 +202,7 @@ static void
test_base_uri(void)
{
SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
- SerdNode* const eg = serd_new_uri(NULL, serd_string(NS_EG));
+ SerdNode* const eg = serd_node_new(NULL, serd_a_uri_string(NS_EG));
// Test that invalid calls work as expected
assert(!serd_env_base_uri(env));
@@ -262,7 +262,7 @@ test_set_prefix(void)
static void
test_expand_untyped_literal(void)
{
- SerdNode* const untyped = serd_new_string(NULL, serd_string("data"));
+ SerdNode* const untyped = serd_node_new(NULL, serd_a_string("data"));
SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
assert(!serd_env_expand_node(env, untyped));
@@ -277,7 +277,7 @@ test_expand_bad_uri_datatype(void)
const SerdStringView type = serd_string("Type");
SerdNode* const typed =
- serd_new_literal(NULL, serd_string("data"), SERD_HAS_DATATYPE, type);
+ serd_node_new(NULL, serd_a_typed_literal(serd_string("data"), type));
SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
@@ -293,9 +293,9 @@ test_expand_uri(void)
const SerdStringView base = serd_string("http://example.org/b/");
SerdEnv* const env = serd_env_new(NULL, base);
- SerdNode* const rel = serd_new_uri(NULL, serd_string("rel"));
+ SerdNode* const rel = serd_node_new(NULL, serd_a_uri_string("rel"));
SerdNode* const rel_out = serd_env_expand_node(env, rel);
- SerdNode* const empty = serd_new_uri(NULL, serd_empty_string());
+ SerdNode* const empty = serd_node_new(NULL, serd_a_uri_string(""));
SerdNode* const empty_out = serd_env_expand_node(env, empty);
assert(!strcmp(serd_node_string(rel_out), "http://example.org/b/rel"));
@@ -313,7 +313,7 @@ test_expand_empty_uri_ref(void)
{
const SerdStringView base = serd_string("http://example.org/b/");
- SerdNode* const rel = serd_new_uri(NULL, serd_string("rel"));
+ SerdNode* const rel = serd_node_new(NULL, serd_a_uri_string("rel"));
SerdEnv* const env = serd_env_new(NULL, base);
SerdNode* const rel_out = serd_env_expand_node(env, rel);
@@ -327,7 +327,7 @@ test_expand_empty_uri_ref(void)
static void
test_expand_bad_uri(void)
{
- SerdNode* const bad_uri = serd_new_uri(NULL, serd_string("rel"));
+ SerdNode* const bad_uri = serd_node_new(NULL, serd_a_uri_string("rel"));
SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
assert(!serd_env_expand_node(env, bad_uri));
@@ -372,7 +372,7 @@ test_expand_bad_curie(void)
static void
test_expand_blank(void)
{
- SerdNode* const blank = serd_new_blank(NULL, serd_string("b1"));
+ SerdNode* const blank = serd_node_new(NULL, serd_a_blank_string("b1"));
SerdEnv* const env = serd_env_new(NULL, serd_empty_string());
assert(!serd_env_expand_node(env, blank));
diff --git a/test/test_log.c b/test/test_log.c
index 5da8ec09..aba9fe23 100644
--- a/test/test_log.c
+++ b/test/test_log.c
@@ -83,7 +83,8 @@ static void
test_caret(void)
{
SerdWorld* const world = serd_world_new(NULL);
- SerdNode* const name = serd_new_string(NULL, serd_string("filename"));
+
+ SerdNode* const name = serd_node_new(NULL, serd_a_string("filename"));
SerdCaret* const caret = serd_caret_new(NULL, name, 46, 2);
serd_logf_at(world, SERD_LOG_LEVEL_NOTICE, caret, "is just ahead of me");
diff --git a/test/test_node.c b/test/test_node.c
index 23d1a45a..6b159007 100644
--- a/test/test_node.c
+++ b/test/test_node.c
@@ -7,6 +7,7 @@
#include "serd/status.h"
#include "serd/string_view.h"
#include "serd/uri.h"
+#include "serd/value.h"
#include "serd/write_result.h"
#include <assert.h>
@@ -48,54 +49,178 @@
#endif
static void
+test_new(void)
+{
+ const SerdNodeArgs bad_args = {(SerdNodeArgsType)-1,
+ {{(SerdNodeType)-1, {NULL, 0U}}}};
+
+ assert(!serd_node_new(NULL, bad_args));
+}
+
+static void
+test_value(void)
+{
+ static const double double_one = 1.0;
+ static const float float_two = 2.0f;
+
+ SerdNode* const null_node =
+ serd_node_new(NULL, serd_a_primitive(serd_nothing()));
+ SerdNode* const bool_node =
+ serd_node_new(NULL, serd_a_primitive(serd_bool(false)));
+ SerdNode* const double_node =
+ serd_node_new(NULL, serd_a_primitive(serd_double(1.0)));
+ SerdNode* const float_node =
+ serd_node_new(NULL, serd_a_primitive(serd_float(2.0f)));
+ SerdNode* const long_node =
+ serd_node_new(NULL, serd_a_primitive(serd_long(3)));
+ SerdNode* const int_node = serd_node_new(NULL, serd_a_primitive(serd_int(4)));
+ SerdNode* const short_node =
+ serd_node_new(NULL, serd_a_primitive(serd_short(5)));
+ SerdNode* const byte_node =
+ serd_node_new(NULL, serd_a_primitive(serd_byte(6)));
+ SerdNode* const ulong_node =
+ serd_node_new(NULL, serd_a_primitive(serd_ulong(7U)));
+ SerdNode* const uint_node =
+ serd_node_new(NULL, serd_a_primitive(serd_uint(8U)));
+ SerdNode* const ushort_node =
+ serd_node_new(NULL, serd_a_primitive(serd_ushort(9U)));
+ SerdNode* const ubyte_node =
+ serd_node_new(NULL, serd_a_primitive(serd_ubyte(10U)));
+
+ assert(!null_node);
+
+ assert(!strcmp(serd_node_string(bool_node), "false"));
+ assert(serd_node_value(bool_node).type == SERD_BOOL);
+ assert(serd_node_value(bool_node).data.as_bool == false);
+
+ assert(!strcmp(serd_node_string(double_node), "1.0E0"));
+ assert(serd_node_value(double_node).type == SERD_DOUBLE);
+ {
+ const double double_value = serd_node_value(double_node).data.as_double;
+ assert(!memcmp(&double_value, &double_one, sizeof(double)));
+ }
+
+ assert(!strcmp(serd_node_string(float_node), "2.0E0"));
+ assert(serd_node_value(float_node).type == SERD_FLOAT);
+ {
+ const float float_value = serd_node_value(float_node).data.as_float;
+ assert(!memcmp(&float_value, &float_two, sizeof(float)));
+ }
+
+ assert(!strcmp(serd_node_string(long_node), "3"));
+ assert(serd_node_value(long_node).type == SERD_LONG);
+ assert(serd_node_value(long_node).data.as_long == 3);
+
+ assert(!strcmp(serd_node_string(int_node), "4"));
+ assert(serd_node_value(int_node).type == SERD_INT);
+ assert(serd_node_value(int_node).data.as_int == 4);
+
+ assert(!strcmp(serd_node_string(short_node), "5"));
+ assert(serd_node_value(short_node).type == SERD_SHORT);
+ assert(serd_node_value(short_node).data.as_short == 5);
+
+ assert(!strcmp(serd_node_string(byte_node), "6"));
+ assert(serd_node_value(byte_node).type == SERD_BYTE);
+ assert(serd_node_value(byte_node).data.as_byte == 6);
+
+ assert(!strcmp(serd_node_string(ulong_node), "7"));
+ assert(serd_node_value(ulong_node).type == SERD_ULONG);
+ assert(serd_node_value(ulong_node).data.as_ulong == 7U);
+
+ assert(!strcmp(serd_node_string(uint_node), "8"));
+ assert(serd_node_value(uint_node).type == SERD_UINT);
+ assert(serd_node_value(uint_node).data.as_uint == 8U);
+
+ assert(!strcmp(serd_node_string(ushort_node), "9"));
+ assert(serd_node_value(ushort_node).type == SERD_USHORT);
+ assert(serd_node_value(ushort_node).data.as_ushort == 9U);
+
+ assert(!strcmp(serd_node_string(ubyte_node), "10"));
+ assert(serd_node_value(ubyte_node).type == SERD_UBYTE);
+ assert(serd_node_value(ubyte_node).data.as_ubyte == 10U);
+
+ serd_node_free(NULL, bool_node);
+ serd_node_free(NULL, double_node);
+ serd_node_free(NULL, float_node);
+ serd_node_free(NULL, long_node);
+ serd_node_free(NULL, int_node);
+ serd_node_free(NULL, short_node);
+ serd_node_free(NULL, byte_node);
+ serd_node_free(NULL, ulong_node);
+ serd_node_free(NULL, uint_node);
+ serd_node_free(NULL, ushort_node);
+ serd_node_free(NULL, ubyte_node);
+}
+
+static void
test_boolean(void)
{
- SerdNode* const true_node = serd_new_boolean(NULL, true);
- assert(!strcmp(serd_node_string(true_node), "true"));
- assert(serd_get_boolean(true_node));
-
- const SerdNode* const true_datatype = serd_node_datatype(true_node);
- assert(true_datatype);
- assert(!strcmp(serd_node_string(true_datatype), NS_XSD "boolean"));
- serd_node_free(NULL, true_node);
-
- SerdNode* const false_node = serd_new_boolean(NULL, false);
- assert(!strcmp(serd_node_string(false_node), "false"));
- assert(!serd_get_boolean(false_node));
-
- const SerdNode* const false_datatype = serd_node_datatype(false_node);
- assert(false_datatype);
- assert(!strcmp(serd_node_string(false_datatype), NS_XSD "boolean"));
- serd_node_free(NULL, false_node);
+ {
+ SerdNode* const true_node =
+ serd_node_new(NULL, serd_a_primitive(serd_bool(true)));
+ assert(true_node);
+ assert(!strcmp(serd_node_string(true_node), "true"));
+ assert(serd_node_value(true_node).data.as_bool);
+
+ const SerdNode* const true_datatype = serd_node_datatype(true_node);
+ assert(true_datatype);
+ assert(!strcmp(serd_node_string(true_datatype), NS_XSD "boolean"));
+ serd_node_free(NULL, true_node);
+ }
+ {
+ SerdNode* const false_node =
+ serd_node_new(NULL, serd_a_primitive(serd_bool(false)));
+ assert(false_node);
+ assert(!strcmp(serd_node_string(false_node), "false"));
+ assert(!serd_node_value(false_node).data.as_bool);
+
+ const SerdNode* const false_datatype = serd_node_datatype(false_node);
+ assert(false_datatype);
+ assert(!strcmp(serd_node_string(false_datatype), NS_XSD "boolean"));
+ serd_node_free(NULL, false_node);
+ }
}
static void
-check_get_boolean(const char* string,
- const char* datatype_uri,
- const bool expected)
+check_get_bool(const char* string,
+ const char* datatype_uri,
+ const bool lossy,
+ const SerdValueType value_type,
+ const bool expected)
{
- SerdNode* const node = serd_new_literal(
- NULL, serd_string(string), SERD_HAS_DATATYPE, serd_string(datatype_uri));
+ SerdNode* const node = serd_node_new(
+ NULL, serd_a_typed_literal(serd_string(string), serd_string(datatype_uri)));
assert(node);
- assert(serd_get_boolean(node) == expected);
+
+ const SerdValue value = serd_node_value_as(node, SERD_BOOL, lossy);
+
+ assert(value.type == value_type);
+ assert(value.data.as_bool == expected);
serd_node_free(NULL, node);
}
static void
-test_get_boolean(void)
+test_get_bool(void)
{
- check_get_boolean("false", NS_XSD "boolean", false);
- check_get_boolean("true", NS_XSD "boolean", true);
- check_get_boolean("0", NS_XSD "boolean", false);
- check_get_boolean("1", NS_XSD "boolean", true);
- check_get_boolean("0", NS_XSD "integer", false);
- check_get_boolean("1", NS_XSD "integer", true);
- check_get_boolean("0.0", NS_XSD "double", false);
- check_get_boolean("1.0", NS_XSD "double", true);
- check_get_boolean("unknown", NS_XSD "string", false);
- check_get_boolean("!invalid", NS_XSD "long", false);
+ check_get_bool("false", NS_XSD "boolean", false, SERD_BOOL, false);
+ check_get_bool("true", NS_XSD "boolean", false, SERD_BOOL, true);
+ check_get_bool("0", NS_XSD "boolean", false, SERD_BOOL, false);
+ check_get_bool("1", NS_XSD "boolean", false, SERD_BOOL, true);
+ check_get_bool("0", NS_XSD "integer", false, SERD_BOOL, false);
+ check_get_bool("1", NS_XSD "integer", false, SERD_BOOL, true);
+ check_get_bool("0.0", NS_XSD "double", false, SERD_BOOL, false);
+ check_get_bool("1.0", NS_XSD "double", false, SERD_BOOL, true);
+
+ check_get_bool("2", NS_XSD "integer", false, SERD_NOTHING, false);
+ check_get_bool("1.5", NS_XSD "double", false, SERD_NOTHING, false);
+
+ check_get_bool("2", NS_XSD "integer", true, SERD_BOOL, true);
+ check_get_bool("1.5", NS_XSD "double", true, SERD_BOOL, true);
+
+ check_get_bool("unknown", NS_XSD "string", true, SERD_NOTHING, false);
+ check_get_bool("!invalid", NS_XSD "long", true, SERD_NOTHING, false);
}
static void
@@ -114,7 +239,7 @@ test_decimal(void)
"0.0000000001"};
for (size_t i = 0; i < sizeof(test_values) / sizeof(double); ++i) {
- SerdNode* node = serd_new_decimal(NULL, test_values[i], NULL);
+ SerdNode* node = serd_node_new(NULL, serd_a_decimal(test_values[i]));
const char* node_str = serd_node_string(node);
assert(!strcmp(node_str, test_strings[i]));
@@ -125,8 +250,8 @@ test_decimal(void)
assert(datatype);
assert(!strcmp(serd_node_string(datatype), NS_XSD "decimal"));
- const double value = serd_get_double(node);
- assert(!memcmp(&value, &test_values[i], sizeof(value)));
+ const SerdValue value = serd_node_value(node);
+ assert(!memcmp(&value.data.as_double, &test_values[i], sizeof(double)));
serd_node_free(NULL, node);
}
}
@@ -139,7 +264,8 @@ test_double(void)
"0.0E0", "-0.0E0", "1.2E0", "-2.3E0", "4.56789E6"};
for (size_t i = 0; i < sizeof(test_values) / sizeof(double); ++i) {
- SerdNode* node = serd_new_double(NULL, test_values[i]);
+ SerdNode* node =
+ serd_node_new(NULL, serd_a_primitive(serd_double(test_values[i])));
const char* node_str = serd_node_string(node);
assert(!strcmp(node_str, test_strings[i]));
@@ -150,24 +276,35 @@ test_double(void)
assert(datatype);
assert(!strcmp(serd_node_string(datatype), NS_XSD "double"));
- const double value = serd_get_double(node);
- assert(!memcmp(&value, &test_values[i], sizeof(value)));
+ const SerdValue value = serd_node_value(node);
+ assert(!memcmp(&value.data.as_double, &test_values[i], sizeof(double)));
serd_node_free(NULL, node);
}
}
static void
-check_get_double(const char* string,
- const char* datatype_uri,
- const double expected)
+check_get_double(const char* string,
+ const char* datatype_uri,
+ const bool lossy,
+ const SerdValueType value_type,
+ const double expected)
{
- SerdNode* const node = serd_new_literal(
- NULL, serd_string(string), SERD_HAS_DATATYPE, serd_string(datatype_uri));
+ SerdNode* const node = serd_node_new(
+ NULL, serd_a_typed_literal(serd_string(string), serd_string(datatype_uri)));
assert(node);
- const double value = serd_get_double(node);
- assert(!memcmp(&value, &expected, sizeof(value)));
+ const SerdValue value = serd_node_value_as(node, SERD_DOUBLE, lossy);
+
+ assert(value.type == value_type);
+
+ SERD_DISABLE_CONVERSION_WARNINGS
+
+ assert(value_type == SERD_NOTHING ||
+ ((isnan(value.data.as_double) && isnan(expected)) ||
+ !memcmp(&value.data.as_double, &expected, sizeof(double))));
+
+ SERD_RESTORE_WARNINGS
serd_node_free(NULL, node);
}
@@ -175,34 +312,19 @@ check_get_double(const char* string,
static void
test_get_double(void)
{
- check_get_double("1.2", NS_XSD "double", 1.2);
- check_get_double("-.5", NS_XSD "float", -0.5);
- check_get_double("-67", NS_XSD "long", -67.0);
- check_get_double("8.9", NS_XSD "decimal", 8.9);
- check_get_double("false", NS_XSD "boolean", 0.0);
- check_get_double("true", NS_XSD "boolean", 1.0);
-
- static const uint8_t blob[] = {1U, 2U, 3U, 4U};
+ check_get_double("1.2", NS_XSD "double", false, SERD_DOUBLE, 1.2);
+ check_get_double("-.5", NS_XSD "float", false, SERD_DOUBLE, -0.5);
+ check_get_double("-67", NS_XSD "long", false, SERD_DOUBLE, -67.0);
+ check_get_double("67", NS_XSD "unsignedLong", false, SERD_DOUBLE, 67.0);
+ check_get_double("8.9", NS_XSD "decimal", false, SERD_DOUBLE, 8.9);
+ check_get_double("false", NS_XSD "boolean", false, SERD_DOUBLE, 0.0);
+ check_get_double("true", NS_XSD "boolean", false, SERD_DOUBLE, 1.0);
SERD_DISABLE_CONVERSION_WARNINGS
-
- SerdNode* const nan = serd_new_string(NULL, serd_string("unknown"));
- assert(isnan(serd_get_double(nan)));
- serd_node_free(NULL, nan);
-
- SerdNode* const invalid = serd_new_literal(NULL,
- serd_string("!invalid"),
- SERD_HAS_DATATYPE,
- serd_string(NS_XSD "long"));
-
- assert(isnan(serd_get_double(invalid)));
- serd_node_free(NULL, invalid);
-
- SerdNode* const base64 = serd_new_base64(NULL, blob, sizeof(blob));
-
- assert(isnan(serd_get_double(base64)));
- serd_node_free(NULL, base64);
-
+ check_get_double("str", NS_XSD "string", true, SERD_NOTHING, NAN);
+ check_get_double("!invalid", NS_XSD "long", true, SERD_NOTHING, NAN);
+ check_get_double("D3AD", NS_XSD "hexBinary", true, SERD_NOTHING, NAN);
+ check_get_double("Zm9v", NS_XSD "base64Binary", true, SERD_NOTHING, NAN);
SERD_RESTORE_WARNINGS
}
@@ -214,7 +336,8 @@ test_float(void)
"0.0E0", "-0.0E0", "1.5E0", "-2.5E0", "4.56789E6"};
for (size_t i = 0; i < sizeof(test_values) / sizeof(float); ++i) {
- SerdNode* node = serd_new_float(NULL, test_values[i]);
+ SerdNode* node =
+ serd_node_new(NULL, serd_a_primitive(serd_float(test_values[i])));
const char* node_str = serd_node_string(node);
assert(!strcmp(node_str, test_strings[i]));
@@ -225,24 +348,35 @@ test_float(void)
assert(datatype);
assert(!strcmp(serd_node_string(datatype), NS_XSD "float"));
- const float value = serd_get_float(node);
- assert(!memcmp(&value, &test_values[i], sizeof(value)));
+ const SerdValue value = serd_node_value(node);
+ assert(!memcmp(&value.data.as_float, &test_values[i], sizeof(float)));
serd_node_free(NULL, node);
}
}
static void
-check_get_float(const char* string,
- const char* datatype_uri,
- const float expected)
+check_get_float(const char* string,
+ const char* datatype_uri,
+ const bool lossy,
+ const SerdValueType value_type,
+ const float expected)
{
- SerdNode* const node = serd_new_literal(
- NULL, serd_string(string), SERD_HAS_DATATYPE, serd_string(datatype_uri));
+ SerdNode* const node = serd_node_new(
+ NULL, serd_a_typed_literal(serd_string(string), serd_string(datatype_uri)));
assert(node);
- const float value = serd_get_float(node);
- assert(!memcmp(&value, &expected, sizeof(value)));
+ const SerdValue value = serd_node_value_as(node, SERD_FLOAT, lossy);
+
+ assert(value.type == value_type);
+
+ SERD_DISABLE_CONVERSION_WARNINGS
+
+ assert(value_type == SERD_NOTHING ||
+ ((isnan(value.data.as_float) && isnan(expected)) ||
+ !memcmp(&value.data.as_float, &expected, sizeof(float))));
+
+ SERD_RESTORE_WARNINGS
serd_node_free(NULL, node);
}
@@ -250,29 +384,20 @@ check_get_float(const char* string,
static void
test_get_float(void)
{
- check_get_float("1.2", NS_XSD "float", 1.2f);
- check_get_float("-.5", NS_XSD "float", -0.5f);
- check_get_float("-67", NS_XSD "long", -67.0f);
- check_get_float("1.5", NS_XSD "decimal", 1.5f);
- check_get_float("false", NS_XSD "boolean", 0.0f);
- check_get_float("true", NS_XSD "boolean", 1.0f);
+ check_get_float("1.2", NS_XSD "float", false, SERD_FLOAT, 1.2f);
+ check_get_float("-.5", NS_XSD "float", false, SERD_FLOAT, -0.5f);
+ check_get_float("-67", NS_XSD "long", false, SERD_FLOAT, -67.0f);
+ check_get_float("false", NS_XSD "boolean", false, SERD_FLOAT, 0.0f);
+ check_get_float("true", NS_XSD "boolean", false, SERD_FLOAT, 1.0f);
- SERD_DISABLE_CONVERSION_WARNINGS
-
- SerdNode* const nan = serd_new_string(NULL, serd_string("unknown"));
- assert(isnan(serd_get_float(nan)));
- serd_node_free(NULL, nan);
-
- SerdNode* const invalid = serd_new_literal(NULL,
- serd_string("!invalid"),
- SERD_HAS_DATATYPE,
- serd_string(NS_XSD "long"));
-
- assert(isnan(serd_get_double(invalid)));
+ check_get_float("1.5", NS_XSD "decimal", true, SERD_FLOAT, 1.5f);
+ SERD_DISABLE_CONVERSION_WARNINGS
+ check_get_float("str", NS_XSD "string", true, SERD_NOTHING, NAN);
+ check_get_float("!invalid", NS_XSD "long", true, SERD_NOTHING, NAN);
+ check_get_float("D3AD", NS_XSD "hexBinary", true, SERD_NOTHING, NAN);
+ check_get_float("Zm9v", NS_XSD "base64Binary", true, SERD_NOTHING, NAN);
SERD_RESTORE_WARNINGS
-
- serd_node_free(NULL, invalid);
}
static void
@@ -283,7 +408,7 @@ test_integer(void)
"0", "0", "-23", "23", "-12340", "1000", "-1000"};
for (size_t i = 0; i < sizeof(test_values) / sizeof(double); ++i) {
- SerdNode* node = serd_new_integer(NULL, test_values[i]);
+ SerdNode* node = serd_node_new(NULL, serd_a_integer(test_values[i]));
const char* node_str = serd_node_string(node);
assert(!strcmp(node_str, test_strings[i]));
const size_t len = strlen(node_str);
@@ -293,21 +418,27 @@ test_integer(void)
assert(datatype);
assert(!strcmp(serd_node_string(datatype), NS_XSD "integer"));
- assert(serd_get_integer(node) == test_values[i]);
+ assert(serd_node_value(node).data.as_long == test_values[i]);
serd_node_free(NULL, node);
}
}
static void
-check_get_integer(const char* string,
- const char* datatype_uri,
- const int64_t expected)
+check_get_integer(const char* string,
+ const char* datatype_uri,
+ const bool lossy,
+ const SerdValueType value_type,
+ const int64_t expected)
{
- SerdNode* const node = serd_new_literal(
- NULL, serd_string(string), SERD_HAS_DATATYPE, serd_string(datatype_uri));
+ SerdNode* const node = serd_node_new(
+ NULL, serd_a_typed_literal(serd_string(string), serd_string(datatype_uri)));
assert(node);
- assert(serd_get_integer(node) == expected);
+
+ const SerdValue value = serd_node_value_as(node, SERD_LONG, lossy);
+
+ assert(value.type == value_type);
+ assert(value_type == SERD_NOTHING || value.data.as_long == expected);
serd_node_free(NULL, node);
}
@@ -315,20 +446,66 @@ check_get_integer(const char* string,
static void
test_get_integer(void)
{
- check_get_integer("12", NS_XSD "long", 12);
- check_get_integer("-34", NS_XSD "long", -34);
- check_get_integer("56", NS_XSD "integer", 56);
- check_get_integer("false", NS_XSD "boolean", 0);
- check_get_integer("true", NS_XSD "boolean", 1);
- check_get_integer("78.0", NS_XSD "decimal", 78);
- check_get_integer("unknown", NS_XSD "string", 0);
- check_get_integer("!invalid", NS_XSD "long", 0);
+ check_get_integer("12", NS_XSD "long", false, SERD_LONG, 12);
+ check_get_integer("-34", NS_XSD "long", false, SERD_LONG, -34);
+ check_get_integer("56", NS_XSD "integer", false, SERD_LONG, 56);
+ check_get_integer("false", NS_XSD "boolean", false, SERD_LONG, 0);
+ check_get_integer("true", NS_XSD "boolean", false, SERD_LONG, 1);
+ check_get_integer("78.0", NS_XSD "decimal", false, SERD_LONG, 78);
+
+ check_get_integer("0", NS_XSD "nonPositiveInteger", false, SERD_LONG, 0);
+ check_get_integer("-1", NS_XSD "negativeInteger", false, SERD_LONG, -1);
+ check_get_integer("2", NS_XSD "nonNegativeInteger", false, SERD_LONG, 2);
+ check_get_integer("3", NS_XSD "positiveInteger", false, SERD_LONG, 3);
+
+ check_get_integer("78.5", NS_XSD "decimal", false, SERD_NOTHING, 0);
+ check_get_integer("78.5", NS_XSD "decimal", true, SERD_LONG, 78);
+
+ check_get_integer("unknown", NS_XSD "string", true, SERD_NOTHING, 0);
+ check_get_integer("!invalid", NS_XSD "long", true, SERD_NOTHING, 0);
+}
+
+static void
+test_hex(void)
+{
+ assert(!serd_node_new(NULL, serd_a_hex(0, &SERD_URI_NULL)));
+
+ // Test valid hex blobs with a range of sizes
+ for (size_t size = 1; size < 256; ++size) {
+ uint8_t* const data = (uint8_t*)malloc(size);
+ for (size_t i = 0; i < size; ++i) {
+ data[i] = (uint8_t)((size + i) % 256);
+ }
+
+ SerdNode* blob = serd_node_new(NULL, serd_a_hex(size, data));
+ const char* blob_str = serd_node_string(blob);
+ const size_t max_size = serd_node_decoded_size(blob);
+ uint8_t* out = (uint8_t*)calloc(1, max_size);
+
+ const SerdWriteResult r = serd_node_decode(blob, max_size, out);
+ assert(r.status == SERD_SUCCESS);
+ assert(r.count == size);
+ assert(r.count <= max_size);
+ assert(serd_node_length(blob) == strlen(blob_str));
+
+ for (size_t i = 0; i < size; ++i) {
+ assert(out[i] == data[i]);
+ }
+
+ const SerdNode* const datatype = serd_node_datatype(blob);
+ assert(datatype);
+ assert(!strcmp(serd_node_string(datatype), NS_XSD "hexBinary"));
+
+ serd_node_free(NULL, blob);
+ free(out);
+ free(data);
+ }
}
static void
test_base64(void)
{
- assert(!serd_new_base64(NULL, &SERD_URI_NULL, 0));
+ assert(!serd_node_new(NULL, serd_a_base64(0, &SERD_URI_NULL)));
// Test valid base64 blobs with a range of sizes
for (size_t size = 1; size < 256; ++size) {
@@ -337,12 +514,12 @@ test_base64(void)
data[i] = (uint8_t)((size + i) % 256);
}
- SerdNode* blob = serd_new_base64(NULL, data, size);
+ SerdNode* blob = serd_node_new(NULL, serd_a_base64(size, data));
const char* blob_str = serd_node_string(blob);
- const size_t max_size = serd_get_base64_size(blob);
+ const size_t max_size = serd_node_decoded_size(blob);
uint8_t* out = (uint8_t*)calloc(1, max_size);
- const SerdWriteResult r = serd_get_base64(blob, max_size, out);
+ const SerdWriteResult r = serd_node_decode(blob, max_size, out);
assert(r.status == SERD_SUCCESS);
assert(r.count == size);
assert(r.count <= max_size);
@@ -363,19 +540,17 @@ test_base64(void)
}
static void
-check_get_base64(const char* string,
- const char* datatype_uri,
- const char* expected)
+check_decode(const char* string, const char* datatype_uri, const char* expected)
{
- SerdNode* const node = serd_new_literal(
- NULL, serd_string(string), SERD_HAS_DATATYPE, serd_string(datatype_uri));
+ SerdNode* const node = serd_node_new(
+ NULL, serd_a_typed_literal(serd_string(string), serd_string(datatype_uri)));
assert(node);
- const size_t max_size = serd_get_base64_size(node);
+ const size_t max_size = serd_node_decoded_size(node);
char* const decoded = (char*)calloc(1, max_size + 1);
- const SerdWriteResult r = serd_get_base64(node, max_size, decoded);
+ const SerdWriteResult r = serd_node_decode(node, max_size, decoded);
assert(!r.status);
assert(r.count <= max_size);
@@ -387,22 +562,53 @@ check_get_base64(const char* string,
}
static void
-test_get_base64(void)
+test_decode(void)
{
- check_get_base64("Zm9vYmFy", NS_XSD "base64Binary", "foobar");
- check_get_base64("Zm9vYg==", NS_XSD "base64Binary", "foob");
- check_get_base64(" \f\n\r\t\vZm9v \f\n\r\t\v", NS_XSD "base64Binary", "foo");
+ check_decode("666F6F626172", NS_XSD "hexBinary", "foobar");
+ check_decode("666F6F62", NS_XSD "hexBinary", "foob");
- SerdNode* const node = serd_new_literal(NULL,
- serd_string("Zm9v"),
- SERD_HAS_DATATYPE,
- serd_string(NS_XSD "base64Binary"));
+ check_decode("Zm9vYmFy", NS_XSD "base64Binary", "foobar");
+ check_decode("Zm9vYg==", NS_XSD "base64Binary", "foob");
+ check_decode(" \f\n\r\t\vZm9v \f\n\r\t\v", NS_XSD "base64Binary", "foo");
- char small[2] = {0};
- const SerdWriteResult r = serd_get_base64(node, sizeof(small), small);
+ char small[2] = {0};
- assert(r.status == SERD_OVERFLOW);
- serd_node_free(NULL, node);
+ {
+ SerdNode* const node =
+ serd_node_new(NULL,
+ serd_a_typed_literal(serd_string("Zm9v"),
+ serd_string(NS_XSD "base64Binary")));
+
+ const SerdWriteResult r = serd_node_decode(node, sizeof(small), small);
+
+ assert(r.status == SERD_OVERFLOW);
+ serd_node_free(NULL, node);
+ }
+ {
+ SerdNode* const string = serd_node_new(NULL, serd_a_string("string"));
+
+ assert(serd_node_decoded_size(string) == 0U);
+
+ const SerdWriteResult r = serd_node_decode(string, sizeof(small), small);
+
+ assert(r.status == SERD_BAD_ARG);
+ assert(r.count == 0U);
+ serd_node_free(NULL, string);
+ }
+ {
+ SerdNode* const unknown = serd_node_new(
+ NULL,
+ serd_a_typed_literal(serd_string("secret"),
+ serd_string("http://example.org/Datatype")));
+
+ assert(serd_node_decoded_size(unknown) == 0U);
+
+ const SerdWriteResult r = serd_node_decode(unknown, sizeof(small), small);
+
+ assert(r.status == SERD_BAD_ARG);
+ assert(r.count == 0U);
+ serd_node_free(NULL, unknown);
+ }
}
static void
@@ -413,8 +619,8 @@ test_node_equals(void)
static const SerdStringView replacement_char = {
(const char*)replacement_char_str, 3};
- SerdNode* lhs = serd_new_string(NULL, replacement_char);
- SerdNode* rhs = serd_new_string(NULL, serd_string("123"));
+ SerdNode* lhs = serd_node_new(NULL, serd_a_string_view(replacement_char));
+ SerdNode* rhs = serd_node_new(NULL, serd_a_string("123"));
assert(serd_node_equals(lhs, lhs));
assert(!serd_node_equals(lhs, rhs));
@@ -428,7 +634,7 @@ test_node_equals(void)
static void
test_node_from_string(void)
{
- SerdNode* const hello = serd_new_string(NULL, serd_string("hello\""));
+ SerdNode* const hello = serd_node_new(NULL, serd_a_string("hello\""));
assert(serd_node_length(hello) == 6);
assert(!serd_node_flags(hello));
assert(!strncmp(serd_node_string(hello), "hello\"", 6));
@@ -436,7 +642,8 @@ test_node_from_string(void)
assert(serd_node_string_view(hello).length == 6);
serd_node_free(NULL, hello);
- SerdNode* const uri = serd_new_uri(NULL, serd_string("http://example.org/"));
+ SerdNode* const uri =
+ serd_node_new(NULL, serd_a_uri_string("http://example.org/"));
assert(serd_node_length(uri) == 19);
assert(!strcmp(serd_node_string(uri), "http://example.org/"));
assert(serd_node_uri_view(uri).authority.length == 11);
@@ -447,7 +654,8 @@ test_node_from_string(void)
static void
test_node_from_substring(void)
{
- SerdNode* const a_b = serd_new_string(NULL, serd_substring("a\"bc", 3));
+ SerdNode* const a_b =
+ serd_node_new(NULL, serd_a_string_view(serd_substring("a\"bc", 3)));
assert(serd_node_length(a_b) == 3);
assert(!serd_node_flags(a_b));
assert(strlen(serd_node_string(a_b)) == 3);
@@ -471,48 +679,42 @@ test_literal(void)
const SerdStringView hello_str = serd_string("hello");
const SerdStringView empty_str = serd_empty_string();
- assert(!serd_new_literal(NULL,
- hello_str,
- SERD_HAS_DATATYPE | SERD_HAS_LANGUAGE,
- serd_string("whatever")));
-
- assert(!serd_new_literal(NULL, hello_str, SERD_HAS_DATATYPE, empty_str));
- assert(!serd_new_literal(NULL, hello_str, SERD_HAS_LANGUAGE, empty_str));
+ assert(!serd_node_new(NULL, serd_a_typed_literal(hello_str, empty_str)));
+ assert(!serd_node_new(NULL, serd_a_plain_literal(hello_str, empty_str)));
assert(
- !serd_new_literal(NULL, hello_str, SERD_HAS_DATATYPE, serd_string("Type")));
+ !serd_node_new(NULL, serd_a_typed_literal(hello_str, serd_string("Type"))));
assert(
- !serd_new_literal(NULL, hello_str, SERD_HAS_DATATYPE, serd_string("de")));
+ !serd_node_new(NULL, serd_a_typed_literal(hello_str, serd_string("de"))));
assert(
- !serd_new_literal(NULL, hello_str, SERD_HAS_LANGUAGE, serd_string("3n")));
+ !serd_node_new(NULL, serd_a_plain_literal(hello_str, serd_string("3n"))));
assert(
- !serd_new_literal(NULL, hello_str, SERD_HAS_LANGUAGE, serd_string("d3")));
+ !serd_node_new(NULL, serd_a_plain_literal(hello_str, serd_string("d3"))));
assert(
- !serd_new_literal(NULL, hello_str, SERD_HAS_LANGUAGE, serd_string("d3")));
+ !serd_node_new(NULL, serd_a_plain_literal(hello_str, serd_string("d3"))));
assert(
- !serd_new_literal(NULL, hello_str, SERD_HAS_LANGUAGE, serd_string("en-!")));
+ !serd_node_new(NULL, serd_a_plain_literal(hello_str, serd_string("en-!"))));
- SerdNode* hello2 = serd_new_string(NULL, serd_string("hello\""));
+ SerdNode* hello2 = serd_node_new(NULL, serd_a_string("hello\""));
assert(serd_node_length(hello2) == 6 &&
!strcmp(serd_node_string(hello2), "hello\""));
check_copy_equals(hello2);
- assert(!serd_new_literal(NULL,
- serd_string("plain"),
- SERD_HAS_DATATYPE,
- serd_string(NS_RDF "langString")));
+ assert(
+ !serd_node_new(NULL,
+ serd_a_typed_literal(serd_string("plain"),
+ serd_string(NS_RDF "langString"))));
serd_node_free(NULL, hello2);
const char* lang_lit_str = "\"Hello\"@en-ca";
SerdNode* sliced_lang_lit =
- serd_new_literal(NULL,
- serd_substring(lang_lit_str + 1, 5),
- SERD_HAS_LANGUAGE,
- serd_substring(lang_lit_str + 8, 5));
+ serd_node_new(NULL,
+ serd_a_plain_literal(serd_substring(lang_lit_str + 1, 5),
+ serd_substring(lang_lit_str + 8, 5)));
assert(!strcmp(serd_node_string(sliced_lang_lit), "Hello"));
@@ -524,10 +726,9 @@ test_literal(void)
const char* type_lit_str = "\"Hallo\"^^<http://example.org/Greeting>";
SerdNode* sliced_type_lit =
- serd_new_literal(NULL,
- serd_substring(type_lit_str + 1, 5),
- SERD_HAS_DATATYPE,
- serd_substring(type_lit_str + 10, 27));
+ serd_node_new(NULL,
+ serd_a_typed_literal(serd_substring(type_lit_str + 1, 5),
+ serd_substring(type_lit_str + 10, 27)));
assert(!strcmp(serd_node_string(sliced_type_lit), "Hallo"));
@@ -540,7 +741,7 @@ test_literal(void)
static void
test_blank(void)
{
- SerdNode* blank = serd_new_blank(NULL, serd_string("b0"));
+ SerdNode* blank = serd_node_new(NULL, serd_a_blank_string("b0"));
assert(serd_node_length(blank) == 2);
assert(serd_node_flags(blank) == 0);
assert(!strcmp(serd_node_string(blank), "b0"));
@@ -550,37 +751,34 @@ test_blank(void)
static void
test_compare(void)
{
- SerdNode* xsd_short =
- serd_new_uri(NULL, serd_string("http://www.w3.org/2001/XMLSchema#short"));
+ SerdNode* angst = serd_node_new(NULL, serd_a_string("angst"));
- SerdNode* angst = serd_new_string(NULL, serd_string("angst"));
-
- SerdNode* angst_de = serd_new_literal(
- NULL, serd_string("angst"), SERD_HAS_LANGUAGE, serd_string("de"));
+ SerdNode* angst_de = serd_node_new(
+ NULL, serd_a_plain_literal(serd_string("angst"), serd_string("de")));
assert(angst_de);
- SerdNode* angst_en = serd_new_literal(
- NULL, serd_string("angst"), SERD_HAS_LANGUAGE, serd_string("en"));
+ SerdNode* angst_en = serd_node_new(
+ NULL, serd_a_plain_literal(serd_string("angst"), serd_string("en")));
- SerdNode* hallo = serd_new_literal(
- NULL, serd_string("Hallo"), SERD_HAS_LANGUAGE, serd_string("de"));
+ SerdNode* hallo = serd_node_new(
+ NULL, serd_a_typed_literal(serd_string("Hallo"), serd_string("de")));
- SerdNode* hello = serd_new_string(NULL, serd_string("Hello"));
- SerdNode* universe = serd_new_string(NULL, serd_string("Universe"));
- SerdNode* integer = serd_new_integer(NULL, 4);
- SerdNode* blank = serd_new_blank(NULL, serd_string("b1"));
- SerdNode* uri = serd_new_uri(NULL, serd_string("http://example.org/"));
+ SerdNode* hello = serd_node_new(NULL, serd_a_string("Hello"));
+ SerdNode* universe = serd_node_new(NULL, serd_a_string("Universe"));
+ SerdNode* integer = serd_node_new(NULL, serd_a_integer(4));
+ SerdNode* short_int = serd_node_new(NULL, serd_a_primitive(serd_short(4)));
+ SerdNode* blank = serd_node_new(NULL, serd_a_blank_string("b1"));
+ SerdNode* uri = serd_node_new(NULL, serd_a_uri_string("http://example.org/"));
- SerdNode* aardvark =
- serd_new_literal(NULL,
- serd_string("alex"),
- SERD_HAS_DATATYPE,
- serd_string("http://example.org/Aardvark"));
+ SerdNode* aardvark = serd_node_new(
+ NULL,
+ serd_a_typed_literal(serd_string("alex"),
+ serd_string("http://example.org/Aardvark")));
- SerdNode* badger = serd_new_literal(NULL,
- serd_string("bobby"),
- SERD_HAS_DATATYPE,
- serd_string("http://example.org/Badger"));
+ SerdNode* badger = serd_node_new(
+ NULL,
+ serd_a_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(integer, hello) < 0);
@@ -594,26 +792,29 @@ test_compare(void)
assert(serd_node_compare(angst, angst_de) < 0);
assert(serd_node_compare(angst_de, angst_en) < 0);
assert(serd_node_compare(aardvark, badger) < 0);
+ assert(serd_node_compare(integer, short_int) < 0);
+ serd_node_free(NULL, badger);
+ serd_node_free(NULL, aardvark);
serd_node_free(NULL, uri);
serd_node_free(NULL, blank);
+ serd_node_free(NULL, short_int);
serd_node_free(NULL, integer);
- serd_node_free(NULL, badger);
- serd_node_free(NULL, aardvark);
serd_node_free(NULL, universe);
serd_node_free(NULL, hello);
serd_node_free(NULL, hallo);
serd_node_free(NULL, angst_en);
serd_node_free(NULL, angst_de);
serd_node_free(NULL, angst);
- serd_node_free(NULL, xsd_short);
}
int
main(void)
{
+ test_new();
+ test_value();
test_boolean();
- test_get_boolean();
+ test_get_bool();
test_decimal();
test_double();
test_get_double();
@@ -621,8 +822,9 @@ main(void)
test_get_float();
test_integer();
test_get_integer();
+ test_hex();
test_base64();
- test_get_base64();
+ test_decode();
test_node_equals();
test_node_from_string();
test_node_from_substring();
diff --git a/test/test_overflow.c b/test/test_overflow.c
index 7b1693a8..8b47cd2b 100644
--- a/test/test_overflow.c
+++ b/test/test_overflow.c
@@ -29,7 +29,7 @@ test_size(SerdWorld* const world,
return SERD_BAD_STACK;
}
- SerdNode* string_name = serd_new_string(NULL, serd_string("string"));
+ SerdNode* string_name = serd_node_new(NULL, serd_a_string("string"));
const char* position = str;
SerdInputStream in = serd_open_input_string(&position);
serd_reader_start(reader, &in, string_name, 1);
diff --git a/test/test_reader.c b/test/test_reader.c
index a0eaee5c..54dbca9f 100644
--- a/test/test_reader.c
+++ b/test/test_reader.c
@@ -624,7 +624,7 @@ test_error_cursor(void)
"<http://example.org/s> <http://example.org/p> "
"<http://example.org/o> .";
- SerdNode* const string_name = serd_new_string(NULL, serd_string("string"));
+ SerdNode* const string_name = serd_node_new(NULL, serd_a_string("string"));
const char* position = string;
SerdInputStream in = serd_open_input_string(&position);
diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c
index d6a2675d..aea0976d 100644
--- a/test/test_reader_writer.c
+++ b/test/test_reader_writer.c
@@ -154,7 +154,7 @@ test_writer(const char* const path)
serd_writer_chop_blank_prefix(writer, "tmp");
serd_writer_chop_blank_prefix(writer, NULL);
- SerdNode* lit = serd_new_string(NULL, serd_string("hello"));
+ SerdNode* lit = serd_node_new(NULL, serd_a_string("hello"));
const SerdSink* const iface = serd_writer_sink(writer);
assert(serd_sink_write_base(iface, lit));
@@ -164,9 +164,10 @@ test_writer(const char* const path)
static const uint8_t bad_buf[] = {0xEF, 0xBF, 0xBD, 0};
const SerdStringView bad_buf_view = {(const char*)bad_buf, 3};
- SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org"));
- SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/pred"));
- SerdNode* bad = serd_new_string(NULL, bad_buf_view);
+ SerdNode* s = serd_node_new(NULL, serd_a_uri_string("http://example.org"));
+ SerdNode* p =
+ serd_node_new(NULL, serd_a_uri_string("http://example.org/pred"));
+ SerdNode* bad = serd_node_new(NULL, serd_a_string_view(bad_buf_view));
// Write 3 invalid statements (should write nothing)
const SerdNode* junk[][3] = {{s, bad, bad}, {bad, p, bad}, {s, bad, p}};
@@ -179,13 +180,13 @@ test_writer(const char* const path)
const SerdStringView urn_Type = serd_string("urn:Type");
const SerdStringView en = serd_string("en");
- SerdNode* const o = serd_new_string(NULL, serd_string("o"));
+ SerdNode* const o = serd_node_new(NULL, serd_a_string("o"));
SerdNode* const t =
- serd_new_literal(NULL, serd_string("t"), SERD_HAS_DATATYPE, urn_Type);
+ serd_node_new(NULL, serd_a_typed_literal(serd_string("t"), urn_Type));
SerdNode* const l =
- serd_new_literal(NULL, serd_string("l"), SERD_HAS_LANGUAGE, en);
+ serd_node_new(NULL, serd_a_plain_literal(serd_string("l"), en));
const SerdNode* good[][3] = {{s, p, o}, {s, p, t}, {s, p, l}};
@@ -200,15 +201,15 @@ test_writer(const char* const path)
static const char* const bad_uri_str = (const char*)bad_uri_buf;
// Write statements with bad UTF-8 (should be replaced)
- SerdNode* bad_lit = serd_new_string(NULL, serd_string(bad_lit_str));
- SerdNode* bad_uri = serd_new_uri(NULL, serd_string(bad_uri_str));
+ SerdNode* bad_lit = serd_node_new(NULL, serd_a_string(bad_lit_str));
+ SerdNode* bad_uri = serd_node_new(NULL, serd_a_uri_string(bad_uri_str));
assert(!serd_sink_write(iface, 0, s, p, bad_lit, 0));
assert(!serd_sink_write(iface, 0, s, p, bad_uri, 0));
serd_node_free(NULL, bad_uri);
serd_node_free(NULL, bad_lit);
// Write 1 valid statement
- SerdNode* const hello = serd_new_string(NULL, serd_string("hello"));
+ SerdNode* const hello = serd_node_new(NULL, serd_a_string("hello"));
assert(!serd_sink_write(iface, 0, s, p, hello, 0));
serd_node_free(NULL, hello);
@@ -223,7 +224,7 @@ test_writer(const char* const path)
// Test buffer sink
SerdBuffer buffer = {NULL, NULL, 0};
SerdNode* const base =
- serd_new_uri(NULL, serd_string("http://example.org/base"));
+ serd_node_new(NULL, serd_a_uri_string("http://example.org/base"));
output = serd_open_output_buffer(&buffer);
writer = serd_writer_new(world, SERD_TURTLE, 0, env, &output, 1U);
diff --git a/test/test_sink.c b/test/test_sink.c
index 9c7959de..72c45df6 100644
--- a/test/test_sink.c
+++ b/test/test_sink.c
@@ -11,7 +11,6 @@
#include "serd/sink.h"
#include "serd/statement.h"
#include "serd/status.h"
-#include "serd/string_view.h"
#include <assert.h>
#include <stddef.h>
@@ -111,10 +110,10 @@ test_failed_alloc(void)
static void
test_callbacks(void)
{
- SerdNode* const base = serd_new_uri(NULL, serd_string(NS_EG));
- SerdNode* const name = serd_new_string(NULL, serd_string("eg"));
- SerdNode* const uri = serd_new_uri(NULL, serd_string(NS_EG "uri"));
- SerdNode* const blank = serd_new_blank(NULL, serd_string("b1"));
+ SerdNode* const base = serd_node_new(NULL, serd_a_uri_string(NS_EG));
+ SerdNode* const name = serd_node_new(NULL, serd_a_string("eg"));
+ SerdNode* const uri = serd_node_new(NULL, serd_a_uri_string(NS_EG "uri"));
+ SerdNode* const blank = serd_node_new(NULL, serd_a_blank_string("b1"));
SerdEnv* env = serd_env_new(NULL, serd_node_string_view(base));
State state = {0, 0, 0, 0, 0, SERD_SUCCESS};
diff --git a/test/test_statement.c b/test/test_statement.c
index 0127b7bf..fe1ce818 100644
--- a/test/test_statement.c
+++ b/test/test_statement.c
@@ -6,7 +6,6 @@
#include "serd/caret.h"
#include "serd/node.h"
#include "serd/statement.h"
-#include "serd/string_view.h"
#include <assert.h>
#include <stddef.h>
@@ -16,9 +15,9 @@
static void
test_new(void)
{
- SerdNode* const u = serd_new_uri(NULL, serd_string(NS_EG "s"));
- SerdNode* const b = serd_new_blank(NULL, serd_string("b0"));
- SerdNode* const l = serd_new_string(NULL, serd_string("str"));
+ SerdNode* const u = serd_node_new(NULL, serd_a_uri_string(NS_EG "s"));
+ SerdNode* const b = serd_node_new(NULL, serd_a_blank_string("b0"));
+ SerdNode* const l = serd_node_new(NULL, serd_a_string("str"));
assert(!serd_statement_new(NULL, u, b, u, NULL, NULL));
assert(!serd_statement_new(NULL, l, u, u, NULL, NULL));
@@ -37,11 +36,11 @@ test_copy(void)
{
assert(!serd_statement_copy(NULL, NULL));
- SerdNode* const f = serd_new_string(NULL, serd_string("file"));
- SerdNode* const s = serd_new_uri(NULL, serd_string(NS_EG "s"));
- SerdNode* const p = serd_new_uri(NULL, serd_string(NS_EG "p"));
- SerdNode* const o = serd_new_uri(NULL, serd_string(NS_EG "o"));
- SerdNode* const g = serd_new_uri(NULL, serd_string(NS_EG "g"));
+ SerdNode* const f = serd_node_new(NULL, serd_a_string("file"));
+ SerdNode* const s = serd_node_new(NULL, serd_a_uri_string(NS_EG "s"));
+ SerdNode* const p = serd_node_new(NULL, serd_a_uri_string(NS_EG "p"));
+ SerdNode* const o = serd_node_new(NULL, serd_a_uri_string(NS_EG "o"));
+ SerdNode* const g = serd_node_new(NULL, serd_a_uri_string(NS_EG "g"));
SerdCaret* const caret = serd_caret_new(NULL, f, 1, 1);
SerdStatement* const statement = serd_statement_new(NULL, s, p, o, g, caret);
@@ -69,11 +68,11 @@ test_free(void)
static void
test_fields(void)
{
- SerdNode* const f = serd_new_string(NULL, serd_string("file"));
- SerdNode* const s = serd_new_uri(NULL, serd_string(NS_EG "s"));
- SerdNode* const p = serd_new_uri(NULL, serd_string(NS_EG "p"));
- SerdNode* const o = serd_new_uri(NULL, serd_string(NS_EG "o"));
- SerdNode* const g = serd_new_uri(NULL, serd_string(NS_EG "g"));
+ SerdNode* const f = serd_node_new(NULL, serd_a_string("file"));
+ SerdNode* const s = serd_node_new(NULL, serd_a_uri_string(NS_EG "s"));
+ SerdNode* const p = serd_node_new(NULL, serd_a_uri_string(NS_EG "p"));
+ SerdNode* const o = serd_node_new(NULL, serd_a_uri_string(NS_EG "o"));
+ SerdNode* const g = serd_node_new(NULL, serd_a_uri_string(NS_EG "g"));
SerdCaret* const caret = serd_caret_new(NULL, f, 1, 1);
SerdStatement* const statement = serd_statement_new(NULL, s, p, o, g, caret);
diff --git a/test/test_terse_write.c b/test/test_terse_write.c
index 0bdb0280..3fa08fbd 100644
--- a/test/test_terse_write.c
+++ b/test/test_terse_write.c
@@ -43,16 +43,16 @@ test(void)
SerdWorld* world = serd_world_new(NULL);
SerdEnv* env = serd_env_new(NULL, serd_empty_string());
- SerdNode* b1 = serd_new_blank(NULL, serd_string("b1"));
- SerdNode* l1 = serd_new_blank(NULL, serd_string("l1"));
- SerdNode* l2 = serd_new_blank(NULL, serd_string("l2"));
- SerdNode* s1 = serd_new_string(NULL, serd_string("s1"));
- SerdNode* s2 = serd_new_string(NULL, serd_string("s2"));
-
- SerdNode* rdf_first = serd_new_uri(NULL, serd_string(NS_RDF "first"));
- SerdNode* rdf_value = serd_new_uri(NULL, serd_string(NS_RDF "value"));
- SerdNode* rdf_rest = serd_new_uri(NULL, serd_string(NS_RDF "rest"));
- SerdNode* rdf_nil = serd_new_uri(NULL, serd_string(NS_RDF "nil"));
+ SerdNode* b1 = serd_node_new(NULL, serd_a_blank_string("b1"));
+ SerdNode* l1 = serd_node_new(NULL, serd_a_blank_string("l1"));
+ SerdNode* l2 = serd_node_new(NULL, serd_a_blank_string("l2"));
+ SerdNode* s1 = serd_node_new(NULL, serd_a_string("s1"));
+ SerdNode* s2 = serd_node_new(NULL, serd_a_string("s2"));
+
+ SerdNode* rdf_first = serd_node_new(NULL, serd_a_uri_string(NS_RDF "first"));
+ SerdNode* rdf_value = serd_node_new(NULL, serd_a_uri_string(NS_RDF "value"));
+ SerdNode* rdf_rest = serd_node_new(NULL, serd_a_uri_string(NS_RDF "rest"));
+ SerdNode* rdf_nil = serd_node_new(NULL, serd_a_uri_string(NS_RDF "nil"));
serd_env_set_prefix(env, serd_string("rdf"), serd_string(NS_RDF));
diff --git a/test/test_uri.c b/test/test_uri.c
index 79d3f73e..7a15ffb8 100644
--- a/test/test_uri.c
+++ b/test/test_uri.c
@@ -75,8 +75,8 @@ test_file_uri(const char* const hostname,
expected_path = path;
}
- SerdNode* node =
- serd_new_file_uri(NULL, serd_string(path), serd_string(hostname));
+ SerdNode* node = serd_node_new(
+ NULL, serd_a_file_uri(serd_string(path), serd_string(hostname)));
const char* node_str = serd_node_string(node);
char* out_hostname = NULL;
@@ -166,8 +166,8 @@ test_parse_uri(void)
const SerdURIView base_uri = serd_parse_uri(base.data);
const SerdURIView empty_uri = serd_parse_uri("");
- SerdNode* const nil =
- serd_new_parsed_uri(NULL, serd_resolve_uri(empty_uri, base_uri));
+ SerdNode* const nil = serd_node_new(
+ NULL, serd_a_parsed_uri(serd_resolve_uri(empty_uri, base_uri)));
assert(serd_node_type(nil) == SERD_URI);
assert(!strcmp(serd_node_string(nil), base.data));
@@ -227,21 +227,26 @@ check_relative_uri(const char* const uri_string,
assert(base_string);
assert(expected_string);
- SerdNode* const uri_node = serd_new_uri(NULL, serd_string(uri_string));
- const SerdURIView uri = serd_node_uri_view(uri_node);
- SerdNode* const base_node = serd_new_uri(NULL, serd_string(base_string));
- const SerdURIView base = serd_node_uri_view(base_node);
+ SerdNode* const uri_node = serd_node_new(NULL, serd_a_uri_string(uri_string));
+ const SerdURIView uri = serd_node_uri_view(uri_node);
+ SerdNode* const base_node =
+ serd_node_new(NULL, serd_a_uri_string(base_string));
+ const SerdURIView base = serd_node_uri_view(base_node);
SerdNode* result_node = NULL;
if (!root_string) {
- result_node = serd_new_parsed_uri(NULL, serd_relative_uri(uri, base));
+ result_node =
+ serd_node_new(NULL, serd_a_parsed_uri(serd_relative_uri(uri, base)));
} else {
- SerdNode* const root_node = serd_new_uri(NULL, serd_string(root_string));
- const SerdURIView root = serd_node_uri_view(root_node);
+ SerdNode* const root_node =
+ serd_node_new(NULL, serd_a_uri_string(root_string));
+ const SerdURIView root = serd_node_uri_view(root_node);
+
+ result_node =
+ serd_uri_is_within(uri, root)
+ ? serd_node_new(NULL, serd_a_parsed_uri(serd_relative_uri(uri, base)))
+ : serd_node_new(NULL, serd_a_uri_string(uri_string));
- result_node = serd_uri_is_within(uri, root)
- ? serd_new_parsed_uri(NULL, serd_relative_uri(uri, base))
- : serd_new_uri(NULL, serd_string(uri_string));
serd_node_free(NULL, root_node);
}
@@ -359,7 +364,7 @@ test_relative_uri(void)
static void
check_uri_string(const SerdURIView uri, const char* const expected)
{
- SerdNode* const node = serd_new_parsed_uri(NULL, uri);
+ SerdNode* const node = serd_node_new(NULL, serd_a_parsed_uri(uri));
assert(!strcmp(serd_node_string(node), expected));
serd_node_free(NULL, node);
}
diff --git a/test/test_writer.c b/test/test_writer.c
index 39bcd34a..8f4fef5c 100644
--- a/test/test_writer.c
+++ b/test/test_writer.c
@@ -78,13 +78,14 @@ test_write_failed_alloc(void)
SerdBuffer buffer = {&allocator.base, NULL, 0};
SerdOutputStream output = serd_open_output_buffer(&buffer);
- SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s"));
- SerdNode* p1 = serd_new_uri(NULL, serd_string("http://example.org/p"));
+ SerdNode* s = serd_node_new(NULL, serd_a_uri_string("http://example.org/s"));
+ SerdNode* p1 = serd_node_new(NULL, serd_a_uri_string("http://example.org/p"));
- SerdNode* p2 = serd_new_uri(
- NULL, serd_string("http://example.org/dramatically/longer/predicate"));
+ SerdNode* p2 = serd_node_new(
+ NULL,
+ serd_a_uri_string("http://example.org/dramatically/longer/predicate"));
- SerdNode* o = serd_new_token(NULL, SERD_BLANK, serd_string("o"));
+ SerdNode* o = serd_node_new(NULL, serd_a_blank_string("o"));
const size_t n_setup_allocs = allocator.n_allocations;
@@ -168,12 +169,13 @@ test_write_long_literal(void)
serd_writer_new(world, SERD_TURTLE, 0U, env, &output, 1U);
assert(writer);
- SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s"));
- SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p"));
- SerdNode* o = serd_new_literal(NULL,
- serd_string("hello \"\"\"world\"\"\"!"),
+ SerdNode* s = serd_node_new(NULL, serd_a_uri_string("http://example.org/s"));
+ SerdNode* p = serd_node_new(NULL, serd_a_uri_string("http://example.org/p"));
+ SerdNode* o =
+ serd_node_new(NULL,
+ serd_a_literal(serd_string("hello \"\"\"world\"\"\"!"),
SERD_IS_LONG,
- serd_empty_string());
+ serd_empty_string()));
assert(serd_node_flags(o) & SERD_IS_LONG);
assert(!serd_sink_write(serd_writer_sink(writer), 0, s, p, o, NULL));
@@ -224,9 +226,9 @@ test_writer_cleanup(void)
const SerdSink* sink = serd_writer_sink(writer);
- SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s"));
- SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p"));
- SerdNode* o = serd_new_blank(NULL, serd_string("start"));
+ SerdNode* s = serd_node_new(NULL, serd_a_uri_string("http://example.org/s"));
+ SerdNode* p = serd_node_new(NULL, serd_a_uri_string("http://example.org/p"));
+ SerdNode* o = serd_node_new(NULL, serd_a_blank_string("start"));
st = serd_sink_write(sink, SERD_ANON_O, s, p, o, NULL);
assert(!st);
@@ -236,7 +238,7 @@ test_writer_cleanup(void)
char buf[12] = {0};
snprintf(buf, sizeof(buf), "b%u", i);
- SerdNode* next_o = serd_new_blank(NULL, serd_string(buf));
+ SerdNode* next_o = serd_node_new(NULL, serd_a_blank_string(buf));
st = serd_sink_write(sink, SERD_ANON_O, o, p, next_o, NULL);
@@ -248,7 +250,7 @@ test_writer_cleanup(void)
assert(!(st = serd_writer_finish(writer)));
// Set the base to an empty URI
- SerdNode* empty_uri = serd_new_uri(NULL, serd_string(""));
+ SerdNode* empty_uri = serd_node_new(NULL, serd_a_uri_string(""));
assert(!(st = serd_sink_write_base(sink, empty_uri)));
serd_node_free(NULL, empty_uri);
@@ -280,11 +282,12 @@ test_strict_write(void)
const uint8_t bad_str[] = {0xFF, 0x90, 'h', 'i', 0};
- SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s"));
- SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p"));
+ SerdNode* s = serd_node_new(NULL, serd_a_uri_string("http://example.org/s"));
+ SerdNode* p = serd_node_new(NULL, serd_a_uri_string("http://example.org/p"));
- SerdNode* bad_lit = serd_new_string(NULL, serd_string((const char*)bad_str));
- SerdNode* bad_uri = serd_new_uri(NULL, serd_string((const char*)bad_str));
+ SerdNode* bad_lit = serd_node_new(NULL, serd_a_string((const char*)bad_str));
+ SerdNode* bad_uri =
+ serd_node_new(NULL, serd_a_uri_string((const char*)bad_str));
assert(serd_sink_write(sink, 0, s, p, bad_lit, NULL) == SERD_BAD_TEXT);
assert(serd_sink_write(sink, 0, s, p, bad_uri, NULL) == SERD_BAD_TEXT);
@@ -322,7 +325,7 @@ test_write_error(void)
SerdOutputStream out = serd_open_output_stream(error_sink, NULL, NULL, NULL);
SerdStatus st = SERD_SUCCESS;
- SerdNode* u = serd_new_uri(NULL, serd_string("http://example.com/u"));
+ SerdNode* u = serd_node_new(NULL, serd_a_uri_string("http://example.com/u"));
SerdWriter* const writer =
serd_writer_new(world, SERD_TURTLE, (SerdWriterFlags)0, env, &out, 1U);
@@ -353,10 +356,12 @@ test_writer_stack_overflow(void)
const SerdSink* sink = serd_writer_sink(writer);
- SerdNode* const s = serd_new_uri(NULL, serd_string("http://example.org/s"));
- SerdNode* const p = serd_new_uri(NULL, serd_string("http://example.org/p"));
+ SerdNode* const s =
+ serd_node_new(NULL, serd_a_uri_string("http://example.org/s"));
+ SerdNode* const p =
+ serd_node_new(NULL, serd_a_uri_string("http://example.org/p"));
- SerdNode* o = serd_new_blank(NULL, serd_string("blank"));
+ SerdNode* o = serd_node_new(NULL, serd_a_blank_string("blank"));
SerdStatus st = serd_sink_write(sink, SERD_ANON_O, s, p, o, NULL);
assert(!st);
@@ -365,7 +370,7 @@ test_writer_stack_overflow(void)
char buf[1024];
snprintf(buf, sizeof(buf), "b%u", i);
- SerdNode* next_o = serd_new_blank(NULL, serd_string(buf));
+ SerdNode* next_o = serd_node_new(NULL, serd_a_blank_string(buf));
st = serd_sink_write(sink, SERD_ANON_O, o, p, next_o, NULL);
@@ -395,9 +400,9 @@ test_write_empty_syntax(void)
SerdWorld* world = serd_world_new(NULL);
SerdEnv* env = serd_env_new(NULL, serd_empty_string());
- SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s"));
- SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p"));
- SerdNode* o = serd_new_uri(NULL, serd_string("http://example.org/o"));
+ SerdNode* s = serd_node_new(NULL, serd_a_uri_string("http://example.org/s"));
+ SerdNode* p = serd_node_new(NULL, serd_a_uri_string("http://example.org/p"));
+ SerdNode* o = serd_node_new(NULL, serd_a_uri_string("http://example.org/o"));
SerdBuffer buffer = {NULL, NULL, 0};
SerdOutputStream output = serd_open_output_buffer(&buffer);
@@ -441,14 +446,14 @@ check_pname_escape(const char* const lname, const char* const expected)
serd_env_set_prefix(env, serd_string("eg"), serd_string(prefix));
- SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s"));
- SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p"));
+ SerdNode* s = serd_node_new(NULL, serd_a_uri_string("http://example.org/s"));
+ SerdNode* p = serd_node_new(NULL, serd_a_uri_string("http://example.org/p"));
char* const uri = (char*)calloc(1, prefix_len + strlen(lname) + 1);
memcpy(uri, prefix, prefix_len + 1);
memcpy(uri + prefix_len, lname, strlen(lname) + 1);
- SerdNode* node = serd_new_uri(NULL, serd_string(uri));
+ SerdNode* node = serd_node_new(NULL, serd_a_uri_string(uri));
assert(!serd_sink_write(serd_writer_sink(writer), 0, s, p, node, NULL));
serd_node_free(NULL, node);
@@ -503,9 +508,9 @@ test_write_bad_uri(void)
{
SerdWorld* world = serd_world_new(NULL);
SerdEnv* env = serd_env_new(NULL, serd_empty_string());
- SerdNode* s = serd_new_uri(NULL, serd_string("http://example.org/s"));
- SerdNode* p = serd_new_uri(NULL, serd_string("http://example.org/p"));
- SerdNode* rel = serd_new_uri(NULL, serd_string("rel"));
+ SerdNode* s = serd_node_new(NULL, serd_a_uri_string("http://example.org/s"));
+ SerdNode* p = serd_node_new(NULL, serd_a_uri_string("http://example.org/p"));
+ SerdNode* rel = serd_node_new(NULL, serd_a_uri_string("rel"));
SerdBuffer buffer = {NULL, NULL, 0};
SerdOutputStream output = serd_open_output_buffer(&buffer);
diff --git a/tools/console.c b/tools/console.c
index 012c50a3..72b9b222 100644
--- a/tools/console.c
+++ b/tools/console.c
@@ -53,8 +53,8 @@ serd_set_base_uri_from_path(SerdEnv* const env, const char* const path)
return SERD_BAD_ARG;
}
- SerdNode* const file_uri =
- serd_new_file_uri(NULL, serd_string(input_path), serd_empty_string());
+ SerdNode* const file_uri = serd_node_new(
+ NULL, serd_a_file_uri(serd_string(input_path), serd_empty_string()));
serd_env_set_base_uri(env, serd_node_string_view(file_uri));
serd_node_free(NULL, file_uri);
diff --git a/tools/serd-pipe.c b/tools/serd-pipe.c
index 9be11d66..3f1c3f53 100644
--- a/tools/serd-pipe.c
+++ b/tools/serd-pipe.c
@@ -163,7 +163,7 @@ main(int argc, char** argv)
return missing_arg(prog, 'B');
}
- base = serd_new_uri(NULL, serd_string(argv[a]));
+ base = serd_node_new(NULL, serd_a_uri_string(argv[a]));
break;
} else if (opt == 'b') {
if (argv[a][o + 1] || ++a == argc) {
@@ -281,8 +281,9 @@ main(int argc, char** argv)
// Choose base URI from the single input path
char* const input_path = zix_canonical_path(NULL, inputs[0]);
if (!input_path ||
- !(base = serd_new_file_uri(
- NULL, serd_string(input_path), serd_empty_string()))) {
+ !(base = serd_node_new(
+ NULL,
+ serd_a_file_uri(serd_string(input_path), serd_empty_string())))) {
SERDI_ERRORF("unable to determine base URI from path %s\n", inputs[0]);
}
zix_free(NULL, input_path);