| @@ -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) | |||