diff options
Diffstat (limited to 'sord')
-rw-r--r-- | sord/sord.h | 657 | ||||
-rw-r--r-- | sord/sordmm.hpp | 714 |
2 files changed, 0 insertions, 1371 deletions
diff --git a/sord/sord.h b/sord/sord.h deleted file mode 100644 index 4665b50..0000000 --- a/sord/sord.h +++ /dev/null @@ -1,657 +0,0 @@ -/* - Copyright 2011-2016 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file sord.h API for Sord, a lightweight RDF model library. -*/ - -#ifndef SORD_SORD_H -#define SORD_SORD_H - -#include "serd/serd.h" - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -#ifdef SORD_SHARED -# ifdef _WIN32 -# define SORD_LIB_IMPORT __declspec(dllimport) -# define SORD_LIB_EXPORT __declspec(dllexport) -# else -# define SORD_LIB_IMPORT __attribute__((visibility("default"))) -# define SORD_LIB_EXPORT __attribute__((visibility("default"))) -# endif -# ifdef SORD_INTERNAL -# define SORD_API SORD_LIB_EXPORT -# else -# define SORD_API SORD_LIB_IMPORT -# endif -#else -# define SORD_API -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - @defgroup sord Sord - A lightweight RDF model library. - - Sord stores RDF (subject object predicate context) quads, where the context - may be omitted (to represent triples in the default graph). - @{ -*/ - -/** - Sord World. - The World represents all library state, including interned strings. -*/ -typedef struct SordWorldImpl SordWorld; - -/** - Sord Model. - - A model is an indexed set of Quads (i.e. it can contain several RDF - graphs). It may be searched using various patterns depending on which - indices are enabled. -*/ -typedef struct SordModelImpl SordModel; - -/** - Model Inserter. - - An inserter is used for writing statements to a model using the Serd sink - interface. This makes it simple to write to a model directly using a - SerdReader, or any other code that writes statements to a SerdStatementSink. -*/ -typedef struct SordInserterImpl SordInserter; - -/** - Model Iterator. -*/ -typedef struct SordIterImpl SordIter; - -/** - RDF Node. - A Node is a component of a Quad. Nodes may be URIs, blank nodes, or - (in the case of quad objects only) string literals. Literal nodes may - have an associate language or datatype (but not both). -*/ -typedef struct SordNodeImpl SordNode; - -/** - Quad of nodes (a statement), or a quad pattern. - - Nodes are ordered (S P O G). The ID of the default graph is 0. -*/ -typedef const SordNode* SordQuad[4]; - -/** - Index into a SordQuad. -*/ -typedef enum { - SORD_SUBJECT = 0, /**< Subject */ - SORD_PREDICATE = 1, /**< Predicate ("key") */ - SORD_OBJECT = 2, /**< Object ("value") */ - SORD_GRAPH = 3 /**< Graph ("context") */ -} SordQuadIndex; - -/** - Type of a node. -*/ -typedef enum { - SORD_URI = 1, /**< URI */ - SORD_BLANK = 2, /**< Blank node identifier */ - SORD_LITERAL = 3 /**< Literal (string with optional lang or datatype) */ -} SordNodeType; - -/** - Indexing option. -*/ -typedef enum { - SORD_SPO = 1, /**< Subject, Predicate, Object */ - SORD_SOP = 1 << 1, /**< Subject, Object, Predicate */ - SORD_OPS = 1 << 2, /**< Object, Predicate, Subject */ - SORD_OSP = 1 << 3, /**< Object, Subject, Predicate */ - SORD_PSO = 1 << 4, /**< Predicate, Subject, Object */ - SORD_POS = 1 << 5 /**< Predicate, Object, Subject */ -} SordIndexOption; - -/** - @name World - @{ -*/ - -/** - Create a new Sord World. - It is safe to use multiple worlds in one process, though no data - (e.g. nodes) can be shared between worlds, and this should be avoided if - possible for performance reasons. -*/ -SORD_API -SordWorld* -sord_world_new(void); - -/** - Free `world`. -*/ -SORD_API -void -sord_world_free(SordWorld* world); - -/** - Set a function to be called when errors occur. - - The `error_sink` will be called with `handle` as its first argument. If - no error function is set, errors are printed to stderr. -*/ -SORD_API -void -sord_world_set_error_sink(SordWorld* world, - SerdErrorSink error_sink, - void* handle); - -/** - @} - @name Node - @{ -*/ - -/** - Get a URI node from a string. - - Note this function measures `str`, which is a common bottleneck. - Use sord_node_from_serd_node() instead if `str` is already measured. -*/ -SORD_API -SordNode* -sord_new_uri(SordWorld* world, const uint8_t* uri); - -/** - Get a URI node from a relative URI string. -*/ -SORD_API -SordNode* -sord_new_relative_uri(SordWorld* world, - const uint8_t* uri, - const uint8_t* base_uri); - -/** - Get a blank node from a string. - - Note this function measures `str`, which is a common bottleneck. - Use sord_node_from_serd_node() instead if `str` is already measured. -*/ -SORD_API -SordNode* -sord_new_blank(SordWorld* world, const uint8_t* str); - -/** - Get a literal node from a string. - - Note this function measures `str`, which is a common bottleneck. - Use sord_node_from_serd_node() instead if `str` is already measured. -*/ -SORD_API -SordNode* -sord_new_literal(SordWorld* world, - SordNode* datatype, - const uint8_t* str, - const char* lang); - -/** - Copy a node (obtain a reference). - - Node that since nodes are interned and reference counted, this does not - actually create a deep copy of `node`. -*/ -SORD_API -SordNode* -sord_node_copy(const SordNode* node); - -/** - Free a node (drop a reference). -*/ -SORD_API -void -sord_node_free(SordWorld* world, SordNode* node); - -/** - Return the type of a node (SORD_URI, SORD_BLANK, or SORD_LITERAL). -*/ -SORD_API -SordNodeType -sord_node_get_type(const SordNode* node); - -/** - Return the string value of a node. -*/ -SORD_API -const uint8_t* -sord_node_get_string(const SordNode* node); - -/** - Return the string value of a node, and set `bytes` to its length in bytes. -*/ -SORD_API -const uint8_t* -sord_node_get_string_counted(const SordNode* node, size_t* bytes); - -/** - Return the string value of a node, and set `bytes` to its length in bytes, - and `count` to its length in characters. -*/ -SORD_API -const uint8_t* -sord_node_get_string_measured(const SordNode* node, - size_t* bytes, - size_t* chars); - -/** - Return the language of a literal node (or NULL). -*/ -SORD_API -const char* -sord_node_get_language(const SordNode* node); - -/** - Return the datatype URI of a literal node (or NULL). -*/ -SORD_API -SordNode* -sord_node_get_datatype(const SordNode* node); - -/** - Return the flags (string attributes) of a node. -*/ -SORD_API -SerdNodeFlags -sord_node_get_flags(const SordNode* node); - -/** - Return true iff node can be serialised as an inline object. - - More specifically, this returns true iff the node is the object field - of exactly one statement, and therefore can be inlined since it needn't - be referred to by name. -*/ -SORD_API -bool -sord_node_is_inline_object(const SordNode* node); - -/** - Return true iff `a` is equal to `b`. - - Note this is much faster than comparing the node's strings. -*/ -SORD_API -bool -sord_node_equals(const SordNode* a, - const SordNode* b); - -/** - Return a SordNode as a SerdNode. - - The returned node is shared and must not be freed or modified. -*/ -SORD_API -const SerdNode* -sord_node_to_serd_node(const SordNode* node); - -/** - Create a new SordNode from a SerdNode. - - The returned node must be freed using sord_node_free(). -*/ -SORD_API -SordNode* -sord_node_from_serd_node(SordWorld* world, - SerdEnv* env, - const SerdNode* node, - const SerdNode* datatype, - const SerdNode* lang); - -/** - @} - @name Model - @{ -*/ - -/** - Create a new model. - - @param world The world in which to make this model. - - @param indices SordIndexOption flags (e.g. SORD_SPO|SORD_OPS). Be sure to - enable an index where the most significant node(s) are not variables in your - queries (e.g. to make (? P O) queries, enable either SORD_OPS or SORD_POS). - - @param graphs If true, store (and index) graph contexts. -*/ -SORD_API -SordModel* -sord_new(SordWorld* world, - unsigned indices, - bool graphs); - -/** - Close and free `model`. -*/ -SORD_API -void -sord_free(SordModel* model); - -/** - Get the world associated with `model`. -*/ -SORD_API -SordWorld* -sord_get_world(SordModel* model); - -/** - Return the number of nodes stored in `world`. - - Nodes are included in this count iff they are a part of a quad in `world`. -*/ -SORD_API -size_t -sord_num_nodes(const SordWorld* world); - -/** - Return the number of quads stored in `model`. -*/ -SORD_API -size_t -sord_num_quads(const SordModel* model); - -/** - Return an iterator to the start of `model`. -*/ -SORD_API -SordIter* -sord_begin(const SordModel* model); - -/** - Search for statements by a quad pattern. - @return an iterator to the first match, or NULL if no matches found. -*/ -SORD_API -SordIter* -sord_find(SordModel* model, const SordQuad pat); - -/** - Search for statements by nodes. - @return an iterator to the first match, or NULL if no matches found. -*/ -SORD_API -SordIter* -sord_search(SordModel* model, - const SordNode* s, - const SordNode* p, - const SordNode* o, - const SordNode* g); -/** - Search for a single node that matches a pattern. - Exactly one of `s`, `p`, `o` must be NULL. - This function is mainly useful for predicates that only have one value. - The returned node must be freed using sord_node_free(). - @return the first matching node, or NULL if no matches are found. -*/ -SORD_API -SordNode* -sord_get(SordModel* model, - const SordNode* s, - const SordNode* p, - const SordNode* o, - const SordNode* g); - -/** - Return true iff a statement exists. -*/ -SORD_API -bool -sord_ask(SordModel* model, - const SordNode* s, - const SordNode* p, - const SordNode* o, - const SordNode* g); - -/** - Return the number of matching statements. -*/ -SORD_API -uint64_t -sord_count(SordModel* model, - const SordNode* s, - const SordNode* p, - const SordNode* o, - const SordNode* g); - -/** - Check if `model` contains a triple pattern. - - @return true if `model` contains a match for `pat`, otherwise false. -*/ -SORD_API -bool -sord_contains(SordModel* model, const SordQuad pat); - -/** - Add a quad to a model. - - Calling this function invalidates all iterators on `model`. - - @return true on success, false, on error. -*/ -SORD_API -bool -sord_add(SordModel* model, const SordQuad tup); - -/** - Remove a quad from a model. - - Calling this function invalidates all iterators on `model`. To remove quads - while iterating, use sord_erase() instead. -*/ -SORD_API -void -sord_remove(SordModel* model, const SordQuad tup); - -/** - Remove a quad from a model via an iterator. - - Calling this function invalidates all iterators on `model` except `iter`. - - @param model The model which `iter` points to. - @param iter Iterator to the element to erase, which is incremented to the - next value on return. -*/ -SORD_API -SerdStatus -sord_erase(SordModel* model, SordIter* iter); - -/** - @} - @name Inserter - @{ -*/ - -/** - Create an inserter for writing statements to a model. -*/ -SORD_API -SordInserter* -sord_inserter_new(SordModel* model, - SerdEnv* env); - -/** - Free an inserter. -*/ -SORD_API -void -sord_inserter_free(SordInserter* inserter); - -/** - Set the current base URI for writing to the model. - - Note this function can be safely casted to SerdBaseSink. -*/ -SORD_API -SerdStatus -sord_inserter_set_base_uri(SordInserter* inserter, - const SerdNode* uri); - -/** - Set a namespace prefix for writing to the model. - - Note this function can be safely casted to SerdPrefixSink. -*/ -SORD_API -SerdStatus -sord_inserter_set_prefix(SordInserter* inserter, - const SerdNode* name, - const SerdNode* uri); - -/** - Write a statement to the model. - - Note this function can be safely casted to SerdStatementSink. -*/ -SORD_API -SerdStatus -sord_inserter_write_statement(SordInserter* inserter, - SerdStatementFlags flags, - const SerdNode* graph, - const SerdNode* subject, - const SerdNode* predicate, - const SerdNode* object, - const SerdNode* object_datatype, - const SerdNode* object_lang); - -/** - @} - @name Iteration - @{ -*/ - -/** - Set `quad` to the quad pointed to by `iter`. -*/ -SORD_API -void -sord_iter_get(const SordIter* iter, SordQuad tup); - -/** - Return a field of the quad pointed to by `iter`. - - Returns NULL if `iter` is NULL or is at the end. -*/ -SORD_API -const SordNode* -sord_iter_get_node(const SordIter* iter, SordQuadIndex index); - -/** - Return the store pointed to by `iter`. -*/ -SORD_API -const SordModel* -sord_iter_get_model(SordIter* iter); - -/** - Increment `iter` to point to the next statement. -*/ -SORD_API -bool -sord_iter_next(SordIter* iter); - -/** - Return true iff `iter` is at the end of its range. -*/ -SORD_API -bool -sord_iter_end(const SordIter* iter); - -/** - Free `iter`. -*/ -SORD_API -void -sord_iter_free(SordIter* iter); - -/** - @} - @name Utilities - @{ -*/ - -/** - Match two quads (using ID comparison only). - - This function is a straightforward and fast equivalence match with wildcard - support (ID 0 is a wildcard). It does not actually read node data. - @return true iff `x` and `y` match. -*/ -SORD_API -bool -sord_quad_match(const SordQuad x, const SordQuad y); - -/** - @} - @name Serialisation - @{ -*/ - -/** - Return a reader that will read into `model`. -*/ -SORD_API -SerdReader* -sord_new_reader(SordModel* model, - SerdEnv* env, - SerdSyntax syntax, - SordNode* graph); - -/** - Write a model to a writer. -*/ -SORD_API -bool -sord_write(SordModel* model, - SerdWriter* writer, - SordNode* graph); - -/** - Write a range to a writer. - - This increments `iter` to its end, then frees it. -*/ -SORD_API -bool -sord_write_iter(SordIter* iter, - SerdWriter* writer); - -/** - @} - @} -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* SORD_SORD_H */ diff --git a/sord/sordmm.hpp b/sord/sordmm.hpp deleted file mode 100644 index 1cb34e7..0000000 --- a/sord/sordmm.hpp +++ /dev/null @@ -1,714 +0,0 @@ -/* - Copyright 2011-2013 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file sordmm.hpp - Public Sord C++ API. -*/ - -#ifndef SORD_SORDMM_HPP -#define SORD_SORDMM_HPP - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -#endif - -#include "serd/serd.h" -#include "sord/sord.h" - -#if defined(__clang__) -# pragma clang diagnostic pop -#endif - -#include <cassert> -#include <cstdint> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <iostream> -#include <set> -#include <sstream> -#include <string> - -#define SORD_NS_XSD "http://www.w3.org/2001/XMLSchema#" - -namespace Sord { - -/** Utility base class to prevent copying or moving. */ -class Noncopyable { -public: - Noncopyable() = default; - ~Noncopyable() = default; - - Noncopyable(const Noncopyable&) = delete; - const Noncopyable& operator=(const Noncopyable&) = delete; - - Noncopyable(Noncopyable&&) = delete; - Noncopyable& operator=(Noncopyable&&) = delete; -}; - -/** C++ wrapper for a Sord object. */ -template <typename T> -class Wrapper { -public: - inline Wrapper(T* c_obj = nullptr) : _c_obj(c_obj) {} - - inline T* c_obj() { return _c_obj; } - inline const T* c_obj() const { return _c_obj; } - -protected: - T* _c_obj; -}; - -/** Collection of RDF namespaces with prefixes. */ -class Namespaces : public Wrapper<SerdEnv> { -public: - Namespaces() : Wrapper<SerdEnv>(serd_env_new(nullptr)) {} - ~Namespaces() { serd_env_free(_c_obj); } - - static inline SerdNode string_to_node(SerdType type, const std::string& s) { - SerdNode ret = {reinterpret_cast<const uint8_t*>(s.c_str()), - s.length(), - s.length(), - 0, - type}; - return ret; - } - - inline void add(const std::string& name, - const std::string& uri) { - const SerdNode name_node = string_to_node(SERD_LITERAL, name); - const SerdNode uri_node = string_to_node(SERD_URI, uri); - serd_env_set_prefix(_c_obj, &name_node, &uri_node); - } - - inline std::string qualify(std::string uri) const { - const SerdNode uri_node = string_to_node(SERD_URI, uri); - SerdNode prefix; - SerdChunk suffix; - if (serd_env_qualify(_c_obj, &uri_node, &prefix, &suffix)) { - std::string ret(reinterpret_cast<const char*>(prefix.buf), - prefix.n_bytes); - ret.append(":").append(reinterpret_cast<const char*>(suffix.buf), - suffix.len); - return ret; - } - return uri; - } - - inline std::string expand(const std::string& curie) const { - assert(curie.find(':') != std::string::npos); - SerdNode curie_node = string_to_node(SERD_CURIE, curie); - SerdChunk uri_prefix; - SerdChunk uri_suffix; - if (!serd_env_expand(_c_obj, &curie_node, &uri_prefix, &uri_suffix)) { - std::string ret(reinterpret_cast<const char*>(uri_prefix.buf), - uri_prefix.len); - ret.append(reinterpret_cast<const char*>(uri_suffix.buf), - uri_suffix.len); - return ret; - } - std::cerr << "CURIE `" << curie << "' has unknown prefix." << std::endl; - return curie; - } -}; - -/** Sord library state. */ -class World : public Noncopyable, public Wrapper<SordWorld> { -public: - inline World() - : _next_blank_id(0) - { - _c_obj = sord_world_new(); - } - - inline ~World() { - sord_world_free(_c_obj); - } - - inline uint64_t blank_id() { return _next_blank_id++; } - - inline void add_prefix(const std::string& prefix, const std::string& uri) { - _prefixes.add(prefix, uri); - } - - inline const Namespaces& prefixes() const { return _prefixes; } - inline Namespaces& prefixes() { return _prefixes; } - inline SordWorld* world() { return _c_obj; } - -private: - Namespaces _prefixes; - std::set<std::string> _blank_ids; - uint64_t _next_blank_id; -}; - -/** An RDF Node (resource, literal, etc) - */ -class Node : public Wrapper<SordNode> { -public: - enum Type { - UNKNOWN = 0, - URI = SORD_URI, - BLANK = SORD_BLANK, - LITERAL = SORD_LITERAL - }; - - inline Node() : Wrapper<SordNode>(nullptr), _world(nullptr) {} - - inline Node(World& world, Type t, const std::string& s); - inline Node(World& world); - inline Node(World& world, const SordNode* node); - inline Node(World& world, SordNode* node, bool copy=false); - inline Node(const Node& other); - inline ~Node(); - - inline Type type() const { - return _c_obj ? static_cast<Type>(sord_node_get_type(_c_obj)) : UNKNOWN; - } - - inline const SordNode* get_node() const { return _c_obj; } - inline SordNode* get_node() { return _c_obj; } - - const SerdNode* to_serd_node() const { - return sord_node_to_serd_node(_c_obj); - } - - inline bool is_valid() const { return type() != UNKNOWN; } - - inline bool operator<(const Node& other) const { - if (type() != other.type()) { - return type() < other.type(); - } else { - return to_string() < other.to_string(); - } - } - - Node& operator=(const Node& other) { - if (&other != this) { - if (_c_obj) { - sord_node_free(_world->c_obj(), _c_obj); - } - _world = other._world; - _c_obj = other._c_obj ? sord_node_copy(other._c_obj) : nullptr; - } - return *this; - } - - inline bool operator==(const Node& other) const { - return sord_node_equals(_c_obj, other._c_obj); - } - - inline const uint8_t* to_u_string() const; - inline const char* to_c_string() const; - inline std::string to_string() const; - - inline bool is_literal_type(const char* type_uri) const; - - inline bool is_uri() const { return _c_obj && type() == URI; } - inline bool is_blank() const { return _c_obj && type() == BLANK; } - inline bool is_int() const { return is_literal_type(SORD_NS_XSD "integer"); } - inline bool is_float() const { return is_literal_type(SORD_NS_XSD "decimal"); } - inline bool is_bool() const { return is_literal_type(SORD_NS_XSD "boolean"); } - - inline int to_int() const; - inline float to_float() const; - inline bool to_bool() const; - - inline static Node blank_id(World& world, const std::string& base="b") { - const uint64_t num = world.blank_id(); - std::ostringstream ss; - ss << base << num; - return Node(world, Node::BLANK, ss.str()); - } - -private: - World* _world; -}; - -inline std::ostream& -operator<<(std::ostream& os, const Node& node) -{ - return os << node.to_string(); -} - -class URI : public Node { -public: - inline URI(World& world, const std::string& s) - : Node(world, Node::URI, s) {} - inline URI(World& world, const std::string& s, const std::string& base) - : Node(world, - sord_new_relative_uri( - world.world(), - reinterpret_cast<const uint8_t*>(s.c_str()), - reinterpret_cast<const uint8_t*>(base.c_str()))) - { - } -}; - -class Curie : public Node { -public: - inline Curie(World& world, const std::string& s) - : Node(world, Node::URI, world.prefixes().expand(s)) {} -}; - -class Literal : public Node { -public: - inline Literal(World& world, const std::string& s) - : Node(world, Node::LITERAL, s) {} - - static inline Node decimal(World& world, double d, unsigned frac_digits) { - const SerdNode val = serd_node_new_decimal(d, frac_digits); - const SerdNode type = serd_node_from_string( - SERD_URI, reinterpret_cast<const uint8_t*>(SORD_NS_XSD "decimal")); - - return Node( - world, - sord_node_from_serd_node( - world.c_obj(), world.prefixes().c_obj(), &val, &type, nullptr), - false); - } - - static inline Node integer(World& world, int64_t i) { - const SerdNode val = serd_node_new_integer(i); - const SerdNode type = serd_node_from_string( - SERD_URI, reinterpret_cast<const uint8_t*>(SORD_NS_XSD "integer")); - - return Node( - world, - sord_node_from_serd_node( - world.c_obj(), world.prefixes().c_obj(), &val, &type, nullptr), - false); - } -}; - -inline -Node::Node(World& world, Type type, const std::string& s) - : _world(&world) -{ - switch (type) { - case URI: - _c_obj = - sord_new_uri(world.world(), - reinterpret_cast<const unsigned char*>(s.c_str())); - break; - case LITERAL: - _c_obj = - sord_new_literal(world.world(), - nullptr, - reinterpret_cast<const unsigned char*>(s.c_str()), - nullptr); - break; - case BLANK: - _c_obj = - sord_new_blank(world.world(), - reinterpret_cast<const unsigned char*>(s.c_str())); - break; - default: - _c_obj = nullptr; - } - - assert(this->type() == type); -} - -inline -Node::Node(World& world) - : _world(&world) -{ - Node me = blank_id(world); - *this = me; -} - -inline -Node::Node(World& world, const SordNode* node) - : _world(&world) -{ - _c_obj = sord_node_copy(node); -} - -inline -Node::Node(World& world, SordNode* node, bool copy) - : _world(&world) -{ - _c_obj = copy ? sord_node_copy(node) : node; -} - -inline -Node::Node(const Node& other) // NOLINT(bugprone-copy-constructor-init) - : Wrapper<SordNode>() - , _world(other._world) -{ - if (_world) { - _c_obj = other._c_obj ? sord_node_copy(other._c_obj) : nullptr; - } - - assert((!_c_obj && !other._c_obj) || to_string() == other.to_string()); -} - -inline -Node::~Node() -{ - if (_world) { - sord_node_free(_world->c_obj(), _c_obj); - } -} - -inline std::string -Node::to_string() const -{ - return _c_obj ? reinterpret_cast<const char*>(sord_node_get_string(_c_obj)) - : ""; -} - -inline const char* -Node::to_c_string() const -{ - return reinterpret_cast<const char*>(sord_node_get_string(_c_obj)); -} - -inline const uint8_t* -Node::to_u_string() const -{ - return sord_node_get_string(_c_obj); -} - -inline bool -Node::is_literal_type(const char* type_uri) const -{ - if (_c_obj && sord_node_get_type(_c_obj) == SORD_LITERAL) { - const SordNode* datatype = sord_node_get_datatype(_c_obj); - if (datatype && !strcmp(reinterpret_cast<const char*>( - sord_node_get_string(datatype)), - type_uri)) { - return true; - } - } - return false; -} - -inline int -Node::to_int() const -{ - assert(is_int()); - char* endptr = nullptr; - return strtol(reinterpret_cast<const char*>(sord_node_get_string(_c_obj)), - &endptr, - 10); -} - -inline float -Node::to_float() const -{ - assert(is_float()); - return serd_strtod(reinterpret_cast<const char*>( - sord_node_get_string(_c_obj)), - nullptr); -} - -inline bool -Node::to_bool() const -{ - assert(is_bool()); - return !strcmp(reinterpret_cast<const char*>(sord_node_get_string(_c_obj)), - "true"); -} - -struct Iter : public Wrapper<SordIter> { - inline Iter(World& world, SordIter* c_obj) - : Wrapper<SordIter>(c_obj), _world(world) {} - - Iter(const Iter&) = delete; - Iter& operator=(const Iter&) = delete; - - inline Iter(Iter&& iter) noexcept - : Wrapper<SordIter>(iter) - , _world(iter._world) - {} - - inline ~Iter() { sord_iter_free(_c_obj); } - - inline bool end() const { return sord_iter_end(_c_obj); } - inline bool next() const { return sord_iter_next(_c_obj); } - inline Iter& operator++() { - assert(!end()); - next(); - return *this; - } - inline Node get_subject() const { - SordQuad quad; - sord_iter_get(_c_obj, quad); - return Node(_world, quad[SORD_SUBJECT]); - } - inline Node get_predicate() const { - SordQuad quad; - sord_iter_get(_c_obj, quad); - return Node(_world, quad[SORD_PREDICATE]); - } - inline Node get_object() const { - SordQuad quad; - sord_iter_get(_c_obj, quad); - return Node(_world, quad[SORD_OBJECT]); - } - World& _world; -}; - -/** An RDF Model (collection of triples). - */ -class Model : public Noncopyable, public Wrapper<SordModel> { -public: - inline Model(World& world, - const std::string& base_uri, - unsigned indices = (SORD_SPO | SORD_OPS), - bool graphs = true); - - inline ~Model(); - - inline const Node& base_uri() const { return _base; } - - size_t num_quads() const { return sord_num_quads(_c_obj); } - - inline void load_file(SerdEnv* env, - SerdSyntax syntax, - const std::string& uri, - const std::string& base_uri=""); - - inline void load_string(SerdEnv* env, - SerdSyntax syntax, - const char* str, - size_t len, - const std::string& base_uri); - - inline SerdStatus write_to_file( - const std::string& uri, - SerdSyntax syntax = SERD_TURTLE, - SerdStyle style = static_cast<SerdStyle>( - SERD_STYLE_ABBREVIATED - |SERD_STYLE_CURIED - |SERD_STYLE_RESOLVED)); - - inline std::string write_to_string( - const std::string& base_uri, - SerdSyntax syntax = SERD_TURTLE, - SerdStyle style = static_cast<SerdStyle>( - SERD_STYLE_ABBREVIATED - |SERD_STYLE_CURIED - |SERD_STYLE_RESOLVED)); - - inline void add_statement(const Node& subject, - const Node& predicate, - const Node& object); - - inline Iter find(const Node& subject, - const Node& predicate, - const Node& object); - - inline Node get(const Node& subject, - const Node& predicate, - const Node& object); - - inline World& world() const { return _world; } - -private: - World& _world; - Node _base; -}; - -/** Create an empty in-memory RDF model. - */ -inline -Model::Model(World& world, - const std::string& base_uri, - unsigned indices, - bool graphs) - : _world(world) - , _base(world, Node::URI, base_uri) -{ - _c_obj = sord_new(_world.world(), indices, graphs); -} - -inline void -Model::load_string(SerdEnv* env, - SerdSyntax syntax, - const char* str, - size_t /*len*/, - const std::string& /*base_uri*/) -{ - SerdReader* reader = sord_new_reader(_c_obj, env, syntax, nullptr); - serd_reader_read_string(reader, reinterpret_cast<const uint8_t*>(str)); - serd_reader_free(reader); -} - -inline Model::~Model() -{ - sord_free(_c_obj); -} - -inline void -Model::load_file(SerdEnv* env, - SerdSyntax syntax, - const std::string& data_uri, - const std::string& /*base_uri*/) -{ - uint8_t* path = - serd_file_uri_parse(reinterpret_cast<const uint8_t*>(data_uri.c_str()), - nullptr); - if (!path) { - fprintf(stderr, "Failed to parse file URI <%s>\n", data_uri.c_str()); - return; - } - - // FIXME: blank prefix parameter? - SerdReader* reader = sord_new_reader(_c_obj, env, syntax, nullptr); - serd_reader_read_file(reader, path); - serd_reader_free(reader); - serd_free(path); -} - -inline SerdStatus -Model::write_to_file(const std::string& uri, SerdSyntax syntax, SerdStyle style) -{ - uint8_t* path = - serd_file_uri_parse(reinterpret_cast<const uint8_t*>(uri.c_str()), - nullptr); - if (!path) { - fprintf(stderr, "Failed to parse file URI <%s>\n", uri.c_str()); - return SERD_ERR_BAD_ARG; - } - - FILE* const fd = fopen(reinterpret_cast<const char*>(path), "w"); - if (!fd) { - fprintf(stderr, "Failed to open file %s\n", path); - serd_free(path); - return SERD_ERR_UNKNOWN; - } - serd_free(path); - - SerdURI base_uri = SERD_URI_NULL; - if (serd_uri_parse(reinterpret_cast<const uint8_t*>(uri.c_str()), - &base_uri)) { - fprintf(stderr, "Invalid base URI <%s>\n", uri.c_str()); - fclose(fd); - return SERD_ERR_BAD_ARG; - } - - SerdWriter* writer = serd_writer_new(syntax, - style, - _world.prefixes().c_obj(), - &base_uri, - serd_file_sink, - fd); - - serd_env_foreach(_world.prefixes().c_obj(), - reinterpret_cast<SerdPrefixSink>(serd_writer_set_prefix), - writer); - - sord_write(_c_obj, writer, nullptr); - serd_writer_free(writer); - fclose(fd); - - return SERD_SUCCESS; -} - -extern "C" { - -static size_t -string_sink(const void* buf, size_t len, void* stream) -{ - try { - auto* str = static_cast<std::string*>(stream); - str->append(static_cast<const char*>(buf), len); - return len; - } catch (...) { - return 0; - } -} - -} - -inline std::string -Model::write_to_string(const std::string& base_uri_str, - SerdSyntax syntax, - SerdStyle style) -{ - SerdURI base_uri = SERD_URI_NULL; - if (serd_uri_parse(reinterpret_cast<const uint8_t*>(base_uri_str.c_str()), - &base_uri)) { - fprintf(stderr, "Invalid base URI <%s>\n", base_uri_str.c_str()); - return ""; - } - - std::string ret; - - SerdWriter* writer = serd_writer_new(syntax, - style, - _world.prefixes().c_obj(), - &base_uri, - string_sink, - &ret); - - const SerdNode base_uri_node = serd_node_from_string( - SERD_URI, reinterpret_cast<const uint8_t*>(base_uri_str.c_str())); - serd_writer_set_base_uri(writer, &base_uri_node); - - serd_env_foreach(_world.prefixes().c_obj(), - reinterpret_cast<SerdPrefixSink>(serd_writer_set_prefix), - writer); - - sord_write(_c_obj, writer, nullptr); - - serd_writer_free(writer); - return ret; -} - -inline void -Model::add_statement(const Node& subject, - const Node& predicate, - const Node& object) -{ - SordQuad quad = { subject.c_obj(), - predicate.c_obj(), - object.c_obj(), - nullptr }; - - sord_add(_c_obj, quad); -} - -inline Iter -Model::find(const Node& subject, - const Node& predicate, - const Node& object) -{ - SordQuad quad = { subject.c_obj(), - predicate.c_obj(), - object.c_obj(), - nullptr }; - - return Iter(_world, sord_find(_c_obj, quad)); -} - -inline Node -Model::get(const Node& subject, - const Node& predicate, - const Node& object) -{ - SordNode* c_node = sord_get( - _c_obj, subject.c_obj(), predicate.c_obj(), object.c_obj(), nullptr); - return Node(_world, c_node, false); -} - -} // namespace Sord - -#endif // SORD_SORDMM_HPP |