nokogiri 1.3.1-java → 1.3.2-java

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

Files changed (62) hide show
  1. data/CHANGELOG.ja.rdoc +25 -0
  2. data/CHANGELOG.rdoc +23 -0
  3. data/Manifest.txt +5 -0
  4. data/README.ja.rdoc +5 -5
  5. data/README.rdoc +3 -3
  6. data/Rakefile +25 -21
  7. data/ext/nokogiri/extconf.rb +54 -12
  8. data/ext/nokogiri/xml_document.c +4 -1
  9. data/ext/nokogiri/xml_document.h +2 -0
  10. data/ext/nokogiri/xml_dtd.c +29 -0
  11. data/ext/nokogiri/xml_node.c +9 -1
  12. data/ext/nokogiri/xml_node_set.c +5 -1
  13. data/ext/nokogiri/xml_relax_ng.c +50 -3
  14. data/ext/nokogiri/xml_sax_parser.c +84 -77
  15. data/ext/nokogiri/xml_schema.c +52 -3
  16. data/ext/nokogiri/xml_syntax_error.c +7 -0
  17. data/ext/nokogiri/xml_syntax_error.h +1 -0
  18. data/lib/nokogiri.rb +2 -2
  19. data/lib/nokogiri/css/parser.rb +2 -2
  20. data/lib/nokogiri/ffi/io_callbacks.rb +20 -12
  21. data/lib/nokogiri/ffi/libxml.rb +8 -0
  22. data/lib/nokogiri/ffi/xml/document.rb +1 -1
  23. data/lib/nokogiri/ffi/xml/dtd.rb +22 -6
  24. data/lib/nokogiri/ffi/xml/namespace.rb +9 -7
  25. data/lib/nokogiri/ffi/xml/node.rb +4 -0
  26. data/lib/nokogiri/ffi/xml/node_set.rb +4 -1
  27. data/lib/nokogiri/ffi/xml/relax_ng.rb +35 -3
  28. data/lib/nokogiri/ffi/xml/sax/parser.rb +20 -19
  29. data/lib/nokogiri/ffi/xml/schema.rb +41 -4
  30. data/lib/nokogiri/html.rb +2 -2
  31. data/lib/nokogiri/html/document.rb +3 -3
  32. data/lib/nokogiri/version.rb +2 -2
  33. data/lib/nokogiri/xml.rb +3 -3
  34. data/lib/nokogiri/xml/document.rb +14 -4
  35. data/lib/nokogiri/xml/fragment_handler.rb +8 -0
  36. data/lib/nokogiri/xml/node.rb +1 -104
  37. data/lib/nokogiri/xml/node_set.rb +46 -6
  38. data/lib/nokogiri/xml/parse_options.rb +7 -2
  39. data/lib/nokogiri/xml/relax_ng.rb +2 -2
  40. data/lib/nokogiri/xml/sax.rb +1 -0
  41. data/lib/nokogiri/xml/sax/document.rb +4 -4
  42. data/lib/nokogiri/xml/sax/legacy_handlers.rb +65 -0
  43. data/lib/nokogiri/xml/sax/parser.rb +7 -0
  44. data/lib/nokogiri/xml/sax/push_parser.rb +3 -0
  45. data/lib/nokogiri/xml/schema.rb +1 -5
  46. data/lib/xsd/xmlparser/nokogiri.rb +14 -7
  47. data/tasks/test.rb +1 -62
  48. data/test/files/bar/bar.xsd +4 -0
  49. data/test/files/foo/foo.xsd +4 -0
  50. data/test/files/snuggles.xml +3 -0
  51. data/test/files/valid_bar.xml +2 -0
  52. data/test/helper.rb +9 -8
  53. data/test/html/test_document_fragment.rb +14 -0
  54. data/test/test_reader.rb +10 -10
  55. data/test/xml/sax/test_parser.rb +77 -0
  56. data/test/xml/sax/test_push_parser.rb +11 -7
  57. data/test/xml/test_document.rb +25 -0
  58. data/test/xml/test_dtd.rb +6 -1
  59. data/test/xml/test_node.rb +7 -0
  60. data/test/xml/test_node_set.rb +19 -0
  61. data/test/xml/test_schema.rb +24 -0
  62. metadata +10 -5
