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