@@ -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 | |||
SORD_VERSION = 0.13.0 | |||
SORD_VERSION = 0.14.0 | |||
SRATOM_VERSION = 0.4.7 | |||
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) |