@@ -1,5 +1,11 @@
1
1
  #include <nokogiri.h>
2
2
 
3
+ #define STRING_OR_NULL(str) \
4
+ (RTEST(str) ? StringValuePtr(str) : NULL)
5
+
6
+ #define RBSTR_OR_QNIL(_str, rb_enc) \
7
+ (_str ? NOKOGIRI_STR_NEW2(_str, STRING_OR_NULL(rb_enc)) : Qnil)
8
+
3
9
  /*
4
10
  * call-seq:
5
11
  * parse_memory(data)
@@ -89,7 +95,7 @@ static void start_element(void * ctx, const xmlChar *name, const xmlChar **atts)
89
95
  if(atts) {
90
96
  while((attr = atts[i]) != NULL) {
91
97
  rb_funcall(attributes, rb_intern("<<"), 1,
92
- NOKOGIRI_STR_NEW2(attr, RTEST(enc) ? StringValuePtr(enc) : NULL)
98
+ NOKOGIRI_STR_NEW2(attr, STRING_OR_NULL(enc))
93
99
  );
94
100
  i++;
95
101
  }
@@ -98,7 +104,7 @@ static void start_element(void * ctx, const xmlChar *name, const xmlChar **atts)
98
104
  rb_funcall( doc,
99
105
  rb_intern("start_element"),
100
106
  2,
101
- NOKOGIRI_STR_NEW2(name, RTEST(enc) ? StringValuePtr(enc) : NULL),
107
+ NOKOGIRI_STR_NEW2(name, STRING_OR_NULL(enc)),
102
108
  attributes
103
109
  );
104
110
  }
@@ -109,19 +115,51 @@ static void end_element(void * ctx, const xmlChar *name)
109
115
  VALUE MAYBE_UNUSED(enc) = rb_iv_get(self, "@encoding");
110
116
  VALUE doc = rb_funcall(self, rb_intern("document"), 0);
111
117
  rb_funcall(doc, rb_intern("end_element"), 1,
112
- NOKOGIRI_STR_NEW2(name, RTEST(enc) ? StringValuePtr(enc) : NULL)
118
+ NOKOGIRI_STR_NEW2(name, STRING_OR_NULL(enc))
113
119
  );
114
120
  }
115
121
 
116
- /**
117
- * start_element_ns was borrowed heavily from libxml-ruby.
118
- */
122
+ static VALUE attributes_as_list(
123
+ VALUE self,
124
+ int nb_attributes,
125
+ const xmlChar ** attributes)
126
+ {
127
+ VALUE list = rb_ary_new2(nb_attributes);
128
+ VALUE MAYBE_UNUSED(enc) = rb_iv_get(self, "@encoding");
129
+
130
+ VALUE attr_klass = rb_const_get(cNokogiriXmlSaxParser, rb_intern("Attribute"));
131
+ if (attributes) {
132
+ /* Each attribute is an array of [localname, prefix, URI, value, end] */
133
+ int i;
134
+ for (i = 0; i < nb_attributes * 5; i += 5) {
135
+ VALUE attribute = rb_funcall(attr_klass, rb_intern("new"), 4,
136
+ /* localname */
137
+ RBSTR_OR_QNIL(attributes[i + 0], enc),
138
+
139
+ /* prefix */
140
+ RBSTR_OR_QNIL(attributes[i + 1], enc),
141
+
142
+ /* URI */
143
+ RBSTR_OR_QNIL(attributes[i + 2], enc),
144
+
145
+ /* value */
146
+ NOKOGIRI_STR_NEW((const char*)attributes[i+3],
147
+ (attributes[i+4] - attributes[i+3]),
148
+ STRING_OR_NULL(enc))
149
+ );
150
+ rb_ary_push(list, attribute);
151
+ }
152
+ }
153
+
154
+ return list;
155
+ }
156
+
119
157
  static void
