@@ -1 +1 @@ | |||||
../modules/lilv/sord-0.13.0/sord/ | |||||
../modules/lilv/sord-0.14.0/sord/ |
@@ -11,7 +11,7 @@ include ../Makefile.mk | |||||
# ---------------------------------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------------------------------- | ||||
SERD_VERSION = 0.22.0 | SERD_VERSION = 0.22.0 | ||||
SORD_VERSION = 0.13.0 | |||||
SORD_VERSION = 0.14.0 | |||||
SRATOM_VERSION = 0.4.7 | SRATOM_VERSION = 0.4.7 | ||||
LILV_VERSION = 0.21.3 | LILV_VERSION = 0.21.3 | ||||
@@ -1 +0,0 @@ | |||||
David Robillard <d@drobilla.net> |
@@ -1,13 +0,0 @@ | |||||
Copyright 2011-2014 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. |
@@ -1,59 +0,0 @@ | |||||
Installation Instructions | |||||
========================= | |||||
Basic Installation | |||||
------------------ | |||||
Building this software requires only Python. To install with default options: | |||||
./waf configure | |||||
./waf | |||||
./waf install | |||||
You may need to become root for the install stage, for example: | |||||
sudo ./waf install | |||||
Configuration Options | |||||
--------------------- | |||||
All supported options can be viewed using the command: | |||||
./waf --help | |||||
Most options only need to be passed during the configure stage, for example: | |||||
./waf configure --prefix=/usr | |||||
./waf | |||||
./waf install | |||||
Compiler Configuration | |||||
---------------------- | |||||
Several standard environment variables can be used to control how compilers are | |||||
invoked: | |||||
* CC: Path to C compiler | |||||
* CFLAGS: C compiler options | |||||
* CXX: Path to C++ compiler | |||||
* CXXFLAGS: C++ compiler options | |||||
* CPPFLAGS: C preprocessor options | |||||
* LINKFLAGS: Linker options | |||||
Installation Directories | |||||
------------------------ | |||||
The --prefix option (or the PREFIX environment variable) can be used to change | |||||
the prefix which all files are installed under. There are also several options | |||||
allowing for more fine-tuned control, see the --help output for details. | |||||
Packaging | |||||
--------- | |||||
Everything can be installed to a specific root directory by passing a --destdir | |||||
option to the install stage (or setting the DESTDIR environment variable), | |||||
which adds a prefix to all install paths. For example: | |||||
./waf configure --prefix=/usr | |||||
./waf | |||||
./waf install --destdir=/tmp/package |
@@ -1,101 +0,0 @@ | |||||
sord (0.13.0) unstable; | |||||
* Reduce memory usage and increase performance with a better data structure | |||||
* Add sord_erase() for erasing statements via an iterator | |||||
* Fix bugs with stores that contain both graphs and default graph statements | |||||
* Fix compilation on compilers that do not support -pthread flag | |||||
* sord_validate: More extensive validation, including cardinality, | |||||
PlainLiteral, and someValuesFrom restrictions. | |||||
* This release does not break the ABI, but the semantics of iterators has | |||||
changed: any modification to a model invalidates iterators on that model | |||||
-- David Robillard <d@drobilla.net> Thu, 19 Feb 2015 23:18:02 -0500 | |||||
sord (0.12.2) stable; | |||||
* Fix iteration over an entire graph (* * * graph) | |||||
* sordmm.hpp: Remove unused members | |||||
* Update to waf 1.7.16 | |||||
-- David Robillard <d@drobilla.net> Fri, 08 Aug 2014 18:03:02 -0400 | |||||
sord (0.12.0) stable; | |||||
* Update to waf 1.7.9 and autowaf r90 (install docs to versioned directory) | |||||
* Add sord_get() for easily getting single property values | |||||
* sord_validate: Pass type check when range is xsd:anyURI and value is a URI | |||||
* sord_validate: Support any subClassOf rdf:Property, not just baked-in ones | |||||
* sordmm.hpp: Add convenient constructors for decimal and integer literals | |||||
* sordmm.hpp: Add Node::to_serd_node() | |||||
* sordmm.hpp: Don't automatically add RDF namespace prefix to world | |||||
-- David Robillard <d@drobilla.net> Mon, 18 Feb 2013 11:05:59 -0500 | |||||
sord (0.10.4) stable; | |||||
* Implement better data type validation in sord_validate conformant with | |||||
the XSD and OWL specifications | |||||
* Fix memory leaks in sord_validate | |||||
* Install sord_validate man page | |||||
* Disable timestamps in HTML documentation for reproducible build | |||||
-- David Robillard <d@drobilla.net> Sun, 14 Oct 2012 18:23:55 -0400 | |||||
sord (0.10.0) stable; | |||||
* Add error callback to world for custom error reporting | |||||
* Performance and space (per node) improvements | |||||
* SSE4.2 accelerated hashing for node interning, where available | |||||
* Make all 'zix' symbols private to avoid symbol clashes in static builds | |||||
* Remove problematic "Loaded n statements" output from serdi | |||||
* Strip down API documentation to a single clean page | |||||
* Fix various hyper-strict warnings | |||||
* Do not require a C++ compiler to build | |||||
* Add option to build utilities as static binaries | |||||
* Upgrade to waf 1.7.2 | |||||
* sordmm.hpp: Add indices and graphs parameters to Model constructor | |||||
* sordmm.hpp: Remove overzealous URI scheme assertion | |||||
* sordmm.hpp: Correctly handle Sord::Node self-assignment | |||||
-- David Robillard <d@drobilla.net> Thu, 23 Aug 2012 00:19:51 -0400 | |||||
sord (0.8.0) stable; | |||||
* Use path variables in pkgconfig files | |||||
* Install man page to DATADIR (e.g. PREFIX/share/man, not PREFIX/man) | |||||
* Tolerate serd passing NULL nodes to reader callback (serd 0.6.0) | |||||
* Fix comparison of typed literals | |||||
* Take advantage of interning in sord_node_equals() | |||||
* Support compilation as C++ under MSVC++. | |||||
* Add sord_iter_get_node() | |||||
* Refuse to intern relative URIs in sord_new_uri*() | |||||
* Add sord_new_relative_uri() | |||||
* Add SordInserter for writing to a model via Serd sink functions. | |||||
* Add convenient sord_search(), sord_ask(), and sord_count() | |||||
* Add sord_validate tool for validating data against RDF/OWL schemas | |||||
-- David Robillard <d@drobilla.net> Tue, 17 Apr 2012 18:24:53 -0400 | |||||
sord (0.5.0) stable; | |||||
* Remove glib dependency | |||||
* Add function sord_contains for checking for a triple pattern | |||||
* Add function sord_write_iter for writing a queried range | |||||
* Fix Sord::Namespaces::qualify to no longer chop prefixes | |||||
* Add ability to build static library | |||||
-- David Robillard <d@drobilla.net> Thu, 29 Sep 2011 00:00:00 -0400 | |||||
sord (0.4.2) stable; | |||||
* Fix compilation issues on some systems | |||||
* Fix build system Python 3 compatibility | |||||
* Bump Serd dependency to 0.4.0 | |||||
-- David Robillard <d@drobilla.net> Wed, 25 May 2011 19:00:00 -0400 | |||||
sord (0.4.0) stable; | |||||
* Initial release | |||||
-- David Robillard <d@drobilla.net> Tue, 24 May 2011 23:00:00 -0400 |
@@ -1,29 +0,0 @@ | |||||
This library is designed to allow parallel installation of different major | |||||
versions. To facilitate this, the shared library name, include directory, and | |||||
pkg-config file are suffixed with the major version number of the library. | |||||
For example, if this library was named "foo" and at version 1.x.y: | |||||
/usr/include/foo-1/foo/foo.h | |||||
/usr/lib/foo-1.so.1.x.y | |||||
/usr/lib/pkgconfig/foo-1.pc | |||||
Dependencies check for pkg-config name "foo-1" and will build | |||||
against a compatible version 1, regardless any other installed versions. | |||||
*** IMPORTANT GUIDELINES FOR PACKAGERS *** | |||||
Packages should follow the same conventions as above, i.e. include the major | |||||
version (and only the major version) in the name of the package. Continuing the | |||||
example above, the package(s) would be named foo-1 and foo-1-dev. This way, | |||||
if/when version 2 comes out, it may be installed at the same time as version 1 | |||||
without breaking anything. | |||||
Please do not create packages of this library that do not follow these | |||||
guidelines, you will break things and cause unnecessary headaches. Please do | |||||
not use any number as a suffix other than the actual major version number of the | |||||
upstream source package. | |||||
Because program and documentation names are not versioned, these should be | |||||
included in separate packages which may replace previous versions, since | |||||
there is little use in having parallel installations of them. |
@@ -1,9 +0,0 @@ | |||||
Sord | |||||
==== | |||||
Sord is a lightweight C library for storing RDF statements in memory. | |||||
For more information, see <http://drobilla.net/software/sord>. | |||||
-- David Robillard <d@drobilla.net> | |||||
@@ -1,187 +0,0 @@ | |||||
<doxygenlayout version="1.0"> | |||||
<!-- Navigation index tabs for HTML output --> | |||||
<navindex> | |||||
<tab type="mainpage" visible="yes" title=""/> | |||||
<tab type="pages" visible="yes" title="" intro=""/> | |||||
<tab type="modules" visible="yes" title="" intro=""/> | |||||
<tab type="namespaces" visible="yes" title=""> | |||||
<tab type="namespacelist" visible="yes" title="" intro=""/> | |||||
<tab type="namespacemembers" visible="yes" title="" intro=""/> | |||||
</tab> | |||||
<tab type="classes" visible="yes" title=""> | |||||
<tab type="classlist" visible="yes" title="" intro=""/> | |||||
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/> | |||||
<tab type="hierarchy" visible="yes" title="" intro=""/> | |||||
<tab type="classmembers" visible="yes" title="" intro=""/> | |||||
</tab> | |||||
<tab type="files" visible="yes" title=""> | |||||
<tab type="filelist" visible="yes" title="" intro=""/> | |||||
<tab type="globals" visible="yes" title="" intro=""/> | |||||
</tab> | |||||
<tab type="examples" visible="yes" title="" intro=""/> | |||||
</navindex> | |||||
<!-- Layout definition for a class page --> | |||||
<class> | |||||
<briefdescription visible="yes"/> | |||||
<includes visible="$SHOW_INCLUDE_FILES"/> | |||||
<inheritancegraph visible="$CLASS_GRAPH"/> | |||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/> | |||||
<allmemberslink visible="yes"/> | |||||
<memberdecl> | |||||
<nestedclasses visible="yes" title=""/> | |||||
<publictypes title=""/> | |||||
<publicslots title=""/> | |||||
<signals title=""/> | |||||
<publicmethods title=""/> | |||||
<publicstaticmethods title=""/> | |||||
<publicattributes title=""/> | |||||
<publicstaticattributes title=""/> | |||||
<protectedtypes title=""/> | |||||
<protectedslots title=""/> | |||||
<protectedmethods title=""/> | |||||
<protectedstaticmethods title=""/> | |||||
<protectedattributes title=""/> | |||||
<protectedstaticattributes title=""/> | |||||
<packagetypes title=""/> | |||||
<packagemethods title=""/> | |||||
<packagestaticmethods title=""/> | |||||
<packageattributes title=""/> | |||||
<packagestaticattributes title=""/> | |||||
<properties title=""/> | |||||
<events title=""/> | |||||
<privatetypes title=""/> | |||||
<privateslots title=""/> | |||||
<privatemethods title=""/> | |||||
<privatestaticmethods title=""/> | |||||
<privateattributes title=""/> | |||||
<privatestaticattributes title=""/> | |||||
<friends title=""/> | |||||
<related title="" subtitle=""/> | |||||
<membergroups visible="yes"/> | |||||
</memberdecl> | |||||
<detaileddescription title=""/> | |||||
<memberdef> | |||||
<inlineclasses title=""/> | |||||
<typedefs title=""/> | |||||
<enums title=""/> | |||||
<constructors title=""/> | |||||
<functions title=""/> | |||||
<related title=""/> | |||||
<variables title=""/> | |||||
<properties title=""/> | |||||
<events title=""/> | |||||
</memberdef> | |||||
<usedfiles visible="$SHOW_USED_FILES"/> | |||||
<authorsection visible="yes"/> | |||||
</class> | |||||
<!-- Layout definition for a namespace page --> | |||||
<namespace> | |||||
<briefdescription visible="yes"/> | |||||
<memberdecl> | |||||
<nestednamespaces visible="yes" title=""/> | |||||
<classes visible="yes" title=""/> | |||||
<typedefs title=""/> | |||||
<enums title=""/> | |||||
<functions title=""/> | |||||
<variables title=""/> | |||||
<membergroups visible="yes"/> | |||||
</memberdecl> | |||||
<detaileddescription title=""/> | |||||
<memberdef> | |||||
<inlineclasses title=""/> | |||||
<typedefs title=""/> | |||||
<enums title=""/> | |||||
<functions title=""/> | |||||
<variables title=""/> | |||||
</memberdef> | |||||
<authorsection visible="yes"/> | |||||
</namespace> | |||||
<!-- Layout definition for a file page --> | |||||
<file> | |||||
<briefdescription visible="yes"/> | |||||
<includes visible="$SHOW_INCLUDE_FILES"/> | |||||
<includegraph visible="$INCLUDE_GRAPH"/> | |||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/> | |||||
<sourcelink visible="yes"/> | |||||
<memberdecl> | |||||
<classes visible="yes" title=""/> | |||||
<namespaces visible="yes" title=""/> | |||||
<defines title=""/> | |||||
<typedefs title=""/> | |||||
<enums title=""/> | |||||
<functions title=""/> | |||||
<variables title=""/> | |||||
<membergroups visible="yes"/> | |||||
</memberdecl> | |||||
<detaileddescription title=""/> | |||||
<memberdef> | |||||
<inlineclasses title=""/> | |||||
<defines title=""/> | |||||
<typedefs title=""/> | |||||
<enums title=""/> | |||||
<functions title=""/> | |||||
<variables title=""/> | |||||
</memberdef> | |||||
<authorsection/> | |||||
</file> | |||||
<!-- Layout definition for a group page --> | |||||
<group> | |||||
<briefdescription visible="no"/> | |||||
<groupgraph visible="$GROUP_GRAPHS"/> | |||||
<detaileddescription title=""/> | |||||
<memberdecl> | |||||
<nestedgroups visible="yes" title=""/> | |||||
<dirs visible="yes" title=""/> | |||||
<files visible="yes" title=""/> | |||||
<namespaces visible="yes" title=""/> | |||||
<classes visible="yes" title=""/> | |||||
<defines title=""/> | |||||
<typedefs title=""/> | |||||
<enums title=""/> | |||||
<enumvalues title=""/> | |||||
<functions title=""/> | |||||
<variables title=""/> | |||||
<signals title=""/> | |||||
<publicslots title=""/> | |||||
<protectedslots title=""/> | |||||
<privateslots title=""/> | |||||
<events title=""/> | |||||
<properties title=""/> | |||||
<friends title=""/> | |||||
<membergroups visible="yes"/> | |||||
</memberdecl> | |||||
<memberdef> | |||||
<pagedocs/> | |||||
<inlineclasses title=""/> | |||||
<defines title=""/> | |||||
<typedefs title=""/> | |||||
<enums title=""/> | |||||
<enumvalues title=""/> | |||||
<functions title=""/> | |||||
<variables title=""/> | |||||
<signals title=""/> | |||||
<publicslots title=""/> | |||||
<protectedslots title=""/> | |||||
<privateslots title=""/> | |||||
<events title=""/> | |||||
<properties title=""/> | |||||
<friends title=""/> | |||||
</memberdef> | |||||
<authorsection visible="yes"/> | |||||
</group> | |||||
<!-- Layout definition for a directory page --> | |||||
<directory> | |||||
<briefdescription visible="yes"/> | |||||
<directorygraph visible="yes"/> | |||||
<memberdecl> | |||||
<dirs visible="yes"/> | |||||
<files visible="yes"/> | |||||
</memberdecl> | |||||
<detaileddescription title=""/> | |||||
</directory> | |||||
</doxygenlayout> |
@@ -1,57 +0,0 @@ | |||||
.TH SORD_VALIDATE 1 "21 Mar 2012" | |||||
.SH NAME | |||||
.B sord_validate \- Validate RDF data | |||||
.SH SYNOPSIS | |||||
sord_validate [OPTION]... INPUT... | |||||
.SH OPTIONS | |||||
.TP | |||||
\fB\-h\fR | |||||
Print the command line options. | |||||
.TP | |||||
\fB\-l\fR | |||||
Print errors on a single line. | |||||
.TP | |||||
\fB\-v\fR | |||||
Display version information and exit. | |||||
.SH DESCRIPTION | |||||
This is a simple validator which checks that all used properties are actually | |||||
defined, and that the domain and range of properties is explicitly correct. | |||||
Note that an "error" from this program does not necessarily mean data is | |||||
invalid, since it is not required to explicitly list types in RDF, however it | |||||
is a good idea to do so. | |||||
This program never retrieves data from the web or magical places on the file | |||||
system, it only processes files passed directly on the command line. This | |||||
means you must pass all used vocabularies to get a useful result. | |||||
If an appropriate schema is available, literals are checked against datatype | |||||
definitions (both the explicit datatype of the literal itself as well as any | |||||
types implied by the corresponding property). Three XML Schema Datatypes (XSD) | |||||
constraints are currently supported: regular expressions (xsd:pattern), and | |||||
inclusive range (xsd:minimumInclusive and xsd:maximumInclusive). Given an | |||||
appropriate schema, this is enough to validate against most of the standard XSD | |||||
datatypes. | |||||
.SH EXAMPLES | |||||
sord_validate `find ~/schemas/ -name '*.ttl'` data.ttl | |||||
.SH AUTHOR | |||||
sord_validate was written by David Robillard <d@drobilla.net> | |||||
.SH COPYRIGHT | |||||
Copyright \(co 2012-2013 David Robillard. | |||||
.br | |||||
License: <http://www.opensource.org/licenses/isc-license> | |||||
.br | |||||
This is free software; you are free to change and redistribute it. | |||||
.br | |||||
There is NO WARRANTY, to the extent permitted by law. | |||||
.SH "SEE ALSO" | |||||
<http://drobilla.net/software/sord> |
@@ -1,43 +0,0 @@ | |||||
.TH SORDI 1 "17 Jan 2012" | |||||
.SH NAME | |||||
.B sordi \- Load and re-serialise RDF data | |||||
.SH SYNOPSIS | |||||
sordi [OPTION]... INPUT BASE_URI | |||||
.SH OPTIONS | |||||
.TP | |||||
\fB\-h\fR | |||||
Print the command line options. | |||||
.TP | |||||
\fB\-i SYNTAX\fR | |||||
Read input in SYNTAX (`turtle' or `ntriples'). | |||||
.TP | |||||
\fB\-o SYNTAX\fR | |||||
Write output in SYNTAX (`turtle' or `ntriples'). | |||||
.TP | |||||
\fB\-s INPUT\fR | |||||
Parse INPUT as a string (terminates options). | |||||
.TP | |||||
\fB\-v\fR | |||||
Display version information and exit. | |||||
.SH AUTHOR | |||||
Sordi was written by David Robillard <d@drobilla.net> | |||||
.SH COPYRIGHT | |||||
Copyright \(co 2011-2013 David Robillard. | |||||
.br | |||||
License: <http://www.opensource.org/licenses/isc-license> | |||||
.br | |||||
This is free software; you are free to change and redistribute it. | |||||
.br | |||||
There is NO WARRANTY, to the extent permitted by law. | |||||
.SH "SEE ALSO" | |||||
<http://drobilla.net/software/sord> |
@@ -1,563 +0,0 @@ | |||||
body { | |||||
font-size: medium; | |||||
font-family: sans-serif; | |||||
} | |||||
#top { | |||||
background-color: #F3F3F3; | |||||
margin: 0; | |||||
padding: 0; | |||||
border-bottom: 1px solid #DDD; | |||||
margin-bottom: 1ex; | |||||
font-size: xx-large; | |||||
font-weight: bold; | |||||
} | |||||
div.header { | |||||
display: none; | |||||
} | |||||
.tabs { | |||||
display: none; | |||||
} | |||||
h1 h2 h3 h4 h5 h6 { | |||||
font-weight: bold; | |||||
} | |||||
h1 { | |||||
font-size: 164%; | |||||
} | |||||
h2 { | |||||
font-size: 132%; | |||||
} | |||||
h3 { | |||||
font-size: 124%; | |||||
} | |||||
h4 { | |||||
font-size: 116%; | |||||
} | |||||
h5 { | |||||
font-size: 108%; | |||||
} | |||||
h6 { | |||||
font-size: 100%; | |||||
} | |||||
p { | |||||
margin: 0 0 1ex 0; | |||||
} | |||||
br { | |||||
display: none; | |||||
} | |||||
dt { | |||||
font-weight: 700; | |||||
} | |||||
div.multicol { | |||||
} | |||||
p.startli,p.startdd,p.starttd { | |||||
margin-top: 2px; | |||||
} | |||||
p.endli { | |||||
margin-bottom: 0; | |||||
} | |||||
p.enddd { | |||||
margin-bottom: 4px; | |||||
} | |||||
p.endtd { | |||||
margin-bottom: 2px; | |||||
} | |||||
caption { | |||||
font-weight: 700; | |||||
} | |||||
span.legend { | |||||
font-size: 70%; | |||||
text-align: center; | |||||
} | |||||
h3.version { | |||||
font-size: 90%; | |||||
text-align: center; | |||||
} | |||||
div.qindex,div.navtab { | |||||
background-color: #EBEFF6; | |||||
border: 1px solid #A3B4D7; | |||||
text-align: center; | |||||
margin: 2px; | |||||
padding: 2px; | |||||
} | |||||
div.qindex,div.navpath { | |||||
width: 100%; | |||||
line-height: 140%; | |||||
} | |||||
div.navtab { | |||||
margin-right: 15px; | |||||
} | |||||
/* @group Link Styling */ | |||||
a { | |||||
color: #3D8C57; | |||||
text-decoration: none; | |||||
} | |||||
.contents a:visited { | |||||
color: #50755E; | |||||
} | |||||
a:hover { | |||||
text-decoration: underline; | |||||
} | |||||
a.qindexHL { | |||||
background-color: #9CAFD4; | |||||
color: #FFF; | |||||
border: 1px double #869DCA; | |||||
} | |||||
a.code { | |||||
color: #4665A2; | |||||
} | |||||
a.codeRef { | |||||
color: #4665A2; | |||||
} | |||||
/* @end */ | |||||
dl.el { | |||||
margin-left: -1cm; | |||||
} | |||||
.fragment { | |||||
font-family: monospace, fixed; | |||||
font-size: 105%; | |||||
} | |||||
pre.fragment { | |||||
border: 1px solid #C4C4C4; | |||||
background-color: #F9F9F9; | |||||
padding: 4px 6px; | |||||
margin: 4px 8px 4px 2px; | |||||
overflow: auto; | |||||
font-size: 9pt; | |||||
line-height: 125%; | |||||
} | |||||
div.ah { | |||||
background-color: #000; | |||||
font-weight: 700; | |||||
color: #FFF; | |||||
margin-bottom: 3px; | |||||
margin-top: 3px; | |||||
padding: .2em; | |||||
border: thin solid #333; | |||||
} | |||||
div.groupHeader { | |||||
margin-left: 16px; | |||||
margin-top: 12px; | |||||
margin-bottom: 6px; | |||||
font-weight: 700; | |||||
} | |||||
div.groupText { | |||||
margin-left: 16px; | |||||
font-style: italic; | |||||
} | |||||
body { | |||||
background: #FFF; | |||||
color: #000; | |||||
margin: 0; | |||||
} | |||||
div.contents { | |||||
margin-top: 10px; | |||||
margin-left: 10px; | |||||
margin-right: 10px; | |||||
} | |||||
td.indexkey { | |||||
background-color: #EBEFF6; | |||||
font-weight: 700; | |||||
border: 1px solid #C4CFE5; | |||||
margin: 2px 0; | |||||
padding: 2px 10px; | |||||
} | |||||
td.indexvalue { | |||||
background-color: #EBEFF6; | |||||
border: 1px solid #C4CFE5; | |||||
padding: 2px 10px; | |||||
margin: 2px 0; | |||||
} | |||||
tr.memlist { | |||||
background-color: #EEF1F7; | |||||
} | |||||
p.formulaDsp { | |||||
text-align: center; | |||||
} | |||||
img.formulaDsp { | |||||
} | |||||
img.formulaInl { | |||||
vertical-align: middle; | |||||
} | |||||
div.center { | |||||
text-align: center; | |||||
margin-top: 0; | |||||
margin-bottom: 0; | |||||
padding: 0; | |||||
} | |||||
div.center img { | |||||
border: 0; | |||||
} | |||||
address.footer { | |||||
text-align: right; | |||||
padding: 0 0.25em 0.25em 0; | |||||
} | |||||
img.footer { | |||||
border: 0; | |||||
vertical-align: middle; | |||||
} | |||||
/* @group Code Colorization */ | |||||
span.keyword { | |||||
color: green; | |||||
} | |||||
span.keywordtype { | |||||
color: #604020; | |||||
} | |||||
span.keywordflow { | |||||
color: #e08000; | |||||
} | |||||
span.comment { | |||||
color: maroon; | |||||
} | |||||
span.preprocessor { | |||||
color: #806020; | |||||
} | |||||
span.stringliteral { | |||||
color: #002080; | |||||
} | |||||
span.charliteral { | |||||
color: teal; | |||||
} | |||||
span.vhdldigit { | |||||
color: #F0F; | |||||
} | |||||
span.vhdlkeyword { | |||||
color: #700070; | |||||
} | |||||
span.vhdllogic { | |||||
color: red; | |||||
} | |||||
/* @end */ | |||||
td.tiny { | |||||
font-size: 75%; | |||||
} | |||||
.dirtab { | |||||
padding: 4px; | |||||
border-collapse: collapse; | |||||
border: 1px solid #A3B4D7; | |||||
} | |||||
th.dirtab { | |||||
background: #EBEFF6; | |||||
font-weight: 700; | |||||
} | |||||
hr { | |||||
height: 0; | |||||
border: none; | |||||
border-top: 1px solid #DDD; | |||||
margin: 2em 0 1em; | |||||
} | |||||
hr.footer { | |||||
height: 1px; | |||||
} | |||||
/* @group Member Descriptions */ | |||||
table.memberdecls { | |||||
border-spacing: 0; | |||||
font-size: small; | |||||
} | |||||
.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,.memTemplItemLeft,.memTemplItemRight,.memTemplParams { | |||||
background-color: #FBFBFB; | |||||
margin: 0; | |||||
padding: 0.25ex; | |||||
} | |||||
.mdescLeft,.mdescRight { | |||||
color: #555; | |||||
} | |||||
.memItemLeft,.memItemRight,.memTemplParams { | |||||
border-top: 1px solid #DDD; | |||||
} | |||||
.memItemLeft,.memTemplItemLeft { | |||||
white-space: nowrap; | |||||
padding-left: 2em; | |||||
} | |||||
.memTemplParams { | |||||
color: #464646; | |||||
white-space: nowrap; | |||||
} | |||||
/* @end */ | |||||
/* @group Member Details */ | |||||
/* Styles for detailed member documentation */ | |||||
.memtemplate { | |||||
font-size: 80%; | |||||
color: #4665A2; | |||||
font-weight: bold; | |||||
} | |||||
.memnav { | |||||
background-color: #EBEFF6; | |||||
border: 1px solid #A3B4D7; | |||||
text-align: center; | |||||
margin: 2px; | |||||
margin-right: 15px; | |||||
padding: 2px; | |||||
} | |||||
.memitem { | |||||
padding: 0; | |||||
margin: 1ex 0 2ex 0; | |||||
border: 1px solid #CCC; | |||||
} | |||||
.memname { | |||||
white-space: nowrap; | |||||
font-weight: bold; | |||||
} | |||||
.memproto { | |||||
border-bottom: 1px solid #DDD; | |||||
padding: 0.5ex; | |||||
font-weight: bold; | |||||
background-color: #F3F3F3; | |||||
} | |||||
.memdoc { | |||||
padding: 1ex; | |||||
background-color: #FBFBFB; | |||||
border-top-width: 0; | |||||
} | |||||
.paramkey { | |||||
text-align: right; | |||||
} | |||||
.paramtype { | |||||
white-space: nowrap; | |||||
} | |||||
.paramname { | |||||
color: #602020; | |||||
white-space: nowrap; | |||||
} | |||||
.paramname em { | |||||
font-style: normal; | |||||
} | |||||
/* @end */ | |||||
/* @group Directory (tree) */ | |||||
/* for the tree view */ | |||||
.ftvtree { | |||||
font-family: sans-serif; | |||||
margin: 0; | |||||
} | |||||
/* these are for tree view when used as main index */ | |||||
.directory { | |||||
font-size: 9pt; | |||||
font-weight: bold; | |||||
margin: 5px; | |||||
} | |||||
.directory h3 { | |||||
margin: 0; | |||||
margin-top: 1em; | |||||
font-size: 11pt; | |||||
} | |||||
.directory > h3 { | |||||
margin-top: 0; | |||||
} | |||||
.directory p { | |||||
margin: 0; | |||||
white-space: nowrap; | |||||
} | |||||
.directory div { | |||||
display: none; | |||||
margin: 0; | |||||
} | |||||
.directory img { | |||||
vertical-align: -30%; | |||||
} | |||||
/* these are for tree view when not used as main index */ | |||||
.directory-alt { | |||||
font-size: 100%; | |||||
font-weight: bold; | |||||
} | |||||
.directory-alt h3 { | |||||
margin: 0; | |||||
margin-top: 1em; | |||||
font-size: 11pt; | |||||
} | |||||
.directory-alt > h3 { | |||||
margin-top: 0; | |||||
} | |||||
.directory-alt p { | |||||
margin: 0; | |||||
white-space: nowrap; | |||||
} | |||||
.directory-alt div { | |||||
display: none; | |||||
margin: 0; | |||||
} | |||||
.directory-alt img { | |||||
vertical-align: -30%; | |||||
} | |||||
/* @end */ | |||||
div.dynheader { | |||||
margin-top: 8px; | |||||
} | |||||
address { | |||||
font-style: normal; | |||||
color: #2A3D61; | |||||
} | |||||
table.doxtable { | |||||
border-collapse: collapse; | |||||
margin: 0.5ex; | |||||
} | |||||
table.doxtable td,table.doxtable th { | |||||
border: 1px solid #DDD; | |||||
padding: 3px 7px 2px; | |||||
} | |||||
table.doxtable th { | |||||
background-color: #F3F3F3; | |||||
color: #000; | |||||
padding-bottom: 4px; | |||||
padding-top: 5px; | |||||
text-align: left; | |||||
font-weight: bold; | |||||
} | |||||
.tabsearch { | |||||
top: 0; | |||||
left: 10px; | |||||
height: 36px; | |||||
z-index: 101; | |||||
overflow: hidden; | |||||
font-size: 13px; | |||||
} | |||||
.navpath ul { | |||||
font-size: 11px; | |||||
height: 30px; | |||||
line-height: 30px; | |||||
color: #8AA0CC; | |||||
border: 1px solid #C2CDE4; | |||||
overflow: hidden; | |||||
margin: 0; | |||||
padding: 0; | |||||
} | |||||
.navpath li { | |||||
list-style-type: none; | |||||
float: left; | |||||
padding-left: 10px; | |||||
padding-right: 15px; | |||||
color: #364D7C; | |||||
} | |||||
.navpath a { | |||||
height: 32px; | |||||
display: block; | |||||
text-decoration: none; | |||||
outline: none; | |||||
} | |||||
.navpath a:hover { | |||||
color: #6884BD; | |||||
} | |||||
div.summary { | |||||
float: right; | |||||
font-size: 8pt; | |||||
padding-right: 5px; | |||||
width: 50%; | |||||
text-align: right; | |||||
} | |||||
div.summary a { | |||||
white-space: nowrap; | |||||
} | |||||
div.header { | |||||
background-color: #F3F3F3; | |||||
margin: 0; | |||||
border-bottom: 1px solid #DDD; | |||||
} | |||||
div.headertitle { | |||||
padding: 5px 5px 5px 10px; | |||||
font-size: 180%; | |||||
font-weight: bold; | |||||
} |
@@ -1,11 +0,0 @@ | |||||
prefix=@PREFIX@ | |||||
exec_prefix=@EXEC_PREFIX@ | |||||
libdir=@LIBDIR@ | |||||
includedir=@INCLUDEDIR@ | |||||
Name: Sord | |||||
Version: @SORD_VERSION@ | |||||
Description: A lightweight C library for storing RDF statements in memory. | |||||
Requires: @PKG_serd_0@ | |||||
Libs: -L${libdir} -l@LIB_SORD@ -lserd-0 -lm | |||||
Cflags: -I${includedir}/sord-@SORD_MAJOR_VERSION@ |
@@ -1,646 +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 sord.h API for Sord, a lightweight RDF model library. | |||||
*/ | |||||
#ifndef SORD_SORD_H | |||||
#define SORD_SORD_H | |||||
#include <stddef.h> | |||||
#include <stdint.h> | |||||
#include <stdio.h> | |||||
#include "serd/serd.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" { | |||||
#else | |||||
# include <stdbool.h> | |||||
#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 (a.k.a. "key") */ | |||||
SORD_OBJECT = 2, /**< Object (a.k.a. "value") */ | |||||
SORD_GRAPH = 3 /**< Graph (a.k.a. "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* str, | |||||
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 `len` to its length. | |||||
*/ | |||||
SORD_API | |||||
const uint8_t* | |||||
sord_node_get_string_counted(const SordNode* node, size_t* len); | |||||
/** | |||||
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 quad); | |||||
/** | |||||
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 quad); | |||||
/** | |||||
Remove a quad from a model via an iterator. | |||||
Calling this function invalidates all iterators on `model` except `iter`. | |||||
@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 quad); | |||||
/** | |||||
Return a field of the quad pointed to by `iter`. | |||||
*/ | |||||
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 */ |
@@ -1,653 +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 | |||||
#include <cassert> | |||||
#include <cstring> | |||||
#include <cstdlib> | |||||
#include <iostream> | |||||
#include <set> | |||||
#include <string> | |||||
#include <sstream> | |||||
#include "serd/serd.h" | |||||
#include "sord/sord.h" | |||||
#define SORD_NS_XSD "http://www.w3.org/2001/XMLSchema#" | |||||
namespace Sord { | |||||
/** Utility base class to prevent copying. */ | |||||
class Noncopyable { | |||||
protected: | |||||
Noncopyable() {} | |||||
~Noncopyable() {} | |||||
private: | |||||
Noncopyable(const Noncopyable&); | |||||
const Noncopyable& operator=(const Noncopyable&); | |||||
}; | |||||
/** C++ wrapper for a Sord object. */ | |||||
template <typename T> | |||||
class Wrapper { | |||||
public: | |||||
inline Wrapper(T c_obj = NULL) : _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(NULL)) {} | |||||
~Namespaces() { serd_env_free(_c_obj); } | |||||
static inline SerdNode string_to_node(SerdType type, const std::string& s) { | |||||
SerdNode ret = { | |||||
(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((const char*)prefix.buf, prefix.n_bytes); | |||||
ret.append(":").append((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((const char*)uri_prefix.buf, uri_prefix.len); | |||||
ret.append((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 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*>(NULL), _world(NULL) {} | |||||
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 ? (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() { | |||||
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) : NULL; | |||||
} | |||||
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(), | |||||
(const uint8_t*)s.c_str(), | |||||
(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, 7); | |||||
const SerdNode type = serd_node_from_string( | |||||
SERD_URI, (const uint8_t*)SORD_NS_XSD "decimal"); | |||||
return Node( | |||||
world, | |||||
sord_node_from_serd_node( | |||||
world.c_obj(), world.prefixes().c_obj(), &val, &type, NULL), | |||||
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, (const uint8_t*)SORD_NS_XSD "integer"); | |||||
return Node( | |||||
world, | |||||
sord_node_from_serd_node( | |||||
world.c_obj(), world.prefixes().c_obj(), &val, &type, NULL), | |||||
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(), (const unsigned char*)s.c_str()); | |||||
break; | |||||
case LITERAL: | |||||
_c_obj = sord_new_literal( | |||||
world.world(), NULL, (const unsigned char*)s.c_str(), NULL); | |||||
break; | |||||
case BLANK: | |||||
_c_obj = sord_new_blank( | |||||
world.world(), (const unsigned char*)s.c_str()); | |||||
break; | |||||
default: | |||||
_c_obj = NULL; | |||||
} | |||||
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) | |||||
: Wrapper<SordNode*>() | |||||
, _world(other._world) | |||||
{ | |||||
if (_world) { | |||||
_c_obj = other._c_obj ? sord_node_copy(other._c_obj) : NULL; | |||||
} | |||||
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 ? (const char*)sord_node_get_string(_c_obj) : ""; | |||||
} | |||||
inline const char* | |||||
Node::to_c_string() const | |||||
{ | |||||
return (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((const char*)sord_node_get_string(datatype), | |||||
type_uri)) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
inline int | |||||
Node::to_int() const | |||||
{ | |||||
assert(is_int()); | |||||
char* endptr; | |||||
return strtol((const char*)sord_node_get_string(_c_obj), &endptr, 10); | |||||
} | |||||
inline float | |||||
Node::to_float() const | |||||
{ | |||||
assert(is_float()); | |||||
char* endptr; | |||||
return serd_strtod((const char*)sord_node_get_string(_c_obj), &endptr); | |||||
} | |||||
inline bool | |||||
Node::to_bool() const | |||||
{ | |||||
assert(is_bool()); | |||||
return !strcmp((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) {} | |||||
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 const Node get_subject() const { | |||||
SordQuad quad; | |||||
sord_iter_get(_c_obj, quad); | |||||
return Node(_world, quad[SORD_SUBJECT]); | |||||
} | |||||
inline const Node get_predicate() const { | |||||
SordQuad quad; | |||||
sord_iter_get(_c_obj, quad); | |||||
return Node(_world, quad[SORD_PREDICATE]); | |||||
} | |||||
inline const 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 = (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 = (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, NULL); | |||||
serd_reader_read_string(reader, (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((const uint8_t*)data_uri.c_str(), NULL); | |||||
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, NULL); | |||||
serd_reader_read_file(reader, path); | |||||
serd_reader_free(reader); | |||||
free(path); | |||||
} | |||||
inline SerdStatus | |||||
Model::write_to_file(const std::string& uri, SerdSyntax syntax, SerdStyle style) | |||||
{ | |||||
uint8_t* path = serd_file_uri_parse((const uint8_t*)uri.c_str(), NULL); | |||||
if (!path) { | |||||
fprintf(stderr, "Failed to parse file URI <%s>\n", uri.c_str()); | |||||
return SERD_ERR_BAD_ARG; | |||||
} | |||||
FILE* const fd = fopen((const char*)path, "w"); | |||||
if (!fd) { | |||||
fprintf(stderr, "Failed to open file %s\n", path); | |||||
free(path); | |||||
return SERD_ERR_UNKNOWN; | |||||
} | |||||
free(path); | |||||
SerdURI base_uri = SERD_URI_NULL; | |||||
if (serd_uri_parse((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(), | |||||
(SerdPrefixSink)serd_writer_set_prefix, | |||||
writer); | |||||
sord_write(_c_obj, writer, 0); | |||||
serd_writer_free(writer); | |||||
fclose(fd); | |||||
return SERD_SUCCESS; | |||||
} | |||||
static size_t | |||||
string_sink(const void* buf, size_t len, void* stream) | |||||
{ | |||||
std::string* str = (std::string*)stream; | |||||
str->append((const char*)buf, len); | |||||
return len; | |||||
} | |||||
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((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, (const uint8_t*)base_uri_str.c_str()); | |||||
serd_writer_set_base_uri(writer, &base_uri_node); | |||||
serd_env_foreach(_world.prefixes().c_obj(), | |||||
(SerdPrefixSink)serd_writer_set_prefix, | |||||
writer); | |||||
sord_write(_c_obj, writer, 0); | |||||
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(), | |||||
NULL }; | |||||
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(), | |||||
NULL }; | |||||
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(), NULL); | |||||
Node node(_world, c_node); | |||||
sord_node_free(_world.c_obj(), c_node); | |||||
return node; | |||||
} | |||||
} // namespace Sord | |||||
#endif // SORD_SORDMM_HPP |
@@ -1,46 +0,0 @@ | |||||
/* | |||||
Copyright 2011-2012 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. | |||||
*/ | |||||
#ifndef SORD_SORD_INTERNAL_H | |||||
#define SORD_SORD_INTERNAL_H | |||||
#include <stddef.h> | |||||
#include <stdint.h> | |||||
#include "sord/sord.h" | |||||
/** Resource node metadata */ | |||||
typedef struct { | |||||
size_t refs_as_obj; ///< References as a quad object | |||||
} SordResourceMetadata; | |||||
/** Literal node metadata */ | |||||
typedef struct { | |||||
SordNode* datatype; ///< Optional literal data type URI | |||||
char lang[16]; ///< Optional language tag | |||||
} SordLiteralMetadata; | |||||
/** Node */ | |||||
struct SordNodeImpl { | |||||
SerdNode node; ///< Serd node | |||||
size_t refs; ///< Reference count (# of containing quads) | |||||
union { | |||||
SordResourceMetadata res; | |||||
SordLiteralMetadata lit; | |||||
} meta; | |||||
}; | |||||
#endif /* SORD_SORD_INTERNAL_H */ |
@@ -1,588 +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. | |||||
*/ | |||||
#include <stdarg.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include "sord/sord.h" | |||||
static const int DIGITS = 3; | |||||
static const int MAX_NUM = 999; | |||||
static const unsigned n_objects_per = 2; | |||||
typedef struct { | |||||
SordQuad query; | |||||
int expected_num_results; | |||||
} QueryTest; | |||||
#define USTR(s) ((const uint8_t*)(s)) | |||||
static SordNode* | |||||
uri(SordWorld* world, int num) | |||||
{ | |||||
if (num == 0) | |||||
return 0; | |||||
char str[] = "eg:000"; | |||||
char* uri_num = str + 3; // First `0' | |||||
snprintf(uri_num, DIGITS + 1, "%0*d", DIGITS, num); | |||||
return sord_new_uri(world, (const uint8_t*)str); | |||||
} | |||||
static int | |||||
test_fail(const char* fmt, ...) | |||||
{ | |||||
va_list args; | |||||
va_start(args, fmt); | |||||
fprintf(stderr, "error: "); | |||||
vfprintf(stderr, fmt, args); | |||||
va_end(args); | |||||
return 1; | |||||
} | |||||
static int | |||||
generate(SordWorld* world, | |||||
SordModel* sord, | |||||
size_t n_quads, | |||||
SordNode* graph) | |||||
{ | |||||
fprintf(stderr, "Generating %zu (S P *) quads with %u objects each\n", | |||||
n_quads, n_objects_per); | |||||
for (size_t i = 0; i < n_quads; ++i) { | |||||
int num = (i * n_objects_per) + 1; | |||||
SordNode* ids[2 + n_objects_per]; | |||||
for (unsigned j = 0; j < 2 + n_objects_per; ++j) { | |||||
ids[j] = uri(world, num++); | |||||
} | |||||
for (unsigned j = 0; j < n_objects_per; ++j) { | |||||
SordQuad tup = { ids[0], ids[1], ids[2 + j], graph }; | |||||
if (!sord_add(sord, tup)) { | |||||
return test_fail("Fail: Failed to add quad\n"); | |||||
} | |||||
} | |||||
for (unsigned j = 0; j < 2 + n_objects_per; ++j) { | |||||
sord_node_free(world, ids[j]); | |||||
} | |||||
} | |||||
// Add some literals | |||||
// (98 4 "hello") and (98 4 "hello"^^<5>) | |||||
SordQuad tup = { 0, 0, 0, 0}; | |||||
tup[0] = uri(world, 98); | |||||
tup[1] = uri(world, 4); | |||||
tup[2] = sord_new_literal(world, 0, USTR("hello"), NULL); | |||||
tup[3] = graph; | |||||
sord_add(sord, tup); | |||||
sord_node_free(world, (SordNode*)tup[2]); | |||||
tup[2] = sord_new_literal(world, uri(world, 5), USTR("hello"), NULL); | |||||
if (!sord_add(sord, tup)) { | |||||
return test_fail("Failed to add typed literal\n"); | |||||
} | |||||
// (96 4 "hello"^^<4>) and (96 4 "hello"^^<5>) | |||||
tup[0] = uri(world, 96); | |||||
tup[1] = uri(world, 4); | |||||
tup[2] = sord_new_literal(world, uri(world, 4), USTR("hello"), NULL); | |||||
tup[3] = graph; | |||||
sord_add(sord, tup); | |||||
sord_node_free(world, (SordNode*)tup[2]); | |||||
tup[2] = sord_new_literal(world, uri(world, 5), USTR("hello"), NULL); | |||||
if (!sord_add(sord, tup)) { | |||||
return test_fail("Failed to add typed literal\n"); | |||||
} | |||||
// (94 5 "hello") and (94 5 "hello"@en-gb) | |||||
tup[0] = uri(world, 94); | |||||
tup[1] = uri(world, 5); | |||||
tup[2] = sord_new_literal(world, 0, USTR("hello"), NULL); | |||||
tup[3] = graph; | |||||
sord_add(sord, tup); | |||||
sord_node_free(world, (SordNode*)tup[2]); | |||||
tup[2] = sord_new_literal(world, NULL, USTR("hello"), "en-gb"); | |||||
if (!sord_add(sord, tup)) { | |||||
return test_fail("Failed to add literal with language\n"); | |||||
} | |||||
// (92 6 "hello"@en-us) and (92 5 "hello"@en-gb) | |||||
tup[0] = uri(world, 92); | |||||
tup[1] = uri(world, 6); | |||||
tup[2] = sord_new_literal(world, 0, USTR("hello"), "en-us"); | |||||
tup[3] = graph; | |||||
sord_add(sord, tup); | |||||
sord_node_free(world, (SordNode*)tup[2]); | |||||
tup[2] = sord_new_literal(world, NULL, USTR("hello"), "en-gb"); | |||||
if (!sord_add(sord, tup)) { | |||||
return test_fail("Failed to add literal with language\n"); | |||||
} | |||||
sord_node_free(world, (SordNode*)tup[0]); | |||||
sord_node_free(world, (SordNode*)tup[2]); | |||||
tup[0] = uri(world, 14); | |||||
tup[2] = sord_new_literal(world, 0, USTR("bonjour"), "fr"); | |||||
sord_add(sord, tup); | |||||
sord_node_free(world, (SordNode*)tup[2]); | |||||
tup[2] = sord_new_literal(world, 0, USTR("salut"), "fr"); | |||||
sord_add(sord, tup); | |||||
// Attempt to add some duplicates | |||||
if (sord_add(sord, tup)) { | |||||
return test_fail("Fail: Successfully added duplicate quad\n"); | |||||
} | |||||
if (sord_add(sord, tup)) { | |||||
return test_fail("Fail: Successfully added duplicate quad\n"); | |||||
} | |||||
// Add a blank node subject | |||||
sord_node_free(world, (SordNode*)tup[0]); | |||||
tup[0] = sord_new_blank(world, USTR("ablank")); | |||||
sord_add(sord, tup); | |||||
sord_node_free(world, (SordNode*)tup[1]); | |||||
sord_node_free(world, (SordNode*)tup[2]); | |||||
tup[1] = uri(world, 6); | |||||
tup[2] = uri(world, 7); | |||||
sord_add(sord, tup); | |||||
sord_node_free(world, (SordNode*)tup[0]); | |||||
sord_node_free(world, (SordNode*)tup[1]); | |||||
sord_node_free(world, (SordNode*)tup[2]); | |||||
return EXIT_SUCCESS; | |||||
} | |||||
#define TUP_FMT "(%6s %6s %6s)" | |||||
#define TUP_FMT_ARGS(t) \ | |||||
((t)[0] ? sord_node_get_string((t)[0]) : USTR("*")), \ | |||||
((t)[1] ? sord_node_get_string((t)[1]) : USTR("*")), \ | |||||
((t)[2] ? sord_node_get_string((t)[2]) : USTR("*")) | |||||
static int | |||||
test_read(SordWorld* world, SordModel* sord, SordNode* g, | |||||
const size_t n_quads) | |||||
{ | |||||
int ret = EXIT_SUCCESS; | |||||
SordQuad id; | |||||
SordIter* iter = sord_begin(sord); | |||||
if (sord_iter_get_model(iter) != sord) { | |||||
return test_fail("Fail: Iterator has incorrect sord pointer\n"); | |||||
} | |||||
for (; !sord_iter_end(iter); sord_iter_next(iter)) | |||||
sord_iter_get(iter, id); | |||||
// Attempt to increment past end | |||||
if (!sord_iter_next(iter)) { | |||||
return test_fail("Fail: Successfully incremented past end\n"); | |||||
} | |||||
sord_iter_free(iter); | |||||
const uint8_t* s = USTR("hello"); | |||||
SordNode* plain_hello = sord_new_literal(world, 0, s, NULL); | |||||
SordNode* type4_hello = sord_new_literal(world, uri(world, 4), s, NULL); | |||||
SordNode* type5_hello = sord_new_literal(world, uri(world, 5), s, NULL); | |||||
SordNode* gb_hello = sord_new_literal(world, NULL, s, "en-gb"); | |||||
SordNode* us_hello = sord_new_literal(world, NULL, s, "en-us"); | |||||
#define NUM_PATTERNS 17 | |||||
QueryTest patterns[NUM_PATTERNS] = { | |||||
{ { 0, 0, 0 }, (n_quads * n_objects_per) + 12 }, | |||||
{ { uri(world, 9), uri(world, 9), uri(world, 9) }, 0 }, | |||||
{ { uri(world, 1), uri(world, 2), uri(world, 4) }, 1 }, | |||||
{ { uri(world, 3), uri(world, 4), uri(world, 0) }, 2 }, | |||||
{ { uri(world, 0), uri(world, 2), uri(world, 4) }, 1 }, | |||||
{ { uri(world, 0), uri(world, 0), uri(world, 4) }, 1 }, | |||||
{ { uri(world, 1), uri(world, 0), uri(world, 0) }, 2 }, | |||||
{ { uri(world, 1), uri(world, 0), uri(world, 4) }, 1 }, | |||||
{ { uri(world, 0), uri(world, 2), uri(world, 0) }, 2 }, | |||||
{ { uri(world, 98), uri(world, 4), plain_hello }, 1 }, | |||||
{ { uri(world, 98), uri(world, 4), type5_hello }, 1 }, | |||||
{ { uri(world, 96), uri(world, 4), type4_hello }, 1 }, | |||||
{ { uri(world, 96), uri(world, 4), type5_hello }, 1 }, | |||||
{ { uri(world, 94), uri(world, 5), plain_hello }, 1 }, | |||||
{ { uri(world, 94), uri(world, 5), gb_hello }, 1 }, | |||||
{ { uri(world, 92), uri(world, 6), gb_hello }, 1 }, | |||||
{ { uri(world, 92), uri(world, 6), us_hello }, 1 } }; | |||||
SordQuad match = { uri(world, 1), uri(world, 2), uri(world, 4), g }; | |||||
if (!sord_contains(sord, match)) { | |||||
return test_fail("Fail: No match for " TUP_FMT "\n", | |||||
TUP_FMT_ARGS(match)); | |||||
} | |||||
SordQuad nomatch = { uri(world, 1), uri(world, 2), uri(world, 9), g }; | |||||
if (sord_contains(sord, nomatch)) { | |||||
return test_fail("Fail: False match for " TUP_FMT "\n", | |||||
TUP_FMT_ARGS(nomatch)); | |||||
} | |||||
if (sord_get(sord, NULL, NULL, uri(world, 3), g)) { | |||||
return test_fail("Fail: Get *,*,3 succeeded\n"); | |||||
} else if (!sord_node_equals( | |||||
sord_get(sord, uri(world, 1), uri(world, 2), NULL, g), | |||||
uri(world, 3))) { | |||||
return test_fail("Fail: Get 1,2,* != 3\n"); | |||||
} else if (!sord_node_equals( | |||||
sord_get(sord, uri(world, 1), NULL, uri(world, 3), g), | |||||
uri(world, 2))) { | |||||
return test_fail("Fail: Get 1,*,3 != 2\n"); | |||||
} else if (!sord_node_equals( | |||||
sord_get(sord, NULL, uri(world, 2), uri(world, 3), g), | |||||
uri(world, 1))) { | |||||
return test_fail("Fail: Get *,2,3 != 1\n"); | |||||
} | |||||
for (unsigned i = 0; i < NUM_PATTERNS; ++i) { | |||||
QueryTest test = patterns[i]; | |||||
SordQuad pat = { test.query[0], test.query[1], test.query[2], g }; | |||||
fprintf(stderr, "Query " TUP_FMT "... ", TUP_FMT_ARGS(pat)); | |||||
iter = sord_find(sord, pat); | |||||
int num_results = 0; | |||||
for (; !sord_iter_end(iter); sord_iter_next(iter)) { | |||||
sord_iter_get(iter, id); | |||||
++num_results; | |||||
if (!sord_quad_match(pat, id)) { | |||||
sord_iter_free(iter); | |||||
return test_fail( | |||||
"Fail: Query result " TUP_FMT " does not match pattern\n", | |||||
TUP_FMT_ARGS(id)); | |||||
} | |||||
} | |||||
sord_iter_free(iter); | |||||
if (num_results != test.expected_num_results) { | |||||
return test_fail("Fail: Expected %d results, got %d\n", | |||||
test.expected_num_results, num_results); | |||||
} | |||||
fprintf(stderr, "OK (%u matches)\n", test.expected_num_results); | |||||
} | |||||
// Query blank node subject | |||||
SordQuad pat = { sord_new_blank(world, USTR("ablank")), 0, 0 }; | |||||
if (!pat[0]) { | |||||
return test_fail("Blank node subject lost\n"); | |||||
} | |||||
fprintf(stderr, "Query " TUP_FMT "... ", TUP_FMT_ARGS(pat)); | |||||
iter = sord_find(sord, pat); | |||||
int num_results = 0; | |||||
for (; !sord_iter_end(iter); sord_iter_next(iter)) { | |||||
sord_iter_get(iter, id); | |||||
++num_results; | |||||
if (!sord_quad_match(pat, id)) { | |||||
sord_iter_free(iter); | |||||
return test_fail( | |||||
"Fail: Query result " TUP_FMT " does not match pattern\n", | |||||
TUP_FMT_ARGS(id)); | |||||
} | |||||
} | |||||
fprintf(stderr, "OK\n"); | |||||
sord_node_free(world, (SordNode*)pat[0]); | |||||
sord_iter_free(iter); | |||||
if (num_results != 2) { | |||||
return test_fail("Blank node subject query failed\n"); | |||||
} | |||||
// Test nested queries | |||||
fprintf(stderr, "Nested Queries... "); | |||||
const SordNode* last_subject = 0; | |||||
iter = sord_search(sord, NULL, NULL, NULL, NULL); | |||||
for (; !sord_iter_end(iter); sord_iter_next(iter)) { | |||||
sord_iter_get(iter, id); | |||||
if (id[0] == last_subject) | |||||
continue; | |||||
SordQuad subpat = { id[0], 0, 0 }; | |||||
SordIter* subiter = sord_find(sord, subpat); | |||||
uint64_t num_sub_results = 0; | |||||
if (sord_iter_get_node(subiter, SORD_SUBJECT) != id[0]) { | |||||
return test_fail("Fail: Incorrect initial submatch\n"); | |||||
} | |||||
for (; !sord_iter_end(subiter); sord_iter_next(subiter)) { | |||||
SordQuad subid; | |||||
sord_iter_get(subiter, subid); | |||||
if (!sord_quad_match(subpat, subid)) { | |||||
sord_iter_free(iter); | |||||
sord_iter_free(subiter); | |||||
return test_fail( | |||||
"Fail: Nested query result does not match pattern\n"); | |||||
} | |||||
++num_sub_results; | |||||
} | |||||
sord_iter_free(subiter); | |||||
if (num_sub_results != n_objects_per) { | |||||
return test_fail( | |||||
"Fail: Nested query " TUP_FMT " failed" | |||||
" (%d results, expected %d)\n", | |||||
TUP_FMT_ARGS(subpat), num_sub_results, n_objects_per); | |||||
} | |||||
uint64_t count = sord_count(sord, id[0], 0, 0, 0); | |||||
if (count != num_sub_results) { | |||||
return test_fail("Fail: Query " TUP_FMT " sord_count() %d" | |||||
"does not match result count %d\n", | |||||
TUP_FMT_ARGS(subpat), count, num_sub_results); | |||||
} | |||||
last_subject = id[0]; | |||||
} | |||||
fprintf(stderr, "OK\n\n"); | |||||
sord_iter_free(iter); | |||||
return ret; | |||||
} | |||||
int | |||||
main(int argc, char** argv) | |||||
{ | |||||
static const size_t n_quads = 300; | |||||
sord_free(NULL); // Shouldn't crash | |||||
SordWorld* world = sord_world_new(); | |||||
// Create with minimal indexing | |||||
SordModel* sord = sord_new(world, SORD_SPO, false); | |||||
generate(world, sord, n_quads, NULL); | |||||
if (test_read(world, sord, NULL, n_quads)) { | |||||
sord_free(sord); | |||||
sord_world_free(world); | |||||
return EXIT_FAILURE; | |||||
} | |||||
// Check adding tuples with NULL fields fails | |||||
const size_t initial_num_quads = sord_num_quads(sord); | |||||
SordQuad tup = { 0, 0, 0, 0}; | |||||
if (sord_add(sord, tup)) { | |||||
return test_fail("Added NULL tuple\n"); | |||||
} | |||||
tup[0] = uri(world, 1); | |||||
if (sord_add(sord, tup)) { | |||||
return test_fail("Added tuple with NULL P and O\n"); | |||||
} | |||||
tup[1] = uri(world, 2); | |||||
if (sord_add(sord, tup)) { | |||||
return test_fail("Added tuple with NULL O\n"); | |||||
} | |||||
if (sord_num_quads(sord) != initial_num_quads) { | |||||
return test_fail("Num quads %zu != %zu\n", | |||||
sord_num_quads(sord), initial_num_quads); | |||||
} | |||||
// Check interning merges equivalent values | |||||
SordNode* uri_id = sord_new_uri(world, USTR("http://example.org")); | |||||
SordNode* blank_id = sord_new_blank(world, USTR("testblank")); | |||||
SordNode* lit_id = sord_new_literal(world, uri_id, USTR("hello"), NULL); | |||||
if (sord_node_get_type(uri_id) != SORD_URI) { | |||||
return test_fail("URI node has incorrect type\n"); | |||||
} else if (sord_node_get_type(blank_id) != SORD_BLANK) { | |||||
return test_fail("Blank node has incorrect type\n"); | |||||
} else if (sord_node_get_type(lit_id) != SORD_LITERAL) { | |||||
return test_fail("Literal node has incorrect type\n"); | |||||
} | |||||
const size_t initial_num_nodes = sord_num_nodes(world); | |||||
SordNode* uri_id2 = sord_new_uri(world, USTR("http://example.org")); | |||||
SordNode* blank_id2 = sord_new_blank(world, USTR("testblank")); | |||||
SordNode* lit_id2 = sord_new_literal(world, uri_id, USTR("hello"), NULL); | |||||
if (uri_id2 != uri_id || !sord_node_equals(uri_id2, uri_id)) { | |||||
fprintf(stderr, "Fail: URI interning failed (duplicates)\n"); | |||||
goto fail; | |||||
} else if (blank_id2 != blank_id | |||||
|| !sord_node_equals(blank_id2, blank_id)) { | |||||
fprintf(stderr, "Fail: Blank node interning failed (duplicates)\n"); | |||||
goto fail; | |||||
} else if (lit_id2 != lit_id || !sord_node_equals(lit_id2, lit_id)) { | |||||
fprintf(stderr, "Fail: Literal interning failed (duplicates)\n"); | |||||
goto fail; | |||||
} | |||||
size_t len; | |||||
const uint8_t* str = sord_node_get_string_counted(lit_id2, &len); | |||||
if (strcmp((const char*)str, "hello")) { | |||||
return test_fail("Literal node corrupt\n"); | |||||
} else if (len != strlen("hello")) { | |||||
return test_fail("Literal length incorrect\n"); | |||||
} | |||||
if (sord_num_nodes(world) != initial_num_nodes) { | |||||
return test_fail("Num nodes %zu != %zu\n", | |||||
sord_num_nodes(world), initial_num_nodes); | |||||
} | |||||
// Check interning doesn't clash non-equivalent values | |||||
SordNode* uri_id3 = sord_new_uri(world, USTR("http://example.orgX")); | |||||
SordNode* blank_id3 = sord_new_blank(world, USTR("testblankX")); | |||||
SordNode* lit_id3 = sord_new_literal(world, uri_id, USTR("helloX"), NULL); | |||||
if (uri_id3 == uri_id || sord_node_equals(uri_id3, uri_id)) { | |||||
fprintf(stderr, "Fail: URI interning failed (clash)\n"); | |||||
goto fail; | |||||
} else if (blank_id3 == blank_id || sord_node_equals(blank_id3, blank_id)) { | |||||
fprintf(stderr, "Fail: Blank node interning failed (clash)\n"); | |||||
goto fail; | |||||
} else if (lit_id3 == lit_id || sord_node_equals(lit_id3, lit_id)) { | |||||
fprintf(stderr, "Fail: Literal interning failed (clash)\n"); | |||||
goto fail; | |||||
} | |||||
// Check literal interning | |||||
SordNode* lit4 = sord_new_literal(world, NULL, USTR("hello"), NULL); | |||||
SordNode* lit5 = sord_new_literal(world, uri_id2, USTR("hello"), NULL); | |||||
SordNode* lit6 = sord_new_literal(world, NULL, USTR("hello"), "en-ca"); | |||||
if (lit4 == lit5 || sord_node_equals(lit4, lit5) | |||||
|| lit4 == lit6 || sord_node_equals(lit4, lit6) | |||||
|| lit5 == lit6 || sord_node_equals(lit5, lit6)) { | |||||
fprintf(stderr, "Fail: Literal interning failed (type/lang clash)\n"); | |||||
goto fail; | |||||
} | |||||
// Check relative URI construction | |||||
SordNode* reluri = sord_new_relative_uri( | |||||
world, USTR("a/b"), USTR("http://example.org/")); | |||||
if (strcmp((const char*)sord_node_get_string(reluri), | |||||
"http://example.org/a/b")) { | |||||
fprintf(stderr, "Fail: Bad relative URI constructed: <%s>\n", | |||||
sord_node_get_string(reluri)); | |||||
goto fail; | |||||
} | |||||
SordNode* reluri2 = sord_new_relative_uri( | |||||
world, USTR("http://drobilla.net/"), USTR("http://example.org/")); | |||||
if (strcmp((const char*)sord_node_get_string(reluri2), | |||||
"http://drobilla.net/")) { | |||||
fprintf(stderr, "Fail: Bad relative URI constructed: <%s>\n", | |||||
sord_node_get_string(reluri)); | |||||
goto fail; | |||||
} | |||||
// Check comparison with NULL | |||||
sord_node_free(world, uri_id); | |||||
sord_node_free(world, blank_id); | |||||
sord_node_free(world, lit_id); | |||||
sord_node_free(world, uri_id2); | |||||
sord_node_free(world, blank_id2); | |||||
sord_node_free(world, lit_id2); | |||||
sord_node_free(world, uri_id3); | |||||
sord_node_free(world, blank_id3); | |||||
sord_node_free(world, lit_id3); | |||||
sord_free(sord); | |||||
static const char* const index_names[6] = { | |||||
"spo", "sop", "ops", "osp", "pso", "pos" | |||||
}; | |||||
for (int i = 0; i < 6; ++i) { | |||||
sord = sord_new(world, (1 << i), false); | |||||
printf("Testing Index `%s'\n", index_names[i]); | |||||
generate(world, sord, n_quads, 0); | |||||
if (test_read(world, sord, 0, n_quads)) | |||||
goto fail; | |||||
sord_free(sord); | |||||
} | |||||
static const char* const graph_index_names[6] = { | |||||
"gspo", "gsop", "gops", "gosp", "gpso", "gpos" | |||||
}; | |||||
for (int i = 0; i < 6; ++i) { | |||||
sord = sord_new(world, (1 << i), true); | |||||
printf("Testing Index `%s'\n", graph_index_names[i]); | |||||
SordNode* graph = uri(world, 42); | |||||
generate(world, sord, n_quads, graph); | |||||
if (test_read(world, sord, graph, n_quads)) | |||||
goto fail; | |||||
sord_free(sord); | |||||
} | |||||
// Test removing | |||||
sord = sord_new(world, SORD_SPO, true); | |||||
tup[0] = uri(world, 1); | |||||
tup[1] = uri(world, 2); | |||||
tup[2] = sord_new_literal(world, 0, USTR("hello"), NULL); | |||||
tup[3] = 0; | |||||
sord_add(sord, tup); | |||||
if (!sord_ask(sord, tup[0], tup[1], tup[2], tup[3])) { | |||||
fprintf(stderr, "Failed to add tuple\n"); | |||||
goto fail; | |||||
} | |||||
sord_node_free(world, (SordNode*)tup[2]); | |||||
tup[2] = sord_new_literal(world, 0, USTR("hi"), NULL); | |||||
sord_add(sord, tup); | |||||
sord_remove(sord, tup); | |||||
if (sord_num_quads(sord) != 1) { | |||||
fprintf(stderr, "Remove failed (%zu quads, expected 1)\n", | |||||
sord_num_quads(sord)); | |||||
goto fail; | |||||
} | |||||
SordIter* iter = sord_find(sord, tup); | |||||
if (!sord_iter_end(iter)) { | |||||
fprintf(stderr, "Found removed tuple\n"); | |||||
goto fail; | |||||
} | |||||
sord_iter_free(iter); | |||||
// Load a couple graphs | |||||
SordNode* graph42 = uri(world, 42); | |||||
SordNode* graph43 = uri(world, 43); | |||||
generate(world, sord, 1, graph42); | |||||
generate(world, sord, 1, graph43); | |||||
// Remove one graph via iterator | |||||
SerdStatus st; | |||||
iter = sord_search(sord, NULL, NULL, NULL, graph43); | |||||
while (!sord_iter_end(iter)) { | |||||
if ((st = sord_erase(sord, iter))) { | |||||
fprintf(stderr, "Remove by iterator failed (%s)\n", | |||||
serd_strerror(st)); | |||||
goto fail; | |||||
} | |||||
} | |||||
sord_iter_free(iter); | |||||
// Ensure only the other graph is left | |||||
SordQuad quad; | |||||
SordQuad pat = { 0, 0, 0, graph42 }; | |||||
for (iter = sord_begin(sord); !sord_iter_end(iter); sord_iter_next(iter)) { | |||||
sord_iter_get(iter, quad); | |||||
if (!sord_quad_match(quad, pat)) { | |||||
fprintf(stderr, "Graph removal via iteration failed\n"); | |||||
goto fail; | |||||
} | |||||
} | |||||
sord_iter_free(iter); | |||||
sord_free(sord); | |||||
sord_world_free(world); | |||||
return EXIT_SUCCESS; | |||||
fail: | |||||
sord_free(sord); | |||||
sord_world_free(world); | |||||
return EXIT_FAILURE; | |||||
} |
@@ -1,746 +0,0 @@ | |||||
/* | |||||
Copyright 2012-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. | |||||
*/ | |||||
#define _BSD_SOURCE // for realpath | |||||
#include <assert.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#ifdef _WIN32 | |||||
# include <windows.h> | |||||
#endif | |||||
#include "serd/serd.h" | |||||
#include "sord/sord.h" | |||||
#include "sord_config.h" | |||||
#ifdef HAVE_PCRE | |||||
# include <pcre.h> | |||||
#endif | |||||
#define USTR(s) ((const uint8_t*)s) | |||||
#define NS_foaf (const uint8_t*)"http://xmlns.com/foaf/0.1/" | |||||
#define NS_owl (const uint8_t*)"http://www.w3.org/2002/07/owl#" | |||||
#define NS_rdf (const uint8_t*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||||
#define NS_rdfs (const uint8_t*)"http://www.w3.org/2000/01/rdf-schema#" | |||||
#define NS_xsd (const uint8_t*)"http://www.w3.org/2001/XMLSchema#" | |||||
typedef struct { | |||||
SordNode* foaf_Document; | |||||
SordNode* owl_AnnotationProperty; | |||||
SordNode* owl_Class; | |||||
SordNode* owl_DatatypeProperty; | |||||
SordNode* owl_FunctionalProperty; | |||||
SordNode* owl_InverseFunctionalProperty; | |||||
SordNode* owl_ObjectProperty; | |||||
SordNode* owl_OntologyProperty; | |||||
SordNode* owl_Restriction; | |||||
SordNode* owl_Thing; | |||||
SordNode* owl_cardinality; | |||||
SordNode* owl_equivalentClass; | |||||
SordNode* owl_minCardinality; | |||||
SordNode* owl_onDatatype; | |||||
SordNode* owl_onProperty; | |||||
SordNode* owl_someValuesFrom; | |||||
SordNode* owl_withRestrictions; | |||||
SordNode* rdf_PlainLiteral; | |||||
SordNode* rdf_Property; | |||||
SordNode* rdf_first; | |||||
SordNode* rdf_rest; | |||||
SordNode* rdf_type; | |||||
SordNode* rdfs_Class; | |||||
SordNode* rdfs_Literal; | |||||
SordNode* rdfs_Resource; | |||||
SordNode* rdfs_domain; | |||||
SordNode* rdfs_label; | |||||
SordNode* rdfs_range; | |||||
SordNode* rdfs_subClassOf; | |||||
SordNode* xsd_anyURI; | |||||
SordNode* xsd_decimal; | |||||
SordNode* xsd_maxInclusive; | |||||
SordNode* xsd_minInclusive; | |||||
SordNode* xsd_pattern; | |||||
SordNode* xsd_string; | |||||
} URIs; | |||||
int n_errors = 0; | |||||
int n_restrictions = 0; | |||||
bool one_line_errors = false; | |||||
static int | |||||
print_version(void) | |||||
{ | |||||
printf("sord_validate " SORD_VERSION | |||||
" <http://drobilla.net/software/sord>\n"); | |||||
printf("Copyright 2012-2013 David Robillard <http://drobilla.net>.\n" | |||||
"License: <http://www.opensource.org/licenses/isc>\n" | |||||
"This is free software; you are free to change and redistribute it." | |||||
"\nThere is NO WARRANTY, to the extent permitted by law.\n"); | |||||
return 0; | |||||
} | |||||
static int | |||||
print_usage(const char* name, bool error) | |||||
{ | |||||
FILE* const os = error ? stderr : stdout; | |||||
fprintf(os, "Usage: %s [OPTION]... INPUT...\n", name); | |||||
fprintf(os, "Validate RDF data\n\n"); | |||||
fprintf(os, " -h Display this help and exit\n"); | |||||
fprintf(os, " -l Print errors on a single line.\n"); | |||||
fprintf(os, " -v Display version information and exit\n"); | |||||
fprintf(os, | |||||
"Validate RDF data. This is a simple validator which checks\n" | |||||
"that all used properties are actually defined. It does not do\n" | |||||
"any fancy file retrieval, the files passed on the command line\n" | |||||
"are the only data that is read. In other words, you must pass\n" | |||||
"the definition of all vocabularies used on the command line.\n"); | |||||
return error ? 1 : 0; | |||||
} | |||||
static uint8_t* | |||||
absolute_path(const uint8_t* path) | |||||
{ | |||||
#ifdef _WIN32 | |||||
char* out = (char*)malloc(MAX_PATH); | |||||
GetFullPathName((const char*)path, MAX_PATH, out, NULL); | |||||
return (uint8_t*)out; | |||||
#else | |||||
return (uint8_t*)realpath((const char*)path, NULL); | |||||
#endif | |||||
} | |||||
static int | |||||
error(const char* msg, const SordQuad quad) | |||||
{ | |||||
const char* sep = one_line_errors ? "\t" : "\n "; | |||||
++n_errors; | |||||
fprintf(stderr, "error: %s:%s%s%s%s%s%s\n", | |||||
msg, | |||||
sep, (const char*)sord_node_get_string(quad[SORD_SUBJECT]), | |||||
sep, (const char*)sord_node_get_string(quad[SORD_PREDICATE]), | |||||
sep, (const char*)sord_node_get_string(quad[SORD_OBJECT])); | |||||
return 1; | |||||
} | |||||
static int | |||||
errorf(const char* fmt, ...) | |||||
{ | |||||
va_list args; | |||||
va_start(args, fmt); | |||||
vfprintf(stderr, fmt, args); | |||||
va_end(args); | |||||
return 1; | |||||
} | |||||
static bool | |||||
is_descendant_of(SordModel* model, | |||||
const URIs* uris, | |||||
const SordNode* child, | |||||
const SordNode* parent, | |||||
const SordNode* pred) | |||||
{ | |||||
if (!child) { | |||||
return false; | |||||
} else if (sord_node_equals(child, parent) || | |||||
sord_ask(model, child, uris->owl_equivalentClass, parent, NULL)) { | |||||
return true; | |||||
} | |||||
SordIter* i = sord_search(model, child, pred, NULL, NULL); | |||||
for (; !sord_iter_end(i); sord_iter_next(i)) { | |||||
const SordNode* o = sord_iter_get_node(i, SORD_OBJECT); | |||||
if (sord_node_equals(child, o)) { | |||||
continue; // Weird class is explicitly a descendent of itself | |||||
} | |||||
if (is_descendant_of(model, uris, o, parent, pred)) { | |||||
sord_iter_free(i); | |||||
return true; | |||||
} | |||||
} | |||||
sord_iter_free(i); | |||||
return false; | |||||
} | |||||
static bool | |||||
regexp_match(const uint8_t* pat, const char* str) | |||||
{ | |||||
#ifdef HAVE_PCRE | |||||
// Append a $ to the pattern so we only match if the entire string matches | |||||
const size_t len = strlen((const char*)pat); | |||||
char* const regx = (char*)malloc(len + 2); | |||||
memcpy(regx, pat, len); | |||||
regx[len] = '$'; | |||||
regx[len + 1] = '\0'; | |||||
const char* err; | |||||
int erroffset; | |||||
pcre* re = pcre_compile(regx, PCRE_ANCHORED, &err, &erroffset, NULL); | |||||
free(regx); | |||||
if (!re) { | |||||
fprintf(stderr, "Error in pattern `%s' at offset %d (%s)\n", | |||||
pat, erroffset, err); | |||||
return false; | |||||
} | |||||
const bool ret = pcre_exec(re, NULL, str, strlen(str), 0, 0, NULL, 0) >= 0; | |||||
pcre_free(re); | |||||
return ret; | |||||
#endif // HAVE_PCRE | |||||
return true; | |||||
} | |||||
static bool | |||||
check_restriction(SordModel* model, | |||||
const URIs* uris, | |||||
const SordNode* literal, | |||||
const SordNode* type, | |||||
const SordNode* restriction) | |||||
{ | |||||
size_t len = 0; | |||||
const char* str = (const char*)sord_node_get_string_counted(literal, &len); | |||||
++n_restrictions; | |||||
// Check xsd:pattern | |||||
SordIter* p = sord_search(model, restriction, uris->xsd_pattern, 0, 0); | |||||
if (p) { | |||||
const SordNode* pat = sord_iter_get_node(p, SORD_OBJECT); | |||||
const bool good = regexp_match(sord_node_get_string(pat), str); | |||||
if (!good) { | |||||
fprintf(stderr, "`%s' does not match <%s> pattern `%s'\n", | |||||
sord_node_get_string(literal), | |||||
sord_node_get_string(type), | |||||
sord_node_get_string(pat)); | |||||
} | |||||
sord_iter_free(p); | |||||
return good; | |||||
} | |||||
/* We'll do some comparison tricks for xsd:decimal types, where | |||||
lexicographical comparison would be incorrect. Note that if the | |||||
literal's type is a descendant of xsd:decimal, we'll end up checking it | |||||
against the xsd:decimal pattern so there's no need to validate digits | |||||
here. At worst we'll get a false positive but it will fail later. */ | |||||
const bool is_decimal = is_descendant_of( | |||||
model, uris, type, uris->xsd_decimal, uris->owl_onDatatype); | |||||
// Check xsd:minInclusive | |||||
SordIter* l = sord_search(model, restriction, uris->xsd_minInclusive, 0, 0); | |||||
if (l) { | |||||
const SordNode* lower = sord_iter_get_node(l, SORD_OBJECT); | |||||
size_t lower_len = 0; | |||||
const char* lower_str = (const char*)sord_node_get_string_counted(lower, &lower_len); | |||||
bool good = false; | |||||
if (!is_decimal || len == lower_len) { | |||||
// Not decimal, or equal lengths, strcmp | |||||
good = (strcmp(str, lower_str) >= 0); | |||||
} else { | |||||
// Decimal with different length, only good if longer than the min | |||||
good = (len > lower_len); | |||||
} | |||||
if (!good) { | |||||
fprintf(stderr, "`%s' is not >= <%s> minimum `%s'\n", | |||||
sord_node_get_string(literal), | |||||
sord_node_get_string(type), | |||||
sord_node_get_string(lower)); | |||||
} | |||||
sord_iter_free(l); | |||||
return good; | |||||
} | |||||
// Check xsd:maxInclusive | |||||
SordIter* u = sord_search(model, restriction, uris->xsd_maxInclusive, 0, 0); | |||||
if (u) { | |||||
const SordNode* upper = sord_iter_get_node(u, SORD_OBJECT); | |||||
size_t upper_len = 0; | |||||
const char* upper_str = (const char*)sord_node_get_string_counted(upper, &upper_len); | |||||
bool good = false; | |||||
if (!is_decimal || len == upper_len) { | |||||
// Not decimal, or equal lengths, strcmp | |||||
good = (strcmp(str, upper_str) <= 0); | |||||
} else { | |||||
// Decimal with different length, only good if shorter than the max | |||||
good = (len < upper_len); | |||||
} | |||||
if (!good) { | |||||
fprintf(stderr, "`%s' is not <= <%s> maximum `%s'\n", | |||||
sord_node_get_string(literal), | |||||
sord_node_get_string(type), | |||||
sord_node_get_string(upper)); | |||||
} | |||||
sord_iter_free(u); | |||||
return good; | |||||
} | |||||
--n_restrictions; | |||||
return true; // Unknown restriction, be quietly tolerant | |||||
} | |||||
static bool | |||||
literal_is_valid(SordModel* model, | |||||
const URIs* uris, | |||||
const SordNode* literal, | |||||
const SordNode* type) | |||||
{ | |||||
if (!type) { | |||||
return true; | |||||
} | |||||
/* Check that literal data is related to required type. We don't do a | |||||
strict subtype check here because e.g. an xsd:decimal might be a valid | |||||
xsd:unsignedInt, which the pattern checks will verify, but if the | |||||
literal type is not related to the required type at all | |||||
(e.g. xsd:decimal and xsd:string) there is a problem. */ | |||||
const SordNode* datatype = sord_node_get_datatype(literal); | |||||
if (datatype && datatype != type) { | |||||
if (!is_descendant_of( | |||||
model, uris, | |||||
datatype, type, uris->owl_onDatatype) && | |||||
!is_descendant_of( | |||||
model, uris, | |||||
type, datatype, uris->owl_onDatatype)) { | |||||
errorf("Literal `%s' datatype <%s> is not compatible with <%s>\n", | |||||
sord_node_get_string(literal), | |||||
sord_node_get_string(datatype), | |||||
sord_node_get_string(type)); | |||||
return false; | |||||
} | |||||
} | |||||
// Find restrictions list | |||||
SordIter* rs = sord_search(model, type, uris->owl_withRestrictions, 0, 0); | |||||
if (sord_iter_end(rs)) { | |||||
return true; // No restrictions | |||||
} | |||||
// Walk list, checking each restriction | |||||
const SordNode* head = sord_iter_get_node(rs, SORD_OBJECT); | |||||
while (head) { | |||||
SordIter* f = sord_search(model, head, uris->rdf_first, 0, 0); | |||||
if (!f) { | |||||
break; // Reached end of restrictions list without failure | |||||
} | |||||
// Check this restriction | |||||
const bool good = check_restriction( | |||||
model, uris, literal, type, sord_iter_get_node(f, SORD_OBJECT)); | |||||
sord_iter_free(f); | |||||
if (!good) { | |||||
sord_iter_free(rs); | |||||
return false; // Failed, literal is invalid | |||||
} | |||||
// Seek to next list node | |||||
SordIter* n = sord_search(model, head, uris->rdf_rest, 0, 0); | |||||
head = n ? sord_iter_get_node(n, SORD_OBJECT) : NULL; | |||||
sord_iter_free(n); | |||||
} | |||||
sord_iter_free(rs); | |||||
SordIter* s = sord_search(model, type, uris->owl_onDatatype, 0, 0); | |||||
if (s) { | |||||
const SordNode* super = sord_iter_get_node(s, SORD_OBJECT); | |||||
const bool good = literal_is_valid(model, uris, literal, super); | |||||
sord_iter_free(s); | |||||
return good; // Match iff literal also matches supertype | |||||
} | |||||
return true; // Matches top level type | |||||
} | |||||
static bool | |||||
check_type(SordModel* model, | |||||
const URIs* uris, | |||||
const SordNode* node, | |||||
const SordNode* type) | |||||
{ | |||||
if (sord_node_equals(type, uris->rdfs_Resource) || | |||||
sord_node_equals(type, uris->owl_Thing)) { | |||||
return true; | |||||
} | |||||
if (sord_node_get_type(node) == SORD_LITERAL) { | |||||
if (sord_node_equals(type, uris->rdfs_Literal)) { | |||||
return true; | |||||
} else if (sord_node_equals(type, uris->rdf_PlainLiteral)) { | |||||
return !sord_node_get_language(node); | |||||
} else { | |||||
return literal_is_valid(model, uris, node, type); | |||||
} | |||||
} else if (sord_node_get_type(node) == SORD_URI) { | |||||
if (sord_node_equals(type, uris->foaf_Document)) { | |||||
return true; // Questionable... | |||||
} else if (is_descendant_of( | |||||
model, uris, | |||||
type, uris->xsd_anyURI, uris->owl_onDatatype)) { | |||||
/* Type is any URI and this is a URI, so pass. Restrictions on | |||||
anyURI subtypes are not currently checked (very uncommon). */ | |||||
return true; // Type is anyURI, and this is a URI | |||||
} else { | |||||
SordIter* t = sord_search(model, node, uris->rdf_type, NULL, NULL); | |||||
for (; !sord_iter_end(t); sord_iter_next(t)) { | |||||
if (is_descendant_of(model, uris, | |||||
sord_iter_get_node(t, SORD_OBJECT), | |||||
type, | |||||
uris->rdfs_subClassOf)) { | |||||
sord_iter_free(t); | |||||
return true; | |||||
} | |||||
} | |||||
sord_iter_free(t); | |||||
return false; | |||||
} | |||||
} else { | |||||
return true; // Blanks often lack explicit types, ignore | |||||
} | |||||
return false; | |||||
} | |||||
static int | |||||
check_properties(SordModel* model, URIs* uris) | |||||
{ | |||||
int st = 0; | |||||
SordIter* i = sord_begin(model); | |||||
for (; !sord_iter_end(i); sord_iter_next(i)) { | |||||
SordQuad quad; | |||||
sord_iter_get(i, quad); | |||||
const SordNode* subj = quad[SORD_SUBJECT]; | |||||
const SordNode* pred = quad[SORD_PREDICATE]; | |||||
const SordNode* obj = quad[SORD_OBJECT]; | |||||
bool is_any_property = false; | |||||
SordIter* t = sord_search(model, pred, uris->rdf_type, NULL, NULL); | |||||
for (; !sord_iter_end(t); sord_iter_next(t)) { | |||||
if (is_descendant_of(model, uris, | |||||
sord_iter_get_node(t, SORD_OBJECT), | |||||
uris->rdf_Property, | |||||
uris->rdfs_subClassOf)) { | |||||
is_any_property = true; | |||||
break; | |||||
} | |||||
} | |||||
sord_iter_free(t); | |||||
const bool is_ObjectProperty = sord_ask( | |||||
model, pred, uris->rdf_type, uris->owl_ObjectProperty, 0); | |||||
const bool is_FunctionalProperty = sord_ask( | |||||
model, pred, uris->rdf_type, uris->owl_FunctionalProperty, 0); | |||||
const bool is_InverseFunctionalProperty = sord_ask( | |||||
model, pred, uris->rdf_type, uris->owl_InverseFunctionalProperty, 0); | |||||
const bool is_DatatypeProperty = sord_ask( | |||||
model, pred, uris->rdf_type, uris->owl_DatatypeProperty, 0); | |||||
if (!is_any_property) { | |||||
st = error("Use of undefined property", quad); | |||||
} | |||||
if (!sord_ask(model, pred, uris->rdfs_label, NULL, NULL)) { | |||||
st = errorf("Property <%s> has no label\n", | |||||
sord_node_get_string(pred)); | |||||
} | |||||
if (is_DatatypeProperty && | |||||
sord_node_get_type(obj) != SORD_LITERAL) { | |||||
st = error("Datatype property with non-literal value", quad); | |||||
} | |||||
if (is_ObjectProperty && | |||||
sord_node_get_type(obj) == SORD_LITERAL) { | |||||
st = error("Object property with literal value", quad); | |||||
} | |||||
if (is_FunctionalProperty && | |||||
sord_count(model, subj, pred, NULL, NULL) > 1) { | |||||
st = error("Functional property with several objects", quad); | |||||
} | |||||
if (is_InverseFunctionalProperty && | |||||
sord_count(model, NULL, pred, obj, NULL) > 1) { | |||||
st = error("Inverse functional property with several subjects", quad); | |||||
} | |||||
if (sord_node_equals(pred, uris->rdf_type) && | |||||
!sord_ask(model, obj, uris->rdf_type, uris->rdfs_Class, NULL) && | |||||
!sord_ask(model, obj, uris->rdf_type, uris->owl_Class, NULL)) { | |||||
st = error("Type is not a rdfs:Class or owl:Class", quad); | |||||
} | |||||
if (sord_node_get_type(obj) == SORD_LITERAL && | |||||
!literal_is_valid(model, uris, obj, sord_node_get_datatype(obj))) { | |||||
st = error("Literal does not match datatype", quad); | |||||
} | |||||
SordIter* r = sord_search(model, pred, uris->rdfs_range, NULL, NULL); | |||||
for (; !sord_iter_end(r); sord_iter_next(r)) { | |||||
const SordNode* range = sord_iter_get_node(r, SORD_OBJECT); | |||||
if (!check_type(model, uris, obj, range)) { | |||||
st = error("Object not in property range", quad); | |||||
fprintf(stderr, "note: Range is <%s>\n", | |||||
sord_node_get_string(range)); | |||||
} | |||||
} | |||||
sord_iter_free(r); | |||||
SordIter* d = sord_search(model, pred, uris->rdfs_domain, NULL, NULL); | |||||
if (d) { | |||||
const SordNode* domain = sord_iter_get_node(d, SORD_OBJECT); | |||||
if (!check_type(model, uris, subj, domain)) { | |||||
st = error("Subject not in property domain", quad); | |||||
fprintf(stderr, "note: Domain is <%s>\n", | |||||
sord_node_get_string(domain)); | |||||
} | |||||
sord_iter_free(d); | |||||
} | |||||
} | |||||
sord_iter_free(i); | |||||
return st; | |||||
} | |||||
static int | |||||
check_instance(SordModel* model, | |||||
const URIs* uris, | |||||
const SordNode* restriction, | |||||
const SordNode* instance) | |||||
{ | |||||
int st = 0; | |||||
const SordNode* prop = sord_get( | |||||
model, restriction, uris->owl_onProperty, NULL, NULL); | |||||
if (!prop) { | |||||
return 0; | |||||
} | |||||
const unsigned values = sord_count(model, instance, prop, NULL, NULL); | |||||
// Check exact cardinality | |||||
const SordNode* card = sord_get( | |||||
model, restriction, uris->owl_cardinality, NULL, NULL); | |||||
if (card) { | |||||
const unsigned c = atoi((const char*)sord_node_get_string(card)); | |||||
if (values != c) { | |||||
st = errorf("Property %s on %s has %u != %u values\n", | |||||
sord_node_get_string(prop), | |||||
sord_node_get_string(instance), | |||||
values, c); | |||||
} | |||||
} | |||||
// Check minimum cardinality | |||||
const SordNode* minCard = sord_get( | |||||
model, restriction, uris->owl_minCardinality, NULL, NULL); | |||||
if (minCard) { | |||||
const unsigned m = atoi((const char*)sord_node_get_string(minCard)); | |||||
if (values < m) { | |||||
st = errorf("Property %s on %s has %u < %u values\n", | |||||
sord_node_get_string(prop), | |||||
sord_node_get_string(instance), | |||||
values, m); | |||||
} | |||||
} | |||||
// Check someValuesFrom | |||||
SordIter* sf = sord_search( | |||||
model, restriction, uris->owl_someValuesFrom, NULL, NULL); | |||||
if (sf) { | |||||
const SordNode* type = sord_iter_get_node(sf, SORD_OBJECT); | |||||
SordIter* v = sord_search(model, instance, prop, NULL, NULL); | |||||
bool found = false; | |||||
for (; !sord_iter_end(v); sord_iter_next(v)) { | |||||
const SordNode* value = sord_iter_get_node(v, SORD_OBJECT); | |||||
if (check_type(model, uris, value, type)) { | |||||
found = true; | |||||
break; | |||||
} | |||||
} | |||||
if (!found) { | |||||
st = errorf("%s has no <%s> values of type <%s>\n", | |||||
sord_node_get_string(instance), | |||||
sord_node_get_string(prop), | |||||
sord_node_get_string(type)); | |||||
} | |||||
sord_iter_free(v); | |||||
} | |||||
sord_iter_free(sf); | |||||
return st; | |||||
} | |||||
static int | |||||
check_class_instances(SordModel* model, | |||||
const URIs* uris, | |||||
const SordNode* restriction, | |||||
const SordNode* klass) | |||||
{ | |||||
// Check immediate instances of this class | |||||
SordIter* i = sord_search(model, NULL, uris->rdf_type, klass, NULL); | |||||
for (; !sord_iter_end(i); sord_iter_next(i)) { | |||||
const SordNode* instance = sord_iter_get_node(i, SORD_SUBJECT); | |||||
check_instance(model, uris, restriction, instance); | |||||
} | |||||
sord_iter_free(i); | |||||
// Check instances of all subclasses recursively | |||||
SordIter* s = sord_search(model, NULL, uris->rdfs_subClassOf, klass, NULL); | |||||
for (; !sord_iter_end(s); sord_iter_next(s)) { | |||||
const SordNode* subklass = sord_iter_get_node(s, SORD_SUBJECT); | |||||
check_class_instances(model, uris, restriction, subklass); | |||||
} | |||||
sord_iter_free(s); | |||||
return 0; | |||||
} | |||||
static int | |||||
check_instances(SordModel* model, const URIs* uris) | |||||
{ | |||||
int st = 0; | |||||
SordIter* r = sord_search( | |||||
model, NULL, uris->rdf_type, uris->owl_Restriction, NULL); | |||||
for (; !sord_iter_end(r); sord_iter_next(r)) { | |||||
const SordNode* restriction = sord_iter_get_node(r, SORD_SUBJECT); | |||||
const SordNode* prop = sord_get( | |||||
model, restriction, uris->owl_onProperty, NULL, NULL); | |||||
if (!prop) { | |||||
continue; | |||||
} | |||||
SordIter* c = sord_search( | |||||
model, NULL, uris->rdfs_subClassOf, restriction, NULL); | |||||
for (; !sord_iter_end(c); sord_iter_next(c)) { | |||||
const SordNode* klass = sord_iter_get_node(c, SORD_SUBJECT); | |||||
check_class_instances(model, uris, restriction, klass); | |||||
} | |||||
sord_iter_free(c); | |||||
} | |||||
sord_iter_free(r); | |||||
return st; | |||||
} | |||||
int | |||||
main(int argc, char** argv) | |||||
{ | |||||
if (argc < 2) { | |||||
return print_usage(argv[0], true); | |||||
} | |||||
int a = 1; | |||||
for (; a < argc && argv[a][0] == '-'; ++a) { | |||||
if (argv[a][1] == 'l') { | |||||
one_line_errors = true; | |||||
} else if (argv[a][1] == 'v') { | |||||
return print_version(); | |||||
} else { | |||||
fprintf(stderr, "%s: Unknown option `%s'\n", argv[0], argv[a]); | |||||
return print_usage(argv[0], true); | |||||
} | |||||
} | |||||
SordWorld* world = sord_world_new(); | |||||
SordModel* model = sord_new(world, SORD_SPO|SORD_OPS, false); | |||||
SerdEnv* env = serd_env_new(&SERD_NODE_NULL); | |||||
SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); | |||||
for (; a < argc; ++a) { | |||||
const uint8_t* input = (const uint8_t*)argv[a]; | |||||
uint8_t* in_path = absolute_path(serd_uri_to_path(input)); | |||||
if (!in_path) { | |||||
fprintf(stderr, "Skipping file %s\n", input); | |||||
continue; | |||||
} | |||||
SerdURI base_uri; | |||||
SerdNode base_uri_node = serd_node_new_file_uri( | |||||
in_path, NULL, &base_uri, false); | |||||
serd_env_set_base_uri(env, &base_uri_node); | |||||
const SerdStatus st = serd_reader_read_file(reader, in_path); | |||||
if (st) { | |||||
fprintf(stderr, "error reading %s: %s\n", | |||||
in_path, serd_strerror(st)); | |||||
} | |||||
serd_node_free(&base_uri_node); | |||||
free(in_path); | |||||
} | |||||
serd_reader_free(reader); | |||||
serd_env_free(env); | |||||
#define URI(prefix, suffix) \ | |||||
uris.prefix##_##suffix = sord_new_uri(world, NS_##prefix #suffix) | |||||
URIs uris; | |||||
URI(foaf, Document); | |||||
URI(owl, AnnotationProperty); | |||||
URI(owl, Class); | |||||
URI(owl, DatatypeProperty); | |||||
URI(owl, FunctionalProperty); | |||||
URI(owl, InverseFunctionalProperty); | |||||
URI(owl, ObjectProperty); | |||||
URI(owl, OntologyProperty); | |||||
URI(owl, Restriction); | |||||
URI(owl, Thing); | |||||
URI(owl, cardinality); | |||||
URI(owl, equivalentClass); | |||||
URI(owl, minCardinality); | |||||
URI(owl, onDatatype); | |||||
URI(owl, onProperty); | |||||
URI(owl, someValuesFrom); | |||||
URI(owl, withRestrictions); | |||||
URI(rdf, PlainLiteral); | |||||
URI(rdf, Property); | |||||
URI(rdf, first); | |||||
URI(rdf, rest); | |||||
URI(rdf, type); | |||||
URI(rdfs, Class); | |||||
URI(rdfs, Literal); | |||||
URI(rdfs, Resource); | |||||
URI(rdfs, domain); | |||||
URI(rdfs, label); | |||||
URI(rdfs, range); | |||||
URI(rdfs, subClassOf); | |||||
URI(xsd, anyURI); | |||||
URI(xsd, decimal); | |||||
URI(xsd, maxInclusive); | |||||
URI(xsd, minInclusive); | |||||
URI(xsd, pattern); | |||||
URI(xsd, string); | |||||
#ifndef HAVE_PCRE | |||||
fprintf(stderr, "warning: Built without PCRE, datatypes not checked.\n"); | |||||
#endif | |||||
const int prop_st = check_properties(model, &uris); | |||||
const int inst_st = check_instances(model, &uris); | |||||
printf("Found %d errors among %d files (checked %d restrictions)\n", | |||||
n_errors, argc - 1, n_restrictions); | |||||
sord_free(model); | |||||
sord_world_free(world); | |||||
return prop_st || inst_st; | |||||
} |
@@ -1,215 +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. | |||||
*/ | |||||
#define _BSD_SOURCE // for realpath | |||||
#include <assert.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#ifdef _WIN32 | |||||
# include <windows.h> | |||||
#endif | |||||
#include "serd/serd.h" | |||||
#include "sord/sord.h" | |||||
#include "sord_config.h" | |||||
typedef struct { | |||||
SerdWriter* writer; | |||||
SerdEnv* env; | |||||
SerdNode base_uri_node; | |||||
SerdURI base_uri; | |||||
SordModel* sord; | |||||
} State; | |||||
static int | |||||
print_version(void) | |||||
{ | |||||
printf("sordi " SORD_VERSION " <http://drobilla.net/software/sord>\n"); | |||||
printf("Copyright 2011-2013 David Robillard <http://drobilla.net>.\n" | |||||
"License: <http://www.opensource.org/licenses/isc>\n" | |||||
"This is free software; you are free to change and redistribute it." | |||||
"\nThere is NO WARRANTY, to the extent permitted by law.\n"); | |||||
return 0; | |||||
} | |||||
static int | |||||
print_usage(const char* name, bool error) | |||||
{ | |||||
FILE* const os = error ? stderr : stdout; | |||||
fprintf(os, "Usage: %s [OPTION]... INPUT [BASE_URI]\n", name); | |||||
fprintf(os, "Load and re-serialise RDF data.\n"); | |||||
fprintf(os, "Use - for INPUT to read from standard input.\n\n"); | |||||
fprintf(os, " -h Display this help and exit\n"); | |||||
fprintf(os, " -i SYNTAX Input syntax (`turtle' or `ntriples')\n"); | |||||
fprintf(os, " -o SYNTAX Output syntax (`turtle' or `ntriples')\n"); | |||||
fprintf(os, " -s INPUT Parse INPUT as string (terminates options)\n"); | |||||
fprintf(os, " -v Display version information and exit\n"); | |||||
return error ? 1 : 0; | |||||
} | |||||
static bool | |||||
set_syntax(SerdSyntax* syntax, const char* name) | |||||
{ | |||||
if (!strcmp(name, "turtle")) { | |||||
*syntax = SERD_TURTLE; | |||||
} else if (!strcmp(name, "ntriples")) { | |||||
*syntax = SERD_NTRIPLES; | |||||
} else { | |||||
fprintf(stderr, "Unknown input format `%s'\n", name); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
static uint8_t* | |||||
absolute_path(const uint8_t* path) | |||||
{ | |||||
#ifdef _WIN32 | |||||
char* out = (char*)malloc(MAX_PATH); | |||||
GetFullPathName((const char*)path, MAX_PATH, out, NULL); | |||||
return (uint8_t*)out; | |||||
#else | |||||
return (uint8_t*)realpath((const char*)path, NULL); | |||||
#endif | |||||
} | |||||
int | |||||
main(int argc, char** argv) | |||||
{ | |||||
if (argc < 2) { | |||||
return print_usage(argv[0], true); | |||||
} | |||||
FILE* in_fd = NULL; | |||||
SerdSyntax input_syntax = SERD_TURTLE; | |||||
SerdSyntax output_syntax = SERD_NTRIPLES; | |||||
bool from_file = true; | |||||
const uint8_t* in_name = NULL; | |||||
int a = 1; | |||||
for (; a < argc && argv[a][0] == '-'; ++a) { | |||||
if (argv[a][1] == '\0') { | |||||
in_name = (const uint8_t*)"(stdin)"; | |||||
in_fd = stdin; | |||||
break; | |||||
} else if (argv[a][1] == 'h') { | |||||
return print_usage(argv[0], false); | |||||
} else if (argv[a][1] == 'v') { | |||||
return print_version(); | |||||
} else if (argv[a][1] == 's') { | |||||
in_name = (const uint8_t*)"(string)"; | |||||
from_file = false; | |||||
++a; | |||||
break; | |||||
} else if (argv[a][1] == 'i') { | |||||
if (++a == argc) { | |||||
fprintf(stderr, "Missing value for -i\n"); | |||||
return 1; | |||||
} | |||||
if (!set_syntax(&input_syntax, argv[a])) { | |||||
return 1; | |||||
} | |||||
} else if (argv[a][1] == 'o') { | |||||
if (++a == argc) { | |||||
fprintf(stderr, "Missing value for -o\n"); | |||||
return 1; | |||||
} | |||||
if (!set_syntax(&output_syntax, argv[a])) { | |||||
return 1; | |||||
} | |||||
} else { | |||||
fprintf(stderr, "Unknown option `%s'\n", argv[a]); | |||||
return print_usage(argv[0], true); | |||||
} | |||||
} | |||||
if (a == argc) { | |||||
fprintf(stderr, "Missing input\n"); | |||||
return 1; | |||||
} | |||||
const uint8_t* input = (const uint8_t*)argv[a++]; | |||||
uint8_t* in_path = NULL; | |||||
if (from_file) { | |||||
in_name = in_name ? in_name : input; | |||||
if (!in_fd) { | |||||
in_path = absolute_path(serd_uri_to_path(in_name)); | |||||
if (!in_path || !(in_fd = fopen((const char*)in_path, "rb"))) { | |||||
return 1; | |||||
} | |||||
} | |||||
} | |||||
SerdURI base_uri = SERD_URI_NULL; | |||||
SerdNode base_uri_node = SERD_NODE_NULL; | |||||
if (a < argc) { // Base URI given on command line | |||||
base_uri_node = serd_node_new_uri_from_string( | |||||
(const uint8_t*)argv[a], NULL, &base_uri); | |||||
} else if (from_file) { // Use input file URI | |||||
base_uri_node = serd_node_new_file_uri(in_path, NULL, &base_uri, false); | |||||
} | |||||
if (!base_uri_node.buf) { | |||||
fprintf(stderr, "Missing base URI\n"); | |||||
return 1; | |||||
} | |||||
SordWorld* world = sord_world_new(); | |||||
SordModel* sord = sord_new(world, SORD_SPO|SORD_OPS, false); | |||||
SerdEnv* env = serd_env_new(&base_uri_node); | |||||
SerdReader* reader = sord_new_reader(sord, env, input_syntax, NULL); | |||||
const SerdStatus status = (from_file) | |||||
? serd_reader_read_file_handle(reader, in_fd, in_name) | |||||
: serd_reader_read_string(reader, input); | |||||
serd_reader_free(reader); | |||||
SerdEnv* write_env = serd_env_new(&base_uri_node); | |||||
int output_style = SERD_STYLE_RESOLVED; | |||||
if (output_syntax == SERD_NTRIPLES) { | |||||
output_style |= SERD_STYLE_ASCII; | |||||
} else { | |||||
output_style |= SERD_STYLE_CURIED | SERD_STYLE_ABBREVIATED; | |||||
} | |||||
SerdWriter* writer = serd_writer_new( | |||||
output_syntax, | |||||
(SerdStyle)output_style, | |||||
write_env, &base_uri, serd_file_sink, stdout); | |||||
// Write @prefix directives | |||||
serd_env_foreach(env, | |||||
(SerdPrefixSink)serd_writer_set_prefix, | |||||
writer); | |||||
// Write statements | |||||
sord_write(sord, writer, NULL); | |||||
serd_writer_finish(writer); | |||||
serd_writer_free(writer); | |||||
serd_env_free(env); | |||||
serd_env_free(write_env); | |||||
serd_node_free(&base_uri_node); | |||||
sord_free(sord); | |||||
sord_world_free(world); | |||||
return (status > SERD_FAILURE) ? 1 : 0; | |||||
} |
@@ -1,25 +0,0 @@ | |||||
/* | |||||
Copyright 2011 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. | |||||
*/ | |||||
#include "sord/sordmm.hpp" | |||||
int | |||||
main(int argc, char** argv) | |||||
{ | |||||
Sord::World world; | |||||
Sord::Model model(world, "http://example.org/"); | |||||
return 0; | |||||
} |
@@ -1,205 +0,0 @@ | |||||
/* | |||||
Copyright 2011-2012 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. | |||||
*/ | |||||
#include <assert.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include "serd/serd.h" | |||||
#include "sord_config.h" | |||||
#include "sord_internal.h" | |||||
struct SordInserterImpl { | |||||
SordModel* model; | |||||
SerdEnv* env; | |||||
}; | |||||
SordInserter* | |||||
sord_inserter_new(SordModel* model, | |||||
SerdEnv* env) | |||||
{ | |||||
SordInserter* inserter = (SordInserter*)malloc(sizeof(SordInserter)); | |||||
inserter->model = model; | |||||
inserter->env = env; | |||||
return inserter; | |||||
} | |||||
void | |||||
sord_inserter_free(SordInserter* inserter) | |||||
{ | |||||
free(inserter); | |||||
} | |||||
SerdStatus | |||||
sord_inserter_set_base_uri(SordInserter* inserter, | |||||
const SerdNode* uri_node) | |||||
{ | |||||
return serd_env_set_base_uri(inserter->env, uri_node); | |||||
} | |||||
SerdStatus | |||||
sord_inserter_set_prefix(SordInserter* inserter, | |||||
const SerdNode* name, | |||||
const SerdNode* uri_node) | |||||
{ | |||||
return serd_env_set_prefix(inserter->env, name, uri_node); | |||||
} | |||||
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) | |||||
{ | |||||
SordWorld* world = sord_get_world(inserter->model); | |||||
SerdEnv* env = inserter->env; | |||||
SordNode* g = sord_node_from_serd_node(world, env, graph, NULL, NULL); | |||||
SordNode* s = sord_node_from_serd_node(world, env, subject, NULL, NULL); | |||||
SordNode* p = sord_node_from_serd_node(world, env, predicate, NULL, NULL); | |||||
SordNode* o = sord_node_from_serd_node(world, env, object, | |||||
object_datatype, object_lang); | |||||
const SordQuad tup = { s, p, o, g }; | |||||
sord_add(inserter->model, tup); | |||||
sord_node_free(world, o); | |||||
sord_node_free(world, p); | |||||
sord_node_free(world, s); | |||||
sord_node_free(world, g); | |||||
return SERD_SUCCESS; | |||||
} | |||||
SORD_API | |||||
SerdReader* | |||||
sord_new_reader(SordModel* model, | |||||
SerdEnv* env, | |||||
SerdSyntax syntax, | |||||
SordNode* graph) | |||||
{ | |||||
SordInserter* inserter = sord_inserter_new(model, env); | |||||
SerdReader* reader = serd_reader_new( | |||||
syntax, inserter, (void (*)(void*))sord_inserter_free, | |||||
(SerdBaseSink)sord_inserter_set_base_uri, | |||||
(SerdPrefixSink)sord_inserter_set_prefix, | |||||
(SerdStatementSink)sord_inserter_write_statement, | |||||
NULL); | |||||
if (graph) { | |||||
serd_reader_set_default_graph(reader, sord_node_to_serd_node(graph)); | |||||
} | |||||
return reader; | |||||
} | |||||
static void | |||||
write_statement(SordModel* sord, | |||||
SerdWriter* writer, | |||||
SordQuad tup, | |||||
SerdStatementFlags flags) | |||||
{ | |||||
const SordNode* s = tup[SORD_SUBJECT]; | |||||
const SordNode* p = tup[SORD_PREDICATE]; | |||||
const SordNode* o = tup[SORD_OBJECT]; | |||||
const SordNode* d = sord_node_get_datatype(o); | |||||
const SerdNode* ss = sord_node_to_serd_node(s); | |||||
const SerdNode* sp = sord_node_to_serd_node(p); | |||||
const SerdNode* so = sord_node_to_serd_node(o); | |||||
const SerdNode* sd = sord_node_to_serd_node(d); | |||||
const char* lang_str = sord_node_get_language(o); | |||||
size_t lang_len = lang_str ? strlen(lang_str) : 0; | |||||
SerdNode language = SERD_NODE_NULL; | |||||
if (lang_str) { | |||||
language.type = SERD_LITERAL; | |||||
language.n_bytes = lang_len; | |||||
language.n_chars = lang_len; | |||||
language.buf = (const uint8_t*)lang_str; | |||||
}; | |||||
// TODO: Subject abbreviation | |||||
if (sord_node_is_inline_object(s) && !(flags & SERD_ANON_CONT)) { | |||||
return; | |||||
} | |||||
SerdStatus st = SERD_SUCCESS; | |||||
if (sord_node_is_inline_object(o)) { | |||||
SordQuad sub_pat = { o, 0, 0, 0 }; | |||||
SordIter* sub_iter = sord_find(sord, sub_pat); | |||||
SerdStatementFlags start_flags = flags | |||||
| ((sub_iter) ? SERD_ANON_O_BEGIN : SERD_EMPTY_O); | |||||
st = serd_writer_write_statement( | |||||
writer, start_flags, NULL, ss, sp, so, sd, &language); | |||||
if (!st && sub_iter) { | |||||
flags |= SERD_ANON_CONT; | |||||
for (; !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) { | |||||
SordQuad sub_tup; | |||||
sord_iter_get(sub_iter, sub_tup); | |||||
write_statement(sord, writer, sub_tup, flags); | |||||
} | |||||
sord_iter_free(sub_iter); | |||||
serd_writer_end_anon(writer, so); | |||||
} | |||||
} else { | |||||
st = serd_writer_write_statement( | |||||
writer, flags, NULL, ss, sp, so, sd, &language); | |||||
} | |||||
if (st) { | |||||
fprintf(stderr, "Failed to write statement (%s)\n", | |||||
serd_strerror(st)); | |||||
return; | |||||
} | |||||
} | |||||
bool | |||||
sord_write(SordModel* model, | |||||
SerdWriter* writer, | |||||
SordNode* graph) | |||||
{ | |||||
SordQuad pat = { 0, 0, 0, graph }; | |||||
SordIter* iter = sord_find(model, pat); | |||||
return sord_write_iter(iter, writer); | |||||
} | |||||
bool | |||||
sord_write_iter(SordIter* iter, | |||||
SerdWriter* writer) | |||||
{ | |||||
if (!iter) { | |||||
return false; | |||||
} | |||||
SordModel* model = (SordModel*)sord_iter_get_model(iter); | |||||
for (; !sord_iter_end(iter); sord_iter_next(iter)) { | |||||
SordQuad tup; | |||||
sord_iter_get(iter, tup); | |||||
write_statement(model, writer, tup, 0); | |||||
} | |||||
sord_iter_free(iter); | |||||
return true; | |||||
} |
@@ -1,738 +0,0 @@ | |||||
/* | |||||
Copyright 2011-2014 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. | |||||
*/ | |||||
#include <assert.h> | |||||
#include <stdint.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include "zix/btree.h" | |||||
// #define ZIX_BTREE_DEBUG 1 | |||||
#define ZIX_BTREE_PAGE_SIZE 4096 | |||||
#define ZIX_BTREE_NODE_SPACE (ZIX_BTREE_PAGE_SIZE - 2 * sizeof(uint16_t)) | |||||
#define ZIX_BTREE_LEAF_VALS ((ZIX_BTREE_NODE_SPACE / sizeof(void*)) - 1) | |||||
#define ZIX_BTREE_INODE_VALS (ZIX_BTREE_LEAF_VALS / 2) | |||||
struct ZixBTreeImpl { | |||||
ZixBTreeNode* root; | |||||
ZixDestroyFunc destroy; | |||||
ZixComparator cmp; | |||||
void* cmp_data; | |||||
size_t size; | |||||
unsigned height; ///< Number of levels, i.e. root only has height 1 | |||||
}; | |||||
struct ZixBTreeNodeImpl { | |||||
uint16_t is_leaf; | |||||
uint16_t n_vals; | |||||
// On 64-bit we rely on some padding here to get page-sized nodes | |||||
void* vals[ZIX_BTREE_INODE_VALS]; // ZIX_BTREE_LEAF_VALS for leaves | |||||
ZixBTreeNode* children[ZIX_BTREE_INODE_VALS + 1]; // Nonexistent for leaves | |||||
}; | |||||
typedef struct { | |||||
ZixBTreeNode* node; | |||||
unsigned index; | |||||
} ZixBTreeIterFrame; | |||||
struct ZixBTreeIterImpl { | |||||
unsigned level; ///< Current level in stack | |||||
ZixBTreeIterFrame stack[]; ///< Position stack | |||||
}; | |||||
#ifdef ZIX_BTREE_DEBUG | |||||
ZIX_PRIVATE void | |||||
print_node(const ZixBTreeNode* n, const char* prefix) | |||||
{ | |||||
printf("%s[", prefix); | |||||
for (uint16_t v = 0; v < n->n_vals; ++v) { | |||||
printf(" %lu", (uintptr_t)n->vals[v]); | |||||
} | |||||
printf(" ]\n"); | |||||
} | |||||
ZIX_PRIVATE void | |||||
print_tree(const ZixBTreeNode* parent, const ZixBTreeNode* node, int level) | |||||
{ | |||||
if (node) { | |||||
if (!parent) { | |||||
printf("TREE {\n"); | |||||
} | |||||
for (int i = 0; i < level + 1; ++i) { | |||||
printf(" "); | |||||
} | |||||
print_node(node, ""); | |||||
if (!node->is_leaf) { | |||||
for (uint16_t i = 0; i < node->n_vals + 1; ++i) { | |||||
print_tree(node, node->children[i], level + 1); | |||||
} | |||||
} | |||||
if (!parent) { | |||||
printf("}\n"); | |||||
} | |||||
} | |||||
} | |||||
#endif // ZIX_BTREE_DEBUG | |||||
ZIX_PRIVATE ZixBTreeNode* | |||||
zix_btree_node_new(const bool leaf) | |||||
{ | |||||
assert(sizeof(ZixBTreeNode) == ZIX_BTREE_PAGE_SIZE); | |||||
ZixBTreeNode* node = (ZixBTreeNode*)malloc(sizeof(ZixBTreeNode)); | |||||
if (node) { | |||||
node->is_leaf = leaf; | |||||
node->n_vals = 0; | |||||
} | |||||
return node; | |||||
} | |||||
ZIX_API ZixBTree* | |||||
zix_btree_new(const ZixComparator cmp, | |||||
void* const cmp_data, | |||||
const ZixDestroyFunc destroy) | |||||
{ | |||||
ZixBTree* t = (ZixBTree*)malloc(sizeof(ZixBTree)); | |||||
if (t) { | |||||
t->root = zix_btree_node_new(true); | |||||
t->destroy = destroy; | |||||
t->cmp = cmp; | |||||
t->cmp_data = cmp_data; | |||||
t->size = 0; | |||||
t->height = 1; | |||||
if (!t->root) { | |||||
free(t); | |||||
return NULL; | |||||
} | |||||
} | |||||
return t; | |||||
} | |||||
ZIX_PRIVATE void | |||||
zix_btree_free_rec(ZixBTree* const t, ZixBTreeNode* const n) | |||||
{ | |||||
if (n) { | |||||
if (t->destroy) { | |||||
for (uint16_t i = 0; i < n->n_vals; ++i) { | |||||
t->destroy(n->vals[i]); | |||||
} | |||||
} | |||||
if (!n->is_leaf) { | |||||
for (uint16_t i = 0; i < n->n_vals + 1; ++i) { | |||||
zix_btree_free_rec(t, n->children[i]); | |||||
} | |||||
} | |||||
free(n); | |||||
} | |||||
} | |||||
ZIX_API void | |||||
zix_btree_free(ZixBTree* const t) | |||||
{ | |||||
if (t) { | |||||
zix_btree_free_rec(t, t->root); | |||||
free(t); | |||||
} | |||||
} | |||||
ZIX_API size_t | |||||
zix_btree_size(const ZixBTree* const t) | |||||
{ | |||||
return t->size; | |||||
} | |||||
ZIX_PRIVATE uint16_t | |||||
zix_btree_max_vals(const ZixBTreeNode* const node) | |||||
{ | |||||
return node->is_leaf ? ZIX_BTREE_LEAF_VALS : ZIX_BTREE_INODE_VALS; | |||||
} | |||||
ZIX_PRIVATE uint16_t | |||||
zix_btree_min_vals(const ZixBTreeNode* const node) | |||||
{ | |||||
return ((zix_btree_max_vals(node) + 1) / 2) - 1; | |||||
} | |||||
/** Shift pointers in `array` of length `n` right starting at `i`. */ | |||||
ZIX_PRIVATE void | |||||
zix_btree_ainsert(void** const array, | |||||
const uint16_t n, | |||||
const uint16_t i, | |||||
void* const e) | |||||
{ | |||||
memmove(array + i + 1, array + i, (n - i) * sizeof(e)); | |||||
array[i] = e; | |||||
} | |||||
/** Erase element `i` in `array` of length `n` and return erased element. */ | |||||
ZIX_PRIVATE void* | |||||
zix_btree_aerase(void** const array, const uint16_t n, const uint16_t i) | |||||
{ | |||||
void* const ret = array[i]; | |||||
memmove(array + i, array + i + 1, (n - i) * sizeof(ret)); | |||||
return ret; | |||||
} | |||||
/** Split lhs, the i'th child of `n`, into two nodes. */ | |||||
ZIX_PRIVATE ZixBTreeNode* | |||||
zix_btree_split_child(ZixBTreeNode* const n, | |||||
const uint16_t i, | |||||
ZixBTreeNode* const lhs) | |||||
{ | |||||
assert(lhs->n_vals == zix_btree_max_vals(lhs)); | |||||
assert(n->n_vals < ZIX_BTREE_INODE_VALS); | |||||
assert(i < n->n_vals + 1); | |||||
assert(n->children[i] == lhs); | |||||
const uint16_t max_n_vals = zix_btree_max_vals(lhs); | |||||
ZixBTreeNode* rhs = zix_btree_node_new(lhs->is_leaf); | |||||
if (!rhs) { | |||||
return NULL; | |||||
} | |||||
// LHS and RHS get roughly half, less the middle value which moves up | |||||
lhs->n_vals = max_n_vals / 2; | |||||
rhs->n_vals = max_n_vals - lhs->n_vals - 1; | |||||
// Copy large half of values from LHS to new RHS node | |||||
memcpy(rhs->vals, | |||||
lhs->vals + lhs->n_vals + 1, | |||||
rhs->n_vals * sizeof(void*)); | |||||
// Copy large half of children from LHS to new RHS node | |||||
if (!lhs->is_leaf) { | |||||
memcpy(rhs->children, | |||||
lhs->children + lhs->n_vals + 1, | |||||
(rhs->n_vals + 1) * sizeof(ZixBTreeNode*)); | |||||
} | |||||
// Move middle value up to parent | |||||
zix_btree_ainsert(n->vals, n->n_vals, i, lhs->vals[lhs->n_vals]); | |||||
// Insert new RHS node in parent at position i | |||||
zix_btree_ainsert((void**)n->children, ++n->n_vals, i + 1, rhs); | |||||
return rhs; | |||||
} | |||||
/** Find the first value in `n` that is not less than `e` (lower bound). */ | |||||
ZIX_PRIVATE uint16_t | |||||
zix_btree_node_find(const ZixBTree* const t, | |||||
const ZixBTreeNode* const n, | |||||
const void* const e, | |||||
bool* const equal) | |||||
{ | |||||
uint16_t first = 0; | |||||
uint16_t len = n->n_vals; | |||||
while (len > 0) { | |||||
const uint16_t half = len >> 1; | |||||
const uint16_t i = first + half; | |||||
const int cmp = t->cmp(n->vals[i], e, t->cmp_data); | |||||
if (cmp == 0) { | |||||
*equal = true; | |||||
len = half; // Keep searching for wildcard matches | |||||
} else if (cmp < 0) { | |||||
const uint16_t chop = half + 1; | |||||
first += chop; | |||||
len -= chop; | |||||
} else { | |||||
len = half; | |||||
} | |||||
} | |||||
assert(!*equal || t->cmp(n->vals[first], e, t->cmp_data) == 0); | |||||
return first; | |||||
} | |||||
ZIX_API ZixStatus | |||||
zix_btree_insert(ZixBTree* const t, void* const e) | |||||
{ | |||||
ZixBTreeNode* parent = NULL; // Parent of n | |||||
ZixBTreeNode* n = t->root; // Current node | |||||
uint16_t i = 0; // Index of n in parent | |||||
while (n) { | |||||
if (n->n_vals == zix_btree_max_vals(n)) { | |||||
// Node is full, split to ensure there is space for a leaf split | |||||
if (!parent) { | |||||
// Root is full, grow tree upwards | |||||
if (!(parent = zix_btree_node_new(false))) { | |||||
return ZIX_STATUS_NO_MEM; | |||||
} | |||||
t->root = parent; | |||||
parent->children[0] = n; | |||||
++t->height; | |||||
} | |||||
ZixBTreeNode* const rhs = zix_btree_split_child(parent, i, n); | |||||
if (!rhs) { | |||||
return ZIX_STATUS_NO_MEM; | |||||
} | |||||
const int cmp = t->cmp(parent->vals[i], e, t->cmp_data); | |||||
if (cmp == 0) { | |||||
return ZIX_STATUS_EXISTS; | |||||
} else if (cmp < 0) { | |||||
// Move to new RHS | |||||
n = rhs; | |||||
++i; | |||||
} | |||||
} | |||||
assert(!parent || parent->children[i] == n); | |||||
bool equal = false; | |||||
i = zix_btree_node_find(t, n, e, &equal); | |||||
if (equal) { | |||||
return ZIX_STATUS_EXISTS; | |||||
} else if (!n->is_leaf) { | |||||
// Descend to child node left of value | |||||
parent = n; | |||||
n = n->children[i]; | |||||
} else { | |||||
// Insert into internal node | |||||
zix_btree_ainsert(n->vals, n->n_vals++, i, e); | |||||
break; | |||||
} | |||||
} | |||||
++t->size; | |||||
return ZIX_STATUS_SUCCESS; | |||||
} | |||||
ZIX_PRIVATE ZixBTreeIter* | |||||
zix_btree_iter_new(const ZixBTree* const t) | |||||
{ | |||||
const size_t s = t->height * sizeof(ZixBTreeIterFrame); | |||||
ZixBTreeIter* const i = (ZixBTreeIter*)malloc(sizeof(ZixBTreeIter) + s); | |||||
if (i) { | |||||
i->level = 0; | |||||
} | |||||
return i; | |||||
} | |||||
ZIX_PRIVATE void | |||||
zix_btree_iter_set_frame(ZixBTreeIter* const ti, | |||||
ZixBTreeNode* const n, | |||||
const uint16_t i) | |||||
{ | |||||
if (ti) { | |||||
ti->stack[ti->level].node = n; | |||||
ti->stack[ti->level].index = i; | |||||
} | |||||
} | |||||
ZIX_PRIVATE bool | |||||
zix_btree_node_is_minimal(ZixBTreeNode* const n) | |||||
{ | |||||
assert(n->n_vals >= zix_btree_min_vals(n)); | |||||
return n->n_vals == zix_btree_min_vals(n); | |||||
} | |||||
/** Enlarge left child by stealing a value from its right sibling. */ | |||||
ZIX_PRIVATE ZixBTreeNode* | |||||
zix_btree_rotate_left(ZixBTreeNode* const parent, const uint16_t i) | |||||
{ | |||||
ZixBTreeNode* const lhs = parent->children[i]; | |||||
ZixBTreeNode* const rhs = parent->children[i + 1]; | |||||
// Move parent value to end of LHS | |||||
lhs->vals[lhs->n_vals++] = parent->vals[i]; | |||||
// Move first child pointer from RHS to end of LHS | |||||
if (!lhs->is_leaf) { | |||||
lhs->children[lhs->n_vals] = (ZixBTreeNode*)zix_btree_aerase( | |||||
(void**)rhs->children, rhs->n_vals, 0); | |||||
} | |||||
// Move first value in RHS to parent | |||||
parent->vals[i] = zix_btree_aerase(rhs->vals, --rhs->n_vals, 0); | |||||
return lhs; | |||||
} | |||||
/** Enlarge right child by stealing a value from its left sibling. */ | |||||
ZIX_PRIVATE ZixBTreeNode* | |||||
zix_btree_rotate_right(ZixBTreeNode* const parent, const uint16_t i) | |||||
{ | |||||
ZixBTreeNode* const lhs = parent->children[i - 1]; | |||||
ZixBTreeNode* const rhs = parent->children[i]; | |||||
// Prepend parent value to RHS | |||||
zix_btree_ainsert(rhs->vals, rhs->n_vals++, 0, parent->vals[i - 1]); | |||||
// Move last child pointer from LHS and prepend to RHS | |||||
if (!lhs->is_leaf) { | |||||
zix_btree_ainsert((void**)rhs->children, | |||||
rhs->n_vals, | |||||
0, | |||||
lhs->children[lhs->n_vals]); | |||||
} | |||||
// Move last value from LHS to parent | |||||
parent->vals[i - 1] = lhs->vals[--lhs->n_vals]; | |||||
return rhs; | |||||
} | |||||
/** Move n[i] down, merge the left and right child, return the merged node. */ | |||||
ZIX_PRIVATE ZixBTreeNode* | |||||
zix_btree_merge(ZixBTree* const t, ZixBTreeNode* const n, const uint16_t i) | |||||
{ | |||||
ZixBTreeNode* const lhs = n->children[i]; | |||||
ZixBTreeNode* const rhs = n->children[i + 1]; | |||||
assert(zix_btree_node_is_minimal(n->children[i])); | |||||
assert(lhs->n_vals + rhs->n_vals < zix_btree_max_vals(lhs)); | |||||
// Move parent value to end of LHS | |||||
lhs->vals[lhs->n_vals++] = zix_btree_aerase(n->vals, n->n_vals, i); | |||||
// Erase corresponding child pointer (to RHS) in parent | |||||
zix_btree_aerase((void**)n->children, n->n_vals, i + 1); | |||||
// Add everything from RHS to end of LHS | |||||
memcpy(lhs->vals + lhs->n_vals, rhs->vals, rhs->n_vals * sizeof(void*)); | |||||
if (!lhs->is_leaf) { | |||||
memcpy(lhs->children + lhs->n_vals, | |||||
rhs->children, | |||||
(rhs->n_vals + 1) * sizeof(void*)); | |||||
} | |||||
lhs->n_vals += rhs->n_vals; | |||||
if (--n->n_vals == 0) { | |||||
// Root is now empty, replace it with its only child | |||||
assert(n == t->root); | |||||
t->root = lhs; | |||||
free(n); | |||||
} | |||||
free(rhs); | |||||
return lhs; | |||||
} | |||||
/** Remove and return the min value from the subtree rooted at `n`. */ | |||||
ZIX_PRIVATE void* | |||||
zix_btree_remove_min(ZixBTree* const t, ZixBTreeNode* n) | |||||
{ | |||||
while (!n->is_leaf) { | |||||
if (zix_btree_node_is_minimal(n->children[0])) { | |||||
// Leftmost child is minimal, must expand | |||||
if (!zix_btree_node_is_minimal(n->children[1])) { | |||||
// Child's right sibling has at least one key to steal | |||||
n = zix_btree_rotate_left(n, 0); | |||||
} else { | |||||
// Both child and right sibling are minimal, merge | |||||
n = zix_btree_merge(t, n, 0); | |||||
} | |||||
} else { | |||||
n = n->children[0]; | |||||
} | |||||
} | |||||
return zix_btree_aerase(n->vals, --n->n_vals, 0); | |||||
} | |||||
/** Remove and return the max value from the subtree rooted at `n`. */ | |||||
ZIX_PRIVATE void* | |||||
zix_btree_remove_max(ZixBTree* const t, ZixBTreeNode* n) | |||||
{ | |||||
while (!n->is_leaf) { | |||||
if (zix_btree_node_is_minimal(n->children[n->n_vals])) { | |||||
// Leftmost child is minimal, must expand | |||||
if (!zix_btree_node_is_minimal(n->children[n->n_vals - 1])) { | |||||
// Child's left sibling has at least one key to steal | |||||
n = zix_btree_rotate_right(n, n->n_vals); | |||||
} else { | |||||
// Both child and left sibling are minimal, merge | |||||
n = zix_btree_merge(t, n, n->n_vals - 1); | |||||
} | |||||
} else { | |||||
n = n->children[n->n_vals]; | |||||
} | |||||
} | |||||
return n->vals[--n->n_vals]; | |||||
} | |||||
ZIX_API ZixStatus | |||||
zix_btree_remove(ZixBTree* const t, | |||||
const void* const e, | |||||
void** const out, | |||||
ZixBTreeIter** const next) | |||||
{ | |||||
ZixBTreeNode* n = t->root; | |||||
ZixBTreeIter* ti = NULL; | |||||
const bool user_iter = next && *next; | |||||
if (next) { | |||||
if (!*next && !(*next = zix_btree_iter_new(t))) { | |||||
return ZIX_STATUS_NO_MEM; | |||||
} | |||||
ti = *next; | |||||
ti->level = 0; | |||||
} | |||||
while (true) { | |||||
/* To remove in a single walk down, the tree is adjusted along the way | |||||
so that the current node always has at least one more value than the | |||||
minimum required in general. Thus, there is always room to remove | |||||
without adjusting on the way back up. */ | |||||
assert(n == t->root || !zix_btree_node_is_minimal(n)); | |||||
bool equal = false; | |||||
const uint16_t i = zix_btree_node_find(t, n, e, &equal); | |||||
zix_btree_iter_set_frame(ti, n, i); | |||||
if (n->is_leaf) { | |||||
if (equal) { | |||||
// Found in leaf node | |||||
*out = zix_btree_aerase(n->vals, --n->n_vals, i); | |||||
if (ti && i == n->n_vals) { | |||||
if (i == 0) { | |||||
ti->stack[ti->level = 0].node = NULL; | |||||
} else { | |||||
--ti->stack[ti->level].index; | |||||
zix_btree_iter_increment(ti); | |||||
} | |||||
} | |||||
--t->size; | |||||
return ZIX_STATUS_SUCCESS; | |||||
} else { | |||||
// Not found in leaf node, or tree | |||||
if (ti && !user_iter) { | |||||
zix_btree_iter_free(ti); | |||||
*next = NULL; | |||||
} | |||||
return ZIX_STATUS_NOT_FOUND; | |||||
} | |||||
} else if (equal) { | |||||
// Found in internal node | |||||
if (!zix_btree_node_is_minimal(n->children[i])) { | |||||
// Left child can remove without merge | |||||
*out = n->vals[i]; | |||||
n->vals[i] = zix_btree_remove_max(t, n->children[i]); | |||||
--t->size; | |||||
return ZIX_STATUS_SUCCESS; | |||||
} else if (!zix_btree_node_is_minimal(n->children[i + 1])) { | |||||
// Right child can remove without merge | |||||
*out = n->vals[i]; | |||||
n->vals[i] = zix_btree_remove_min(t, n->children[i + 1]); | |||||
--t->size; | |||||
return ZIX_STATUS_SUCCESS; | |||||
} else { | |||||
// Both preceding and succeeding child are minimal | |||||
n = zix_btree_merge(t, n, i); | |||||
} | |||||
} else { | |||||
// Not found in internal node, key is in/under children[i] | |||||
if (zix_btree_node_is_minimal(n->children[i])) { | |||||
if (i > 0 && !zix_btree_node_is_minimal(n->children[i - 1])) { | |||||
// Steal a key from child's left sibling | |||||
n = zix_btree_rotate_right(n, i); | |||||
} else if (i < n->n_vals && | |||||
!zix_btree_node_is_minimal(n->children[i + 1])) { | |||||
// Steal a key from child's right sibling | |||||
n = zix_btree_rotate_left(n, i); | |||||
} else { | |||||
// Both child's siblings are minimal, merge them | |||||
if (i < n->n_vals) { | |||||
n = zix_btree_merge(t, n, i); | |||||
} else { | |||||
n = zix_btree_merge(t, n, i - 1); | |||||
if (ti) { | |||||
--ti->stack[ti->level].index; | |||||
} | |||||
} | |||||
} | |||||
} else { | |||||
n = n->children[i]; | |||||
} | |||||
} | |||||
if (ti) { | |||||
++ti->level; | |||||
} | |||||
} | |||||
assert(false); // Not reached | |||||
return ZIX_STATUS_ERROR; | |||||
} | |||||
ZIX_API ZixStatus | |||||
zix_btree_find(const ZixBTree* const t, | |||||
const void* const e, | |||||
ZixBTreeIter** const ti) | |||||
{ | |||||
ZixBTreeNode* n = t->root; | |||||
if (!(*ti = zix_btree_iter_new(t))) { | |||||
return ZIX_STATUS_NO_MEM; | |||||
} | |||||
while (n) { | |||||
bool equal = false; | |||||
const uint16_t i = zix_btree_node_find(t, n, e, &equal); | |||||
zix_btree_iter_set_frame(*ti, n, i); | |||||
if (equal) { | |||||
return ZIX_STATUS_SUCCESS; | |||||
} else if (n->is_leaf) { | |||||
break; | |||||
} else { | |||||
++(*ti)->level; | |||||
n = n->children[i]; | |||||
} | |||||
} | |||||
zix_btree_iter_free(*ti); | |||||
*ti = NULL; | |||||
return ZIX_STATUS_NOT_FOUND; | |||||
} | |||||
ZIX_API ZixStatus | |||||
zix_btree_lower_bound(const ZixBTree* const t, | |||||
const void* const e, | |||||
ZixBTreeIter** const ti) | |||||
{ | |||||
if (!t) { | |||||
*ti = NULL; | |||||
return ZIX_STATUS_BAD_ARG; | |||||
} | |||||
ZixBTreeNode* n = t->root; | |||||
bool found = false; | |||||
unsigned found_level = 0; | |||||
if (!(*ti = zix_btree_iter_new(t))) { | |||||
return ZIX_STATUS_NO_MEM; | |||||
} | |||||
while (n) { | |||||
bool equal = false; | |||||
const uint16_t i = zix_btree_node_find(t, n, e, &equal); | |||||
zix_btree_iter_set_frame(*ti, n, i); | |||||
if (equal) { | |||||
found_level = (*ti)->level; | |||||
found = true; | |||||
} | |||||
if (n->is_leaf) { | |||||
break; | |||||
} else { | |||||
++(*ti)->level; | |||||
n = n->children[i]; | |||||
assert(n); | |||||
} | |||||
} | |||||
const ZixBTreeIterFrame* const frame = &(*ti)->stack[(*ti)->level]; | |||||
if (frame->index == frame->node->n_vals) { | |||||
if (found) { | |||||
// Found on a previous level but went too far | |||||
(*ti)->level = found_level; | |||||
} else { | |||||
// Reached end (key is greater than everything in tree) | |||||
(*ti)->stack[0].node = NULL; | |||||
} | |||||
} | |||||
return ZIX_STATUS_SUCCESS; | |||||
} | |||||
ZIX_API void* | |||||
zix_btree_get(const ZixBTreeIter* const ti) | |||||
{ | |||||
const ZixBTreeIterFrame* const frame = &ti->stack[ti->level]; | |||||
assert(frame->index < frame->node->n_vals); | |||||
return frame->node->vals[frame->index]; | |||||
} | |||||
ZIX_API ZixBTreeIter* | |||||
zix_btree_begin(const ZixBTree* const t) | |||||
{ | |||||
ZixBTreeIter* const i = zix_btree_iter_new(t); | |||||
if (!i) { | |||||
return NULL; | |||||
} else if (t->size == 0) { | |||||
i->stack[0].node = NULL; | |||||
} else { | |||||
ZixBTreeNode* n = t->root; | |||||
i->stack[0].node = n; | |||||
i->stack[0].index = 0; | |||||
while (!n->is_leaf) { | |||||
n = n->children[0]; | |||||
++i->level; | |||||
i->stack[i->level].node = n; | |||||
i->stack[i->level].index = 0; | |||||
} | |||||
} | |||||
return i; | |||||
} | |||||
ZIX_API bool | |||||
zix_btree_iter_is_end(const ZixBTreeIter* const i) | |||||
{ | |||||
return !i || i->stack[0].node == NULL; | |||||
} | |||||
ZIX_API void | |||||
zix_btree_iter_increment(ZixBTreeIter* const i) | |||||
{ | |||||
ZixBTreeIterFrame* f = &i->stack[i->level]; | |||||
if (f->node->is_leaf) { | |||||
// Leaf, move right | |||||
assert(f->index < f->node->n_vals); | |||||
if (++f->index == f->node->n_vals) { | |||||
// Reached end of leaf, move up | |||||
f = &i->stack[i->level]; | |||||
while (i->level > 0 && f->index == f->node->n_vals) { | |||||
f = &i->stack[--i->level]; | |||||
assert(f->index <= f->node->n_vals); | |||||
} | |||||
if (f->index == f->node->n_vals) { | |||||
// Reached end of tree | |||||
assert(i->level == 0); | |||||
f->node = NULL; | |||||
f->index = 0; | |||||
} | |||||
} | |||||
} else { | |||||
// Internal node, move down to next child | |||||
assert(f->index < f->node->n_vals); | |||||
ZixBTreeNode* child = f->node->children[++f->index]; | |||||
f = &i->stack[++i->level]; | |||||
f->node = child; | |||||
f->index = 0; | |||||
// Move down and left until we hit a leaf | |||||
while (!f->node->is_leaf) { | |||||
child = f->node->children[0]; | |||||
f = &i->stack[++i->level]; | |||||
f->node = child; | |||||
f->index = 0; | |||||
} | |||||
} | |||||
} | |||||
ZIX_API void | |||||
zix_btree_iter_free(ZixBTreeIter* const i) | |||||
{ | |||||
free(i); | |||||
} |
@@ -1,151 +0,0 @@ | |||||
/* | |||||
Copyright 2011-2014 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. | |||||
*/ | |||||
#ifndef ZIX_BTREE_H | |||||
#define ZIX_BTREE_H | |||||
#include <stddef.h> | |||||
#include "zix/common.h" | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#else | |||||
# include <stdbool.h> | |||||
#endif | |||||
/** | |||||
@addtogroup zix | |||||
@{ | |||||
@name BTree | |||||
@{ | |||||
*/ | |||||
/** | |||||
A B-Tree. | |||||
*/ | |||||
typedef struct ZixBTreeImpl ZixBTree; | |||||
/** | |||||
A B-Tree node (opaque). | |||||
*/ | |||||
typedef struct ZixBTreeNodeImpl ZixBTreeNode; | |||||
/** | |||||
An iterator over a B-Tree. | |||||
Note that modifying the trees invalidates all iterators, so all iterators | |||||
are const iterators. | |||||
*/ | |||||
typedef struct ZixBTreeIterImpl ZixBTreeIter; | |||||
/** | |||||
Create a new (empty) B-Tree. | |||||
*/ | |||||
ZIX_API ZixBTree* | |||||
zix_btree_new(ZixComparator cmp, | |||||
void* cmp_data, | |||||
ZixDestroyFunc destroy); | |||||
/** | |||||
Free `t`. | |||||
*/ | |||||
ZIX_API void | |||||
zix_btree_free(ZixBTree* t); | |||||
/** | |||||
Return the number of elements in `t`. | |||||
*/ | |||||
ZIX_API size_t | |||||
zix_btree_size(const ZixBTree* t); | |||||
/** | |||||
Insert the element `e` into `t`. | |||||
*/ | |||||
ZIX_API ZixStatus | |||||
zix_btree_insert(ZixBTree* t, void* e); | |||||
/** | |||||
Remove the value `e` from `t`. | |||||
@param out Set to point to the removed pointer (which may not equal `e`). | |||||
@param next If non-NULL, pointed to the value following `e`. If *next is | |||||
also non-NULL, the iterator is reused, otherwise a new one is allocated. To | |||||
reuse an iterator, no items may have been added since its creation. | |||||
*/ | |||||
ZIX_API ZixStatus | |||||
zix_btree_remove(ZixBTree* t, const void* e, void** out, ZixBTreeIter** next); | |||||
/** | |||||
Set `ti` to an element equal to `e` in `t`. | |||||
If no such item exists, `ti` is set to NULL. | |||||
*/ | |||||
ZIX_API ZixStatus | |||||
zix_btree_find(const ZixBTree* t, const void* e, ZixBTreeIter** ti); | |||||
/** | |||||
Set `ti` to the smallest element in `t` that is not less than `e`. | |||||
Wildcards are supported, so if the search key `e` compares equal to many | |||||
values in the tree, `ti` will be set to the least such element. The search | |||||
key `e` is always passed as the second argument to the comparator. | |||||
*/ | |||||
ZIX_API ZixStatus | |||||
zix_btree_lower_bound(const ZixBTree* t, const void* e, ZixBTreeIter** ti); | |||||
/** | |||||
Return the data associated with the given tree item. | |||||
*/ | |||||
ZIX_API void* | |||||
zix_btree_get(const ZixBTreeIter* ti); | |||||
/** | |||||
Return an iterator to the first (smallest) element in `t`. | |||||
The returned iterator must be freed with zix_btree_iter_free(). | |||||
*/ | |||||
ZIX_API ZixBTreeIter* | |||||
zix_btree_begin(const ZixBTree* t); | |||||
/** | |||||
Return true iff `i` is an iterator to the end of its tree. | |||||
*/ | |||||
ZIX_API bool | |||||
zix_btree_iter_is_end(const ZixBTreeIter* i); | |||||
/** | |||||
Increment `i` to point to the next element in the tree. | |||||
*/ | |||||
ZIX_API void | |||||
zix_btree_iter_increment(ZixBTreeIter* i); | |||||
/** | |||||
Free `i`. | |||||
*/ | |||||
ZIX_API void | |||||
zix_btree_iter_free(ZixBTreeIter* i); | |||||
/** | |||||
@} | |||||
@} | |||||
*/ | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* ZIX_BTREE_H */ |
@@ -1,88 +0,0 @@ | |||||
/* | |||||
Copyright 2011 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. | |||||
*/ | |||||
#ifndef ZIX_COMMON_H | |||||
#define ZIX_COMMON_H | |||||
/** | |||||
@addtogroup zix | |||||
@{ | |||||
*/ | |||||
/** @cond */ | |||||
#ifdef ZIX_SHARED | |||||
# ifdef _WIN32 | |||||
# define ZIX_LIB_IMPORT __declspec(dllimport) | |||||
# define ZIX_LIB_EXPORT __declspec(dllexport) | |||||
# else | |||||
# define ZIX_LIB_IMPORT __attribute__((visibility("default"))) | |||||
# define ZIX_LIB_EXPORT __attribute__((visibility("default"))) | |||||
# endif | |||||
# ifdef ZIX_INTERNAL | |||||
# define ZIX_API ZIX_LIB_EXPORT | |||||
# else | |||||
# define ZIX_API ZIX_LIB_IMPORT | |||||
# endif | |||||
# define ZIX_PRIVATE static | |||||
#elif defined(ZIX_INLINE) | |||||
# define ZIX_API static inline | |||||
# define ZIX_PRIVATE static inline | |||||
#else | |||||
# define ZIX_API | |||||
# define ZIX_PRIVATE static | |||||
#endif | |||||
/** @endcond */ | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#else | |||||
# include <stdbool.h> | |||||
#endif | |||||
typedef enum { | |||||
ZIX_STATUS_SUCCESS, | |||||
ZIX_STATUS_ERROR, | |||||
ZIX_STATUS_NO_MEM, | |||||
ZIX_STATUS_NOT_FOUND, | |||||
ZIX_STATUS_EXISTS, | |||||
ZIX_STATUS_BAD_ARG, | |||||
ZIX_STATUS_BAD_PERMS, | |||||
} ZixStatus; | |||||
/** | |||||
Function for comparing two elements. | |||||
*/ | |||||
typedef int (*ZixComparator)(const void* a, const void* b, void* user_data); | |||||
/** | |||||
Function for testing equality of two elements. | |||||
*/ | |||||
typedef bool (*ZixEqualFunc)(const void* a, const void* b); | |||||
/** | |||||
Function to destroy an element. | |||||
*/ | |||||
typedef void (*ZixDestroyFunc)(void* ptr); | |||||
/** | |||||
@} | |||||
*/ | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* ZIX_COMMON_H */ |
@@ -1,57 +0,0 @@ | |||||
/* | |||||
Copyright 2012-2014 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. | |||||
*/ | |||||
#include "zix/digest.h" | |||||
#ifdef __SSE4_2__ | |||||
# include <smmintrin.h> | |||||
#endif | |||||
ZIX_API uint32_t | |||||
zix_digest_start(void) | |||||
{ | |||||
#ifdef __SSE4_2__ | |||||
return 1; // CRC32 initial value | |||||
#else | |||||
return 5381; // DJB hash initial value | |||||
#endif | |||||
} | |||||
ZIX_API uint32_t | |||||
zix_digest_add(uint32_t hash, const void* const buf, const size_t len) | |||||
{ | |||||
const uint8_t* str = (const uint8_t*)buf; | |||||
#ifdef __SSE4_2__ | |||||
// SSE 4.2 CRC32 | |||||
for (size_t i = 0; i < (len / sizeof(uint32_t)); ++i) { | |||||
hash = _mm_crc32_u32(hash, *(const uint32_t*)str); | |||||
str += sizeof(uint32_t); | |||||
} | |||||
if (len & sizeof(uint16_t)) { | |||||
hash = _mm_crc32_u16(hash, *(const uint16_t*)str); | |||||
str += sizeof(uint16_t); | |||||
} | |||||
if (len & sizeof(uint8_t)) { | |||||
hash = _mm_crc32_u8(hash, *(const uint8_t*)str); | |||||
} | |||||
#else | |||||
// Classic DJB hash | |||||
for (size_t i = 0; i < len; ++i) { | |||||
hash = (hash << 5) + hash + str[i]; | |||||
} | |||||
#endif | |||||
return hash; | |||||
} |
@@ -1,39 +0,0 @@ | |||||
/* | |||||
Copyright 2012 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. | |||||
*/ | |||||
#ifndef ZIX_DIGEST_H | |||||
#define ZIX_DIGEST_H | |||||
#include <stddef.h> | |||||
#include <stdint.h> | |||||
#include "zix/common.h" | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
ZIX_API uint32_t | |||||
zix_digest_start(void); | |||||
ZIX_API uint32_t | |||||
zix_digest_add(uint32_t hash, const void* buf, const size_t len); | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* ZIX_DIGEST_H */ |
@@ -1,232 +0,0 @@ | |||||
/* | |||||
Copyright 2011-2014 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. | |||||
*/ | |||||
#include <assert.h> | |||||
#include <stdint.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include "zix/hash.h" | |||||
/** | |||||
Primes, each slightly less than twice its predecessor, and as far away | |||||
from powers of two as possible. | |||||
*/ | |||||
static const unsigned sizes[] = { | |||||
53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, | |||||
196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, | |||||
50331653, 100663319, 201326611, 402653189, 805306457, 1610612741, 0 | |||||
}; | |||||
typedef struct ZixHashEntry { | |||||
struct ZixHashEntry* next; ///< Next entry in bucket | |||||
uint32_t hash; ///< Non-modulo hash value | |||||
// Value follows here (access with zix_hash_value) | |||||
} ZixHashEntry; | |||||
struct ZixHashImpl { | |||||
ZixHashFunc hash_func; | |||||
ZixEqualFunc equal_func; | |||||
ZixHashEntry** buckets; | |||||
const unsigned* n_buckets; | |||||
size_t value_size; | |||||
unsigned count; | |||||
}; | |||||
static inline void* | |||||
zix_hash_value(ZixHashEntry* entry) | |||||
{ | |||||
return entry + 1; | |||||
} | |||||
ZIX_API ZixHash* | |||||
zix_hash_new(ZixHashFunc hash_func, | |||||
ZixEqualFunc equal_func, | |||||
size_t value_size) | |||||
{ | |||||
ZixHash* hash = (ZixHash*)malloc(sizeof(ZixHash)); | |||||
if (hash) { | |||||
hash->hash_func = hash_func; | |||||
hash->equal_func = equal_func; | |||||
hash->n_buckets = &sizes[0]; | |||||
hash->value_size = value_size; | |||||
hash->count = 0; | |||||
if (!(hash->buckets = (ZixHashEntry**)calloc(*hash->n_buckets, | |||||
sizeof(ZixHashEntry*)))) { | |||||
free(hash); | |||||
return NULL; | |||||
} | |||||
} | |||||
return hash; | |||||
} | |||||
ZIX_API void | |||||
zix_hash_free(ZixHash* hash) | |||||
{ | |||||
for (unsigned b = 0; b < *hash->n_buckets; ++b) { | |||||
ZixHashEntry* bucket = hash->buckets[b]; | |||||
for (ZixHashEntry* e = bucket; e;) { | |||||
ZixHashEntry* next = e->next; | |||||
free(e); | |||||
e = next; | |||||
} | |||||
} | |||||
free(hash->buckets); | |||||
free(hash); | |||||
} | |||||
ZIX_API size_t | |||||
zix_hash_size(const ZixHash* hash) | |||||
{ | |||||
return hash->count; | |||||
} | |||||
static inline void | |||||
insert_entry(ZixHashEntry** bucket, ZixHashEntry* entry) | |||||
{ | |||||
entry->next = *bucket; | |||||
*bucket = entry; | |||||
} | |||||
static inline ZixStatus | |||||
rehash(ZixHash* hash, unsigned new_n_buckets) | |||||
{ | |||||
ZixHashEntry** new_buckets = (ZixHashEntry**)calloc( | |||||
new_n_buckets, sizeof(ZixHashEntry*)); | |||||
if (!new_buckets) { | |||||
return ZIX_STATUS_NO_MEM; | |||||
} | |||||
const unsigned old_n_buckets = *hash->n_buckets; | |||||
for (unsigned b = 0; b < old_n_buckets; ++b) { | |||||
for (ZixHashEntry* e = hash->buckets[b]; e;) { | |||||
ZixHashEntry* const next = e->next; | |||||
const unsigned h = e->hash % new_n_buckets; | |||||
insert_entry(&new_buckets[h], e); | |||||
e = next; | |||||
} | |||||
} | |||||
free(hash->buckets); | |||||
hash->buckets = new_buckets; | |||||
return ZIX_STATUS_SUCCESS; | |||||
} | |||||
static inline ZixHashEntry* | |||||
find_entry(const ZixHash* hash, | |||||
const void* key, | |||||
const unsigned h, | |||||
const unsigned h_nomod) | |||||
{ | |||||
for (ZixHashEntry* e = hash->buckets[h]; e; e = e->next) { | |||||
if (e->hash == h_nomod && hash->equal_func(zix_hash_value(e), key)) { | |||||
return e; | |||||
} | |||||
} | |||||
return NULL; | |||||
} | |||||
ZIX_API const void* | |||||
zix_hash_find(const ZixHash* hash, const void* value) | |||||
{ | |||||
const unsigned h_nomod = hash->hash_func(value); | |||||
const unsigned h = h_nomod % *hash->n_buckets; | |||||
ZixHashEntry* const entry = find_entry(hash, value, h, h_nomod); | |||||
return entry ? zix_hash_value(entry) : 0; | |||||
} | |||||
ZIX_API ZixStatus | |||||
zix_hash_insert(ZixHash* hash, const void* value, const void** inserted) | |||||
{ | |||||
unsigned h_nomod = hash->hash_func(value); | |||||
unsigned h = h_nomod % *hash->n_buckets; | |||||
ZixHashEntry* elem = find_entry(hash, value, h, h_nomod); | |||||
if (elem) { | |||||
assert(elem->hash == h_nomod); | |||||
if (inserted) { | |||||
*inserted = zix_hash_value(elem); | |||||
} | |||||
return ZIX_STATUS_EXISTS; | |||||
} | |||||
elem = (ZixHashEntry*)malloc(sizeof(ZixHashEntry) + hash->value_size); | |||||
if (!elem) { | |||||
return ZIX_STATUS_NO_MEM; | |||||
} | |||||
elem->next = NULL; | |||||
elem->hash = h_nomod; | |||||
memcpy(elem + 1, value, hash->value_size); | |||||
const unsigned next_n_buckets = *(hash->n_buckets + 1); | |||||
if (next_n_buckets != 0 && (hash->count + 1) >= next_n_buckets) { | |||||
if (!rehash(hash, next_n_buckets)) { | |||||
h = h_nomod % *(++hash->n_buckets); | |||||
} | |||||
} | |||||
insert_entry(&hash->buckets[h], elem); | |||||
++hash->count; | |||||
if (inserted) { | |||||
*inserted = zix_hash_value(elem); | |||||
} | |||||
return ZIX_STATUS_SUCCESS; | |||||
} | |||||
ZIX_API ZixStatus | |||||
zix_hash_remove(ZixHash* hash, const void* value) | |||||
{ | |||||
const unsigned h_nomod = hash->hash_func(value); | |||||
const unsigned h = h_nomod % *hash->n_buckets; | |||||
ZixHashEntry** next_ptr = &hash->buckets[h]; | |||||
for (ZixHashEntry* e = hash->buckets[h]; e; e = e->next) { | |||||
if (h_nomod == e->hash && | |||||
hash->equal_func(zix_hash_value(e), value)) { | |||||
*next_ptr = e->next; | |||||
free(e); | |||||
return ZIX_STATUS_SUCCESS; | |||||
} | |||||
next_ptr = &e->next; | |||||
} | |||||
if (hash->n_buckets != sizes) { | |||||
const unsigned prev_n_buckets = *(hash->n_buckets - 1); | |||||
if (hash->count - 1 <= prev_n_buckets) { | |||||
if (!rehash(hash, prev_n_buckets)) { | |||||
--hash->n_buckets; | |||||
} | |||||
} | |||||
} | |||||
--hash->count; | |||||
return ZIX_STATUS_NOT_FOUND; | |||||
} | |||||
ZIX_API void | |||||
zix_hash_foreach(ZixHash* hash, | |||||
ZixHashVisitFunc f, | |||||
void* user_data) | |||||
{ | |||||
for (unsigned b = 0; b < *hash->n_buckets; ++b) { | |||||
ZixHashEntry* bucket = hash->buckets[b]; | |||||
for (ZixHashEntry* e = bucket; e; e = e->next) { | |||||
f(zix_hash_value(e), user_data); | |||||
} | |||||
} | |||||
} |
@@ -1,140 +0,0 @@ | |||||
/* | |||||
Copyright 2011-2012 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. | |||||
*/ | |||||
#ifndef ZIX_HASH_H | |||||
#define ZIX_HASH_H | |||||
#include <stddef.h> | |||||
#include <stdint.h> | |||||
#include "zix/common.h" | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/** | |||||
@addtogroup zix | |||||
@{ | |||||
@name Hash | |||||
@{ | |||||
*/ | |||||
typedef struct ZixHashImpl ZixHash; | |||||
/** | |||||
Function for computing the hash of an element. | |||||
*/ | |||||
typedef uint32_t (*ZixHashFunc)(const void* value); | |||||
/** | |||||
Function to visit a hash element. | |||||
*/ | |||||
typedef void (*ZixHashVisitFunc)(void* value, | |||||
void* user_data); | |||||
/** | |||||
Create a new hash table. | |||||
To minimize space overhead, unlike many hash tables this stores a single | |||||
value, not a key and a value. Any size of value can be stored, but all the | |||||
values in the hash table must be the same size, and the values must be safe | |||||
to copy with memcpy. To get key:value behaviour, simply insert a struct | |||||
with a key and value into the hash. | |||||
@param hash_func The hashing function. | |||||
@param equal_func A function to test value equality. | |||||
@param value_size The size of the values to be stored. | |||||
*/ | |||||
ZIX_API ZixHash* | |||||
zix_hash_new(ZixHashFunc hash_func, | |||||
ZixEqualFunc equal_func, | |||||
size_t value_size); | |||||
/** | |||||
Free `hash`. | |||||
*/ | |||||
ZIX_API void | |||||
zix_hash_free(ZixHash* hash); | |||||
/** | |||||
Return the number of elements in `hash`. | |||||
*/ | |||||
ZIX_API size_t | |||||
zix_hash_size(const ZixHash* hash); | |||||
/** | |||||
Insert an item into `hash`. | |||||
If no matching value is found, ZIX_STATUS_SUCCESS will be returned, and @p | |||||
inserted will be pointed to the copy of `value` made in the new hash node. | |||||
If a matching value already exists, ZIX_STATUS_EXISTS will be returned, and | |||||
`inserted` will be pointed to the existing value. | |||||
@param hash The hash table. | |||||
@param value The value to be inserted. | |||||
@param inserted The copy of `value` in the hash table. | |||||
@return ZIX_STATUS_SUCCESS, ZIX_STATUS_EXISTS, or ZIX_STATUS_NO_MEM. | |||||
*/ | |||||
ZIX_API ZixStatus | |||||
zix_hash_insert(ZixHash* hash, | |||||
const void* value, | |||||
const void** inserted); | |||||
/** | |||||
Remove an item from `hash`. | |||||
@param hash The hash table. | |||||
@param value The value to remove. | |||||
@return ZIX_STATUS_SUCCES or ZIX_STATUS_NOT_FOUND. | |||||
*/ | |||||
ZIX_API ZixStatus | |||||
zix_hash_remove(ZixHash* hash, | |||||
const void* value); | |||||
/** | |||||
Search for an item in `hash`. | |||||
@param hash The hash table. | |||||
@param value The value to search for. | |||||
*/ | |||||
ZIX_API const void* | |||||
zix_hash_find(const ZixHash* hash, | |||||
const void* value); | |||||
/** | |||||
Call `f` on each value in `hash`. | |||||
@param hash The hash table. | |||||
@param f The function to call on each value. | |||||
@param user_data The user_data parameter passed to `f`. | |||||
*/ | |||||
ZIX_API void | |||||
zix_hash_foreach(ZixHash* hash, | |||||
ZixHashVisitFunc f, | |||||
void* user_data); | |||||
/** | |||||
@} | |||||
@} | |||||
*/ | |||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#endif /* ZIX_HASH_H */ |
@@ -1,20 +0,0 @@ | |||||
These are the tests for the Turtle Terse RDF Triple Language | |||||
that must be passed by conformant systems. See | |||||
http://www.dajobe.org/2004/01/turtle/ | |||||
for the full conformance information. | |||||
The format is a set of good tests and bad tests. | |||||
Good tests are a pair of files: | |||||
abc.ttl abc.out | |||||
which are the input Turtle file and the expected output RDF triples, | |||||
written in N-Triples. | |||||
bad tests are of the form | |||||
bad-XX.ttl | |||||
which must fail. | |||||
The tests should be performed with an assumed base URI | |||||
of http://www.w3.org/2001/sw/DataAccess/df1/tests/ | |||||
Dave |
@@ -1,126 +0,0 @@ | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#comment> "Indicates membership of a class" . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#label> "type"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#label> "type"@fr . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/2000/01/rdf-schema#comment> "The concept of Class" . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/2000/01/rdf-schema#label> "Class"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/2000/01/rdf-schema#label> "Classe"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintProperty> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintProperty> <http://www.w3.org/2000/01/rdf-schema#comment> "Properties used to express RDF Schema constraints." . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintProperty> <http://www.w3.org/2000/01/rdf-schema#label> "ConstraintProperty"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintProperty> <http://www.w3.org/2000/01/rdf-schema#label> "Propri\u00E9t\u00E9Contrainte"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintProperty> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#ConstraintResource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintProperty> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintResource> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintResource> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintResource> <http://www.w3.org/2000/01/rdf-schema#comment> "Resources used to express RDF Schema constraints." . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintResource> <http://www.w3.org/2000/01/rdf-schema#label> "ConstraintResource"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintResource> <http://www.w3.org/2000/01/rdf-schema#label> "RessourceContrainte"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#ConstraintResource> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/2000/01/rdf-schema#comment> "This represents the set Containers." . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/2000/01/rdf-schema#label> "Container"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/2000/01/rdf-schema#label> "Enveloppe"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty> <http://www.w3.org/2000/01/rdf-schema#label> "ContainerMembershipProperty"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Literal> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Literal> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Literal> <http://www.w3.org/2000/01/rdf-schema#comment> "This represents the set of atomic values, eg. textual strings." . | |||||
<http://www.w3.org/2000/01/rdf-schema#Literal> <http://www.w3.org/2000/01/rdf-schema#label> "Literal"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#Literal> <http://www.w3.org/2000/01/rdf-schema#label> "Litt\u00E9ral"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#Resource> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Resource> <http://www.w3.org/2000/01/rdf-schema#comment> "The most general class" . | |||||
<http://www.w3.org/2000/01/rdf-schema#Resource> <http://www.w3.org/2000/01/rdf-schema#label> "Resource"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#Resource> <http://www.w3.org/2000/01/rdf-schema#label> "Ressource"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#comment> "Use this for descriptions" . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#label> "comment"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#label> "commentaire"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Literal> . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#ConstraintProperty> . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#comment> "This is how we associate a class with properties that its instances can have" . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#label> "domain"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#label> "domaine"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#comment> "Indicates a resource containing and defining the subject resource." . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#label> "esD\u00E9finiPar"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#label> "isDefinedBy"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#seeAlso> . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#comment> "Provides a human-readable version of a resource name." . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#label> "label"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#label> "label"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Literal> . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#ConstraintProperty> . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#comment> "Properties that can be used in a schema to provide constraints" . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#label> "range"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#label> "\u00E9tendue"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#comment> "Indicates a resource that provides information about the subject resource." . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#label> "seeAlso"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#label> "voirAussi"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#comment> "Indicates membership of a class" . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#label> "sousClasseDe"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#label> "subClassOf"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#comment> "Indicates specialization of properties" . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#label> "sousPropri\u00E9t\u00E9De"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#label> "subPropertyOf"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt> <http://www.w3.org/2000/01/rdf-schema#label> "Alt"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt> <http://www.w3.org/2000/01/rdf-schema#label> "Choix"@fr . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Container> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> <http://www.w3.org/2000/01/rdf-schema#label> "Bag"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> <http://www.w3.org/2000/01/rdf-schema#label> "Ensemble"@fr . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Container> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/2000/01/rdf-schema#comment> "The concept of a property." . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/2000/01/rdf-schema#label> "Property"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/2000/01/rdf-schema#label> "Propri\u00E9t\u00E9"@fr . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq> <http://www.w3.org/2000/01/rdf-schema#label> "Sequence"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq> <http://www.w3.org/2000/01/rdf-schema#label> "S\u00E9quence"@fr . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Container> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/2000/01/rdf-schema#comment> "This represents the set of reified statements." . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/2000/01/rdf-schema#label> "D\u00E9claration"@fr . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/2000/01/rdf-schema#label> "Statement"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <http://www.w3.org/2000/01/rdf-schema#label> "object"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <http://www.w3.org/2000/01/rdf-schema#label> "objet"@fr . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/2000/01/rdf-schema#label> "predicate"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/2000/01/rdf-schema#label> "pr\u00E9dicat"@fr . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/2000/01/rdf-schema#label> "subject"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/2000/01/rdf-schema#label> "sujet"@fr . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#value> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#value> <http://www.w3.org/2000/01/rdf-schema#label> "object"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#value> <http://www.w3.org/2000/01/rdf-schema#label> "value"@fr . | |||||
<http://www.w3.org/2000/01/rdf-schema#> <http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema-more> . |
@@ -1,36 +0,0 @@ | |||||
_:genid1 <http://jena.hpl.hp.com/2003/03/result-set#variable> "x" . | |||||
_:genid1 <http://jena.hpl.hp.com/2003/03/result-set#value> "123"^^<http://www.w3.org/2001/XMLSchema#integer> . | |||||
_:genid2 <http://jena.hpl.hp.com/2003/03/result-set#variable> "y" . | |||||
_:genid2 <http://jena.hpl.hp.com/2003/03/result-set#value> <http://example.com/resource1> . | |||||
_:genid3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://jena.hpl.hp.com/2003/03/result-set#ResultSolution> . | |||||
_:genid3 <http://jena.hpl.hp.com/2003/03/result-set#binding> _:genid1 . | |||||
_:genid3 <http://jena.hpl.hp.com/2003/03/result-set#binding> _:genid2 . | |||||
_:genid4 <http://jena.hpl.hp.com/2003/03/result-set#variable> "x" . | |||||
_:genid4 <http://jena.hpl.hp.com/2003/03/result-set#value> "2003-01-21" . | |||||
_:genid5 <http://jena.hpl.hp.com/2003/03/result-set#variable> "y" . | |||||
_:genid5 <http://jena.hpl.hp.com/2003/03/result-set#value> <http://example.com/resource2> . | |||||
_:genid6 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://jena.hpl.hp.com/2003/03/result-set#ResultSolution> . | |||||
_:genid6 <http://jena.hpl.hp.com/2003/03/result-set#binding> _:genid4 . | |||||
_:genid6 <http://jena.hpl.hp.com/2003/03/result-set#binding> _:genid5 . | |||||
_:genid7 <http://jena.hpl.hp.com/2003/03/result-set#variable> "x" . | |||||
_:genid7 <http://jena.hpl.hp.com/2003/03/result-set#value> "anon1" . | |||||
_:genid8 <http://jena.hpl.hp.com/2003/03/result-set#variable> "y" . | |||||
_:genid8 <http://jena.hpl.hp.com/2003/03/result-set#value> _:a . | |||||
_:genid9 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://jena.hpl.hp.com/2003/03/result-set#ResultSolution> . | |||||
_:genid9 <http://jena.hpl.hp.com/2003/03/result-set#binding> _:genid7 . | |||||
_:genid9 <http://jena.hpl.hp.com/2003/03/result-set#binding> _:genid8 . | |||||
_:genid10 <http://jena.hpl.hp.com/2003/03/result-set#variable> "x" . | |||||
_:genid10 <http://jena.hpl.hp.com/2003/03/result-set#value> "anon2" . | |||||
_:genid11 <http://jena.hpl.hp.com/2003/03/result-set#variable> "y" . | |||||
_:genid11 <http://jena.hpl.hp.com/2003/03/result-set#value> _:a . | |||||
_:genid12 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://jena.hpl.hp.com/2003/03/result-set#ResultSolution> . | |||||
_:genid12 <http://jena.hpl.hp.com/2003/03/result-set#binding> _:genid10 . | |||||
_:genid12 <http://jena.hpl.hp.com/2003/03/result-set#binding> _:genid11 . | |||||
<http://www.w3.org/2001/sw/DataAccess/df1/tests/rdfq-results.ttl> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://jena.hpl.hp.com/2003/03/result-set#ResultSet> . | |||||
<http://www.w3.org/2001/sw/DataAccess/df1/tests/rdfq-results.ttl> <http://jena.hpl.hp.com/2003/03/result-set#size> "4"^^<http://www.w3.org/2001/XMLSchema#integer> . | |||||
<http://www.w3.org/2001/sw/DataAccess/df1/tests/rdfq-results.ttl> <http://jena.hpl.hp.com/2003/03/result-set#resultVariable> "x" . | |||||
<http://www.w3.org/2001/sw/DataAccess/df1/tests/rdfq-results.ttl> <http://jena.hpl.hp.com/2003/03/result-set#resultVariable> "y" . | |||||
<http://www.w3.org/2001/sw/DataAccess/df1/tests/rdfq-results.ttl> <http://jena.hpl.hp.com/2003/03/result-set#solution> _:genid3 . | |||||
<http://www.w3.org/2001/sw/DataAccess/df1/tests/rdfq-results.ttl> <http://jena.hpl.hp.com/2003/03/result-set#solution> _:genid6 . | |||||
<http://www.w3.org/2001/sw/DataAccess/df1/tests/rdfq-results.ttl> <http://jena.hpl.hp.com/2003/03/result-set#solution> _:genid9 . | |||||
<http://www.w3.org/2001/sw/DataAccess/df1/tests/rdfq-results.ttl> <http://jena.hpl.hp.com/2003/03/result-set#solution> _:genid12 . |
@@ -1,131 +0,0 @@ | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#comment> "Indicates membership of a class" . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#label> "type"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt> <http://www.w3.org/2000/01/rdf-schema#comment> "A collection of alternatives."@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt> <http://www.w3.org/2000/01/rdf-schema#label> "Alt"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Container> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> <http://www.w3.org/2000/01/rdf-schema#comment> "An unordered collection."@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> <http://www.w3.org/2000/01/rdf-schema#label> "Bag"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Container> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/2000/01/rdf-schema#comment> "The concept of a property." . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/2000/01/rdf-schema#label> "Property"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq> <http://www.w3.org/2000/01/rdf-schema#comment> "An ordered collection."@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq> <http://www.w3.org/2000/01/rdf-schema#label> "Seq"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Container> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/2000/01/rdf-schema#comment> "The class of RDF statements." . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/2000/01/rdf-schema#label> "Statement"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <http://www.w3.org/2000/01/rdf-schema#comment> "The object of an RDF statement." . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#object> <http://www.w3.org/2000/01/rdf-schema#label> "object"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/2000/01/rdf-schema#comment> "the predicate of an RDF statement." . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/2000/01/rdf-schema#label> "predicate"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/2000/01/rdf-schema#comment> "The subject of an RDF statement." . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/2000/01/rdf-schema#label> "subject"@en . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#value> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#value> <http://www.w3.org/2000/01/rdf-schema#comment> "Identifies the principal value (usually a string) of a property when the property value is a structured resource" . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#value> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#value> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |||||
<http://www.w3.org/1999/02/22-rdf-syntax-ns#value> <http://www.w3.org/2000/01/rdf-schema#label> "value"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#> <http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema-more> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/2000/01/rdf-schema#comment> "The concept of Class" . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/2000/01/rdf-schema#label> "Class"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#Class> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/2000/01/rdf-schema#comment> "This represents the set Containers." . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/2000/01/rdf-schema#label> "Container"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#Container> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty> <http://www.w3.org/2000/01/rdf-schema#comment> "The container membership properties, rdf:1, rdf:2, ..., all of which are sub-properties of 'member'." . | |||||
<http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty> <http://www.w3.org/2000/01/rdf-schema#label> "ContainerMembershipProperty"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Literal> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Literal> <http://www.w3.org/2000/01/rdf-schema#comment> "This represents the set of atomic values, eg. textual strings." . | |||||
<http://www.w3.org/2000/01/rdf-schema#Literal> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Literal> <http://www.w3.org/2000/01/rdf-schema#label> "Literal"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#Resource> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Resource> <http://www.w3.org/2000/01/rdf-schema#comment> "The class resource, everything." . | |||||
<http://www.w3.org/2000/01/rdf-schema#Resource> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#Resource> <http://www.w3.org/2000/01/rdf-schema#label> "Resource"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#comment> "Use this for descriptions" . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#label> "comment"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#comment> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Literal> . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#comment> "A domain class for a property type" . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#label> "domain"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#comment> "Indicates the namespace of a resource" . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#label> "isDefinedBy"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#seeAlso> . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#comment> "Provides a human-readable version of a resource name." . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#label> "label"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#label> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Literal> . | |||||
<http://www.w3.org/2000/01/rdf-schema#member> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#member> <http://www.w3.org/2000/01/rdf-schema#comment> "a member of a container" . | |||||
<http://www.w3.org/2000/01/rdf-schema#member> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Container> . | |||||
<http://www.w3.org/2000/01/rdf-schema#member> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#member> <http://www.w3.org/2000/01/rdf-schema#label> "member"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#comment> "A range class for a property type" . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#label> "range"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#comment> "A resource that provides information about the subject resource" . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#label> "seeAlso"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#seeAlso> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Resource> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#comment> "Indicates membership of a class" . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#label> "subClassOf"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/2000/01/rdf-schema#Class> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#comment> "Indicates specialization of properties" . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#isDefinedBy> <http://www.w3.org/2000/01/rdf-schema#> . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#label> "subPropertyOf"@en . | |||||
<http://www.w3.org/2000/01/rdf-schema#subPropertyOf> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> . |
@@ -1 +0,0 @@ | |||||
_:b1 <http://www.w3.org/2001/sw/DataAccess/df1/tests/test-00.ttl#x> <http://www.w3.org/2001/sw/DataAccess/df1/tests/test-00.ttl#y> . |
@@ -1,3 +0,0 @@ | |||||
<http://example.org/base1#a> <http://example.org/base1#b> <http://example.org/base1#c> . | |||||
<http://example.org/base2#a> <http://example.org/base2#b> <http://example.org/base2#c> . | |||||
<http://example.org/base1#a> <http://example.org/base2#a> <http://example.org/base3#a> . |
@@ -1,3 +0,0 @@ | |||||
<http://example.org/base#a> <http://example.org/base#b> <http://example.org/base#c> . | |||||
<http://example.org/base#a> <http://example.org/base#b> <http://example.org/base#d> . | |||||
<http://example.org/base#a> <http://example.org/base#b> <http://example.org/base#e> . |
@@ -1,3 +0,0 @@ | |||||
<http://example.org/base#a> <http://example.org/base#b> <http://example.org/base#c> . | |||||
<http://example.org/base#a> <http://example.org/base#d> <http://example.org/base#e> . | |||||
<http://example.org/base#a> <http://example.org/base#f> <http://example.org/base#g> . |
@@ -1,2 +0,0 @@ | |||||
_:b1 <http://example.org/base#a> <http://example.org/base#b> . | |||||
<http://example.org/base#c> <http://example.org/base#d> _:b2 . |
@@ -1,4 +0,0 @@ | |||||
_:b1 <http://example.org/base#a> <http://example.org/base#b> . | |||||
_:b1 <http://example.org/base#c> <http://example.org/base#d> . | |||||
<http://example.org/base#e> <http://example.org/base#f> _:b2 . | |||||
_:b2 <http://example.org/base#g> <http://example.org/base#h> . |
@@ -1 +0,0 @@ | |||||
<http://example.org/base#a> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/base#b> . |
@@ -1,5 +0,0 @@ | |||||
<http://example.org/stuff/1.0/a> <http://example.org/stuff/1.0/b> _:b1 . | |||||
_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "apple" . | |||||
_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:b2 . | |||||
_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "banana" . | |||||
_:b2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . |
@@ -1 +0,0 @@ | |||||
<http://example.org/stuff/1.0/a> <http://example.org/stuff/1.0/b> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . |
@@ -1,4 +0,0 @@ | |||||
_:hasParent <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#ObjectProperty> . | |||||
_:b1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Restriction> . | |||||
_:b1 <http://www.w3.org/2002/07/owl#onProperty> _:hasParent . | |||||
_:b1 <http://www.w3.org/2002/07/owl#maxCardinality> "2"^^<http://www.w3.org/2001/XMLSchema#integer> . |
@@ -1,5 +0,0 @@ | |||||
<http://example.org/res1> <http://example.org/prop1> "000000"^^<http://www.w3.org/2001/XMLSchema#integer> . | |||||
<http://example.org/res2> <http://example.org/prop2> "0"^^<http://www.w3.org/2001/XMLSchema#integer> . | |||||
<http://example.org/res3> <http://example.org/prop3> "000001"^^<http://www.w3.org/2001/XMLSchema#integer> . | |||||
<http://example.org/res4> <http://example.org/prop4> "2"^^<http://www.w3.org/2001/XMLSchema#integer> . | |||||
<http://example.org/res5> <http://example.org/prop5> "4"^^<http://www.w3.org/2001/XMLSchema#integer> . |
@@ -1,4 +0,0 @@ | |||||
<http://example.org/ex1#foo-bar> <http://example.org/ex1#foo_bar> "a" . | |||||
<http://example.org/ex2#foo-bar> <http://example.org/ex2#foo_bar> "b" . | |||||
<http://example.org/ex3#foo-bar> <http://example.org/ex3#foo_bar> "c" . | |||||
<http://example.org/ex4#foo-bar> <http://example.org/ex4#foo_bar> "d" . |
@@ -1,4 +0,0 @@ | |||||
<http://example.org/ex#foo> <http://www.w3.org/1999/02/22-rdf-syntax-ns#_1> "1" . | |||||
<http://example.org/ex#foo> <http://www.w3.org/1999/02/22-rdf-syntax-ns#_2> "2" . | |||||
<http://example.org/ex#foo> <http://example.org/myprop#_abc> "def" . | |||||
<http://example.org/ex#foo> <http://example.org/myprop#_345> "678" . |
@@ -1,2 +0,0 @@ | |||||
_:b1 <http://example.org/ron> _:b2 . | |||||
<http://example.org/ron> <http://example.org/ron> <http://example.org/ron> . |
@@ -1 +0,0 @@ | |||||
<http://example.org/ex#a> <http://example.org/ex#b> "a long\n\tliteral\nwith\nnewlines" . |
@@ -1,2 +0,0 @@ | |||||
<http://example.org/foo#a> <http://example.org/foo#b> "\nthis \ris a \U00015678long\t\nliteral\uABCD\n" . | |||||
<http://example.org/foo#d> <http://example.org/foo#e> "\tThis \uABCDis\r \U00015678another\n\none\n" . |
@@ -1 +0,0 @@ | |||||
<http://example.org/#a> <http://example.org/#b> "1.0"^^<http://www.w3.org/2001/XMLSchema#decimal> . |
@@ -1,2 +0,0 @@ | |||||
<http://example.org/#a> <http://example.org/#b> "" . | |||||
<http://example.org/#c> <http://example.org/#d> "" . |
@@ -1,3 +0,0 @@ | |||||
<http://example.org#a> <http://example.org#b> "1.0"^^<http://www.w3.org/2001/XMLSchema#decimal> . | |||||
<http://example.org#c> <http://example.org#d> "1"^^<http://www.w3.org/2001/XMLSchema#integer> . | |||||
<http://example.org#e> <http://example.org#f> "1.0e0"^^<http://www.w3.org/2001/XMLSchema#double> . |
@@ -1,3 +0,0 @@ | |||||
<http://example.org#a> <http://example.org#b> "-1.0"^^<http://www.w3.org/2001/XMLSchema#decimal> . | |||||
<http://example.org#c> <http://example.org#d> "-1"^^<http://www.w3.org/2001/XMLSchema#integer> . | |||||
<http://example.org#e> <http://example.org#f> "-1.0e0"^^<http://www.w3.org/2001/XMLSchema#double> . |
@@ -1 +0,0 @@ | |||||
<http://example.org/ex#a> <http://example.org/ex#b> "John said: \"Hello World!\"" . |
@@ -1,2 +0,0 @@ | |||||
<http://example.org#a> <http://example.org#b> "true"^^<http://www.w3.org/2001/XMLSchema#boolean> . | |||||
<http://example.org#c> <http://example.org#d> "false"^^<http://www.w3.org/2001/XMLSchema#boolean> . |
@@ -1,7 +0,0 @@ | |||||
<http://example.org/#a> <http://example.org/#b> <http://example.org/#c> . | |||||
<http://example.org/#d> <http://example.org/#e> <http://example.org/#f> . | |||||
<http://example.org/#g> <http://example.org/#h> <http://example.org/#i> . | |||||
<http://example.org/#g> <http://example.org/#h> <http://example.org/#j> . | |||||
<http://example.org/#k> <http://example.org/#l> <http://example.org/#m> . | |||||
<http://example.org/#k> <http://example.org/#n> <http://example.org/#o> . | |||||
<http://example.org/#k> <http://example.org/#p> <http://example.org/#q> . |
@@ -1 +0,0 @@ | |||||
<http://example.org/#a> <http://example.org/#b> <http://example.org/#c> . |
@@ -1 +0,0 @@ | |||||
<http://example.org/bar#blah> <http://example.org/bar#blah> <http://example.org/bar#blah> . |
@@ -1,5 +0,0 @@ | |||||
<http://www.w3.org/2001/sw/DataAccess/df1/tests/a1> <http://www.w3.org/2001/sw/DataAccess/df1/tests/b1> <http://www.w3.org/2001/sw/DataAccess/df1/tests/c1> . | |||||
<http://example.org/ns/a2> <http://example.org/ns/b2> <http://example.org/ns/c2> . | |||||
<http://example.org/ns/foo/a3> <http://example.org/ns/foo/b3> <http://example.org/ns/foo/c3> . | |||||
<http://example.org/ns/foo/bar#a4> <http://example.org/ns/foo/bar#b4> <http://example.org/ns/foo/bar#c4> . | |||||
<http://example.org/ns2#a5> <http://example.org/ns2#b5> <http://example.org/ns2#c5> . |
@@ -1,2 +0,0 @@ | |||||
<http://example.org/base#c> <http://example.org/base#d> _:b1 . | |||||
_:B1 <http://example.org/base#a> <http://example.org/base#b> . |
@@ -1,5 +0,0 @@ | |||||
<http://example.org/test-lang#thing> <http://example.org/test-lang#greeting> "Hello"@en . | |||||
<http://example.org/test-lang#thing> <http://example.org/test-lang#greeting> "Howdy"@en-us . | |||||
<http://example.org/test-lang#thing> <http://example.org/test-lang#greeting> "Bonjour"@fr . | |||||
<http://example.org/test-lang#thing> <http://example.org/test-lang#greeting> "Guten Tag"@de-latn-de . | |||||
<http://example.org/test-lang#thing> <http://example.org/test-lang#greeting> "HEY MAN"@en-crazy0place . |
@@ -1,10 +0,0 @@ | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> "0.1"^^<http://www.w3.org/2001/XMLSchema#decimal> . | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> "+0.2"^^<http://www.w3.org/2001/XMLSchema#decimal> . | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> "-0.3"^^<http://www.w3.org/2001/XMLSchema#decimal> . | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> ".4"^^<http://www.w3.org/2001/XMLSchema#decimal> . | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> "+.5"^^<http://www.w3.org/2001/XMLSchema#decimal> . | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> "-.6"^^<http://www.w3.org/2001/XMLSchema#decimal> . | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> "1.58490e-05"^^<http://www.w3.org/2001/XMLSchema#double> . | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> "1.58490e+05"^^<http://www.w3.org/2001/XMLSchema#double> . | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> "1.58490e05"^^<http://www.w3.org/2001/XMLSchema#double> . | |||||
<http://example.org/eg#thing> <http://example.org/eg#num> "1.58490E05"^^<http://www.w3.org/2001/XMLSchema#double> . |
@@ -1,322 +0,0 @@ | |||||
#!/usr/bin/env python | |||||
import glob | |||||
import os | |||||
import subprocess | |||||
import waflib.Logs as Logs | |||||
import waflib.Options as Options | |||||
import waflib.extras.autowaf as autowaf | |||||
# Library and package version (UNIX style major, minor, micro) | |||||
# major increment <=> incompatible changes | |||||
# minor increment <=> compatible changes (additions) | |||||
# micro increment <=> no interface changes | |||||
SORD_VERSION = '0.13.0' | |||||
SORD_MAJOR_VERSION = '0' | |||||
# Mandatory waf variables | |||||
APPNAME = 'sord' # Package name for waf dist | |||||
VERSION = SORD_VERSION # Package version for waf dist | |||||
top = '.' # Source directory | |||||
out = 'build' # Build directory | |||||
def options(opt): | |||||
opt.load('compiler_c') | |||||
opt.load('compiler_cxx') | |||||
autowaf.set_options(opt) | |||||
opt.add_option('--no-utils', action='store_true', dest='no_utils', | |||||
help='Do not build command line utilities') | |||||
opt.add_option('--test', action='store_true', dest='build_tests', | |||||
help='Build unit tests') | |||||
opt.add_option('--static', action='store_true', dest='static', | |||||
help='Build static library') | |||||
opt.add_option('--no-shared', action='store_true', dest='no_shared', | |||||
help='Do not build shared library') | |||||
opt.add_option('--static-progs', action='store_true', dest='static_progs', | |||||
help='Build programs as static binaries') | |||||
opt.add_option('--dump', type='string', default='', dest='dump', | |||||
help='Dump debugging output (iter, search, write, all)') | |||||
def configure(conf): | |||||
conf.load('compiler_c') | |||||
if Options.options.build_tests: | |||||
try: | |||||
conf.load('compiler_cxx') | |||||
except: | |||||
Logs.warn("No C++ compiler, sordmm.hpp compile test skipped") | |||||
pass | |||||
autowaf.configure(conf) | |||||
autowaf.set_c99_mode(conf) | |||||
autowaf.display_header('Sord configuration') | |||||
conf.env.BUILD_TESTS = Options.options.build_tests | |||||
conf.env.BUILD_UTILS = not Options.options.no_utils | |||||
conf.env.BUILD_SHARED = not Options.options.no_shared | |||||
conf.env.STATIC_PROGS = Options.options.static_progs | |||||
conf.env.BUILD_STATIC = (Options.options.static or | |||||
Options.options.static_progs) | |||||
if conf.env.BUILD_TESTS: | |||||
conf.check(lib = 'gcov', | |||||
define_name = 'HAVE_GCOV', | |||||
mandatory = False) | |||||
autowaf.check_pkg(conf, 'serd-0', uselib_store='SERD', | |||||
atleast_version='0.18.0', mandatory=True) | |||||
autowaf.check_pkg(conf, 'libpcre', uselib_store='PCRE', mandatory=False) | |||||
if conf.env.HAVE_PCRE: | |||||
if conf.check(cflags=['-pthread'], mandatory=False): | |||||
conf.env.PTHREAD_CFLAGS = ['-pthread'] | |||||
conf.env.PTHREAD_LINKFLAGS = ['-pthread'] | |||||
elif conf.check(linkflags=['-lpthread'], mandatory=False): | |||||
conf.env.PTHREAD_CFLAGS = [] | |||||
conf.env.PTHREAD_LINKFLAGS = ['-lpthread'] | |||||
else: | |||||
conf.env.PTHREAD_CFLAGS = [] | |||||
conf.env.PTHREAD_LINKFLAGS = [] | |||||
# Parse dump options and define things accordingly | |||||
dump = Options.options.dump.split(',') | |||||
all = 'all' in dump | |||||
if all or 'iter' in dump: | |||||
autowaf.define(conf, 'SORD_DEBUG_ITER', 1) | |||||
if all or 'search' in dump: | |||||
autowaf.define(conf, 'SORD_DEBUG_SEARCH', 1) | |||||
if all or 'write' in dump: | |||||
autowaf.define(conf, 'SORD_DEBUG_WRITE', 1) | |||||
autowaf.define(conf, 'SORD_VERSION', SORD_VERSION) | |||||
autowaf.set_lib_env(conf, 'sord', SORD_VERSION) | |||||
conf.write_config_header('sord_config.h', remove=False) | |||||
autowaf.display_msg(conf, 'Utilities', bool(conf.env.BUILD_UTILS)) | |||||
autowaf.display_msg(conf, 'Unit tests', bool(conf.env.BUILD_TESTS)) | |||||
autowaf.display_msg(conf, 'Debug dumping', dump) | |||||
print('') | |||||
def build(bld): | |||||
# C/C++ Headers | |||||
includedir = '${INCLUDEDIR}/sord-%s/sord' % SORD_MAJOR_VERSION | |||||
bld.install_files(includedir, bld.path.ant_glob('sord/*.h')) | |||||
bld.install_files(includedir, bld.path.ant_glob('sord/*.hpp')) | |||||
# Pkgconfig file | |||||
autowaf.build_pc(bld, 'SORD', SORD_VERSION, SORD_MAJOR_VERSION, 'SERD', | |||||
{'SORD_MAJOR_VERSION' : SORD_MAJOR_VERSION}) | |||||
source = 'src/sord.c src/syntax.c' | |||||
libflags = ['-fvisibility=hidden'] | |||||
libs = ['m'] | |||||
defines = [] | |||||
if bld.env.MSVC_COMPILER: | |||||
libflags = [] | |||||
libs = [] | |||||
defines = ['snprintf=_snprintf'] | |||||
# Shared Library | |||||
if bld.env.BUILD_SHARED: | |||||
obj = bld(features = 'c cshlib', | |||||
source = source, | |||||
includes = ['.', './src'], | |||||
export_includes = ['.'], | |||||
name = 'libsord', | |||||
target = 'sord-%s' % SORD_MAJOR_VERSION, | |||||
vnum = SORD_VERSION, | |||||
install_path = '${LIBDIR}', | |||||
libs = libs, | |||||
defines = defines + ['SORD_SHARED', 'SORD_INTERNAL'], | |||||
cflags = libflags) | |||||
autowaf.use_lib(bld, obj, 'SERD') | |||||
# Static Library | |||||
if bld.env.BUILD_STATIC: | |||||
obj = bld(features = 'c cstlib', | |||||
source = source, | |||||
includes = ['.', './src'], | |||||
export_includes = ['.'], | |||||
name = 'libsord_static', | |||||
target = 'sord-%s' % SORD_MAJOR_VERSION, | |||||
vnum = SORD_VERSION, | |||||
install_path = '${LIBDIR}', | |||||
libs = libs, | |||||
defines = ['SORD_INTERNAL']) | |||||
autowaf.use_lib(bld, obj, 'SERD') | |||||
if bld.env.BUILD_TESTS: | |||||
test_libs = libs | |||||
test_cflags = [''] | |||||
if bld.is_defined('HAVE_GCOV'): | |||||
test_libs += ['gcov'] | |||||
test_cflags += ['-fprofile-arcs', '-ftest-coverage'] | |||||
# Profiled static library for test coverage | |||||
obj = bld(features = 'c cstlib', | |||||
source = source, | |||||
includes = ['.', './src'], | |||||
name = 'libsord_profiled', | |||||
target = 'sord_profiled', | |||||
install_path = '', | |||||
defines = defines, | |||||
cflags = test_cflags, | |||||
lib = test_libs) | |||||
autowaf.use_lib(bld, obj, 'SERD') | |||||
# Unit test program | |||||
obj = bld(features = 'c cprogram', | |||||
source = 'src/sord_test.c', | |||||
includes = ['.', './src'], | |||||
use = 'libsord_profiled', | |||||
lib = test_libs, | |||||
target = 'sord_test', | |||||
install_path = '', | |||||
defines = defines, | |||||
cflags = test_cflags) | |||||
autowaf.use_lib(bld, obj, 'SERD') | |||||
# Static profiled sordi for tests | |||||
obj = bld(features = 'c cprogram', | |||||
source = 'src/sordi.c', | |||||
includes = ['.', './src'], | |||||
use = 'libsord_profiled', | |||||
lib = test_libs, | |||||
target = 'sordi_static', | |||||
install_path = '', | |||||
defines = defines, | |||||
cflags = test_cflags) | |||||
autowaf.use_lib(bld, obj, 'SERD') | |||||
# C++ build test | |||||
if bld.env.COMPILER_CXX: | |||||
obj = bld(features = 'cxx cxxprogram', | |||||
source = 'src/sordmm_test.cpp', | |||||
includes = ['.', './src'], | |||||
use = 'libsord_profiled', | |||||
lib = test_libs, | |||||
target = 'sordmm_test', | |||||
install_path = '', | |||||
defines = defines) | |||||
autowaf.use_lib(bld, obj, 'SERD') | |||||
# Utilities | |||||
if bld.env.BUILD_UTILS: | |||||
utils = ['sordi'] | |||||
if bld.env.HAVE_PCRE: | |||||
utils += ['sord_validate'] | |||||
for i in utils: | |||||
obj = bld(features = 'c cprogram', | |||||
source = 'src/%s.c' % i, | |||||
includes = ['.', './src'], | |||||
use = 'libsord', | |||||
lib = libs, | |||||
target = i, | |||||
install_path = '${BINDIR}', | |||||
defines = defines) | |||||
if not bld.env.BUILD_SHARED or bld.env.STATIC_PROGS: | |||||
obj.use = 'libsord_static' | |||||
if bld.env.STATIC_PROGS: | |||||
obj.env.SHLIB_MARKER = obj.env.STLIB_MARKER | |||||
obj.linkflags = ['-static', '-Wl,--start-group'] | |||||
autowaf.use_lib(bld, obj, 'SERD') | |||||
if i == 'sord_validate': | |||||
autowaf.use_lib(bld, obj, 'PCRE') | |||||
obj.cflags = bld.env.PTHREAD_CFLAGS | |||||
obj.linkflags = bld.env.PTHREAD_LINKFLAGS | |||||
# Documentation | |||||
autowaf.build_dox(bld, 'SORD', SORD_VERSION, top, out) | |||||
# Man pages | |||||
bld.install_files('${MANDIR}/man1', bld.path.ant_glob('doc/*.1')) | |||||
if bld.env.DOCS: | |||||
bld.add_post_fun(fix_docs) | |||||
def lint(ctx): | |||||
subprocess.call('cpplint.py --filter=+whitespace/comments,-whitespace/tab,-whitespace/braces,-whitespace/labels,-build/header_guard,-readability/casting,-readability/todo,-build/include src/*.* sord/* src/zix/*.*', shell=True) | |||||
def fix_docs(ctx): | |||||
if ctx.cmd == 'build': | |||||
autowaf.make_simple_dox(APPNAME) | |||||
def upload_docs(ctx): | |||||
os.system('rsync -ravz --delete -e ssh build/doc/html/ drobilla@drobilla.net:~/drobilla.net/docs/sord/') | |||||
for page in glob.glob('doc/*.[1-8]'): | |||||
os.system('soelim %s | pre-grohtml troff -man -wall -Thtml | post-grohtml > build/%s.html' % (page, page)) | |||||
os.system('rsync -avz --delete -e ssh build/%s.html drobilla@drobilla.net:~/drobilla.net/man/' % page) | |||||
def test(ctx): | |||||
blddir = autowaf.build_dir(APPNAME, 'tests') | |||||
try: | |||||
os.makedirs(blddir) | |||||
except: | |||||
pass | |||||
for i in glob.glob(blddir + '/*.*'): | |||||
os.remove(i) | |||||
srcdir = ctx.path.abspath() | |||||
orig_dir = os.path.abspath(os.curdir) | |||||
os.chdir(srcdir) | |||||
good_tests = glob.glob('tests/test-*.ttl') | |||||
good_tests.sort() | |||||
os.chdir(orig_dir) | |||||
autowaf.pre_test(ctx, APPNAME) | |||||
os.environ['PATH'] = '.' + os.pathsep + os.getenv('PATH') | |||||
nul = os.devnull | |||||
autowaf.run_tests(ctx, APPNAME, [ | |||||
'sordi_static file://%s/tests/manifest.ttl > %s' % (srcdir, nul), | |||||
'sordi_static %s/tests/UTF-8.ttl > %s' % (srcdir, nul), | |||||
'sordi_static -v > %s' % nul, | |||||
'sordi_static -h > %s' % nul, | |||||
'sordi_static -s "<foo> a <#Thingie> ." file:///test > %s' % nul, | |||||
'sordi_static %s > %s' % (nul, nul)], | |||||
0, name='sordi-cmd-good') | |||||
autowaf.run_tests(ctx, APPNAME, [ | |||||
'sordi_static > %s' % nul, | |||||
'sordi_static ftp://example.org/unsupported.ttl > %s' % nul, | |||||
'sordi_static -i > %s' % nul, | |||||
'sordi_static -o > %s' % nul, | |||||
'sordi_static -z > %s' % nul, | |||||
'sordi_static -p > %s' % nul, | |||||
'sordi_static -c > %s' % nul, | |||||
'sordi_static -i illegal > %s' % nul, | |||||
'sordi_static -o illegal > %s' % nul, | |||||
'sordi_static -i turtle > %s' % nul, | |||||
'sordi_static /no/such/file > %s' % nul], | |||||
1, name='sordi-cmd-bad') | |||||
autowaf.run_tests(ctx, APPNAME, ['sord_test']) | |||||
commands = [] | |||||
for test in good_tests: | |||||
base_uri = 'http://www.w3.org/2001/sw/DataAccess/df1/' + test.replace('\\', '/') | |||||
commands += [ 'sordi_static "%s" "%s" > %s.out' % ( | |||||
os.path.join(srcdir, test), base_uri, test) ] | |||||
autowaf.run_tests(ctx, APPNAME, commands, 0, name='good') | |||||
Logs.pprint('BOLD', '\nVerifying turtle => ntriples') | |||||
for test in good_tests: | |||||
out_filename = test + '.out' | |||||
cmp_filename = srcdir + '/' + test.replace('.ttl', '.out') | |||||
if not os.access(out_filename, os.F_OK): | |||||
Logs.pprint('RED', 'FAIL: %s output is missing' % test) | |||||
else: | |||||
out_lines = sorted(open(out_filename).readlines()) | |||||
cmp_lines = sorted(open(cmp_filename).readlines()) | |||||
if out_lines != cmp_lines: | |||||
Logs.pprint('RED', 'FAIL: %s is incorrect' % out_filename) | |||||
else: | |||||
Logs.pprint('GREEN', 'Pass: %s' % test) | |||||
autowaf.post_test(ctx, APPNAME) |