Chris@2
|
1 /*
|
Chris@2
|
2 Copyright 2011-2013 David Robillard <http://drobilla.net>
|
Chris@2
|
3
|
Chris@2
|
4 Permission to use, copy, modify, and/or distribute this software for any
|
Chris@2
|
5 purpose with or without fee is hereby granted, provided that the above
|
Chris@2
|
6 copyright notice and this permission notice appear in all copies.
|
Chris@2
|
7
|
Chris@2
|
8 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
Chris@2
|
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
Chris@2
|
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
Chris@2
|
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
Chris@2
|
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
Chris@2
|
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
Chris@2
|
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
Chris@2
|
15 */
|
Chris@2
|
16
|
Chris@2
|
17 /**
|
Chris@2
|
18 @file sordmm.hpp
|
Chris@2
|
19 Public Sord C++ API.
|
Chris@2
|
20 */
|
Chris@2
|
21
|
Chris@2
|
22 #ifndef SORD_SORDMM_HPP
|
Chris@2
|
23 #define SORD_SORDMM_HPP
|
Chris@2
|
24
|
Chris@2
|
25 #include <cassert>
|
Chris@2
|
26 #include <cstring>
|
Chris@2
|
27 #include <cstdlib>
|
Chris@2
|
28 #include <iostream>
|
Chris@2
|
29 #include <set>
|
Chris@2
|
30 #include <string>
|
Chris@2
|
31 #include <sstream>
|
Chris@2
|
32
|
Chris@2
|
33 #include "serd/serd.h"
|
Chris@2
|
34 #include "sord/sord.h"
|
Chris@2
|
35
|
Chris@2
|
36 #define SORD_NS_XSD "http://www.w3.org/2001/XMLSchema#"
|
Chris@2
|
37
|
Chris@2
|
38 namespace Sord {
|
Chris@2
|
39
|
Chris@2
|
40 /** Utility base class to prevent copying. */
|
Chris@2
|
41 class Noncopyable {
|
Chris@2
|
42 protected:
|
Chris@2
|
43 Noncopyable() {}
|
Chris@2
|
44 ~Noncopyable() {}
|
Chris@2
|
45 private:
|
Chris@2
|
46 Noncopyable(const Noncopyable&);
|
Chris@2
|
47 const Noncopyable& operator=(const Noncopyable&);
|
Chris@2
|
48 };
|
Chris@2
|
49
|
Chris@2
|
50 /** C++ wrapper for a Sord object. */
|
Chris@2
|
51 template <typename T>
|
Chris@2
|
52 class Wrapper {
|
Chris@2
|
53 public:
|
Chris@2
|
54 inline Wrapper(T c_obj = NULL) : _c_obj(c_obj) {}
|
Chris@2
|
55
|
Chris@2
|
56 inline T c_obj() { return _c_obj; }
|
Chris@2
|
57 inline const T c_obj() const { return _c_obj; }
|
Chris@2
|
58
|
Chris@2
|
59 protected:
|
Chris@2
|
60 T _c_obj;
|
Chris@2
|
61 };
|
Chris@2
|
62
|
Chris@2
|
63 /** Collection of RDF namespaces with prefixes. */
|
Chris@2
|
64 class Namespaces : public Wrapper<SerdEnv*> {
|
Chris@2
|
65 public:
|
Chris@2
|
66 Namespaces() : Wrapper<SerdEnv*>(serd_env_new(NULL)) {}
|
Chris@2
|
67 ~Namespaces() { serd_env_free(_c_obj); }
|
Chris@2
|
68
|
Chris@2
|
69 static inline SerdNode string_to_node(SerdType type, const std::string& s) {
|
Chris@2
|
70 SerdNode ret = {
|
Chris@2
|
71 (const uint8_t*)s.c_str(), s.length(), s.length(), 0, type };
|
Chris@2
|
72 return ret;
|
Chris@2
|
73 }
|
Chris@2
|
74
|
Chris@2
|
75 inline void add(const std::string& name,
|
Chris@2
|
76 const std::string& uri) {
|
Chris@2
|
77 const SerdNode name_node = string_to_node(SERD_LITERAL, name);
|
Chris@2
|
78 const SerdNode uri_node = string_to_node(SERD_URI, uri);
|
Chris@2
|
79 serd_env_set_prefix(_c_obj, &name_node, &uri_node);
|
Chris@2
|
80 }
|
Chris@2
|
81
|
Chris@2
|
82 inline std::string qualify(std::string uri) const {
|
Chris@2
|
83 const SerdNode uri_node = string_to_node(SERD_URI, uri);
|
Chris@2
|
84 SerdNode prefix;
|
Chris@2
|
85 SerdChunk suffix;
|
Chris@2
|
86 if (serd_env_qualify(_c_obj, &uri_node, &prefix, &suffix)) {
|
Chris@2
|
87 std::string ret((const char*)prefix.buf, prefix.n_bytes);
|
Chris@2
|
88 ret.append(":").append((const char*)suffix.buf, suffix.len);
|
Chris@2
|
89 return ret;
|
Chris@2
|
90 }
|
Chris@2
|
91 return uri;
|
Chris@2
|
92 }
|
Chris@2
|
93
|
Chris@2
|
94 inline std::string expand(const std::string& curie) const {
|
Chris@2
|
95 assert(curie.find(":") != std::string::npos);
|
Chris@2
|
96 SerdNode curie_node = string_to_node(SERD_CURIE, curie);
|
Chris@2
|
97 SerdChunk uri_prefix;
|
Chris@2
|
98 SerdChunk uri_suffix;
|
Chris@2
|
99 if (!serd_env_expand(_c_obj, &curie_node, &uri_prefix, &uri_suffix)) {
|
Chris@2
|
100 std::string ret((const char*)uri_prefix.buf, uri_prefix.len);
|
Chris@2
|
101 ret.append((const char*)uri_suffix.buf, uri_suffix.len);
|
Chris@2
|
102 return ret;
|
Chris@2
|
103 }
|
Chris@2
|
104 std::cerr << "CURIE `" << curie << "' has unknown prefix." << std::endl;
|
Chris@2
|
105 return curie;
|
Chris@2
|
106 }
|
Chris@2
|
107 };
|
Chris@2
|
108
|
Chris@2
|
109 /** Sord library state. */
|
Chris@2
|
110 class World : public Noncopyable, public Wrapper<SordWorld*> {
|
Chris@2
|
111 public:
|
Chris@2
|
112 inline World()
|
Chris@2
|
113 : _next_blank_id(0)
|
Chris@2
|
114 {
|
Chris@2
|
115 _c_obj = sord_world_new();
|
Chris@2
|
116 }
|
Chris@2
|
117
|
Chris@2
|
118 inline ~World() {
|
Chris@2
|
119 sord_world_free(_c_obj);
|
Chris@2
|
120 }
|
Chris@2
|
121
|
Chris@2
|
122 inline uint64_t blank_id() { return _next_blank_id++; }
|
Chris@2
|
123
|
Chris@2
|
124 inline void add_prefix(const std::string& prefix, const std::string& uri) {
|
Chris@2
|
125 _prefixes.add(prefix, uri);
|
Chris@2
|
126 }
|
Chris@2
|
127
|
Chris@2
|
128 inline const Namespaces& prefixes() const { return _prefixes; }
|
Chris@2
|
129 inline SordWorld* world() { return _c_obj; }
|
Chris@2
|
130
|
Chris@2
|
131 private:
|
Chris@2
|
132 Namespaces _prefixes;
|
Chris@2
|
133 std::set<std::string> _blank_ids;
|
Chris@2
|
134 uint64_t _next_blank_id;
|
Chris@2
|
135 };
|
Chris@2
|
136
|
Chris@2
|
137 /** An RDF Node (resource, literal, etc)
|
Chris@2
|
138 */
|
Chris@2
|
139 class Node : public Wrapper<SordNode*> {
|
Chris@2
|
140 public:
|
Chris@2
|
141 enum Type {
|
Chris@2
|
142 UNKNOWN = 0,
|
Chris@2
|
143 URI = SORD_URI,
|
Chris@2
|
144 BLANK = SORD_BLANK,
|
Chris@2
|
145 LITERAL = SORD_LITERAL
|
Chris@2
|
146 };
|
Chris@2
|
147
|
Chris@2
|
148 inline Node() : Wrapper<SordNode*>(NULL), _world(NULL) {}
|
Chris@2
|
149
|
Chris@2
|
150 inline Node(World& world, Type t, const std::string& s);
|
Chris@2
|
151 inline Node(World& world);
|
Chris@2
|
152 inline Node(World& world, const SordNode* node);
|
Chris@2
|
153 inline Node(World& world, SordNode* node, bool copy=false);
|
Chris@2
|
154 inline Node(const Node& other);
|
Chris@2
|
155 inline ~Node();
|
Chris@2
|
156
|
Chris@2
|
157 inline Type type() const {
|
Chris@2
|
158 return _c_obj ? (Type)sord_node_get_type(_c_obj) : UNKNOWN;
|
Chris@2
|
159 }
|
Chris@2
|
160
|
Chris@2
|
161 inline const SordNode* get_node() const { return _c_obj; }
|
Chris@2
|
162 inline SordNode* get_node() { return _c_obj; }
|
Chris@2
|
163
|
Chris@2
|
164 const SerdNode* to_serd_node() {
|
Chris@2
|
165 return sord_node_to_serd_node(_c_obj);
|
Chris@2
|
166 }
|
Chris@2
|
167
|
Chris@2
|
168 inline bool is_valid() const { return type() != UNKNOWN; }
|
Chris@2
|
169
|
Chris@2
|
170 inline bool operator<(const Node& other) const {
|
Chris@2
|
171 if (type() != other.type()) {
|
Chris@2
|
172 return type() < other.type();
|
Chris@2
|
173 } else {
|
Chris@2
|
174 return to_string() < other.to_string();
|
Chris@2
|
175 }
|
Chris@2
|
176 }
|
Chris@2
|
177
|
Chris@2
|
178 Node& operator=(const Node& other) {
|
Chris@2
|
179 if (&other != this) {
|
Chris@2
|
180 if (_c_obj) {
|
Chris@2
|
181 sord_node_free(_world->c_obj(), _c_obj);
|
Chris@2
|
182 }
|
Chris@2
|
183 _world = other._world;
|
Chris@2
|
184 _c_obj = other._c_obj ? sord_node_copy(other._c_obj) : NULL;
|
Chris@2
|
185 }
|
Chris@2
|
186 return *this;
|
Chris@2
|
187 }
|
Chris@2
|
188
|
Chris@2
|
189 inline bool operator==(const Node& other) const {
|
Chris@2
|
190 return sord_node_equals(_c_obj, other._c_obj);
|
Chris@2
|
191 }
|
Chris@2
|
192
|
Chris@2
|
193 inline const uint8_t* to_u_string() const;
|
Chris@2
|
194 inline const char* to_c_string() const;
|
Chris@2
|
195 inline std::string to_string() const;
|
Chris@2
|
196
|
Chris@2
|
197 inline bool is_literal_type(const char* type_uri) const;
|
Chris@2
|
198
|
Chris@2
|
199 inline bool is_uri() const { return _c_obj && type() == URI; }
|
Chris@2
|
200 inline bool is_blank() const { return _c_obj && type() == BLANK; }
|
Chris@2
|
201 inline bool is_int() const { return is_literal_type(SORD_NS_XSD "integer"); }
|
Chris@2
|
202 inline bool is_float() const { return is_literal_type(SORD_NS_XSD "decimal"); }
|
Chris@2
|
203 inline bool is_bool() const { return is_literal_type(SORD_NS_XSD "boolean"); }
|
Chris@2
|
204
|
Chris@2
|
205 inline int to_int() const;
|
Chris@2
|
206 inline float to_float() const;
|
Chris@2
|
207 inline bool to_bool() const;
|
Chris@2
|
208
|
Chris@2
|
209 inline static Node blank_id(World& world, const std::string base="b") {
|
Chris@2
|
210 const uint64_t num = world.blank_id();
|
Chris@2
|
211 std::ostringstream ss;
|
Chris@2
|
212 ss << base << num;
|
Chris@2
|
213 return Node(world, Node::BLANK, ss.str());
|
Chris@2
|
214 }
|
Chris@2
|
215
|
Chris@2
|
216 private:
|
Chris@2
|
217 World* _world;
|
Chris@2
|
218 };
|
Chris@2
|
219
|
Chris@2
|
220 inline std::ostream&
|
Chris@2
|
221 operator<<(std::ostream& os, const Node& node)
|
Chris@2
|
222 {
|
Chris@2
|
223 return os << node.to_string();
|
Chris@2
|
224 }
|
Chris@2
|
225
|
Chris@2
|
226 class URI : public Node {
|
Chris@2
|
227 public:
|
Chris@2
|
228 inline URI(World& world, const std::string& s)
|
Chris@2
|
229 : Node(world, Node::URI, s) {}
|
Chris@2
|
230 inline URI(World& world, const std::string& s, const std::string& base)
|
Chris@2
|
231 : Node(world, sord_new_relative_uri(world.world(),
|
Chris@2
|
232 (const uint8_t*)s.c_str(),
|
Chris@2
|
233 (const uint8_t*)base.c_str()))
|
Chris@2
|
234 {}
|
Chris@2
|
235 };
|
Chris@2
|
236
|
Chris@2
|
237 class Curie : public Node {
|
Chris@2
|
238 public:
|
Chris@2
|
239 inline Curie(World& world, const std::string& s)
|
Chris@2
|
240 : Node(world, Node::URI, world.prefixes().expand(s)) {}
|
Chris@2
|
241 };
|
Chris@2
|
242
|
Chris@2
|
243 class Literal : public Node {
|
Chris@2
|
244 public:
|
Chris@2
|
245 inline Literal(World& world, const std::string& s)
|
Chris@2
|
246 : Node(world, Node::LITERAL, s) {}
|
Chris@2
|
247
|
Chris@2
|
248 static inline Node decimal(World& world, double d, unsigned frac_digits) {
|
Chris@2
|
249 const SerdNode val = serd_node_new_decimal(d, 7);
|
Chris@2
|
250 const SerdNode type = serd_node_from_string(
|
Chris@2
|
251 SERD_URI, (const uint8_t*)SORD_NS_XSD "decimal");
|
Chris@2
|
252
|
Chris@2
|
253 return Node(
|
Chris@2
|
254 world,
|
Chris@2
|
255 sord_node_from_serd_node(
|
Chris@2
|
256 world.c_obj(), world.prefixes().c_obj(), &val, &type, NULL),
|
Chris@2
|
257 false);
|
Chris@2
|
258 }
|
Chris@2
|
259
|
Chris@2
|
260 static inline Node integer(World& world, int64_t i) {
|
Chris@2
|
261 const SerdNode val = serd_node_new_integer(i);
|
Chris@2
|
262 const SerdNode type = serd_node_from_string(
|
Chris@2
|
263 SERD_URI, (const uint8_t*)SORD_NS_XSD "integer");
|
Chris@2
|
264
|
Chris@2
|
265 return Node(
|
Chris@2
|
266 world,
|
Chris@2
|
267 sord_node_from_serd_node(
|
Chris@2
|
268 world.c_obj(), world.prefixes().c_obj(), &val, &type, NULL),
|
Chris@2
|
269 false);
|
Chris@2
|
270 }
|
Chris@2
|
271 };
|
Chris@2
|
272
|
Chris@2
|
273 inline
|
Chris@2
|
274 Node::Node(World& world, Type type, const std::string& s)
|
Chris@2
|
275 : _world(&world)
|
Chris@2
|
276 {
|
Chris@2
|
277 switch (type) {
|
Chris@2
|
278 case URI:
|
Chris@2
|
279 _c_obj = sord_new_uri(
|
Chris@2
|
280 world.world(), (const unsigned char*)s.c_str());
|
Chris@2
|
281 break;
|
Chris@2
|
282 case LITERAL:
|
Chris@2
|
283 _c_obj = sord_new_literal(
|
Chris@2
|
284 world.world(), NULL, (const unsigned char*)s.c_str(), NULL);
|
Chris@2
|
285 break;
|
Chris@2
|
286 case BLANK:
|
Chris@2
|
287 _c_obj = sord_new_blank(
|
Chris@2
|
288 world.world(), (const unsigned char*)s.c_str());
|
Chris@2
|
289 break;
|
Chris@2
|
290 default:
|
Chris@2
|
291 _c_obj = NULL;
|
Chris@2
|
292 }
|
Chris@2
|
293
|
Chris@2
|
294 assert(this->type() == type);
|
Chris@2
|
295 }
|
Chris@2
|
296
|
Chris@2
|
297 inline
|
Chris@2
|
298 Node::Node(World& world)
|
Chris@2
|
299 : _world(&world)
|
Chris@2
|
300 {
|
Chris@2
|
301 Node me = blank_id(world);
|
Chris@2
|
302 *this = me;
|
Chris@2
|
303 }
|
Chris@2
|
304
|
Chris@2
|
305 inline
|
Chris@2
|
306 Node::Node(World& world, const SordNode* node)
|
Chris@2
|
307 : _world(&world)
|
Chris@2
|
308 {
|
Chris@2
|
309 _c_obj = sord_node_copy(node);
|
Chris@2
|
310 }
|
Chris@2
|
311
|
Chris@2
|
312 inline
|
Chris@2
|
313 Node::Node(World& world, SordNode* node, bool copy)
|
Chris@2
|
314 : _world(&world)
|
Chris@2
|
315 {
|
Chris@2
|
316 _c_obj = copy ? sord_node_copy(node) : node;
|
Chris@2
|
317 }
|
Chris@2
|
318
|
Chris@2
|
319 inline
|
Chris@2
|
320 Node::Node(const Node& other)
|
Chris@2
|
321 : Wrapper<SordNode*>()
|
Chris@2
|
322 , _world(other._world)
|
Chris@2
|
323 {
|
Chris@2
|
324 if (_world) {
|
Chris@2
|
325 _c_obj = other._c_obj ? sord_node_copy(other._c_obj) : NULL;
|
Chris@2
|
326 }
|
Chris@2
|
327
|
Chris@2
|
328 assert((!_c_obj && !other._c_obj) || to_string() == other.to_string());
|
Chris@2
|
329 }
|
Chris@2
|
330
|
Chris@2
|
331 inline
|
Chris@2
|
332 Node::~Node()
|
Chris@2
|
333 {
|
Chris@2
|
334 if (_world) {
|
Chris@2
|
335 sord_node_free(_world->c_obj(), _c_obj);
|
Chris@2
|
336 }
|
Chris@2
|
337 }
|
Chris@2
|
338
|
Chris@2
|
339 inline std::string
|
Chris@2
|
340 Node::to_string() const
|
Chris@2
|
341 {
|
Chris@2
|
342 return _c_obj ? (const char*)sord_node_get_string(_c_obj) : "";
|
Chris@2
|
343 }
|
Chris@2
|
344
|
Chris@2
|
345 inline const char*
|
Chris@2
|
346 Node::to_c_string() const
|
Chris@2
|
347 {
|
Chris@2
|
348 return (const char*)sord_node_get_string(_c_obj);
|
Chris@2
|
349 }
|
Chris@2
|
350
|
Chris@2
|
351 inline const uint8_t*
|
Chris@2
|
352 Node::to_u_string() const
|
Chris@2
|
353 {
|
Chris@2
|
354 return sord_node_get_string(_c_obj);
|
Chris@2
|
355 }
|
Chris@2
|
356
|
Chris@2
|
357 inline bool
|
Chris@2
|
358 Node::is_literal_type(const char* type_uri) const
|
Chris@2
|
359 {
|
Chris@2
|
360 if (_c_obj && sord_node_get_type(_c_obj) == SORD_LITERAL) {
|
Chris@2
|
361 const SordNode* datatype = sord_node_get_datatype(_c_obj);
|
Chris@2
|
362 if (datatype && !strcmp((const char*)sord_node_get_string(datatype),
|
Chris@2
|
363 type_uri))
|
Chris@2
|
364 return true;
|
Chris@2
|
365 }
|
Chris@2
|
366 return false;
|
Chris@2
|
367 }
|
Chris@2
|
368
|
Chris@2
|
369 inline int
|
Chris@2
|
370 Node::to_int() const
|
Chris@2
|
371 {
|
Chris@2
|
372 assert(is_int());
|
Chris@2
|
373 char* endptr;
|
Chris@2
|
374 return strtol((const char*)sord_node_get_string(_c_obj), &endptr, 10);
|
Chris@2
|
375 }
|
Chris@2
|
376
|
Chris@2
|
377 inline float
|
Chris@2
|
378 Node::to_float() const
|
Chris@2
|
379 {
|
Chris@2
|
380 assert(is_float());
|
Chris@2
|
381 char* endptr;
|
Chris@2
|
382 return serd_strtod((const char*)sord_node_get_string(_c_obj), &endptr);
|
Chris@2
|
383 }
|
Chris@2
|
384
|
Chris@2
|
385 inline bool
|
Chris@2
|
386 Node::to_bool() const
|
Chris@2
|
387 {
|
Chris@2
|
388 assert(is_bool());
|
Chris@2
|
389 return !strcmp((const char*)sord_node_get_string(_c_obj), "true");
|
Chris@2
|
390 }
|
Chris@2
|
391
|
Chris@2
|
392 struct Iter : public Wrapper<SordIter*> {
|
Chris@2
|
393 inline Iter(World& world, SordIter* c_obj)
|
Chris@2
|
394 : Wrapper<SordIter*>(c_obj), _world(world) {}
|
Chris@2
|
395 inline ~Iter() { sord_iter_free(_c_obj); }
|
Chris@2
|
396 inline bool end() const { return sord_iter_end(_c_obj); }
|
Chris@2
|
397 inline bool next() const { return sord_iter_next(_c_obj); }
|
Chris@2
|
398 inline Iter& operator++() {
|
Chris@2
|
399 assert(!end());
|
Chris@2
|
400 next();
|
Chris@2
|
401 return *this;
|
Chris@2
|
402 }
|
Chris@2
|
403 inline const Node get_subject() const {
|
Chris@2
|
404 SordQuad quad;
|
Chris@2
|
405 sord_iter_get(_c_obj, quad);
|
Chris@2
|
406 return Node(_world, quad[SORD_SUBJECT]);
|
Chris@2
|
407 }
|
Chris@2
|
408 inline const Node get_predicate() const {
|
Chris@2
|
409 SordQuad quad;
|
Chris@2
|
410 sord_iter_get(_c_obj, quad);
|
Chris@2
|
411 return Node(_world, quad[SORD_PREDICATE]);
|
Chris@2
|
412 }
|
Chris@2
|
413 inline const Node get_object() const {
|
Chris@2
|
414 SordQuad quad;
|
Chris@2
|
415 sord_iter_get(_c_obj, quad);
|
Chris@2
|
416 return Node(_world, quad[SORD_OBJECT]);
|
Chris@2
|
417 }
|
Chris@2
|
418 World& _world;
|
Chris@2
|
419 };
|
Chris@2
|
420
|
Chris@2
|
421 /** An RDF Model (collection of triples).
|
Chris@2
|
422 */
|
Chris@2
|
423 class Model : public Noncopyable, public Wrapper<SordModel*> {
|
Chris@2
|
424 public:
|
Chris@2
|
425 inline Model(World& world,
|
Chris@2
|
426 const std::string& base_uri,
|
Chris@2
|
427 unsigned indices = (SORD_SPO | SORD_OPS),
|
Chris@2
|
428 bool graphs = true);
|
Chris@2
|
429
|
Chris@2
|
430 inline ~Model();
|
Chris@2
|
431
|
Chris@2
|
432 inline const Node& base_uri() const { return _base; }
|
Chris@2
|
433
|
Chris@2
|
434 size_t num_quads() const { return sord_num_quads(_c_obj); }
|
Chris@2
|
435
|
Chris@2
|
436 inline void load_file(SerdEnv* env,
|
Chris@2
|
437 SerdSyntax syntax,
|
Chris@2
|
438 const std::string& uri,
|
Chris@2
|
439 const std::string& base_uri="");
|
Chris@2
|
440
|
Chris@2
|
441 inline void load_string(SerdEnv* env,
|
Chris@2
|
442 SerdSyntax syntax,
|
Chris@2
|
443 const char* str,
|
Chris@2
|
444 size_t len,
|
Chris@2
|
445 const std::string& base_uri);
|
Chris@2
|
446
|
Chris@2
|
447 inline SerdStatus write_to_file(
|
Chris@2
|
448 const std::string& uri,
|
Chris@2
|
449 SerdSyntax syntax = SERD_TURTLE,
|
Chris@2
|
450 SerdStyle style = (SerdStyle)(SERD_STYLE_ABBREVIATED
|
Chris@2
|
451 |SERD_STYLE_CURIED
|
Chris@2
|
452 |SERD_STYLE_RESOLVED));
|
Chris@2
|
453
|
Chris@2
|
454 inline std::string write_to_string(
|
Chris@2
|
455 const std::string& base_uri,
|
Chris@2
|
456 SerdSyntax syntax = SERD_TURTLE,
|
Chris@2
|
457 SerdStyle style = (SerdStyle)(SERD_STYLE_ABBREVIATED
|
Chris@2
|
458 |SERD_STYLE_CURIED
|
Chris@2
|
459 |SERD_STYLE_RESOLVED));
|
Chris@2
|
460
|
Chris@2
|
461 inline void add_statement(const Node& subject,
|
Chris@2
|
462 const Node& predicate,
|
Chris@2
|
463 const Node& object);
|
Chris@2
|
464
|
Chris@2
|
465 inline Iter find(const Node& subject,
|
Chris@2
|
466 const Node& predicate,
|
Chris@2
|
467 const Node& object);
|
Chris@2
|
468
|
Chris@2
|
469 inline Node get(const Node& subject,
|
Chris@2
|
470 const Node& predicate,
|
Chris@2
|
471 const Node& object);
|
Chris@2
|
472
|
Chris@2
|
473 inline World& world() const { return _world; }
|
Chris@2
|
474
|
Chris@2
|
475 private:
|
Chris@2
|
476 World& _world;
|
Chris@2
|
477 Node _base;
|
Chris@2
|
478 SerdWriter* _writer;
|
Chris@2
|
479 size_t _next_blank_id;
|
Chris@2
|
480 };
|
Chris@2
|
481
|
Chris@2
|
482 /** Create an empty in-memory RDF model.
|
Chris@2
|
483 */
|
Chris@2
|
484 inline
|
Chris@2
|
485 Model::Model(World& world,
|
Chris@2
|
486 const std::string& base_uri,
|
Chris@2
|
487 unsigned indices,
|
Chris@2
|
488 bool graphs)
|
Chris@2
|
489 : _world(world)
|
Chris@2
|
490 , _base(world, Node::URI, base_uri)
|
Chris@2
|
491 , _writer(NULL)
|
Chris@2
|
492 {
|
Chris@2
|
493 _c_obj = sord_new(_world.world(), indices, graphs);
|
Chris@2
|
494 }
|
Chris@2
|
495
|
Chris@2
|
496 inline void
|
Chris@2
|
497 Model::load_string(SerdEnv* env,
|
Chris@2
|
498 SerdSyntax syntax,
|
Chris@2
|
499 const char* str,
|
Chris@2
|
500 size_t len,
|
Chris@2
|
501 const std::string& base_uri)
|
Chris@2
|
502 {
|
Chris@2
|
503 SerdReader* reader = sord_new_reader(_c_obj, env, syntax, NULL);
|
Chris@2
|
504 serd_reader_read_string(reader, (const uint8_t*)str);
|
Chris@2
|
505 serd_reader_free(reader);
|
Chris@2
|
506 }
|
Chris@2
|
507
|
Chris@2
|
508 inline Model::~Model()
|
Chris@2
|
509 {
|
Chris@2
|
510 sord_free(_c_obj);
|
Chris@2
|
511 }
|
Chris@2
|
512
|
Chris@2
|
513 inline void
|
Chris@2
|
514 Model::load_file(SerdEnv* env,
|
Chris@2
|
515 SerdSyntax syntax,
|
Chris@2
|
516 const std::string& data_uri,
|
Chris@2
|
517 const std::string& base_uri)
|
Chris@2
|
518 {
|
Chris@2
|
519 uint8_t* path = serd_file_uri_parse((const uint8_t*)data_uri.c_str(), NULL);
|
Chris@2
|
520 if (!path) {
|
Chris@2
|
521 fprintf(stderr, "Failed to parse file URI <%s>\n", data_uri.c_str());
|
Chris@2
|
522 return;
|
Chris@2
|
523 }
|
Chris@2
|
524
|
Chris@2
|
525 // FIXME: blank prefix parameter?
|
Chris@2
|
526 SerdReader* reader = sord_new_reader(_c_obj, env, syntax, NULL);
|
Chris@2
|
527 serd_reader_read_file(reader, path);
|
Chris@2
|
528 serd_reader_free(reader);
|
Chris@2
|
529 free(path);
|
Chris@2
|
530 }
|
Chris@2
|
531
|
Chris@2
|
532 inline SerdStatus
|
Chris@2
|
533 Model::write_to_file(const std::string& uri, SerdSyntax syntax, SerdStyle style)
|
Chris@2
|
534 {
|
Chris@2
|
535 uint8_t* path = serd_file_uri_parse((const uint8_t*)uri.c_str(), NULL);
|
Chris@2
|
536 if (!path) {
|
Chris@2
|
537 fprintf(stderr, "Failed to parse file URI <%s>\n", uri.c_str());
|
Chris@2
|
538 return SERD_ERR_BAD_ARG;
|
Chris@2
|
539 }
|
Chris@2
|
540
|
Chris@2
|
541 FILE* const fd = fopen((const char*)path, "w");
|
Chris@2
|
542 if (!fd) {
|
Chris@2
|
543 fprintf(stderr, "Failed to open file %s\n", path);
|
Chris@2
|
544 free(path);
|
Chris@2
|
545 return SERD_ERR_UNKNOWN;
|
Chris@2
|
546 }
|
Chris@2
|
547 free(path);
|
Chris@2
|
548
|
Chris@2
|
549 SerdURI base_uri = SERD_URI_NULL;
|
Chris@2
|
550 if (serd_uri_parse((const uint8_t*)uri.c_str(), &base_uri)) {
|
Chris@2
|
551 fprintf(stderr, "Invalid base URI <%s>\n", uri.c_str());
|
Chris@2
|
552 fclose(fd);
|
Chris@2
|
553 return SERD_ERR_BAD_ARG;
|
Chris@2
|
554 }
|
Chris@2
|
555
|
Chris@2
|
556 SerdWriter* writer = serd_writer_new(syntax,
|
Chris@2
|
557 style,
|
Chris@2
|
558 _world.prefixes().c_obj(),
|
Chris@2
|
559 &base_uri,
|
Chris@2
|
560 serd_file_sink,
|
Chris@2
|
561 fd);
|
Chris@2
|
562
|
Chris@2
|
563 serd_env_foreach(_world.prefixes().c_obj(),
|
Chris@2
|
564 (SerdPrefixSink)serd_writer_set_prefix,
|
Chris@2
|
565 writer);
|
Chris@2
|
566
|
Chris@2
|
567 sord_write(_c_obj, writer, 0);
|
Chris@2
|
568 serd_writer_free(writer);
|
Chris@2
|
569 fclose(fd);
|
Chris@2
|
570
|
Chris@2
|
571 return SERD_SUCCESS;
|
Chris@2
|
572 }
|
Chris@2
|
573
|
Chris@2
|
574 static size_t
|
Chris@2
|
575 string_sink(const void* buf, size_t len, void* stream)
|
Chris@2
|
576 {
|
Chris@2
|
577 std::string* str = (std::string*)stream;
|
Chris@2
|
578 str->append((const char*)buf, len);
|
Chris@2
|
579 return len;
|
Chris@2
|
580 }
|
Chris@2
|
581
|
Chris@2
|
582 inline std::string
|
Chris@2
|
583 Model::write_to_string(const std::string& base_uri_str,
|
Chris@2
|
584 SerdSyntax syntax,
|
Chris@2
|
585 SerdStyle style)
|
Chris@2
|
586 {
|
Chris@2
|
587 SerdURI base_uri = SERD_URI_NULL;
|
Chris@2
|
588 if (serd_uri_parse((const uint8_t*)base_uri_str.c_str(), &base_uri)) {
|
Chris@2
|
589 fprintf(stderr, "Invalid base URI <%s>\n", base_uri_str.c_str());
|
Chris@2
|
590 return "";
|
Chris@2
|
591 }
|
Chris@2
|
592
|
Chris@2
|
593 std::string ret;
|
Chris@2
|
594
|
Chris@2
|
595 SerdWriter* writer = serd_writer_new(syntax,
|
Chris@2
|
596 style,
|
Chris@2
|
597 _world.prefixes().c_obj(),
|
Chris@2
|
598 &base_uri,
|
Chris@2
|
599 string_sink,
|
Chris@2
|
600 &ret);
|
Chris@2
|
601
|
Chris@2
|
602 serd_env_foreach(_world.prefixes().c_obj(),
|
Chris@2
|
603 (SerdPrefixSink)serd_writer_set_prefix,
|
Chris@2
|
604 writer);
|
Chris@2
|
605
|
Chris@2
|
606 sord_write(_c_obj, writer, 0);
|
Chris@2
|
607
|
Chris@2
|
608 serd_writer_free(writer);
|
Chris@2
|
609 return ret;
|
Chris@2
|
610 }
|
Chris@2
|
611
|
Chris@2
|
612 inline void
|
Chris@2
|
613 Model::add_statement(const Node& subject,
|
Chris@2
|
614 const Node& predicate,
|
Chris@2
|
615 const Node& object)
|
Chris@2
|
616 {
|
Chris@2
|
617 SordQuad quad = { subject.c_obj(),
|
Chris@2
|
618 predicate.c_obj(),
|
Chris@2
|
619 object.c_obj(),
|
Chris@2
|
620 NULL };
|
Chris@2
|
621
|
Chris@2
|
622 sord_add(_c_obj, quad);
|
Chris@2
|
623 }
|
Chris@2
|
624
|
Chris@2
|
625 inline Iter
|
Chris@2
|
626 Model::find(const Node& subject,
|
Chris@2
|
627 const Node& predicate,
|
Chris@2
|
628 const Node& object)
|
Chris@2
|
629 {
|
Chris@2
|
630 SordQuad quad = { subject.c_obj(),
|
Chris@2
|
631 predicate.c_obj(),
|
Chris@2
|
632 object.c_obj(),
|
Chris@2
|
633 NULL };
|
Chris@2
|
634
|
Chris@2
|
635 return Iter(_world, sord_find(_c_obj, quad));
|
Chris@2
|
636 }
|
Chris@2
|
637
|
Chris@2
|
638 inline Node
|
Chris@2
|
639 Model::get(const Node& subject,
|
Chris@2
|
640 const Node& predicate,
|
Chris@2
|
641 const Node& object)
|
Chris@2
|
642 {
|
Chris@2
|
643 SordNode* c_node = sord_get(
|
Chris@2
|
644 _c_obj, subject.c_obj(), predicate.c_obj(), object.c_obj(), NULL);
|
Chris@2
|
645 Node node(_world, c_node);
|
Chris@2
|
646 sord_node_free(_world.c_obj(), c_node);
|
Chris@2
|
647 return node;
|
Chris@2
|
648 }
|
Chris@2
|
649
|
Chris@2
|
650 } // namespace Sord
|
Chris@2
|
651
|
Chris@2
|
652 #endif // SORD_SORDMM_HPP
|
Chris@2
|
653
|