120
158
  start_element_ns (
121
159
  void * ctx,
122
160
  const xmlChar * localname,
123
161
  const xmlChar * prefix,
124
- const xmlChar * URI,
162
+ const xmlChar * uri,
125
163
  int nb_namespaces,
126
164
  const xmlChar ** namespaces,
127
165
  int nb_attributes,
@@ -132,61 +170,42 @@ start_element_ns (
132
170
  VALUE doc = rb_funcall(self, rb_intern("document"), 0);
133
171
  VALUE MAYBE_UNUSED(enc) = rb_iv_get(self, "@encoding");
134
172
 
135
- VALUE attrHash = rb_hash_new();
136
- VALUE nsHash = rb_hash_new();
173
+ VALUE attribute_list = attributes_as_list(self, nb_attributes, attributes);
137
174
 
138
- if (attributes)
139
- {
140
- /* Each attribute is an array of [localname, prefix, URI, value, end] */
141
- int i;
142
- for (i = 0; i < nb_attributes * 5; i += 5)
143
- {
144
- rb_hash_aset( attrHash,
145
- NOKOGIRI_STR_NEW2((const char*)attributes[i+0], RTEST(enc) ? StringValuePtr(enc) : NULL),
146
- NOKOGIRI_STR_NEW((const char*)attributes[i+3], (attributes[i+4] - attributes[i+3]), RTEST(enc) ? StringValuePtr(enc) : NULL));
147
- }
148
- }
175
+ VALUE ns_list = rb_ary_new2(nb_namespaces);
149
176
 
150
- if (namespaces)
151
- {
177
+ if (namespaces) {
152
178
  int i;
153
179
  for (i = 0; i < nb_namespaces * 2; i += 2)
154
180
  {
155
- rb_hash_aset( nsHash,
156
- namespaces[i+0] ? NOKOGIRI_STR_NEW2((const char*)namespaces[i+0], RTEST(enc) ? StringValuePtr(enc) : NULL) : Qnil,
157
- namespaces[i+1] ? NOKOGIRI_STR_NEW2((const char*)namespaces[i+1], RTEST(enc) ? StringValuePtr(enc) : NULL) : Qnil);
181
+ rb_ary_push(ns_list,
182
+ rb_ary_new3(2,
183
+ RBSTR_OR_QNIL(namespaces[i + 0], enc),
184
+ RBSTR_OR_QNIL(namespaces[i + 1], enc)
185
+ )
186
+ );
158
187
  }
159
188
  }
160
189
 
161
190
  rb_funcall( doc,
162
- rb_intern("start_element_ns"),
191
+ rb_intern("start_element_namespace"),
163
192
  5,
164
- NOKOGIRI_STR_NEW2(localname, RTEST(enc) ? StringValuePtr(enc) : NULL),
165
- attrHash,
166
- prefix ? NOKOGIRI_STR_NEW2(prefix, RTEST(enc) ? StringValuePtr(enc) : NULL) : Qnil,
167
- URI ? NOKOGIRI_STR_NEW2(URI, RTEST(enc) ? StringValuePtr(enc) : NULL) : Qnil,
168
- nsHash
193
+ NOKOGIRI_STR_NEW2(localname, STRING_OR_NULL(enc)),
194
+ attribute_list,
195
+ RBSTR_OR_QNIL(prefix, enc),
196
+ RBSTR_OR_QNIL(uri, enc),
197
+ ns_list
169
198
  );
170
199
 
171
- /* Call start element if it's there' */
172
- if (rb_respond_to(doc, rb_intern("start_element")))
173
- {
174
- VALUE name;
175
- if (prefix)
176
- {
177
- name = NOKOGIRI_STR_NEW2(prefix, RTEST(enc) ? StringValuePtr(enc) : NULL);
178
- rb_funcall(name, rb_intern("<<"), 1, NOKOGIRI_STR_NEW2(":", RTEST(enc) ? StringValuePtr(enc) : NULL));
179
- rb_funcall(name, rb_intern("<<"), 1, NOKOGIRI_STR_NEW2(localname, RTEST(enc) ? StringValuePtr(enc) : NULL));
180
- }
181
- else
182
- {
183
- name = NOKOGIRI_STR_NEW2(localname, RTEST(enc) ? StringValuePtr(enc) : NULL);
184
- }
185
- VALUE attrArray = rb_funcall(attrHash, rb_intern("to_a"), 0);
186
- attrArray = rb_funcall(attrArray, rb_intern("flatten"), 0);
187
- rb_funcall(doc, rb_intern("start_element"), 2, name, attrArray);
188
- }
189
-
200
+ rb_funcall( self,
201
+ rb_intern("start_element_namespace"),
202
+ 5,
203
+ NOKOGIRI_STR_NEW2(localname, STRING_OR_NULL(enc)),
204
+ attribute_list,
205
+ RBSTR_OR_QNIL(prefix, enc),
206
+ RBSTR_OR_QNIL(uri, enc),
207
+ ns_list
208
+ );
190
209
  }
191
210
 
192
211
  /**
@@ -197,35 +216,23 @@ end_element_ns (
197
216
  void * ctx,
198
217
  const xmlChar * localname,
199
218
  const xmlChar * prefix,
200
- const xmlChar * URI)
219
+ const xmlChar * uri)
201
220
  {
202
221
  VALUE self = (VALUE)ctx;
203
222
  VALUE doc = rb_funcall(self, rb_intern("document"), 0);
204
223
  VALUE MAYBE_UNUSED(enc) = rb_iv_get(self, "@encoding");
205
224
 
206
- rb_funcall(doc, rb_intern("end_element_ns"), 3,
207
- NOKOGIRI_STR_NEW2(localname, RTEST(enc) ? StringValuePtr(enc) : NULL),
208
- prefix ? NOKOGIRI_STR_NEW2(prefix, RTEST(enc) ? StringValuePtr(enc) : NULL) : Qnil,
209
- URI ? NOKOGIRI_STR_NEW2(URI, RTEST(enc) ? StringValuePtr(enc) : NULL) : Qnil
225
+ rb_funcall(doc, rb_intern("end_element_namespace"), 3,
226
+ NOKOGIRI_STR_NEW2(localname, STRING_OR_NULL(enc)),
227
+ RBSTR_OR_QNIL(prefix, enc),
228
+ RBSTR_OR_QNIL(uri, enc)
210
229
  );
211
230
 
212
- /* Call end element for old-times sake */
213
- if (rb_respond_to(doc, rb_intern("end_element")))
214
- {
215
- VALUE name;
216
- if (prefix)
217
- {
218
- name = NOKOGIRI_STR_NEW2(prefix, RTEST(enc) ? StringValuePtr(enc) : NULL);
219
- rb_funcall(name, rb_intern("<<"), 1, NOKOGIRI_STR_NEW2(":", RTEST(enc) ? StringValuePtr(enc) : NULL));
220
- rb_funcall(name, rb_intern("<<"), 1, NOKOGIRI_STR_NEW2(localname, RTEST(enc) ? StringValuePtr(enc) : NULL));
221
- }
222
- else
223
- {
224
- name = NOKOGIRI_STR_NEW2(localname, RTEST(enc) ? StringValuePtr(enc) : NULL);
225
- }
226
- rb_funcall(doc, rb_intern("end_element"), 1, name);
227
- }
228
-
231
+ rb_funcall(self, rb_intern("end_element_namespace"), 3,
232
+ NOKOGIRI_STR_NEW2(localname, STRING_OR_NULL(enc)),
233
+ RBSTR_OR_QNIL(prefix, enc),
234
+ RBSTR_OR_QNIL(uri, enc)
235
+ );
229
236
  }
230
237
 
231
238
  static void characters_func(void * ctx, const xmlChar * ch, int len)
@@ -233,7 +240,7 @@ static void characters_func(void * ctx, const xmlChar * ch, int len)
233
240
  VALUE self = (VALUE)ctx;
234
241
  VALUE MAYBE_UNUSED(enc) = rb_iv_get(self, "@encoding");
235
242
  VALUE doc = rb_funcall(self, rb_intern("document"), 0);
236
- VALUE str = NOKOGIRI_STR_NEW(ch, len, RTEST(enc) ? StringValuePtr(enc):NULL);
243
+ VALUE str = NOKOGIRI_STR_NEW(ch, len, STRING_OR_NULL(enc));
237
244
  rb_funcall(doc, rb_intern("characters"), 1, str);
238
245
  }
