rdf-raptor 0.4.2 → 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +32 -11
- data/VERSION +1 -1
- data/lib/rdf/raptor/cli.rb +0 -1
- data/lib/rdf/raptor/ffi/v1/parser.rb +1 -1
- data/lib/rdf/raptor/ffi/v2/iostream.rb +56 -0
- data/lib/rdf/raptor/ffi/v2/iostream_handler.rb +153 -0
- data/lib/rdf/raptor/ffi/v2/parser.rb +205 -0
- data/lib/rdf/raptor/ffi/v2/serializer.rb +137 -0
- data/lib/rdf/raptor/ffi/v2/statement.rb +143 -0
- data/lib/rdf/raptor/ffi/v2/term.rb +95 -0
- data/lib/rdf/raptor/ffi/v2/uri.rb +111 -0
- data/lib/rdf/raptor/ffi/v2/world.rb +20 -0
- data/lib/rdf/raptor/ffi/v2.rb +156 -0
- data/lib/rdf/raptor/ffi.rb +13 -14
- data/lib/rdf/raptor/format.rb +1 -1
- data/lib/rdf/raptor.rb +1 -1
- metadata +19 -10
data/README
CHANGED
@@ -2,8 +2,8 @@ Raptor RDF Parser Plugin for RDF.rb
|
|
2
2
|
===================================
|
3
3
|
[![Build Status](https://secure.travis-ci.org/ruby-rdf/rdf-raptor.png?branch=master)](http://travis-ci.org/ruby-rdf/rdf-raptor)
|
4
4
|
|
5
|
-
This is an [RDF.rb][] plugin that adds support for parsing/serializing
|
6
|
-
[RDF/XML][], [Turtle][] and [
|
5
|
+
This is an [RDF.rb][] plugin that adds support for parsing/serializing [NTriples][],
|
6
|
+
[RDF/XML][], [Turtle][], [RDFa][], and [Graphviz][] data using the [Raptor RDF Parser][Raptor]
|
7
7
|
library.
|
8
8
|
|
9
9
|
* <http://github.com/ruby-rdf/rdf-raptor>
|
@@ -12,12 +12,13 @@ library.
|
|
12
12
|
Features
|
13
13
|
--------
|
14
14
|
|
15
|
-
*
|
16
|
-
* Parses and serializes RDF data from/into the RDF/XML
|
15
|
+
* Uses the fast [Raptor][] C library.
|
16
|
+
* Parses and serializes RDF data from/into the NTriples, RDF/XML, and Turtle formats.
|
17
17
|
* Extracts RDF statements from XHTML+RDFa documents.
|
18
|
+
* Serializes RDF statements into Graphviz format.
|
18
19
|
* Provides serialization format autodetection for RDF/XML, Turtle and RDFa.
|
19
20
|
* Compatible with any operating system supported by Raptor and Ruby.
|
20
|
-
* Compatible with MRI 1.8.x, 1.9.x
|
21
|
+
* Compatible with MRI 1.8.x, 1.9.x, REE, JRuby and Rubinius (1.8 and 1.9 mode).
|
21
22
|
|
22
23
|
Examples
|
23
24
|
--------
|
@@ -27,7 +28,15 @@ Examples
|
|
27
28
|
### Ensuring Raptor is installed and obtaining the version number
|
28
29
|
|
29
30
|
RDF::Raptor.available? #=> true
|
30
|
-
RDF::Raptor.version #=> "
|
31
|
+
RDF::Raptor.version #=> "2.0.8"
|
32
|
+
|
33
|
+
### Parsing RDF statements from an NTriples file
|
34
|
+
|
35
|
+
RDF::Reader.open("http://datagraph.org/jhacker/foaf.nt") do |reader|
|
36
|
+
reader.each_statement do |statement|
|
37
|
+
puts statement.inspect
|
38
|
+
end
|
39
|
+
end
|
31
40
|
|
32
41
|
### Parsing RDF statements from an RDF/XML file
|
33
42
|
|
@@ -105,6 +114,14 @@ Examples
|
|
105
114
|
RDF::Format.for(:file_extension => "html")
|
106
115
|
RDF::Format.for(:content_type => "application/xhtml+xml")
|
107
116
|
|
117
|
+
### Obtaining the Graphviz format specification class
|
118
|
+
|
119
|
+
RDF::Format.for(:graphviz) #=> RDF::Raptor::Graphviz::Format
|
120
|
+
RDF::Format.for("output.dot")
|
121
|
+
RDF::Format.for(:file_name => "output.dot")
|
122
|
+
RDF::Format.for(:file_extension => "")
|
123
|
+
RDF::Format.for(:content_type => "text/vnd.graphviz")
|
124
|
+
|
108
125
|
Documentation
|
109
126
|
-------------
|
110
127
|
|
@@ -120,9 +137,9 @@ Documentation
|
|
120
137
|
Dependencies
|
121
138
|
------------
|
122
139
|
|
123
|
-
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.3.
|
140
|
+
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.3.8)
|
124
141
|
* [FFI](http://rubygems.org/gems/ffi) (>= 1.0.0)
|
125
|
-
* [Raptor][] (>=
|
142
|
+
* [Raptor][] (>= 2.0), the `libraptor` library or the `rapper` binary
|
126
143
|
|
127
144
|
Installation
|
128
145
|
------------
|
@@ -140,7 +157,8 @@ Mac and the most common Linux and BSD distributions:
|
|
140
157
|
% [sudo] port install raptor # Mac OS X with MacPorts
|
141
158
|
% [sudo] fink install raptor-bin # Mac OS X with Fink
|
142
159
|
% brew install raptor # Mac OS X with Homebrew
|
143
|
-
% [sudo] aptitude install raptor-utils # Ubuntu / Debian
|
160
|
+
% [sudo] aptitude install raptor-utils # Ubuntu / Debian with aptitude
|
161
|
+
% [sudo] apt-get install libraptor2-0 # Ubuntu / Debian with apt-get
|
144
162
|
% [sudo] yum install raptor # Fedora / CentOS / RHEL
|
145
163
|
% [sudo] zypper install raptor # openSUSE
|
146
164
|
% [sudo] emerge raptor # Gentoo Linux
|
@@ -175,18 +193,21 @@ Contributors
|
|
175
193
|
------------
|
176
194
|
|
177
195
|
* [Ben Lavender](http://github.com/bhuga) - <http://bhuga.net/>
|
178
|
-
* [David Butler](http://github.com/dwbutler)
|
196
|
+
* [David Butler](http://github.com/dwbutler) - <http://github.com/dwbutler>
|
179
197
|
* [Gregg Kellogg](http://github.com/gkellogg) - <http://greggkellogg.net/>
|
180
198
|
|
181
199
|
License
|
182
200
|
-------
|
183
201
|
|
184
202
|
This is free and unencumbered public domain software. For more information,
|
185
|
-
see <http://unlicense.org/> or the accompanying
|
203
|
+
see <http://unlicense.org/> or the accompanying [UNLICENSE][] file.
|
186
204
|
|
187
205
|
[RDF.rb]: http://rdf.rubyforge.org/
|
206
|
+
[NTriples]: http://en.wikipedia.org/wiki/N-Triples
|
188
207
|
[RDF/XML]: http://www.w3.org/TR/REC-rdf-syntax/
|
189
208
|
[Turtle]: http://en.wikipedia.org/wiki/Turtle_(syntax)
|
190
209
|
[RDFa]: http://rdfa.info/
|
210
|
+
[Graphviz]: http://www.graphviz.org/
|
191
211
|
[Raptor]: http://librdf.org/raptor/
|
192
212
|
[rapper]: http://librdf.org/raptor/rapper.html
|
213
|
+
[UNLICENSE]:https://github.com/ruby-rdf/rdf-raptor/blob/master/UNLICENSE
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0.beta1
|
data/lib/rdf/raptor/cli.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
module RDF::Raptor::FFI::V2
|
2
|
+
##
|
3
|
+
# This class provides an I/O stream that can write to filenames, `FILE*`,
|
4
|
+
# strings and user-defined output via callbacks.
|
5
|
+
#
|
6
|
+
# @see http://librdf.org/raptor/api-1.4/raptor-section-iostream.html
|
7
|
+
class IOStream < ::FFI::ManagedStruct
|
8
|
+
include RDF::Raptor::FFI
|
9
|
+
layout :world, :pointer,
|
10
|
+
:user_data, :pointer,
|
11
|
+
:handler, :pointer,
|
12
|
+
:offset, :size_t,
|
13
|
+
:mode, :int,
|
14
|
+
:flags, :int
|
15
|
+
|
16
|
+
##
|
17
|
+
# @overload initialize(ptr)
|
18
|
+
# @param [FFI::Pointer] ptr
|
19
|
+
#
|
20
|
+
# @overload initialize(handler)
|
21
|
+
# @param [V2::IOStreamHandler] handler
|
22
|
+
#
|
23
|
+
# @overload initialize(file)
|
24
|
+
# @param [File, Tempfile] file
|
25
|
+
#
|
26
|
+
def initialize(ptr_or_obj, options = {})
|
27
|
+
ptr = case ptr_or_obj
|
28
|
+
when FFI::Pointer
|
29
|
+
ptr_or_obj
|
30
|
+
when V2::IOStreamHandler
|
31
|
+
@handler = ptr_or_obj # prevents premature GC
|
32
|
+
V2.raptor_new_iostream_from_handler(V2.world, self, @handler)
|
33
|
+
when File, Tempfile
|
34
|
+
V2.raptor_new_iostream_to_filename(V2.world, File.expand_path(ptr_or_obj.path))
|
35
|
+
when false
|
36
|
+
V2.raptor_new_iostream_to_sink(V2.world)
|
37
|
+
else nil
|
38
|
+
end
|
39
|
+
raise ArgumentError, "invalid argument: #{ptr_or_obj.inspect}" if ptr.nil? || ptr.null?
|
40
|
+
|
41
|
+
@free_iostream = options[:free_iostream] || true
|
42
|
+
super(ptr)
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Releases `libraptor` memory associated with this structure.
|
47
|
+
#
|
48
|
+
# @param [FFI::Pointer] ptr
|
49
|
+
# @return [void]
|
50
|
+
def self.release(ptr)
|
51
|
+
if @free_iostream
|
52
|
+
V2.raptor_free_iostream(ptr)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end # IOStream
|
56
|
+
end # RDF::Raptor::FFI::V2
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module RDF::Raptor::FFI::V2
|
2
|
+
##
|
3
|
+
# @see http://librdf.org/raptor/api-1.4/raptor-section-iostream.html
|
4
|
+
class IOStreamHandler < ::FFI::Struct
|
5
|
+
include RDF::Raptor::FFI
|
6
|
+
layout :version, :int,
|
7
|
+
:init, :raptor_iostream_init_func,
|
8
|
+
:finish, :raptor_iostream_finish_func,
|
9
|
+
:write_byte, :raptor_iostream_write_byte_func,
|
10
|
+
:write_bytes, :raptor_iostream_write_bytes_func,
|
11
|
+
:write_end, :raptor_iostream_write_end_func,
|
12
|
+
:read_bytes, :raptor_iostream_read_bytes_func,
|
13
|
+
:read_eof, :raptor_iostream_read_eof_func
|
14
|
+
|
15
|
+
HANDLERS = [:init, :finish, :write_byte, :write_bytes, :read_bytes, :read_eof]
|
16
|
+
|
17
|
+
##
|
18
|
+
# The IO object to operate upon.
|
19
|
+
#
|
20
|
+
# @return [IO]
|
21
|
+
attr_accessor :io
|
22
|
+
|
23
|
+
##
|
24
|
+
# @overload initialize(ptr)
|
25
|
+
# @param [FFI::Pointer] ptr
|
26
|
+
#
|
27
|
+
# @overload initialize(io)
|
28
|
+
# @param [IO, StringIO] io
|
29
|
+
#
|
30
|
+
def initialize(ptr_or_io = nil)
|
31
|
+
if ptr_or_io.respond_to?(:write)
|
32
|
+
@io = ptr_or_io
|
33
|
+
super()
|
34
|
+
else
|
35
|
+
case ptr_or_io
|
36
|
+
when FFI::Pointer
|
37
|
+
super(ptr_or_io)
|
38
|
+
when nil
|
39
|
+
super()
|
40
|
+
else
|
41
|
+
raise ArgumentError, "invalid argument: #{ptr_or_io.inspect}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
initialize!
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# @return [void]
|
49
|
+
def initialize!
|
50
|
+
self[:version] = 2
|
51
|
+
|
52
|
+
#define_handler(:init) do |context|
|
53
|
+
# $stderr.puts("#{self.class}: init")
|
54
|
+
#end
|
55
|
+
#define_handler(:finish) do |context|
|
56
|
+
# $stderr.puts("#{self.class}: finish")
|
57
|
+
#end
|
58
|
+
define_handler(:write_byte) do |context, byte|
|
59
|
+
begin
|
60
|
+
@io.putc(byte)
|
61
|
+
0
|
62
|
+
rescue => e
|
63
|
+
$stderr.puts("#{e} in #{self.class}#write_byte")
|
64
|
+
1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
define_handler(:write_bytes) do |context, data, size, nmemb|
|
68
|
+
begin
|
69
|
+
@io.write(data.read_string(size * nmemb))
|
70
|
+
0
|
71
|
+
rescue => e
|
72
|
+
$stderr.puts("#{e} in #{self.class}#write_bytes")
|
73
|
+
1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
#define_handler(:write_end) do |context|
|
77
|
+
# $stderr.puts("#{self.class}: write_end")
|
78
|
+
#end
|
79
|
+
#define_handler(:read_bytes) do |context, data, size, nmemb|
|
80
|
+
# $stderr.puts("#{self.class}: read_bytes")
|
81
|
+
#end
|
82
|
+
#define_handler(:read_eof) do |context|
|
83
|
+
# $stderr.puts("#{self.class}: read_eof")
|
84
|
+
#end
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# @param [Proc] func
|
89
|
+
# @return [void]
|
90
|
+
def init_handler=(func)
|
91
|
+
define_handler(:init, &func)
|
92
|
+
end
|
93
|
+
alias_method :init=, :init_handler=
|
94
|
+
|
95
|
+
##
|
96
|
+
# @param [Proc] func
|
97
|
+
# @return [void]
|
98
|
+
def finish_handler=(func)
|
99
|
+
define_handler(:finish, &func)
|
100
|
+
end
|
101
|
+
alias_method :finish=, :finish_handler=
|
102
|
+
|
103
|
+
##
|
104
|
+
# @param [Proc] func
|
105
|
+
# @return [void]
|
106
|
+
def write_byte_handler=(func)
|
107
|
+
define_handler(:write_byte, &func)
|
108
|
+
end
|
109
|
+
alias_method :write_byte=, :write_byte_handler=
|
110
|
+
|
111
|
+
##
|
112
|
+
# @param [Proc] func
|
113
|
+
# @return [void]
|
114
|
+
def write_bytes_handler=(func)
|
115
|
+
define_handler(:write_bytes, &func)
|
116
|
+
end
|
117
|
+
alias_method :write_bytes=, :write_bytes_handler=
|
118
|
+
|
119
|
+
##
|
120
|
+
# @param [Proc] func
|
121
|
+
# @return [void]
|
122
|
+
def write_end_handler=(func)
|
123
|
+
define_handler(:write_end, &func)
|
124
|
+
end
|
125
|
+
alias_method :write_end=, :write_end_handler=
|
126
|
+
|
127
|
+
##
|
128
|
+
# @param [Proc] func
|
129
|
+
# @return [void]
|
130
|
+
def read_bytes_handler=(func)
|
131
|
+
define_handler(:read_bytes, &func)
|
132
|
+
end
|
133
|
+
alias_method :read_bytes=, :read_bytes_handler=
|
134
|
+
|
135
|
+
##
|
136
|
+
# @param [Proc] func
|
137
|
+
# @return [void]
|
138
|
+
def read_eof_handler=(func)
|
139
|
+
define_handler(:read_eof, &func)
|
140
|
+
end
|
141
|
+
alias_method :read_eof=, :read_eof_handler=
|
142
|
+
|
143
|
+
##
|
144
|
+
# @param [Symbol, #to_sym] name
|
145
|
+
# @return [void]
|
146
|
+
def define_handler(name, &block)
|
147
|
+
name = name.to_sym
|
148
|
+
raise ArgumentError, "invalid IOStreamHandler function name: #{name}" unless HANDLERS.include?(name)
|
149
|
+
@procs ||= {} # prevents premature GC of the procs
|
150
|
+
@procs[name] = self[name] = block
|
151
|
+
end
|
152
|
+
end # IOStreamHandler
|
153
|
+
end # RDF::Raptor::FFI::V1
|
@@ -0,0 +1,205 @@
|
|
1
|
+
module RDF::Raptor::FFI::V2
|
2
|
+
##
|
3
|
+
# This class provides the functionality of turning syntaxes into RDF
|
4
|
+
# triples - RDF parsing.
|
5
|
+
#
|
6
|
+
# @see http://librdf.org/raptor/api-1.4/raptor-section-parser.html
|
7
|
+
class Parser < ::FFI::ManagedStruct
|
8
|
+
include RDF::Raptor::FFI
|
9
|
+
layout :world, :pointer # the actual layout is private
|
10
|
+
|
11
|
+
# The default base URI
|
12
|
+
BASE_URI = 'file:///dev/stdin'
|
13
|
+
|
14
|
+
# The maximum chunk size for `#parse_stream`
|
15
|
+
BUFFER_SIZE = 64 * 1024
|
16
|
+
|
17
|
+
##
|
18
|
+
# @overload initialize(ptr)
|
19
|
+
# @param [FFI::Pointer] ptr
|
20
|
+
#
|
21
|
+
# @overload initialize(name)
|
22
|
+
# @param [Symbol, String] name
|
23
|
+
#
|
24
|
+
def initialize(ptr_or_name)
|
25
|
+
ptr = case ptr_or_name
|
26
|
+
when FFI::Pointer then ptr_or_name
|
27
|
+
when Symbol then V2.raptor_new_parser(V2.world, ptr_or_name.to_s)
|
28
|
+
when String then V2.raptor_new_parser(V2.world, ptr_or_name)
|
29
|
+
else nil
|
30
|
+
end
|
31
|
+
raise ArgumentError, "invalid argument: #{ptr_or_name.inspect}" if ptr.nil? || ptr.null?
|
32
|
+
super(ptr)
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Releases `libraptor` memory associated with this structure.
|
37
|
+
#
|
38
|
+
# @param [FFI::Pointer] ptr
|
39
|
+
# @return [void]
|
40
|
+
def self.release(ptr)
|
41
|
+
V2.raptor_free_parser(ptr)
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# @param [Proc] handler
|
46
|
+
# @return [void]
|
47
|
+
def error_handler=(handler)
|
48
|
+
#V2.raptor_set_error_handler(self, self, handler)
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# @param [Proc] handler
|
53
|
+
# @return [void]
|
54
|
+
def warning_handler=(handler)
|
55
|
+
#V2.raptor_set_warning_handler(self, self, handler)
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# @param [Proc] handler
|
60
|
+
# @return [void]
|
61
|
+
def statement_handler=(handler)
|
62
|
+
V2.raptor_parser_set_statement_handler(self, self, handler)
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# @param [Object] input
|
67
|
+
# the input to parse
|
68
|
+
# @param [Hash{Symbol => Object}] options
|
69
|
+
# any additional options for parsing
|
70
|
+
# @option options [String, #to_s] :base_uri (nil)
|
71
|
+
# the base URI to use when resolving relative URIs
|
72
|
+
# @yield [parser, statement]
|
73
|
+
# each statement in the input
|
74
|
+
# @yieldparam [FFI::Pointer] parser
|
75
|
+
# @yieldparam [FFI::Pointer] statement
|
76
|
+
# @yieldreturn [void] ignored
|
77
|
+
# @return [void]
|
78
|
+
def parse(input, options = {}, &block)
|
79
|
+
case input
|
80
|
+
when RDF::URI, URI, %r(^(file|https|http|ftp)://)
|
81
|
+
parse_url(input, options, &block)
|
82
|
+
when File, Tempfile
|
83
|
+
parse_file(input, options, &block)
|
84
|
+
when IO, StringIO
|
85
|
+
parse_stream(input, options, &block)
|
86
|
+
when String
|
87
|
+
parse_buffer(input, options, &block)
|
88
|
+
else
|
89
|
+
raise ArgumentError, "don't know how to parse #{input.inspect}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# @param [RDF::URI, String, #to_s] url
|
95
|
+
# the input URL to parse
|
96
|
+
# @param [Hash{Symbol => Object}] options
|
97
|
+
# any additional options for parsing (see {#parse})
|
98
|
+
# @yield [parser, statement]
|
99
|
+
# each statement in the input
|
100
|
+
# @yieldparam [FFI::Pointer] parser
|
101
|
+
# @yieldparam [FFI::Pointer] statement
|
102
|
+
# @yieldreturn [void] ignored
|
103
|
+
# @return [void]
|
104
|
+
def parse_url(url, options = {}, &block)
|
105
|
+
self.statement_handler = block if block_given?
|
106
|
+
|
107
|
+
data_url = V2::URI.new((url.respond_to?(:to_uri) ? url.to_uri : url).to_s)
|
108
|
+
base_uri = options[:base_uri].to_s.empty? ? nil : V2::URI.new(options[:base_uri].to_s)
|
109
|
+
|
110
|
+
result = V2.raptor_parser_parse_uri(self, data_url, base_uri)
|
111
|
+
# TODO: error handling if result.nonzero?
|
112
|
+
end
|
113
|
+
alias_method :parse_uri, :parse_url
|
114
|
+
|
115
|
+
##
|
116
|
+
# @param [File, Tempfile, #path] file
|
117
|
+
# the input file to parse
|
118
|
+
# @param [Hash{Symbol => Object}] options
|
119
|
+
# any additional options for parsing (see {#parse})
|
120
|
+
# @yield [parser, statement]
|
121
|
+
# each statement in the input
|
122
|
+
# @yieldparam [FFI::Pointer] parser
|
123
|
+
# @yieldparam [FFI::Pointer] statement
|
124
|
+
# @yieldreturn [void] ignored
|
125
|
+
# @return [void]
|
126
|
+
def parse_file(file, options = {}, &block)
|
127
|
+
self.statement_handler = block if block_given?
|
128
|
+
|
129
|
+
data_url = V2::URI.new("file://#{File.expand_path(file.path)}")
|
130
|
+
base_uri = options[:base_uri].to_s.empty? ? nil : V2::URI.new(options[:base_uri].to_s)
|
131
|
+
|
132
|
+
result = V2.raptor_parser_parse_file(self, data_url, base_uri)
|
133
|
+
# TODO: error handling if result.nonzero?
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# @param [IO, StringIO, #readpartial] stream
|
138
|
+
# the input stream to parse
|
139
|
+
# @param [Hash{Symbol => Object}] options
|
140
|
+
# any additional options for parsing (see {#parse})
|
141
|
+
# @yield [parser, statement]
|
142
|
+
# each statement in the input
|
143
|
+
# @yieldparam [FFI::Pointer] parser
|
144
|
+
# @yieldparam [FFI::Pointer] statement
|
145
|
+
# @yieldreturn [void] ignored
|
146
|
+
# @return [void]
|
147
|
+
def parse_stream(stream, options = {}, &block)
|
148
|
+
self.statement_handler = block if block_given?
|
149
|
+
|
150
|
+
begin
|
151
|
+
parse_start!(options[:base_uri] || BASE_URI)
|
152
|
+
loop do
|
153
|
+
parse_chunk(stream.sysread(BUFFER_SIZE))
|
154
|
+
end
|
155
|
+
rescue EOFError => e
|
156
|
+
parse_end!
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
##
|
161
|
+
# @param [String, #to_str] buffer
|
162
|
+
# the input buffer to parse
|
163
|
+
# @param [Hash{Symbol => Object}] options
|
164
|
+
# any additional options for parsing (see {#parse})
|
165
|
+
# @yield [parser, statement]
|
166
|
+
# each statement in the input
|
167
|
+
# @yieldparam [FFI::Pointer] parser
|
168
|
+
# @yieldparam [FFI::Pointer] statement
|
169
|
+
# @yieldreturn [void] ignored
|
170
|
+
# @return [void]
|
171
|
+
def parse_buffer(buffer, options = {}, &block)
|
172
|
+
self.statement_handler = block if block_given?
|
173
|
+
|
174
|
+
parse_start!((options[:base_uri] || BASE_URI).to_s)
|
175
|
+
parse_chunk(buffer.to_str)
|
176
|
+
parse_end!
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# @private
|
181
|
+
# @param [String] base_uri
|
182
|
+
# @return [void]
|
183
|
+
def parse_start!(base_uri = BASE_URI)
|
184
|
+
result = V2.raptor_parser_parse_start(self, V2::URI.new(base_uri))
|
185
|
+
# TODO: error handling if result.nonzero?
|
186
|
+
end
|
187
|
+
|
188
|
+
##
|
189
|
+
# @private
|
190
|
+
# @param [String] buffer
|
191
|
+
# the input chunk to parse
|
192
|
+
# @return [void]
|
193
|
+
def parse_chunk(buffer)
|
194
|
+
result = V2.raptor_parser_parse_chunk(self, buffer, buffer.bytesize, 0)
|
195
|
+
# TODO: error handling if result.nonzero?
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# @private
|
200
|
+
# @return [void]
|
201
|
+
def parse_end!
|
202
|
+
result = V2.raptor_parser_parse_chunk(self, nil, 0, 1) # EOF
|
203
|
+
end
|
204
|
+
end # Parser
|
205
|
+
end # RDF::Raptor::FFI::V2
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module RDF::Raptor::FFI::V2
|
2
|
+
##
|
3
|
+
# This class provides the functionality of turning RDF triples into
|
4
|
+
# syntaxes - RDF serializing.
|
5
|
+
#
|
6
|
+
# @see http://librdf.org/raptor/api-1.4/raptor-section-serializer.html
|
7
|
+
class Serializer < ::FFI::ManagedStruct
|
8
|
+
include RDF::Raptor::FFI
|
9
|
+
|
10
|
+
# Note this layout is private
|
11
|
+
layout :world, :pointer,
|
12
|
+
:locator, :pointer,
|
13
|
+
:failed, :bool,
|
14
|
+
:base_uri, :pointer,
|
15
|
+
:context, :pointer,
|
16
|
+
:iostream, :pointer,
|
17
|
+
:free_iostream_on_end, :bool,
|
18
|
+
:factory, :pointer,
|
19
|
+
:options, :pointer
|
20
|
+
|
21
|
+
##
|
22
|
+
# @overload initialize(ptr)
|
23
|
+
# @param [FFI::Pointer] ptr
|
24
|
+
#
|
25
|
+
# @overload initialize(name)
|
26
|
+
# @param [Symbol, String] name
|
27
|
+
#
|
28
|
+
def initialize(ptr_or_name)
|
29
|
+
ptr = case ptr_or_name
|
30
|
+
when FFI::Pointer then ptr_or_name
|
31
|
+
when Symbol then V2.raptor_new_serializer(V2.world, ptr_or_name.to_s)
|
32
|
+
when String then V2.raptor_new_serializer(V2.world, ptr_or_name)
|
33
|
+
else nil
|
34
|
+
end
|
35
|
+
raise ArgumentError, "invalid argument: #{ptr_or_name.inspect}" if ptr.nil? || ptr.null?
|
36
|
+
super(ptr)
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Releases `libraptor` memory associated with this structure.
|
41
|
+
#
|
42
|
+
# @param [FFI::Pointer] ptr
|
43
|
+
# @return [void]
|
44
|
+
def self.release(ptr)
|
45
|
+
V2.raptor_free_serializer(ptr)
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# @param [Proc] handler
|
50
|
+
# @return [void]
|
51
|
+
def error_handler=(handler)
|
52
|
+
V2.raptor_serializer_set_error_handler(self, self, handler)
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# @param [Proc] handler
|
57
|
+
# @return [void]
|
58
|
+
def warning_handler=(handler)
|
59
|
+
V2.raptor_serializer_set_warning_handler(self, self, handler)
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# @param [Object] output
|
64
|
+
# where output should be written to
|
65
|
+
# @param [Hash{Symbol => Object}] options
|
66
|
+
# any additional options for serializing
|
67
|
+
# @option options [String, #to_s] :base_uri (nil)
|
68
|
+
# the base URI to use when resolving relative URIs
|
69
|
+
# @return [void]
|
70
|
+
def start_to(output, options = {})
|
71
|
+
if output.respond_to?(:write)
|
72
|
+
start_to_stream(output, options)
|
73
|
+
else
|
74
|
+
raise ArgumentError, "don't know how to serialize to #{output.inspect}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# @param [IO, StringIO] stream
|
80
|
+
# @param [Hash{Symbol => Object}] options
|
81
|
+
# any additional options for serializing (see {#start_to})
|
82
|
+
# @return [void]
|
83
|
+
def start_to_stream(stream, options = {})
|
84
|
+
iostream = V2::IOStream.new(V2::IOStreamHandler.new(stream), :free_iostream => self[:free_iostream_on_end])
|
85
|
+
start_to_iostream(iostream, options)
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# @param [V2::IOStream] iostream
|
90
|
+
# @param [Hash{Symbol => Object}] options
|
91
|
+
# any additional options for serializing (see {#start_to})
|
92
|
+
# @return [void]
|
93
|
+
def start_to_iostream(iostream, options = {})
|
94
|
+
@iostream = iostream # prevents premature GC
|
95
|
+
@base_uri = options[:base_uri].to_s.empty? ? nil : V2::URI.new(options[:base_uri].to_s)
|
96
|
+
if V2.raptor_serializer_start_to_iostream(self, @base_uri, @iostream).nonzero?
|
97
|
+
raise RDF::WriterError, "raptor_serialize_start_to_iostream() failed"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# @return [void]
|
103
|
+
def finish
|
104
|
+
if V2.raptor_serializer_serialize_end(self).nonzero?
|
105
|
+
raise RDF::WriterError, "raptor_serialize_end() failed"
|
106
|
+
end
|
107
|
+
@iostream = @base_uri = nil # allows GC
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# @param [RDF::Resource] subject
|
112
|
+
# @param [RDF::URI] predicate
|
113
|
+
# @param [RDF::Term] object
|
114
|
+
# @return [void]
|
115
|
+
def serialize_triple(subject, predicate, object)
|
116
|
+
raptor_statement = V2::Statement.new
|
117
|
+
raptor_statement.subject = subject
|
118
|
+
raptor_statement.predicate = predicate
|
119
|
+
raptor_statement.object = object
|
120
|
+
begin
|
121
|
+
serialize_raw_statement(raptor_statement)
|
122
|
+
ensure
|
123
|
+
raptor_statement.release
|
124
|
+
raptor_statement = nil
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# @param [V2::Statement] statement
|
130
|
+
# @return [void]
|
131
|
+
def serialize_raw_statement(statement)
|
132
|
+
if V2.raptor_serializer_serialize_statement(self, statement).nonzero?
|
133
|
+
raise RDF::WriterError, "raptor_serialize_statement() failed"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end # Serializer
|
137
|
+
end # RDF::Raptor::FFI::V2
|