Chris@45: /* Chris@45: Copyright 2011-2016 David Robillard Chris@45: Chris@45: Permission to use, copy, modify, and/or distribute this software for any Chris@45: purpose with or without fee is hereby granted, provided that the above Chris@45: copyright notice and this permission notice appear in all copies. Chris@45: Chris@45: THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES Chris@45: WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF Chris@45: MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR Chris@45: ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES Chris@45: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN Chris@45: ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF Chris@45: OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Chris@45: */ Chris@45: Chris@45: /** Chris@45: @file serd.h API for Serd, a lightweight RDF syntax library. Chris@45: */ Chris@45: Chris@45: #ifndef SERD_SERD_H Chris@45: #define SERD_SERD_H Chris@45: Chris@45: #include Chris@45: #include Chris@45: #include Chris@45: #include Chris@45: Chris@45: #ifdef SERD_SHARED Chris@45: # ifdef _WIN32 Chris@45: # define SERD_LIB_IMPORT __declspec(dllimport) Chris@45: # define SERD_LIB_EXPORT __declspec(dllexport) Chris@45: # else Chris@45: # define SERD_LIB_IMPORT __attribute__((visibility("default"))) Chris@45: # define SERD_LIB_EXPORT __attribute__((visibility("default"))) Chris@45: # endif Chris@45: # ifdef SERD_INTERNAL Chris@45: # define SERD_API SERD_LIB_EXPORT Chris@45: # else Chris@45: # define SERD_API SERD_LIB_IMPORT Chris@45: # endif Chris@45: #else Chris@45: # define SERD_API Chris@45: #endif Chris@45: Chris@45: #ifdef __cplusplus Chris@45: extern "C" { Chris@45: #else Chris@45: # include Chris@45: #endif Chris@45: Chris@45: /** Chris@45: @defgroup serd Serd Chris@45: A lightweight RDF syntax library. Chris@45: @{ Chris@45: */ Chris@45: Chris@45: /** Chris@45: Environment. Chris@45: Chris@45: Represents the state required to resolve a CURIE or relative URI, e.g. the Chris@45: base URI and set of namespace prefixes at a particular point. Chris@45: */ Chris@45: typedef struct SerdEnvImpl SerdEnv; Chris@45: Chris@45: /** Chris@45: RDF reader. Chris@45: Chris@45: Parses RDF by calling user-provided sink functions as input is consumed Chris@45: (much like an XML SAX parser). Chris@45: */ Chris@45: typedef struct SerdReaderImpl SerdReader; Chris@45: Chris@45: /** Chris@45: RDF writer. Chris@45: Chris@45: Provides a number of functions to allow writing RDF syntax out to some Chris@45: stream. These functions are deliberately compatible with the sink functions Chris@45: used by SerdReader, so a reader can be directly connected to a writer to Chris@45: re-serialise a document with minimal overhead. Chris@45: */ Chris@45: typedef struct SerdWriterImpl SerdWriter; Chris@45: Chris@45: /** Chris@45: Return status code. Chris@45: */ Chris@45: typedef enum { Chris@45: SERD_SUCCESS, /**< No error */ Chris@45: SERD_FAILURE, /**< Non-fatal failure */ Chris@45: SERD_ERR_UNKNOWN, /**< Unknown error */ Chris@45: SERD_ERR_BAD_SYNTAX, /**< Invalid syntax */ Chris@45: SERD_ERR_BAD_ARG, /**< Invalid argument */ Chris@45: SERD_ERR_NOT_FOUND, /**< Not found */ Chris@45: SERD_ERR_ID_CLASH, /**< Encountered clashing blank node IDs */ Chris@45: SERD_ERR_BAD_CURIE, /**< Invalid CURIE (e.g. prefix does not exist) */ Chris@45: SERD_ERR_INTERNAL /**< Unexpected internal error (should not happen) */ Chris@45: } SerdStatus; Chris@45: Chris@45: /** Chris@45: RDF syntax type. Chris@45: */ Chris@45: typedef enum { Chris@45: /** Chris@45: Turtle - Terse RDF Triple Language (UTF-8). Chris@45: @see Turtle Chris@45: */ Chris@45: SERD_TURTLE = 1, Chris@45: Chris@45: /** Chris@45: NTriples - Line-based RDF triples (ASCII). Chris@45: @see NTriples Chris@45: */ Chris@45: SERD_NTRIPLES = 2 Chris@45: } SerdSyntax; Chris@45: Chris@45: /** Chris@45: Flags indication inline abbreviation information for a statement. Chris@45: */ Chris@45: typedef enum { Chris@45: SERD_EMPTY_S = 1 << 1, /**< Empty blank node subject */ Chris@45: SERD_EMPTY_O = 1 << 2, /**< Empty blank node object */ Chris@45: SERD_ANON_S_BEGIN = 1 << 3, /**< Start of anonymous subject */ Chris@45: SERD_ANON_O_BEGIN = 1 << 4, /**< Start of anonymous object */ Chris@45: SERD_ANON_CONT = 1 << 5, /**< Continuation of anonymous node */ Chris@45: SERD_LIST_S_BEGIN = 1 << 6, /**< Start of list subject */ Chris@45: SERD_LIST_O_BEGIN = 1 << 7, /**< Start of list object */ Chris@45: SERD_LIST_CONT = 1 << 8 /**< Continuation of list */ Chris@45: } SerdStatementFlag; Chris@45: Chris@45: /** Chris@45: Bitwise OR of SerdNodeFlag values. Chris@45: */ Chris@45: typedef uint32_t SerdStatementFlags; Chris@45: Chris@45: /** Chris@45: Type of a syntactic RDF node. Chris@45: Chris@45: This is more precise than the type of an abstract RDF node. An abstract Chris@45: node is either a resource, literal, or blank. In syntax there are two ways Chris@45: to refer to a resource (by URI or CURIE) and two ways to refer to a blank Chris@45: (by ID or anonymously). Anonymous (inline) blank nodes are expressed using Chris@45: SerdStatementFlags rather than this type. Chris@45: */ Chris@45: typedef enum { Chris@45: /** Chris@45: The type of a nonexistent node. Chris@45: Chris@45: This type is useful as a sentinel, but is never emitted by the reader. Chris@45: */ Chris@45: SERD_NOTHING = 0, Chris@45: Chris@45: /** Chris@45: Literal value. Chris@45: Chris@45: A literal optionally has either a language, or a datatype (not both). Chris@45: */ Chris@45: SERD_LITERAL = 1, Chris@45: Chris@45: /** Chris@45: URI (absolute or relative). Chris@45: Chris@45: Value is an unquoted URI string, which is either a relative reference Chris@45: with respect to the current base URI (e.g. "foo/bar"), or an absolute Chris@45: URI (e.g. "http://example.org/foo"). Chris@45: @see RFC3986. Chris@45: */ Chris@45: SERD_URI = 2, Chris@45: Chris@45: /** Chris@45: CURIE, a shortened URI. Chris@45: Chris@45: Value is an unquoted CURIE string relative to the current environment, Chris@45: e.g. "rdf:type". Chris@45: @see CURIE Syntax 1.0 Chris@45: */ Chris@45: SERD_CURIE = 3, Chris@45: Chris@45: /** Chris@45: A blank node. Chris@45: Chris@45: Value is a blank node ID, e.g. "id3", which is meaningful only within Chris@45: this serialisation. Chris@45: @see Turtle Chris@45: nodeID Chris@45: */ Chris@45: SERD_BLANK = 4 Chris@45: Chris@45: } SerdType; Chris@45: Chris@45: /** Chris@45: Flags indicating certain string properties relevant to serialisation. Chris@45: */ Chris@45: typedef enum { Chris@45: SERD_HAS_NEWLINE = 1, /**< Contains line breaks ('\\n' or '\\r') */ Chris@45: SERD_HAS_QUOTE = 1 << 1 /**< Contains quotes ('"') */ Chris@45: } SerdNodeFlag; Chris@45: Chris@45: /** Chris@45: Bitwise OR of SerdNodeFlag values. Chris@45: */ Chris@45: typedef uint32_t SerdNodeFlags; Chris@45: Chris@45: /** Chris@45: A syntactic RDF node. Chris@45: */ Chris@45: typedef struct { Chris@45: const uint8_t* buf; /**< Value string */ Chris@45: size_t n_bytes; /**< Size in bytes (not including null) */ Chris@45: size_t n_chars; /**< Length in characters (not including null)*/ Chris@45: SerdNodeFlags flags; /**< Node flags (e.g. string properties) */ Chris@45: SerdType type; /**< Node type */ Chris@45: } SerdNode; Chris@45: Chris@45: /** Chris@45: An unterminated string fragment. Chris@45: */ Chris@45: typedef struct { Chris@45: const uint8_t* buf; /**< Start of chunk */ Chris@45: size_t len; /**< Length of chunk in bytes */ Chris@45: } SerdChunk; Chris@45: Chris@45: /** Chris@45: An error description. Chris@45: */ Chris@45: typedef struct { Chris@45: SerdStatus status; /**< Error code */ Chris@45: const uint8_t* filename; /**< File where error was encountered, or NULL */ Chris@45: unsigned line; /**< Line where error was encountered, or 0 */ Chris@45: unsigned col; /**< Column where error was encountered */ Chris@45: const char* fmt; /**< Message format string (printf style) */ Chris@45: va_list* args; /**< Arguments for fmt */ Chris@45: } SerdError; Chris@45: Chris@45: /** Chris@45: A parsed URI. Chris@45: Chris@45: This struct directly refers to chunks in other strings, it does not own any Chris@45: memory itself. Thus, URIs can be parsed and/or resolved against a base URI Chris@45: in-place without allocating memory. Chris@45: */ Chris@45: typedef struct { Chris@45: SerdChunk scheme; /**< Scheme */ Chris@45: SerdChunk authority; /**< Authority */ Chris@45: SerdChunk path_base; /**< Path prefix if relative */ Chris@45: SerdChunk path; /**< Path suffix */ Chris@45: SerdChunk query; /**< Query */ Chris@45: SerdChunk fragment; /**< Fragment */ Chris@45: } SerdURI; Chris@45: Chris@45: /** Chris@45: Syntax style options. Chris@45: Chris@45: The style of the writer output can be controlled by ORing together Chris@45: values from this enumeration. Note that some options are only supported Chris@45: for some syntaxes (e.g. NTriples does not support abbreviation and is Chris@45: always ASCII). Chris@45: */ Chris@45: typedef enum { Chris@45: SERD_STYLE_ABBREVIATED = 1, /**< Abbreviate triples when possible. */ Chris@45: SERD_STYLE_ASCII = 1 << 1, /**< Escape all non-ASCII characters. */ Chris@45: SERD_STYLE_RESOLVED = 1 << 2, /**< Resolve URIs against base URI. */ Chris@45: SERD_STYLE_CURIED = 1 << 3, /**< Shorten URIs into CURIEs. */ Chris@45: SERD_STYLE_BULK = 1 << 4 /**< Write output in pages. */ Chris@45: } SerdStyle; Chris@45: Chris@45: /** Chris@45: @name String Utilities Chris@45: @{ Chris@45: */ Chris@45: Chris@45: /** Chris@45: Return a string describing a status code. Chris@45: */ Chris@45: SERD_API Chris@45: const uint8_t* Chris@45: serd_strerror(SerdStatus status); Chris@45: Chris@45: /** Chris@45: Measure a UTF-8 string. Chris@45: @return Length of `str` in characters (except NULL). Chris@45: @param str A null-terminated UTF-8 string. Chris@45: @param n_bytes (Output) Set to the size of `str` in bytes (except NULL). Chris@45: @param flags (Output) Set to the applicable flags. Chris@45: */ Chris@45: SERD_API Chris@45: size_t Chris@45: serd_strlen(const uint8_t* str, size_t* n_bytes, SerdNodeFlags* flags); Chris@45: Chris@45: /** Chris@45: Parse a string to a double. Chris@45: Chris@45: The API of this function is identical to the standard C strtod function, Chris@45: except this function is locale-independent and always matches the lexical Chris@45: format used in the Turtle grammar (the decimal point is always "."). Chris@45: */ Chris@45: SERD_API Chris@45: double Chris@45: serd_strtod(const char* str, char** endptr); Chris@45: Chris@45: /** Chris@45: Decode a base64 string. Chris@45: This function can be used to deserialise a blob node created with Chris@45: serd_node_new_blob(). Chris@45: Chris@45: @param str Base64 string to decode. Chris@45: @param len The length of `str`. Chris@45: @param size Set to the size of the returned blob in bytes. Chris@45: @return A newly allocated blob which must be freed with free(). Chris@45: */ Chris@45: SERD_API Chris@45: void* Chris@45: serd_base64_decode(const uint8_t* str, size_t len, size_t* size); Chris@45: Chris@45: /** Chris@45: @} Chris@45: @name URI Chris@45: @{ Chris@45: */ Chris@45: Chris@45: static const SerdURI SERD_URI_NULL = { Chris@45: {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0} Chris@45: }; Chris@45: Chris@45: /** Chris@45: Return the local path for `uri`, or NULL if `uri` is not a file URI. Chris@45: Note this (inappropriately named) function only removes the file scheme if Chris@45: necessary, and returns `uri` unmodified if it is an absolute path. Percent Chris@45: encoding and other issues are not handled, to properly convert a file URI to Chris@45: a path, use serd_file_uri_parse(). Chris@45: */ Chris@45: SERD_API Chris@45: const uint8_t* Chris@45: serd_uri_to_path(const uint8_t* uri); Chris@45: Chris@45: /** Chris@45: Get the unescaped path and hostname from a file URI. Chris@45: @param uri A file URI. Chris@45: @param hostname If non-NULL, set to the hostname, if present. Chris@45: @return The path component of the URI. Chris@45: Chris@45: The returned path and `*hostname` must be freed with free(). Chris@45: */ Chris@45: SERD_API Chris@45: uint8_t* Chris@45: serd_file_uri_parse(const uint8_t* uri, uint8_t** hostname); Chris@45: Chris@45: /** Chris@45: Return true iff `utf8` starts with a valid URI scheme. Chris@45: */ Chris@45: SERD_API Chris@45: bool Chris@45: serd_uri_string_has_scheme(const uint8_t* utf8); Chris@45: Chris@45: /** Chris@45: Parse `utf8`, writing result to `out`. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_uri_parse(const uint8_t* utf8, SerdURI* out); Chris@45: Chris@45: /** Chris@45: Set `out` to `uri` resolved against `base`. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_uri_resolve(const SerdURI* uri, const SerdURI* base, SerdURI* out); Chris@45: Chris@45: /** Chris@45: Sink function for raw string output. Chris@45: */ Chris@45: typedef size_t (*SerdSink)(const void* buf, size_t len, void* stream); Chris@45: Chris@45: /** Chris@45: Serialise `uri` with a series of calls to `sink`. Chris@45: */ Chris@45: SERD_API Chris@45: size_t Chris@45: serd_uri_serialise(const SerdURI* uri, SerdSink sink, void* stream); Chris@45: Chris@45: /** Chris@45: Serialise `uri` relative to `base` with a series of calls to `sink`. Chris@45: Chris@45: The `uri` is written as a relative URI iff if it a child of `base` and @c Chris@45: root. The optional `root` parameter must be a prefix of `base` and can be Chris@45: used keep up-references ("../") within a certain namespace. Chris@45: */ Chris@45: SERD_API Chris@45: size_t Chris@45: serd_uri_serialise_relative(const SerdURI* uri, Chris@45: const SerdURI* base, Chris@45: const SerdURI* root, Chris@45: SerdSink sink, Chris@45: void* stream); Chris@45: Chris@45: /** Chris@45: @} Chris@45: @name Node Chris@45: @{ Chris@45: */ Chris@45: Chris@45: static const SerdNode SERD_NODE_NULL = { NULL, 0, 0, 0, SERD_NOTHING }; Chris@45: Chris@45: /** Chris@45: Make a (shallow) node from `str`. Chris@45: Chris@45: This measures, but does not copy, `str`. No memory is allocated. Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_from_string(SerdType type, const uint8_t* str); Chris@45: Chris@45: /** Chris@45: Make a deep copy of `node`. Chris@45: Chris@45: @return a node that the caller must free with serd_node_free(). Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_copy(const SerdNode* node); Chris@45: Chris@45: /** Chris@45: Return true iff `a` is equal to `b`. Chris@45: */ Chris@45: SERD_API Chris@45: bool Chris@45: serd_node_equals(const SerdNode* a, const SerdNode* b); Chris@45: Chris@45: /** Chris@45: Simple wrapper for serd_node_new_uri() to resolve a URI node. Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_new_uri_from_node(const SerdNode* uri_node, Chris@45: const SerdURI* base, Chris@45: SerdURI* out); Chris@45: Chris@45: /** Chris@45: Simple wrapper for serd_node_new_uri() to resolve a URI string. Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_new_uri_from_string(const uint8_t* str, Chris@45: const SerdURI* base, Chris@45: SerdURI* out); Chris@45: Chris@45: /** Chris@45: Create a new file URI node from a file system path and optional hostname. Chris@45: Chris@45: Backslashes in Windows paths will be converted and '%' will always be Chris@45: percent encoded. If `escape` is true, all other invalid characters will be Chris@45: percent encoded as well. Chris@45: Chris@45: If `path` is relative, `hostname` is ignored. Chris@45: If `out` is not NULL, it will be set to the parsed URI. Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_new_file_uri(const uint8_t* path, Chris@45: const uint8_t* hostname, Chris@45: SerdURI* out, Chris@45: bool escape); Chris@45: Chris@45: /** Chris@45: Create a new node by serialising `uri` into a new string. Chris@45: Chris@45: @param uri The URI to serialise. Chris@45: Chris@45: @param base Base URI to resolve `uri` against (or NULL for no resolution). Chris@45: Chris@45: @param out Set to the parsing of the new URI (i.e. points only to Chris@45: memory owned by the new returned node). Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_new_uri(const SerdURI* uri, const SerdURI* base, SerdURI* out); Chris@45: Chris@45: /** Chris@45: Create a new node by serialising `uri` into a new relative URI. Chris@45: Chris@45: @param uri The URI to serialise. Chris@45: Chris@45: @param base Base URI to make `uri` relative to, if possible. Chris@45: Chris@45: @param root Root URI for resolution (see serd_uri_serialise_relative()). Chris@45: Chris@45: @param out Set to the parsing of the new URI (i.e. points only to Chris@45: memory owned by the new returned node). Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_new_relative_uri(const SerdURI* uri, Chris@45: const SerdURI* base, Chris@45: const SerdURI* root, Chris@45: SerdURI* out); Chris@45: Chris@45: /** Chris@45: Create a new node by serialising `d` into an xsd:decimal string. Chris@45: Chris@45: The resulting node will always contain a `.', start with a digit, and end Chris@45: with a digit (i.e. will have a leading and/or trailing `0' if necessary). Chris@45: It will never be in scientific notation. A maximum of `frac_digits` digits Chris@45: will be written after the decimal point, but trailing zeros will Chris@45: automatically be omitted (except one if `d` is a round integer). Chris@45: Chris@45: Note that about 16 and 8 fractional digits are required to precisely Chris@45: represent a double and float, respectively. Chris@45: Chris@45: @param d The value for the new node. Chris@45: @param frac_digits The maximum number of digits after the decimal place. Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_new_decimal(double d, unsigned frac_digits); Chris@45: Chris@45: /** Chris@45: Create a new node by serialising `i` into an xsd:integer string. Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_new_integer(int64_t i); Chris@45: Chris@45: /** Chris@45: Create a node by serialising `buf` into an xsd:base64Binary string. Chris@45: This function can be used to make a serialisable node out of arbitrary Chris@45: binary data, which can be decoded using serd_base64_decode(). Chris@45: Chris@45: @param buf Raw binary input data. Chris@45: @param size Size of `buf`. Chris@45: @param wrap_lines Wrap lines at 76 characters to conform to RFC 2045. Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_node_new_blob(const void* buf, size_t size, bool wrap_lines); Chris@45: Chris@45: /** Chris@45: Free any data owned by `node`. Chris@45: Chris@45: Note that if `node` is itself dynamically allocated (which is not the case Chris@45: for nodes created internally by serd), it will not be freed. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_node_free(SerdNode* node); Chris@45: Chris@45: /** Chris@45: @} Chris@45: @name Event Handlers Chris@45: @{ Chris@45: */ Chris@45: Chris@45: /** Chris@45: Sink (callback) for errors. Chris@45: Chris@45: @param handle Handle for user data. Chris@45: @param error Error description. Chris@45: */ Chris@45: typedef SerdStatus (*SerdErrorSink)(void* handle, Chris@45: const SerdError* error); Chris@45: Chris@45: /** Chris@45: Sink (callback) for base URI changes. Chris@45: Chris@45: Called whenever the base URI of the serialisation changes. Chris@45: */ Chris@45: typedef SerdStatus (*SerdBaseSink)(void* handle, Chris@45: const SerdNode* uri); Chris@45: Chris@45: /** Chris@45: Sink (callback) for namespace definitions. Chris@45: Chris@45: Called whenever a prefix is defined in the serialisation. Chris@45: */ Chris@45: typedef SerdStatus (*SerdPrefixSink)(void* handle, Chris@45: const SerdNode* name, Chris@45: const SerdNode* uri); Chris@45: Chris@45: /** Chris@45: Sink (callback) for statements. Chris@45: Chris@45: Called for every RDF statement in the serialisation. Chris@45: */ Chris@45: typedef SerdStatus (*SerdStatementSink)(void* handle, Chris@45: SerdStatementFlags flags, Chris@45: const SerdNode* graph, Chris@45: const SerdNode* subject, Chris@45: const SerdNode* predicate, Chris@45: const SerdNode* object, Chris@45: const SerdNode* object_datatype, Chris@45: const SerdNode* object_lang); Chris@45: Chris@45: /** Chris@45: Sink (callback) for anonymous node end markers. Chris@45: Chris@45: This is called to indicate that the anonymous node with the given Chris@45: `value` will no longer be referred to by any future statements Chris@45: (i.e. the anonymous serialisation of the node is finished). Chris@45: */ Chris@45: typedef SerdStatus (*SerdEndSink)(void* handle, Chris@45: const SerdNode* node); Chris@45: Chris@45: /** Chris@45: @} Chris@45: @name Environment Chris@45: @{ Chris@45: */ Chris@45: Chris@45: /** Chris@45: Create a new environment. Chris@45: */ Chris@45: SERD_API Chris@45: SerdEnv* Chris@45: serd_env_new(const SerdNode* base_uri); Chris@45: Chris@45: /** Chris@45: Free `ns`. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_env_free(SerdEnv* env); Chris@45: Chris@45: /** Chris@45: Get the current base URI. Chris@45: */ Chris@45: SERD_API Chris@45: const SerdNode* Chris@45: serd_env_get_base_uri(const SerdEnv* env, Chris@45: SerdURI* out); Chris@45: Chris@45: /** Chris@45: Set the current base URI. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_env_set_base_uri(SerdEnv* env, Chris@45: const SerdNode* uri); Chris@45: Chris@45: /** Chris@45: Set a namespace prefix. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_env_set_prefix(SerdEnv* env, Chris@45: const SerdNode* name, Chris@45: const SerdNode* uri); Chris@45: Chris@45: /** Chris@45: Set a namespace prefix. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_env_set_prefix_from_strings(SerdEnv* env, Chris@45: const uint8_t* name, Chris@45: const uint8_t* uri); Chris@45: Chris@45: /** Chris@45: Qualify `uri` into a CURIE if possible. Chris@45: */ Chris@45: SERD_API Chris@45: bool Chris@45: serd_env_qualify(const SerdEnv* env, Chris@45: const SerdNode* uri, Chris@45: SerdNode* prefix, Chris@45: SerdChunk* suffix); Chris@45: Chris@45: /** Chris@45: Expand `curie`. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_env_expand(const SerdEnv* env, Chris@45: const SerdNode* curie, Chris@45: SerdChunk* uri_prefix, Chris@45: SerdChunk* uri_suffix); Chris@45: Chris@45: /** Chris@45: Expand `node`, which must be a CURIE or URI, to a full URI. Chris@45: */ Chris@45: SERD_API Chris@45: SerdNode Chris@45: serd_env_expand_node(const SerdEnv* env, Chris@45: const SerdNode* node); Chris@45: Chris@45: /** Chris@45: Call `func` for each prefix defined in `env`. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_env_foreach(const SerdEnv* env, Chris@45: SerdPrefixSink func, Chris@45: void* handle); Chris@45: Chris@45: /** Chris@45: @} Chris@45: @name Reader Chris@45: @{ Chris@45: */ Chris@45: Chris@45: /** Chris@45: Create a new RDF reader. Chris@45: */ Chris@45: SERD_API Chris@45: SerdReader* Chris@45: serd_reader_new(SerdSyntax syntax, Chris@45: void* handle, Chris@45: void (*free_handle)(void*), Chris@45: SerdBaseSink base_sink, Chris@45: SerdPrefixSink prefix_sink, Chris@45: SerdStatementSink statement_sink, Chris@45: SerdEndSink end_sink); Chris@45: Chris@45: /** Chris@45: Enable or disable strict parsing. Chris@45: Chris@45: The reader is non-strict (lax) by default, which will tolerate URIs with Chris@45: invalid characters. Setting strict will fail when parsing such files. An Chris@45: error is printed for invalid input in either case. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_reader_set_strict(SerdReader* reader, bool strict); Chris@45: Chris@45: /** Chris@45: Set a function to be called when errors occur during reading. Chris@45: Chris@45: The `error_sink` will be called with `handle` as its first argument. If Chris@45: no error function is set, errors are printed to stderr in GCC style. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_reader_set_error_sink(SerdReader* reader, Chris@45: SerdErrorSink error_sink, Chris@45: void* handle); Chris@45: Chris@45: /** Chris@45: Return the `handle` passed to serd_reader_new(). Chris@45: */ Chris@45: SERD_API Chris@45: void* Chris@45: serd_reader_get_handle(const SerdReader* reader); Chris@45: Chris@45: /** Chris@45: Set a prefix to be added to all blank node identifiers. Chris@45: Chris@45: This is useful when multiple files are to be parsed into the same output Chris@45: (e.g. a store, or other files). Since Serd preserves blank node IDs, this Chris@45: could cause conflicts where two non-equivalent blank nodes are merged, Chris@45: resulting in corrupt data. By setting a unique blank node prefix for each Chris@45: parsed file, this can be avoided, while preserving blank node names. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_reader_add_blank_prefix(SerdReader* reader, Chris@45: const uint8_t* prefix); Chris@45: Chris@45: /** Chris@45: Set the URI of the default graph. Chris@45: Chris@45: If this is set, the reader will emit quads with the graph set to the given Chris@45: node for any statements that are not in a named graph (which is currently Chris@45: all of them since Serd currently does not support any graph syntaxes). Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_reader_set_default_graph(SerdReader* reader, Chris@45: const SerdNode* graph); Chris@45: Chris@45: /** Chris@45: Read a file at a given `uri`. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_reader_read_file(SerdReader* reader, Chris@45: const uint8_t* uri); Chris@45: Chris@45: /** Chris@45: Start an incremental read from a file handle. Chris@45: Chris@45: Iff `bulk` is true, `file` will be read a page at a time. This is more Chris@45: efficient, but uses a page of memory and means that an entire page of input Chris@45: must be ready before any callbacks will fire. To react as soon as input Chris@45: arrives, set `bulk` to false. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_reader_start_stream(SerdReader* me, Chris@45: FILE* file, Chris@45: const uint8_t* name, Chris@45: bool bulk); Chris@45: Chris@45: /** Chris@45: Read a single "chunk" of data during an incremental read. Chris@45: Chris@45: This function will read a single top level description, and return. This Chris@45: may be a directive, statement, or several statements; essentially it reads Chris@45: until a '.' is encountered. This is particularly useful for reading Chris@45: directly from a pipe or socket. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_reader_read_chunk(SerdReader* me); Chris@45: Chris@45: /** Chris@45: Finish an incremental read from a file handle. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_reader_end_stream(SerdReader* me); Chris@45: Chris@45: /** Chris@45: Read `file`. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_reader_read_file_handle(SerdReader* reader, Chris@45: FILE* file, Chris@45: const uint8_t* name); Chris@45: Chris@45: /** Chris@45: Read `utf8`. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_reader_read_string(SerdReader* me, const uint8_t* utf8); Chris@45: Chris@45: /** Chris@45: Free `reader`. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_reader_free(SerdReader* reader); Chris@45: Chris@45: /** Chris@45: @} Chris@45: @name Writer Chris@45: @{ Chris@45: */ Chris@45: Chris@45: /** Chris@45: Create a new RDF writer. Chris@45: */ Chris@45: SERD_API Chris@45: SerdWriter* Chris@45: serd_writer_new(SerdSyntax syntax, Chris@45: SerdStyle style, Chris@45: SerdEnv* env, Chris@45: const SerdURI* base_uri, Chris@45: SerdSink sink, Chris@45: void* stream); Chris@45: Chris@45: /** Chris@45: Free `writer`. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_writer_free(SerdWriter* writer); Chris@45: Chris@45: /** Chris@45: Return the env used by `writer`. Chris@45: */ Chris@45: SERD_API Chris@45: SerdEnv* Chris@45: serd_writer_get_env(SerdWriter* writer); Chris@45: Chris@45: /** Chris@45: A convenience sink function for writing to a FILE*. Chris@45: Chris@45: This function can be used as a SerdSink when writing to a FILE*. The Chris@45: `stream` parameter must be a FILE* opened for writing. Chris@45: */ Chris@45: SERD_API Chris@45: size_t Chris@45: serd_file_sink(const void* buf, size_t len, void* stream); Chris@45: Chris@45: /** Chris@45: A convenience sink function for writing to a string. Chris@45: Chris@45: This function can be used as a SerdSink to write to a SerdChunk which is Chris@45: resized as necessary with realloc(). The `stream` parameter must point to Chris@45: an initialized SerdChunk. When the write is finished, the string should be Chris@45: retrieved with serd_chunk_sink_finish(). Chris@45: */ Chris@45: SERD_API Chris@45: size_t Chris@45: serd_chunk_sink(const void* buf, size_t len, void* stream); Chris@45: Chris@45: /** Chris@45: Finish a serialisation to a chunk with serd_chunk_sink(). Chris@45: Chris@45: The returned string is the result of the serialisation, which is NULL Chris@45: terminated (by this function) and owned by the caller. Chris@45: */ Chris@45: SERD_API Chris@45: uint8_t* Chris@45: serd_chunk_sink_finish(SerdChunk* stream); Chris@45: Chris@45: /** Chris@45: Set a function to be called when errors occur during writing. Chris@45: Chris@45: The `error_sink` will be called with `handle` as its first argument. If Chris@45: no error function is set, errors are printed to stderr. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_writer_set_error_sink(SerdWriter* writer, Chris@45: SerdErrorSink error_sink, Chris@45: void* handle); Chris@45: Chris@45: /** Chris@45: Set a prefix to be removed from matching blank node identifiers. Chris@45: */ Chris@45: SERD_API Chris@45: void Chris@45: serd_writer_chop_blank_prefix(SerdWriter* writer, Chris@45: const uint8_t* prefix); Chris@45: Chris@45: /** Chris@45: Set the current output base URI (and emit directive if applicable). Chris@45: Chris@45: Note this function can be safely casted to SerdBaseSink. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_writer_set_base_uri(SerdWriter* writer, Chris@45: const SerdNode* uri); Chris@45: Chris@45: /** Chris@45: Set the current root URI. Chris@45: Chris@45: The root URI should be a prefix of the base URI. The path of the root URI Chris@45: is the highest path any relative up-reference can refer to. For example, Chris@45: with root and base , Chris@45: will be written as <../>, but will be Chris@45: written non-relatively as . If the root is not explicitly set, Chris@45: it defaults to the base URI, so no up-references will be created at all. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_writer_set_root_uri(SerdWriter* writer, Chris@45: const SerdNode* uri); Chris@45: Chris@45: /** Chris@45: Set a namespace prefix (and emit directive if applicable). Chris@45: Chris@45: Note this function can be safely casted to SerdPrefixSink. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_writer_set_prefix(SerdWriter* writer, Chris@45: const SerdNode* name, Chris@45: const SerdNode* uri); Chris@45: Chris@45: /** Chris@45: Write a statement. Chris@45: Chris@45: Note this function can be safely casted to SerdStatementSink. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_writer_write_statement(SerdWriter* writer, Chris@45: SerdStatementFlags flags, Chris@45: const SerdNode* graph, Chris@45: const SerdNode* subject, Chris@45: const SerdNode* predicate, Chris@45: const SerdNode* object, Chris@45: const SerdNode* object_datatype, Chris@45: const SerdNode* object_lang); Chris@45: Chris@45: /** Chris@45: Mark the end of an anonymous node's description. Chris@45: Chris@45: Note this function can be safely casted to SerdEndSink. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_writer_end_anon(SerdWriter* writer, Chris@45: const SerdNode* node); Chris@45: Chris@45: /** Chris@45: Finish a write. Chris@45: */ Chris@45: SERD_API Chris@45: SerdStatus Chris@45: serd_writer_finish(SerdWriter* writer); Chris@45: Chris@45: /** Chris@45: @} Chris@45: @} Chris@45: */ Chris@45: Chris@45: #ifdef __cplusplus Chris@45: } /* extern "C" */ Chris@45: #endif Chris@45: Chris@45: #endif /* SERD_SERD_H */