239
246
 
@@ -242,7 +249,7 @@ static void comment_func(void * ctx, const xmlChar * value)
242
249
  VALUE self = (VALUE)ctx;
243
250
  VALUE MAYBE_UNUSED(enc) = rb_iv_get(self, "@encoding");
244
251
  VALUE doc = rb_funcall(self, rb_intern("document"), 0);
245
- VALUE str = NOKOGIRI_STR_NEW2(value, RTEST(enc) ? StringValuePtr(enc):NULL);
252
+ VALUE str = NOKOGIRI_STR_NEW2(value, STRING_OR_NULL(enc));
246
253
  rb_funcall(doc, rb_intern("comment"), 1, str);
247
254
  }
248
255
 
@@ -259,7 +266,7 @@ static void warning_func(void * ctx, const char *msg, ...)
259
266
  va_end(args);
260
267
 
261
268
  rb_funcall(doc, rb_intern("warning"), 1,
262
- NOKOGIRI_STR_NEW2(message, RTEST(enc) ? StringValuePtr(enc) : NULL)
269
+ NOKOGIRI_STR_NEW2(message, STRING_OR_NULL(enc))
263
270
  );
264
271
  free(message);
265
272
  }
@@ -277,7 +284,7 @@ static void error_func(void * ctx, const char *msg, ...)
277
284
  va_end(args);
