aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-11-10 22:58:12 +0100
committerDavid Robillard <d@drobilla.net>2020-11-11 00:06:20 +0100
commit9eee20ada8974e53227fa77e8dc0013ceaca88a3 (patch)
tree4b5bedc0a6874c815baab376e1cb6bc22a489897
parent48635c1e2ce5ac764cc273b4f2b93e361016d612 (diff)
downloadserd-9eee20ada8974e53227fa77e8dc0013ceaca88a3.tar.gz
serd-9eee20ada8974e53227fa77e8dc0013ceaca88a3.tar.bz2
serd-9eee20ada8974e53227fa77e8dc0013ceaca88a3.zip
Add nonnull and nullable attributes to API
This will warn if NULL is passed to any nonnull-annotated parameter, and is also supported by sanitizers which can check for violations at runtime. Unfortunately, it is currently only supported by clang. GCC has a similar feature in the nonnull attribute, but this has a different syntax (it's a function attribute) and is more dangerous since it is used by the optimizer to assume a null pointer is undefined behavior. This one just warns and still allows code to handle the situation gracefully, which I think is more appropriate for a library API. Note that this optimization behavior is not some unlikely edge case: switching these attributes to the GCC one will break release builds.
-rw-r--r--include/serd/serd.h397
-rw-r--r--src/env.c1
-rw-r--r--src/writer.c1
-rw-r--r--test/test_reader_writer.c8
-rw-r--r--wscript2
5 files changed, 226 insertions, 183 deletions
diff --git a/include/serd/serd.h b/include/serd/serd.h
index c39414e0..a1a15138 100644
--- a/include/serd/serd.h
+++ b/include/serd/serd.h
@@ -45,6 +45,14 @@
# define SERD_CONST_FUNC
#endif
+#ifdef __clang__
+# define SERD_NONNULL _Nonnull
+# define SERD_NULLABLE _Nullable
+#else
+# define SERD_NONNULL
+# define SERD_NULLABLE
+#endif
+
#define SERD_PURE_API SERD_API SERD_PURE_FUNC
#define SERD_CONST_API SERD_API SERD_CONST_FUNC
@@ -222,31 +230,31 @@ typedef uint32_t SerdNodeFlags;
A syntactic RDF node.
*/
typedef struct {
- const uint8_t* buf; /**< Value string */
- size_t n_bytes; /**< Size in bytes (not including null) */
- size_t n_chars; /**< Length in characters (not including null)*/
- SerdNodeFlags flags; /**< Node flags (e.g. string properties) */
- SerdType type; /**< Node type */
+ const uint8_t* SERD_NULLABLE buf; /**< Value string */
+ size_t n_bytes; /**< Size in bytes (excluding null) */
+ size_t n_chars; /**< String length (excluding null) */
+ SerdNodeFlags flags; /**< Node flags (string properties) */
+ SerdType type; /**< Node type */
} SerdNode;
/**
An unterminated string fragment.
*/
typedef struct {
- const uint8_t* buf; /**< Start of chunk */
- size_t len; /**< Length of chunk in bytes */
+ const uint8_t* SERD_NULLABLE buf; /**< Start of chunk */
+ size_t len; /**< Length of chunk in bytes */
} SerdChunk;
/**
An error description.
*/
typedef struct {
- SerdStatus status; /**< Error code */
- const uint8_t* filename; /**< File where error was encountered, or NULL */
- unsigned line; /**< Line where error was encountered, or 0 */
- unsigned col; /**< Column where error was encountered */
- const char* fmt; /**< Message format string (printf style) */
- va_list* args; /**< Arguments for fmt */
+ SerdStatus status; /**< Error code */
+ const uint8_t* SERD_NULLABLE filename; /**< File with error */
+ unsigned line; /**< Line in file with error or 0 */
+ unsigned col; /**< Column in file with error */
+ const char* SERD_NONNULL fmt; /**< Printf-style format string */
+ va_list* SERD_NONNULL args; /**< Arguments for fmt */
} SerdError;
/**
@@ -290,7 +298,7 @@ typedef enum {
*/
SERD_API
void
-serd_free(void* ptr);
+serd_free(void* SERD_NULLABLE ptr);
/**
@name String Utilities
@@ -301,7 +309,7 @@ serd_free(void* ptr);
Return a string describing a status code.
*/
SERD_CONST_API
-const uint8_t*
+const uint8_t* SERD_NONNULL
serd_strerror(SerdStatus status);
/**
@@ -313,7 +321,9 @@ serd_strerror(SerdStatus status);
*/
SERD_API
size_t
-serd_strlen(const uint8_t* str, size_t* n_bytes, SerdNodeFlags* flags);
+serd_strlen(const uint8_t* SERD_NONNULL str,
+ size_t* SERD_NULLABLE n_bytes,
+ SerdNodeFlags* SERD_NULLABLE flags);
/**
Parse a string to a double.
@@ -324,7 +334,8 @@ serd_strlen(const uint8_t* str, size_t* n_bytes, SerdNodeFlags* flags);
*/
SERD_API
double
-serd_strtod(const char* str, char** endptr);
+serd_strtod(const char* SERD_NONNULL str,
+ char* SERD_NONNULL* SERD_NULLABLE endptr);
/**
Decode a base64 string.
@@ -337,8 +348,10 @@ serd_strtod(const char* str, char** endptr);
@return A newly allocated blob which must be freed with serd_free().
*/
SERD_API
-void*
-serd_base64_decode(const uint8_t* str, size_t len, size_t* size);
+void* SERD_NULLABLE
+serd_base64_decode(const uint8_t* SERD_NONNULL str,
+ size_t len,
+ size_t* SERD_NONNULL size);
/**
@}
@@ -353,7 +366,7 @@ serd_base64_decode(const uint8_t* str, size_t len, size_t* size);
@return Non-zero if `stream` has encountered an error.
*/
-typedef int (*SerdStreamErrorFunc)(void* stream);
+typedef int (*SerdStreamErrorFunc)(void* SERD_NONNULL stream);
/**
Source function for raw string input.
@@ -367,15 +380,17 @@ typedef int (*SerdStreamErrorFunc)(void* stream);
@param stream Stream to read from (FILE* for fread).
@return Number of elements (bytes) read.
*/
-typedef size_t (*SerdSource)(void* buf,
- size_t size,
- size_t nmemb,
- void* stream);
+typedef size_t (*SerdSource)(void* SERD_NONNULL buf,
+ size_t size,
+ size_t nmemb,
+ void* SERD_NONNULL stream);
/**
Sink function for raw string output.
*/
-typedef size_t (*SerdSink)(const void* buf, size_t len, void* stream);
+typedef size_t (*SerdSink)(const void* SERD_NONNULL buf,
+ size_t len,
+ void* SERD_NONNULL stream);
/**
@}
@@ -395,8 +410,8 @@ static const SerdURI SERD_URI_NULL = {
a path, use serd_file_uri_parse().
*/
SERD_API
-const uint8_t*
-serd_uri_to_path(const uint8_t* uri);
+const uint8_t* SERD_NULLABLE
+serd_uri_to_path(const uint8_t* SERD_NONNULL uri);
/**
Get the unescaped path and hostname from a file URI.
@@ -407,22 +422,23 @@ serd_uri_to_path(const uint8_t* uri);
The returned path and `*hostname` must be freed with serd_free().
*/
SERD_API
-uint8_t*
-serd_file_uri_parse(const uint8_t* uri, uint8_t** hostname);
+uint8_t* SERD_NULLABLE
+serd_file_uri_parse(const uint8_t* SERD_NONNULL uri,
+ uint8_t* SERD_NONNULL* SERD_NULLABLE hostname);
/**
Return true iff `utf8` starts with a valid URI scheme.
*/
SERD_PURE_API
bool
-serd_uri_string_has_scheme(const uint8_t* utf8);
+serd_uri_string_has_scheme(const uint8_t* SERD_NULLABLE utf8);
/**
Parse `utf8`, writing result to `out`.
*/
SERD_API
SerdStatus
-serd_uri_parse(const uint8_t* utf8, SerdURI* out);
+serd_uri_parse(const uint8_t* SERD_NONNULL utf8, SerdURI* SERD_NONNULL out);
/**
Set target `t` to reference `r` resolved against `base`.
@@ -431,14 +447,18 @@ serd_uri_parse(const uint8_t* utf8, SerdURI* out);
*/
SERD_API
void
-serd_uri_resolve(const SerdURI* r, const SerdURI* base, SerdURI* t);
+serd_uri_resolve(const SerdURI* SERD_NONNULL r,
+ const SerdURI* SERD_NONNULL base,
+ SerdURI* SERD_NONNULL t);
/**
Serialise `uri` with a series of calls to `sink`.
*/
SERD_API
size_t
-serd_uri_serialise(const SerdURI* uri, SerdSink sink, void* stream);
+serd_uri_serialise(const SerdURI* SERD_NONNULL uri,
+ SerdSink SERD_NONNULL sink,
+ void* SERD_NONNULL stream);
/**
Serialise `uri` relative to `base` with a series of calls to `sink`.
@@ -449,11 +469,11 @@ serd_uri_serialise(const SerdURI* uri, SerdSink sink, void* stream);
*/
SERD_API
size_t
-serd_uri_serialise_relative(const SerdURI* uri,
- const SerdURI* base,
- const SerdURI* root,
- SerdSink sink,
- void* stream);
+serd_uri_serialise_relative(const SerdURI* SERD_NONNULL uri,
+ const SerdURI* SERD_NULLABLE base,
+ const SerdURI* SERD_NULLABLE root,
+ SerdSink SERD_NONNULL sink,
+ void* SERD_NONNULL stream);
/**
@}
@@ -470,7 +490,7 @@ static const SerdNode SERD_NODE_NULL = { NULL, 0, 0, 0, SERD_NOTHING };
*/
SERD_API
SerdNode
-serd_node_from_string(SerdType type, const uint8_t* str);
+serd_node_from_string(SerdType type, const uint8_t* SERD_NULLABLE str);
/**
Make a (shallow) node from a prefix of `str`.
@@ -480,25 +500,27 @@ serd_node_from_string(SerdType type, const uint8_t* str);
*/
SERD_API
SerdNode
-serd_node_from_substring(SerdType type, const uint8_t* str, size_t len);
+serd_node_from_substring(SerdType type,
+ const uint8_t* SERD_NULLABLE str,
+ size_t len);
/**
Simple wrapper for serd_node_new_uri() to resolve a URI node.
*/
SERD_API
SerdNode
-serd_node_new_uri_from_node(const SerdNode* uri_node,
- const SerdURI* base,
- SerdURI* out);
+serd_node_new_uri_from_node(const SerdNode* SERD_NONNULL uri_node,
+ const SerdURI* SERD_NULLABLE base,
+ SerdURI* SERD_NULLABLE out);
/**
Simple wrapper for serd_node_new_uri() to resolve a URI string.
*/
SERD_API
SerdNode
-serd_node_new_uri_from_string(const uint8_t* str,
- const SerdURI* base,
- SerdURI* out);
+serd_node_new_uri_from_string(const uint8_t* SERD_NULLABLE str,
+ const SerdURI* SERD_NULLABLE base,
+ SerdURI* SERD_NULLABLE out);
/**
Create a new file URI node from a file system path and optional hostname.
@@ -512,10 +534,10 @@ serd_node_new_uri_from_string(const uint8_t* str,
*/
SERD_API
SerdNode
-serd_node_new_file_uri(const uint8_t* path,
- const uint8_t* hostname,
- SerdURI* out,
- bool escape);
+serd_node_new_file_uri(const uint8_t* SERD_NONNULL path,
+ const uint8_t* SERD_NULLABLE hostname,
+ SerdURI* SERD_NULLABLE out,
+ bool escape);
/**
Create a new node by serialising `uri` into a new string.
@@ -529,7 +551,9 @@ serd_node_new_file_uri(const uint8_t* path,
*/
SERD_API
SerdNode
-serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out);
+serd_node_new_uri(const SerdURI* SERD_NONNULL uri,
+ const SerdURI* SERD_NULLABLE base,
+ SerdURI* SERD_NULLABLE out);
/**
Create a new node by serialising `uri` into a new relative URI.
@@ -545,10 +569,10 @@ serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out);
*/
SERD_API
SerdNode
-serd_node_new_relative_uri(const SerdURI* uri,
- const SerdURI* base,
- const SerdURI* root,
- SerdURI* out);
+serd_node_new_relative_uri(const SerdURI* SERD_NONNULL uri,
+ const SerdURI* SERD_NULLABLE base,
+ const SerdURI* SERD_NULLABLE root,
+ SerdURI* SERD_NULLABLE out);
/**
Create a new node by serialising `d` into an xsd:decimal string.
@@ -587,7 +611,7 @@ serd_node_new_integer(int64_t i);
*/
SERD_API
SerdNode
-serd_node_new_blob(const void* buf, size_t size, bool wrap_lines);
+serd_node_new_blob(const void* SERD_NONNULL buf, size_t size, bool wrap_lines);
/**
Make a deep copy of `node`.
@@ -596,14 +620,15 @@ serd_node_new_blob(const void* buf, size_t size, bool wrap_lines);
*/
SERD_API
SerdNode
-serd_node_copy(const SerdNode* node);
+serd_node_copy(const SerdNode* SERD_NULLABLE node);
/**
Return true iff `a` is equal to `b`.
*/
SERD_PURE_API
bool
-serd_node_equals(const SerdNode* a, const SerdNode* b);
+serd_node_equals(const SerdNode* SERD_NONNULL a,
+ const SerdNode* SERD_NONNULL b);
/**
Free any data owned by `node`.
@@ -613,7 +638,7 @@ serd_node_equals(const SerdNode* a, const SerdNode* b);
*/
SERD_API
void
-serd_node_free(SerdNode* node);
+serd_node_free(SerdNode* SERD_NULLABLE node);
/**
@}
@@ -627,39 +652,40 @@ serd_node_free(SerdNode* node);
@param handle Handle for user data.
@param error Error description.
*/
-typedef SerdStatus (*SerdErrorSink)(void* handle,
- const SerdError* error);
+typedef SerdStatus (*SerdErrorSink)(void* SERD_NULLABLE handle,
+ const SerdError* SERD_NONNULL error);
/**
Sink (callback) for base URI changes.
Called whenever the base URI of the serialisation changes.
*/
-typedef SerdStatus (*SerdBaseSink)(void* handle,
- const SerdNode* uri);
+typedef SerdStatus (*SerdBaseSink)(void* SERD_NULLABLE handle,
+ const SerdNode* SERD_NONNULL uri);
/**
Sink (callback) for namespace definitions.
Called whenever a prefix is defined in the serialisation.
*/
-typedef SerdStatus (*SerdPrefixSink)(void* handle,
- const SerdNode* name,
- const SerdNode* uri);
+typedef SerdStatus (*SerdPrefixSink)(void* SERD_NULLABLE handle,
+ const SerdNode* SERD_NONNULL name,
+ const SerdNode* SERD_NONNULL uri);
/**
Sink (callback) for statements.
Called for every RDF statement in the serialisation.
*/
-typedef SerdStatus (*SerdStatementSink)(void* handle,
- SerdStatementFlags flags,
- const SerdNode* graph,
- const SerdNode* subject,
- const SerdNode* predicate,
- const SerdNode* object,
- const SerdNode* object_datatype,
- const SerdNode* object_lang);
+typedef SerdStatus (*SerdStatementSink)(
+ void* SERD_NULLABLE handle,
+ SerdStatementFlags flags,
+ const SerdNode* SERD_NULLABLE graph,
+ const SerdNode* SERD_NONNULL subject,
+ const SerdNode* SERD_NONNULL predicate,
+ const SerdNode* SERD_NONNULL object,
+ const SerdNode* SERD_NULLABLE object_datatype,
+ const SerdNode* SERD_NULLABLE object_lang);
/**
Sink (callback) for anonymous node end markers.
@@ -668,8 +694,8 @@ typedef SerdStatus (*SerdStatementSink)(void* handle,
`value` will no longer be referred to by any future statements
(i.e. the anonymous serialisation of the node is finished).
*/
-typedef SerdStatus (*SerdEndSink)(void* handle,
- const SerdNode* node);
+typedef SerdStatus (*SerdEndSink)(void* SERD_NULLABLE handle,
+ const SerdNode* SERD_NONNULL node);
/**
@}
@@ -681,59 +707,59 @@ typedef SerdStatus (*SerdEndSink)(void* handle,
Create a new environment.
*/
SERD_API
-SerdEnv*
-serd_env_new(const SerdNode* base_uri);
+SerdEnv* SERD_NULLABLE
+serd_env_new(const SerdNode* SERD_NULLABLE base_uri);
/**
Free `ns`.
*/
SERD_API
void
-serd_env_free(SerdEnv* env);
+serd_env_free(SerdEnv* SERD_NULLABLE env);
/**
Get the current base URI.
*/
SERD_API
-const SerdNode*
-serd_env_get_base_uri(const SerdEnv* env,
- SerdURI* out);
+const SerdNode* SERD_NULLABLE
+serd_env_get_base_uri(const SerdEnv* SERD_NONNULL env,
+ SerdURI* SERD_NULLABLE out);
/**
Set the current base URI.
*/
SERD_API
SerdStatus
-serd_env_set_base_uri(SerdEnv* env,
- const SerdNode* uri);
+serd_env_set_base_uri(SerdEnv* SERD_NONNULL env,
+ const SerdNode* SERD_NULLABLE uri);
/**
Set a namespace prefix.
*/
SERD_API
SerdStatus
-serd_env_set_prefix(SerdEnv* env,
- const SerdNode* name,
- const SerdNode* uri);
+serd_env_set_prefix(SerdEnv* SERD_NONNULL env,
+ const SerdNode* SERD_NONNULL name,
+ const SerdNode* SERD_NONNULL uri);
/**
Set a namespace prefix.
*/
SERD_API
SerdStatus
-serd_env_set_prefix_from_strings(SerdEnv* env,
- const uint8_t* name,
- const uint8_t* uri);
+serd_env_set_prefix_from_strings(SerdEnv* SERD_NONNULL env,
+ const uint8_t* SERD_NONNULL name,
+ const uint8_t* SERD_NONNULL uri);
/**
Qualify `uri` into a CURIE if possible.
*/
SERD_API
bool
-serd_env_qualify(const SerdEnv* env,
- const SerdNode* uri,
- SerdNode* prefix,
- SerdChunk* suffix);
+serd_env_qualify(const SerdEnv* SERD_NONNULL env,
+ const SerdNode* SERD_NONNULL uri,
+ SerdNode* SERD_NONNULL prefix,
+ SerdChunk* SERD_NONNULL suffix);
/**
Expand `curie`.
@@ -743,10 +769,10 @@ serd_env_qualify(const SerdEnv* env,
*/
SERD_API
SerdStatus
-serd_env_expand(const SerdEnv* env,
- const SerdNode* curie,
- SerdChunk* uri_prefix,
- SerdChunk* uri_suffix);
+serd_env_expand(const SerdEnv* SERD_NONNULL env,
+ const SerdNode* SERD_NONNULL curie,
+ SerdChunk* SERD_NONNULL uri_prefix,
+ SerdChunk* SERD_NONNULL uri_suffix);
/**
Expand `node`, which must be a CURIE or URI, to a full URI.
@@ -755,17 +781,17 @@ serd_env_expand(const SerdEnv* env,
*/
SERD_API
SerdNode
-serd_env_expand_node(const SerdEnv* env,
- const SerdNode* node);
+serd_env_expand_node(const SerdEnv* SERD_NONNULL env,
+ const SerdNode* SERD_NONNULL node);
/**
Call `func` for each prefix defined in `env`.
*/
SERD_API
void
-serd_env_foreach(const SerdEnv* env,
- SerdPrefixSink func,
- void* handle);
+serd_env_foreach(const SerdEnv* SERD_NONNULL env,
+ SerdPrefixSink SERD_NONNULL func,
+ void* SERD_NULLABLE handle);
/**
@}
@@ -777,14 +803,14 @@ serd_env_foreach(const SerdEnv* env,
Create a new RDF reader.
*/
SERD_API
-SerdReader*
-serd_reader_new(SerdSyntax syntax,
- void* handle,
- void (*free_handle)(void*),
- SerdBaseSink base_sink,
- SerdPrefixSink prefix_sink,
- SerdStatementSink statement_sink,
- SerdEndSink end_sink);
+SerdReader* SERD_NULLABLE
+serd_reader_new(SerdSyntax syntax,
+ void* SERD_NULLABLE handle,
+ void (*SERD_NULLABLE free_handle)(void* SERD_NULLABLE),
+ SerdBaseSink SERD_NULLABLE base_sink,
+ SerdPrefixSink SERD_NULLABLE prefix_sink,
+ SerdStatementSink SERD_NULLABLE statement_sink,
+ SerdEndSink SERD_NULLABLE end_sink);
/**
Enable or disable strict parsing.
@@ -795,7 +821,7 @@ serd_reader_new(SerdSyntax syntax,
*/
SERD_API
void
-serd_reader_set_strict(SerdReader* reader, bool strict);
+serd_reader_set_strict(SerdReader* SERD_NONNULL reader, bool strict);
/**
Set a function to be called when errors occur during reading.
@@ -805,16 +831,16 @@ serd_reader_set_strict(SerdReader* reader, bool strict);
*/
SERD_API
void
-serd_reader_set_error_sink(SerdReader* reader,
- SerdErrorSink error_sink,
- void* error_handle);
+serd_reader_set_error_sink(SerdReader* SERD_NONNULL reader,
+ SerdErrorSink SERD_NULLABLE error_sink,
+ void* SERD_NULLABLE error_handle);
/**
Return the `handle` passed to serd_reader_new().
*/
SERD_PURE_API
-void*
-serd_reader_get_handle(const SerdReader* reader);
+void* SERD_NULLABLE
+serd_reader_get_handle(const SerdReader* SERD_NONNULL reader);
/**
Set a prefix to be added to all blank node identifiers.
@@ -827,8 +853,8 @@ serd_reader_get_handle(const SerdReader* reader);
*/
SERD_API
void
-serd_reader_add_blank_prefix(SerdReader* reader,
- const uint8_t* prefix);
+serd_reader_add_blank_prefix(SerdReader* SERD_NONNULL reader,
+ const uint8_t* SERD_NULLABLE prefix);
/**
Set the URI of the default graph.
@@ -839,16 +865,16 @@ serd_reader_add_blank_prefix(SerdReader* reader,
*/
SERD_API
void
-serd_reader_set_default_graph(SerdReader* reader,
- const SerdNode* graph);
+serd_reader_set_default_graph(SerdReader* SERD_NONNULL reader,
+ const SerdNode* SERD_NULLABLE graph);
/**
Read a file at a given `uri`.
*/
SERD_API
SerdStatus
-serd_reader_read_file(SerdReader* reader,
- const uint8_t* uri);
+serd_reader_read_file(SerdReader* SERD_NONNULL reader,
+ const uint8_t* SERD_NONNULL uri);
/**
Start an incremental read from a file handle.
@@ -860,10 +886,10 @@ serd_reader_read_file(SerdReader* reader,
*/
SERD_API
SerdStatus
-serd_reader_start_stream(SerdReader* reader,
- FILE* file,
- const uint8_t* name,
- bool bulk);
+serd_reader_start_stream(SerdReader* SERD_NONNULL reader,
+ FILE* SERD_NONNULL file,
+ const uint8_t* SERD_NULLABLE name,
+ bool bulk);
/**
Start an incremental read from a user-specified source.
@@ -873,12 +899,12 @@ serd_reader_start_stream(SerdReader* reader,
*/
SERD_API
SerdStatus
-serd_reader_start_source_stream(SerdReader* reader,
- SerdSource read_func,
- SerdStreamErrorFunc error_func,
- void* stream,
- const uint8_t* name,
- size_t page_size);
+serd_reader_start_source_stream(SerdReader* SERD_NONNULL reader,
+ SerdSource SERD_NONNULL read_func,
+ SerdStreamErrorFunc SERD_NONNULL error_func,
+ void* SERD_NONNULL stream,
+ const uint8_t* SERD_NULLABLE name,
+ size_t page_size);
/**
Read a single "chunk" of data during an incremental read.
@@ -890,49 +916,50 @@ serd_reader_start_source_stream(SerdReader* reader,
*/
SERD_API
SerdStatus
-serd_reader_read_chunk(SerdReader* reader);
+serd_reader_read_chunk(SerdReader* SERD_NONNULL reader);
/**
Finish an incremental read from a file handle.
*/
SERD_API
SerdStatus
-serd_reader_end_stream(SerdReader* reader);
+serd_reader_end_stream(SerdReader* SERD_NONNULL reader);
/**
Read `file`.
*/
SERD_API
SerdStatus
-serd_reader_read_file_handle(SerdReader* reader,
- FILE* file,
- const uint8_t* name);
+serd_reader_read_file_handle(SerdReader* SERD_NONNULL reader,
+ FILE* SERD_NONNULL file,
+ const uint8_t* SERD_NULLABLE name);
/**
Read a user-specified byte source.
*/
SERD_API
SerdStatus
-serd_reader_read_source(SerdReader* reader,
- SerdSource source,
- SerdStreamErrorFunc error,
- void* stream,
- const uint8_t* name,
- size_t page_size);
+serd_reader_read_source(SerdReader* SERD_NONNULL reader,
+ SerdSource SERD_NONNULL source,
+ SerdStreamErrorFunc SERD_NONNULL error,
+ void* SERD_NONNULL stream,
+ const uint8_t* SERD_NULLABLE name,
+ size_t page_size);
/**
Read `utf8`.
*/
SERD_API
SerdStatus
-serd_reader_read_string(SerdReader* reader, const uint8_t* utf8);
+serd_reader_read_string(SerdReader* SERD_NONNULL reader,
+ const uint8_t* SERD_NONNULL utf8);
/**
Free `reader`.
*/
SERD_API
void
-serd_reader_free(SerdReader* reader);
+serd_reader_free(SerdReader* SERD_NULLABLE reader);
/**
@}
@@ -944,27 +971,27 @@ serd_reader_free(SerdReader* reader);
Create a new RDF writer.
*/
SERD_API
-SerdWriter*
-serd_writer_new(SerdSyntax syntax,
- SerdStyle style,
- SerdEnv* env,
- const SerdURI* base_uri,
- SerdSink ssink,
- void* stream);
+SerdWriter* SERD_NULLABLE
+serd_writer_new(SerdSyntax syntax,
+ SerdStyle style,
+ SerdEnv* SERD_NONNULL env,
+ const SerdURI* SERD_NULLABLE base_uri,
+ SerdSink SERD_NONNULL ssink,
+ void* SERD_NULLABLE stream);
/**
Free `writer`.
*/
SERD_API
void
-serd_writer_free(SerdWriter* writer);
+serd_writer_free(SerdWriter* SERD_NULLABLE writer);
/**
Return the env used by `writer`.
*/
SERD_PURE_API
-SerdEnv*
-serd_writer_get_env(SerdWriter* writer);
+SerdEnv* SERD_NULLABLE
+serd_writer_get_env(SerdWriter* SERD_NONNULL writer);
/**
A convenience sink function for writing to a FILE*.
@@ -974,7 +1001,9 @@ serd_writer_get_env(SerdWriter* writer);
*/
SERD_API
size_t
-serd_file_sink(const void* buf, size_t len, void* stream);
+serd_file_sink(const void* SERD_NONNULL buf,
+ size_t len,
+ void* SERD_NONNULL stream);
/**
A convenience sink function for writing to a string.
@@ -986,7 +1015,9 @@ serd_file_sink(const void* buf, size_t len, void* stream);
*/
SERD_API
size_t
-serd_chunk_sink(const void* buf, size_t len, void* stream);
+serd_chunk_sink(const void* SERD_NONNULL buf,
+ size_t len,
+ void* SERD_NONNULL stream);
/**
Finish a serialisation to a chunk with serd_chunk_sink().
@@ -995,8 +1026,8 @@ serd_chunk_sink(const void* buf, size_t len, void* stream);
terminated (by this function) and owned by the caller.
*/
SERD_API
-uint8_t*
-serd_chunk_sink_finish(SerdChunk* stream);
+uint8_t* SERD_NULLABLE
+serd_chunk_sink_finish(SerdChunk* SERD_NONNULL stream);
/**
Set a function to be called when errors occur during writing.
@@ -1006,17 +1037,17 @@ serd_chunk_sink_finish(SerdChunk* stream);
*/
SERD_API
void
-serd_writer_set_error_sink(SerdWriter* writer,
- SerdErrorSink error_sink,
- void* error_handle);
+serd_writer_set_error_sink(SerdWriter* SERD_NONNULL writer,
+ SerdErrorSink SERD_NONNULL error_sink,
+ void* SERD_NULLABLE error_handle);
/**
Set a prefix to be removed from matching blank node identifiers.
*/
SERD_API
void
-serd_writer_chop_blank_prefix(SerdWriter* writer,
- const uint8_t* prefix);
+serd_writer_chop_blank_prefix(SerdWriter* SERD_NONNULL writer,
+ const uint8_t* SERD_NULLABLE prefix);
/**
Set the current output base URI (and emit directive if applicable).
@@ -1025,8 +1056,8 @@ serd_writer_chop_blank_prefix(SerdWriter* writer,
*/
SERD_API
SerdStatus
-serd_writer_set_base_uri(SerdWriter* writer,
- const SerdNode* uri);
+serd_writer_set_base_uri(SerdWriter* SERD_NONNULL writer,
+ const SerdNode* SERD_NULLABLE uri);
/**
Set the current root URI.
@@ -1040,8 +1071,8 @@ serd_writer_set_base_uri(SerdWriter* writer,
*/
SERD_API
SerdStatus
-serd_writer_set_root_uri(SerdWriter* writer,
- const SerdNode* uri);
+serd_writer_set_root_uri(SerdWriter* SERD_NONNULL writer,
+ const SerdNode* SERD_NULLABLE uri);
/**
Set a namespace prefix (and emit directive if applicable).
@@ -1050,9 +1081,9 @@ serd_writer_set_root_uri(SerdWriter* writer,
*/
SERD_API
SerdStatus
-serd_writer_set_prefix(SerdWriter* writer,
- const SerdNode* name,
- const SerdNode* uri);
+serd_writer_set_prefix(SerdWriter* SERD_NONNULL writer,
+ const SerdNode* SERD_NONNULL name,
+ const SerdNode* SERD_NONNULL uri);
/**
Write a statement.
@@ -1061,14 +1092,14 @@ serd_writer_set_prefix(SerdWriter* writer,
*/
SERD_API
SerdStatus
-serd_writer_write_statement(SerdWriter* writer,
- SerdStatementFlags flags,
- const SerdNode* graph,
- const SerdNode* subject,
- const SerdNode* predicate,
- const SerdNode* object,
- const SerdNode* datatype,
- const SerdNode* lang);
+serd_writer_write_statement(SerdWriter* SERD_NONNULL writer,
+ SerdStatementFlags flags,
+ const SerdNode* SERD_NULLABLE graph,
+ const SerdNode* SERD_NONNULL subject,
+ const SerdNode* SERD_NONNULL predicate,
+ const SerdNode* SERD_NONNULL object,
+ const SerdNode* SERD_NULLABLE datatype,
+ const SerdNode* SERD_NULLABLE lang);
/**
Mark the end of an anonymous node's description.
@@ -1077,15 +1108,15 @@ serd_writer_write_statement(SerdWriter* writer,
*/
SERD_API
SerdStatus
-serd_writer_end_anon(SerdWriter* writer,
- const SerdNode* node);
+serd_writer_end_anon(SerdWriter* SERD_NONNULL writer,
+ const SerdNode* SERD_NULLABLE node);
/**
Finish a write.
*/
SERD_API
SerdStatus
-serd_writer_finish(SerdWriter* writer);
+serd_writer_finish(SerdWriter* SERD_NONNULL writer);
/**
@}
diff --git a/src/env.c b/src/env.c
index 3813391c..431fef41 100644
--- a/src/env.c
+++ b/src/env.c
@@ -70,6 +70,7 @@ serd_env_get_base_uri(const SerdEnv* env,
return &env->base_uri_node;
}
+// TODO: Make env nonnull in next major release
SerdStatus
serd_env_set_base_uri(SerdEnv* env,
const SerdNode* uri)
diff --git a/src/writer.c b/src/writer.c
index 5f312c30..5c84b950 100644
--- a/src/writer.c
+++ b/src/writer.c
@@ -694,6 +694,7 @@ write_list_obj(SerdWriter* writer,
return false;
}
+// TODO: Make subject, predicate,object nonnull in next major release
SerdStatus
serd_writer_write_statement(SerdWriter* writer,
SerdStatementFlags flags,
diff --git a/test/test_reader_writer.c b/test/test_reader_writer.c
index 60f8805f..41f57e77 100644
--- a/test/test_reader_writer.c
+++ b/test/test_reader_writer.c
@@ -286,7 +286,15 @@ test_reader(const char* path)
SerdNode g = serd_node_from_string(SERD_URI, USTR("http://example.org/"));
serd_reader_set_default_graph(reader, &g);
serd_reader_add_blank_prefix(reader, USTR("tmp"));
+
+#if defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wnonnull"
+#endif
serd_reader_add_blank_prefix(reader, NULL);
+#if defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
assert(serd_reader_read_file(reader, USTR("http://notafile")));
assert(serd_reader_read_file(reader, USTR("file:///better/not/exist")));
diff --git a/wscript b/wscript
index f12503e9..bc21d526 100644
--- a/wscript
+++ b/wscript
@@ -60,6 +60,8 @@ def configure(conf):
'-Wno-double-promotion',
'-Wno-format-nonliteral',
'-Wno-implicit-fallthrough',
+ '-Wno-nullability-extension',
+ '-Wno-nullable-to-nonnull-conversion',
'-Wno-padded',
'-Wno-reserved-id-macro',
'-Wno-sign-conversion',