278
285
 
279
286
  rb_funcall(doc, rb_intern("error"), 1,
280
- NOKOGIRI_STR_NEW2(message, RTEST(enc) ? StringValuePtr(enc) : NULL)
287
+ NOKOGIRI_STR_NEW2(message, STRING_OR_NULL(enc))
281
288
  );
282
289
  free(message);
283
290
  }
@@ -288,7 +295,7 @@ static void cdata_block(void * ctx, const xmlChar * value, int len)
288
295
  VALUE MAYBE_UNUSED(enc) = rb_iv_get(self, "@encoding");
289
296
  VALUE doc = rb_funcall(self, rb_intern("document"), 0);
290
297
  VALUE string =
291
- NOKOGIRI_STR_NEW(value, len, RTEST(enc) ? StringValuePtr(enc) : NULL);
298
+ NOKOGIRI_STR_NEW(value, len, STRING_OR_NULL(enc));
292
299
  rb_funcall(doc, rb_intern("cdata_block"), 1, string);
293
300
  }
294
301
 
@@ -78,9 +78,7 @@ static VALUE read_memory(VALUE klass, VALUE content)
78
78
  if(NULL == schema) {
79
79
  xmlErrorPtr error = xmlGetLastError();
80
80
  if(error)
81
- rb_funcall(rb_mKernel, rb_intern("raise"), 1,
82
- Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error)
83
- );
81
+ Nokogiri_error_raise(NULL, error);
84
82
  else
85
83
  rb_raise(rb_eRuntimeError, "Could not parse document");
86
84
 
@@ -93,6 +91,56 @@ static VALUE read_memory(VALUE klass, VALUE content)
93
91
  return rb_schema;
94
92
  }
95
93
 
94
+ /*
95
+ * call-seq:
96
+ * from_document(doc)
97
+ *
98
+ * Create a new Schema from the Nokogiri::XML::Document +doc+
99
+ */
100
+ static VALUE from_document(VALUE klass, VALUE document)
101
+ {
102
+ xmlDocPtr doc;
103
+ Data_Get_Struct(document, xmlDoc, doc);
104
+
105
+ // In case someone passes us a node. ugh.
106
+ doc = doc->doc;
107
+
108
+ xmlSchemaParserCtxtPtr ctx = xmlSchemaNewDocParserCtxt(doc);
109
+
110
+ VALUE errors = rb_ary_new();
111
+ xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
112
+
113
+ #ifdef HAVE_XMLSCHEMASETPARSERSTRUCTUREDERRORS
114
+ xmlSchemaSetParserStructuredErrors(
115
+ ctx,
116
+ Nokogiri_error_array_pusher,
117
+ (void *)errors
118
+ );
119
+ #endif
120
+
121
+ xmlSchemaPtr schema = xmlSchemaParse(ctx);
122
+
123
+ xmlSetStructuredErrorFunc(NULL, NULL);
124
+ xmlSchemaFreeParserCtxt(ctx);
125
+
126
+ if(NULL == schema) {
127
+ xmlErrorPtr error = xmlGetLastError();
128
+ if(error)
129
+ Nokogiri_error_raise(NULL, error);
130
+ else
131
+ rb_raise(rb_eRuntimeError, "Could not parse document");
132
+
133
+ return Qnil;
134
+ }
135
+
136
+ VALUE rb_schema = Data_Wrap_Struct(klass, 0, dealloc, schema);
137
+ rb_iv_set(rb_schema, "@errors", errors);
138
+
139
+ return rb_schema;
140
+
141
+ return Qnil;
142
+ }
143
+
96
144
  VALUE cNokogiriXmlSchema;
97
145
  void init_xml_schema()
98
146
  {
@@ -103,5 +151,6 @@ void init_xml_schema()
103
151
  cNokogiriXmlSchema = klass;
104
152
 
105
153
  rb_define_singleton_method(klass, "read_memory", read_memory, 1);
154
+ rb_define_singleton_method(klass, "from_document", from_document, 1);
106
155
  rb_define_private_method(klass, "validate_document", validate_document, 1);
107
156
  }
@@ -166,6 +166,13 @@ void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error)
166
166
  rb_ary_push(list, Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error));
167
167
  }
168
168
 
169
+ void Nokogiri_error_raise(void * ctx, xmlErrorPtr error)
170
+ {
171
+ rb_funcall(rb_mKernel, rb_intern("raise"), 1,
172
+ Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error)
173
+ );
174
+ }
175
+
169
176
  VALUE Nokogiri_wrap_xml_syntax_error(VALUE klass, xmlErrorPtr error)
170
177
  {
171
178
  if(!klass) klass = cNokogiriXmlSyntaxError;
@@ -6,6 +6,7 @@
6
6
  void init_xml_syntax_error();
7
7
  VALUE Nokogiri_wrap_xml_syntax_error(VALUE klass, xmlErrorPtr error);
8
8
  void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error);
9
+ void Nokogiri_error_raise(void * ctx, xmlErrorPtr error);
9
10
 
10
11
  extern VALUE cNokogiriXmlSyntaxError;
11
12
  #endif
data/lib/nokogiri.rb CHANGED
@@ -55,9 +55,9 @@ module Nokogiri
55
55
  def parse string, url = nil, encoding = nil, options = nil
56
56
  doc =
57
57
  if string =~ /^\s*<[^Hh>]*html/i # Probably html
58
- Nokogiri::HTML::Document.parse(string, url, encoding, options || 2145)
58
+ Nokogiri::HTML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_HTML)
59
59
  else
60
- Nokogiri::XML::Document.parse(string, url, encoding, options || 2159)
60
+ Nokogiri::XML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_XML)
61
61
  end
62
62
  yield doc if block_given?
63
63
  doc
@@ -43,7 +43,7 @@ module Nokogiri
43
43
  def parse selector
44
44
  @warned ||= false
45
45
  unless @warned
46
- $stderr.puts('Nokogiri::CSS::Parser.parse is deprecated, call Nokogiri::CSS.parse()')
46
+ $stderr.puts('Nokogiri::CSS::Parser.parse is deprecated, call Nokogiri::CSS.parse(), this will be removed August 1st or version 1.4.0 (whichever is first)')
47
47
  @warned = true
48
48
  end
49
49
  new.parse selector
@@ -59,7 +59,7 @@ module Nokogiri
59
59
 
60
60
  # Get the xpath for +string+ using +options+
61
61
  def xpath_for string, options={}
62
- key = string + options[:ns].to_s
62
+ key = "#{string}#{options[:ns]}#{options[:prefix]}"
63
63
  v = self.class[key]
64
64
  return v if v
65
65
 
@@ -2,22 +2,30 @@ module Nokogiri
2
2
  module IoCallbacks # :nodoc:
3
3
 
4
4
  class << self
5
+
6
+ def plain_old_reader(io)
7
+ lambda do |ctx, buffer, len|
8
+ string = io.read(len)
9
+ return 0 if string.nil?
10
+ buffer.put_bytes(0, string, 0, string.length)
11
+ string.length
12
+ end
13
+ end
14
+
5
15
  if defined?(FFI::IO.native_read)
6
- def reader(io)
7
- lambda do |ctx, buffer, len|
8
- rcode = FFI::IO.native_read(io, buffer, len)
9
- (rcode < 0) ? 0 : rcode
16
+ def ffi_io_native_reader(io)
17
+ if io.is_a?(StringIO)
18
+ plain_old_reader(io)
19
+ else
20
+ lambda do |ctx, buffer, len|
21
+ rcode = FFI::IO.native_read(io, buffer, len)
22
+ (rcode < 0) ? 0 : rcode
23
+ end
10
24
  end
11
25
  end
26
+ alias :reader :ffi_io_native_reader
12
27
  else
13
- def reader(io) # TODO: this can be removed once JRuby 1.3.0RC2 and ruby-ffi 0.4.0 are both released
14
- lambda do |ctx, buffer, len|
15
- string = io.read(len)
16
- return 0 if string.nil?
17
- buffer.put_bytes(0, string, 0, string.length)
18
- string.length
19
- end
20
- end
28
+ alias :reader :plain_old_reader
21
29
  end
22
30
 
23
31
  def writer(io)
@@ -118,6 +118,7 @@ module Nokogiri
118
118
  attach_function :xmlStringGetNodeList, [:pointer, :pointer], :pointer # second arg should be a :string, but we only ship the results of xmlEncodeEntitiesReentrant, so let's optimize.
119
119
  attach_function :xmlNewNs, [:pointer, :string, :string], :pointer
120
120
  attach_function :xmlNewNsProp, [:pointer, :pointer, :string, :string], :pointer
121
+ attach_function :xmlSearchNs, [:pointer, :pointer, :string], :pointer
121
122
  attach_function :xmlSearchNsByHref, [:pointer, :pointer, :string], :pointer
122
123
  attach_function :xmlGetIntSubset, [:pointer], :pointer
123
124
  attach_function :xmlBufferCreate, [], :pointer
@@ -126,6 +127,11 @@ module Nokogiri
126
127
  attach_function :xmlNewDocProp, [:pointer, :string, :string], :pointer
127
128
  attach_function :xmlFreePropList, [:pointer], :void
128
129
 
130
+ # valid.c
131
+ attach_function :xmlNewValidCtxt, [], :pointer
132
+ attach_function :xmlValidateDtd, [:pointer, :pointer, :pointer], :int
133
+ attach_function :xmlFreeValidCtxt, [:pointer], :void
134
+
129
135
  # xmlsave.c
130
136
  attach_function :xmlDocDumpMemory, [:pointer, :pointer, :pointer], :void
131
137
  attach_function :xmlNodeDump, [:pointer, :pointer, :pointer, :int, :int], :int
@@ -240,6 +246,7 @@ module Nokogiri
240
246
  attach_function :xmlSchemaSetParserStructuredErrors, [:pointer, :syntax_error_handler, :pointer], :void unless Nokogiri.is_2_6_16?
241
247
  attach_function :xmlSchemaParse, [:pointer], :pointer
242
248
  attach_function :xmlSchemaFreeParserCtxt, [:pointer], :void
249
+ attach_function :xmlSchemaNewDocParserCtxt, [:pointer], :pointer
243
250
 
244
251
  # relaxng.c
245
252
  attach_function :xmlRelaxNGNewValidCtxt, [:pointer], :pointer
@@ -250,6 +257,7 @@ module Nokogiri
250
257
  attach_function :xmlRelaxNGSetParserStructuredErrors, [:pointer, :syntax_error_handler, :pointer], :void unless Nokogiri.is_2_6_16?
251
258
  attach_function :xmlRelaxNGParse, [:pointer], :pointer
252
259
  attach_function :xmlRelaxNGFreeParserCtxt, [:pointer], :void
260
+ attach_function :xmlRelaxNGNewDocParserCtxt, [:pointer], :pointer
253
261
 
254
262
  # helpers
255
263
  def self.pointer_offset(n)