nokogiri 1.19.4-java → 1.19.5-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE-DEPENDENCIES.md +29 -0
  3. data/ext/java/nokogiri/XmlNode.java +69 -38
  4. data/ext/java/nokogiri/XmlReader.java +4 -1
  5. data/ext/java/nokogiri/XmlSchema.java +5 -74
  6. data/ext/java/nokogiri/XmlXpathContext.java +5 -15
  7. data/ext/java/nokogiri/internals/NokogiriEntityResolver.java +5 -7
  8. data/ext/java/nokogiri/internals/NokogiriHelpers.java +68 -0
  9. data/ext/java/nokogiri/internals/NokogiriXPathContext.java +37 -0
  10. data/ext/nokogiri/extconf.rb +1 -0
  11. data/ext/nokogiri/gumbo.c +83 -6
  12. data/ext/nokogiri/html4_document.c +10 -3
  13. data/ext/nokogiri/libxml2_polyfill.c +12 -0
  14. data/ext/nokogiri/nokogiri.c +84 -2
  15. data/ext/nokogiri/xml_document.c +42 -16
  16. data/ext/nokogiri/xml_node.c +73 -38
  17. data/ext/nokogiri/xml_node_set.c +9 -9
  18. data/ext/nokogiri/xml_reader.c +198 -107
  19. data/ext/nokogiri/xml_sax_parser.c +3 -3
  20. data/ext/nokogiri/xml_sax_parser_context.c +38 -7
  21. data/ext/nokogiri/xml_sax_push_parser.c +12 -0
  22. data/ext/nokogiri/xml_xpath_context.c +124 -26
  23. data/ext/nokogiri/xslt_stylesheet.c +123 -27
  24. data/lib/nokogiri/css/parser.rb +35 -18
  25. data/lib/nokogiri/css/parser.y +35 -17
  26. data/lib/nokogiri/css/xpath_visitor.rb +71 -28
  27. data/lib/nokogiri/html5/document.rb +9 -0
  28. data/lib/nokogiri/html5/document_fragment.rb +16 -1
  29. data/lib/nokogiri/html5/node.rb +1 -1
  30. data/lib/nokogiri/html5.rb +16 -0
  31. data/lib/nokogiri/nokogiri.jar +0 -0
  32. data/lib/nokogiri/version/constant.rb +1 -1
  33. data/lib/nokogiri/xml/attr.rb +2 -0
  34. data/lib/nokogiri/xml/attribute_decl.rb +2 -1
  35. data/lib/nokogiri/xml/builder.rb +24 -32
  36. data/lib/nokogiri/xml/document.rb +1 -0
  37. data/lib/nokogiri/xml/dtd.rb +2 -1
  38. data/lib/nokogiri/xml/element_decl.rb +2 -1
  39. data/lib/nokogiri/xml/entity_decl.rb +2 -1
  40. data/lib/nokogiri/xml/node.rb +8 -6
  41. metadata +3 -2
@@ -2,29 +2,64 @@
2
2
 
3
3
  VALUE cNokogiriXmlReader;
4
4
 
5
+ typedef struct {
6
+ xmlTextReaderPtr reader;
7
+ VALUE rb_source;
8
+ } nokogiriXmlReaderTuple;
9
+
10
+ static void
11
+ _noko_xml_reader_mark(void *data)
12
+ {
13
+ nokogiriXmlReaderTuple *tuple = data;
14
+ /* Pin the source because libxml2 retains its IO handle or string buffer. */
15
+ rb_gc_mark(tuple->rb_source);
16
+ }
17
+
5
18
  static void
6
19
  xml_reader_deallocate(void *data)
7
20
  {
21
+ nokogiriXmlReaderTuple *tuple = data;
8
22
  // free the document separately because we _may_ have triggered preservation by calling
9
23
  // xmlTextReaderCurrentDoc during a read_more.
10
- xmlTextReaderPtr reader = data;
11
- xmlDocPtr doc = xmlTextReaderCurrentDoc(reader);
12
- xmlFreeTextReader(reader);
24
+ xmlDocPtr doc = xmlTextReaderCurrentDoc(tuple->reader);
25
+ xmlFreeTextReader(tuple->reader);
13
26
  if (doc) {
14
27
  xmlFreeDoc(doc);
15
28
  }
29
+ ruby_xfree(tuple);
16
30
  }
17
31
 
18
32
  static const rb_data_type_t xml_text_reader_type = {
19
33
  .wrap_struct_name = "xmlTextReader",
20
34
  .function = {
35
+ .dmark = _noko_xml_reader_mark,
21
36
  .dfree = xml_reader_deallocate,
22
37
  },
23
38
  .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
24
39
  };
25
40
 
41
+ static xmlTextReaderPtr
42
+ _noko_xml_reader_unwrap(VALUE rb_reader)
43
+ {
44
+ nokogiriXmlReaderTuple *tuple;
45
+ TypedData_Get_Struct(rb_reader, nokogiriXmlReaderTuple, &xml_text_reader_type, tuple);
46
+ return tuple->reader;
47
+ }
48
+
49
+ static VALUE
50
+ _noko_xml_reader_wrap(VALUE klass, xmlTextReaderPtr c_reader, VALUE rb_source)
51
+ {
52
+ nokogiriXmlReaderTuple *tuple;
53
+ VALUE rb_reader = TypedData_Make_Struct(klass, nokogiriXmlReaderTuple, &xml_text_reader_type, tuple);
54
+
55
+ tuple->reader = c_reader;
56
+ RB_OBJ_WRITE(rb_reader, &tuple->rb_source, rb_source);
57
+
58
+ return rb_reader;
59
+ }
60
+
26
61
  static int
27
- has_attributes(xmlTextReaderPtr reader)
62
+ has_attributes(xmlTextReaderPtr c_reader)
28
63
  {
29
64
  /*
30
65
  * this implementation of xmlTextReaderHasAttributes explicitly includes
@@ -32,7 +67,7 @@ has_attributes(xmlTextReaderPtr reader)
32
67
  * namespaces.
33
68
  */
34
69
  xmlNodePtr node ;
35
- node = xmlTextReaderCurrentNode(reader);
70
+ node = xmlTextReaderCurrentNode(c_reader);
36
71
  if (node == NULL) {
37
72
  return (0);
38
73
  }
@@ -79,13 +114,13 @@ Nokogiri_xml_node_namespaces(xmlNodePtr node, VALUE attr_hash)
79
114
  * Was an attribute generated from the default value in the DTD or schema?
80
115
  */
81
116
  static VALUE
82
- default_eh(VALUE self)
117
+ default_eh(VALUE rb_reader)
83
118
  {
84
- xmlTextReaderPtr reader;
119
+ xmlTextReaderPtr c_reader;
85
120
  int eh;
86
121
 
87
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
88
- eh = xmlTextReaderIsDefault(reader);
122
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
123
+ eh = xmlTextReaderIsDefault(c_reader);
89
124
  if (eh == 0) { return Qfalse; }
90
125
  if (eh == 1) { return Qtrue; }
91
126
 
@@ -99,13 +134,13 @@ default_eh(VALUE self)
99
134
  * Does this node have a text value?
100
135
  */
101
136
  static VALUE
102
- value_eh(VALUE self)
137
+ value_eh(VALUE rb_reader)
103
138
  {
104
- xmlTextReaderPtr reader;
139
+ xmlTextReaderPtr c_reader;
105
140
  int eh;
106
141
 
107
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
108
- eh = xmlTextReaderHasValue(reader);
142
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
143
+ eh = xmlTextReaderHasValue(c_reader);
109
144
  if (eh == 0) { return Qfalse; }
110
145
  if (eh == 1) { return Qtrue; }
111
146
 
@@ -119,13 +154,13 @@ value_eh(VALUE self)
119
154
  * Does this node have attributes?
120
155
  */
121
156
  static VALUE
122
- attributes_eh(VALUE self)
157
+ attributes_eh(VALUE rb_reader)
123
158
  {
124
- xmlTextReaderPtr reader;
159
+ xmlTextReaderPtr c_reader;
125
160
  int eh;
126
161
 
127
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
128
- eh = has_attributes(reader);
162
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
163
+ eh = has_attributes(c_reader);
129
164
  if (eh == 0) { return Qfalse; }
130
165
  if (eh == 1) { return Qtrue; }
131
166
 
@@ -145,18 +180,24 @@ rb_xml_reader_namespaces(VALUE rb_reader)
145
180
  xmlTextReaderPtr c_reader;
146
181
  xmlNodePtr c_node;
147
182
  VALUE rb_errors;
183
+ libxmlStructuredErrorHandlerState handler_state;
148
184
 
149
- TypedData_Get_Struct(rb_reader, xmlTextReader, &xml_text_reader_type, c_reader);
185
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
150
186
 
151
187
  if (! has_attributes(c_reader)) {
152
188
  return rb_namespaces ;
153
189
  }
154
190
 
155
191
  rb_errors = rb_funcall(rb_reader, rb_intern("errors"), 0);
192
+ noko__structured_error_func_save_and_set(&handler_state, (void *)rb_errors, noko__error_array_pusher);
156
193
 
157
- xmlSetStructuredErrorFunc((void *)rb_errors, noko__error_array_pusher);
194
+ noko_io_read_reset_exception();
158
195
  c_node = xmlTextReaderExpand(c_reader);
159
- xmlSetStructuredErrorFunc(NULL, NULL);
196
+ VALUE rb_io_read_exception = noko_io_read_take_exception();
197
+
198
+ noko__structured_error_func_restore(&handler_state);
199
+
200
+ if (!NIL_P(rb_io_read_exception)) { noko_io_read_raise_exception(rb_io_read_exception); }
160
201
 
161
202
  if (c_node == NULL) {
162
203
  if (RARRAY_LEN(rb_errors) > 0) {
@@ -187,18 +228,24 @@ rb_xml_reader_attribute_hash(VALUE rb_reader)
187
228
  xmlNodePtr c_node;
188
229
  xmlAttrPtr c_property;
189
230
  VALUE rb_errors;
231
+ libxmlStructuredErrorHandlerState handler_state;
190
232
 
191
- TypedData_Get_Struct(rb_reader, xmlTextReader, &xml_text_reader_type, c_reader);
233
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
192
234
 
193
235
  if (!has_attributes(c_reader)) {
194
236
  return rb_attributes;
195
237
  }
196
238
 
197
239
  rb_errors = rb_funcall(rb_reader, rb_intern("errors"), 0);
240
+ noko__structured_error_func_save_and_set(&handler_state, (void *)rb_errors, noko__error_array_pusher);
198
241
 
199
- xmlSetStructuredErrorFunc((void *)rb_errors, noko__error_array_pusher);
242
+ noko_io_read_reset_exception();
200
243
  c_node = xmlTextReaderExpand(c_reader);
201
- xmlSetStructuredErrorFunc(NULL, NULL);
244
+ VALUE rb_io_read_exception = noko_io_read_take_exception();
245
+
246
+ noko__structured_error_func_restore(&handler_state);
247
+
248
+ if (!NIL_P(rb_io_read_exception)) { noko_io_read_raise_exception(rb_io_read_exception); }
202
249
 
203
250
  if (c_node == NULL) {
204
251
  if (RARRAY_LEN(rb_errors) > 0) {
@@ -235,19 +282,19 @@ rb_xml_reader_attribute_hash(VALUE rb_reader)
235
282
  * Get the value of attribute at +index+
236
283
  */
237
284
  static VALUE
238
- attribute_at(VALUE self, VALUE index)
285
+ attribute_at(VALUE rb_reader, VALUE index)
239
286
  {
240
- xmlTextReaderPtr reader;
287
+ xmlTextReaderPtr c_reader;
241
288
  xmlChar *value;
242
289
  VALUE rb_value;
243
290
 
244
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
291
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
245
292
 
246
293
  if (NIL_P(index)) { return Qnil; }
247
294
  index = rb_Integer(index);
248
295
 
249
296
  value = xmlTextReaderGetAttributeNo(
250
- reader,
297
+ c_reader,
251
298
  (int)NUM2INT(index)
252
299
  );
253
300
  if (value == NULL) { return Qnil; }
@@ -264,18 +311,18 @@ attribute_at(VALUE self, VALUE index)
264
311
  * Get the value of attribute named +name+
265
312
  */
266
313
  static VALUE
267
- reader_attribute(VALUE self, VALUE name)
314
+ reader_attribute(VALUE rb_reader, VALUE name)
268
315
  {
269
- xmlTextReaderPtr reader;
316
+ xmlTextReaderPtr c_reader;
270
317
  xmlChar *value ;
271
318
  VALUE rb_value;
272
319
 
273
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
320
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
274
321
 
275
322
  if (NIL_P(name)) { return Qnil; }
276
323
  name = StringValue(name) ;
277
324
 
278
- value = xmlTextReaderGetAttribute(reader, (xmlChar *)StringValueCStr(name));
325
+ value = xmlTextReaderGetAttribute(c_reader, (xmlChar *)StringValueCStr(name));
279
326
  if (value == NULL) { return Qnil; }
280
327
 
281
328
  rb_value = NOKOGIRI_STR_NEW2(value);
@@ -290,13 +337,13 @@ reader_attribute(VALUE self, VALUE name)
290
337
  * Get the number of attributes for the current node
291
338
  */
292
339
  static VALUE
293
- attribute_count(VALUE self)
340
+ attribute_count(VALUE rb_reader)
294
341
  {
295
- xmlTextReaderPtr reader;
342
+ xmlTextReaderPtr c_reader;
296
343
  int count;
297
344
 
298
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
299
- count = xmlTextReaderAttributeCount(reader);
345
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
346
+ count = xmlTextReaderAttributeCount(c_reader);
300
347
  if (count == -1) { return Qnil; }
301
348
 
302
349
  return INT2NUM(count);
@@ -309,13 +356,13 @@ attribute_count(VALUE self)
309
356
  * Get the depth of the node
310
357
  */
311
358
  static VALUE
312
- depth(VALUE self)
359
+ depth(VALUE rb_reader)
313
360
  {
314
- xmlTextReaderPtr reader;
361
+ xmlTextReaderPtr c_reader;
315
362
  int depth;
316
363
 
317
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
318
- depth = xmlTextReaderDepth(reader);
364
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
365
+ depth = xmlTextReaderDepth(c_reader);
319
366
  if (depth == -1) { return Qnil; }
320
367
 
321
368
  return INT2NUM(depth);
@@ -328,13 +375,13 @@ depth(VALUE self)
328
375
  * Get the XML version of the document being read
329
376
  */
330
377
  static VALUE
331
- xml_version(VALUE self)
378
+ xml_version(VALUE rb_reader)
332
379
  {
333
- xmlTextReaderPtr reader;
380
+ xmlTextReaderPtr c_reader;
334
381
  const char *version;
335
382
 
336
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
337
- version = (const char *)xmlTextReaderConstXmlVersion(reader);
383
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
384
+ version = (const char *)xmlTextReaderConstXmlVersion(c_reader);
338
385
  if (version == NULL) { return Qnil; }
339
386
 
340
387
  return NOKOGIRI_STR_NEW2(version);
@@ -347,13 +394,13 @@ xml_version(VALUE self)
347
394
  * Get the xml:lang scope within which the node resides.
348
395
  */
349
396
  static VALUE
350
- lang(VALUE self)
397
+ lang(VALUE rb_reader)
351
398
  {
352
- xmlTextReaderPtr reader;
399
+ xmlTextReaderPtr c_reader;
353
400
  const char *lang;
354
401
 
355
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
356
- lang = (const char *)xmlTextReaderConstXmlLang(reader);
402
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
403
+ lang = (const char *)xmlTextReaderConstXmlLang(c_reader);
357
404
  if (lang == NULL) { return Qnil; }
358
405
 
359
406
  return NOKOGIRI_STR_NEW2(lang);
@@ -366,13 +413,13 @@ lang(VALUE self)
366
413
  * Get the text value of the node if present. Returns a utf-8 encoded string.
367
414
  */
368
415
  static VALUE
369
- value(VALUE self)
416
+ value(VALUE rb_reader)
370
417
  {
371
- xmlTextReaderPtr reader;
418
+ xmlTextReaderPtr c_reader;
372
419
  const char *value;
373
420
 
374
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
375
- value = (const char *)xmlTextReaderConstValue(reader);
421
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
422
+ value = (const char *)xmlTextReaderConstValue(c_reader);
376
423
  if (value == NULL) { return Qnil; }
377
424
 
378
425
  return NOKOGIRI_STR_NEW2(value);
@@ -385,13 +432,13 @@ value(VALUE self)
385
432
  * Get the shorthand reference to the namespace associated with the node.
386
433
  */
387
434
  static VALUE
388
- prefix(VALUE self)
435
+ prefix(VALUE rb_reader)
389
436
  {
390
- xmlTextReaderPtr reader;
437
+ xmlTextReaderPtr c_reader;
391
438
  const char *prefix;
392
439
 
393
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
394
- prefix = (const char *)xmlTextReaderConstPrefix(reader);
440
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
441
+ prefix = (const char *)xmlTextReaderConstPrefix(c_reader);
395
442
  if (prefix == NULL) { return Qnil; }
396
443
 
397
444
  return NOKOGIRI_STR_NEW2(prefix);
@@ -404,13 +451,13 @@ prefix(VALUE self)
404
451
  * Get the URI defining the namespace associated with the node
405
452
  */
406
453
  static VALUE
407
- namespace_uri(VALUE self)
454
+ namespace_uri(VALUE rb_reader)
408
455
  {
409
- xmlTextReaderPtr reader;
456
+ xmlTextReaderPtr c_reader;
410
457
  const char *uri;
411
458
 
412
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
413
- uri = (const char *)xmlTextReaderConstNamespaceUri(reader);
459
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
460
+ uri = (const char *)xmlTextReaderConstNamespaceUri(c_reader);
414
461
  if (uri == NULL) { return Qnil; }
415
462
 
416
463
  return NOKOGIRI_STR_NEW2(uri);
@@ -423,13 +470,13 @@ namespace_uri(VALUE self)
423
470
  * Get the local name of the node
424
471
  */
425
472
  static VALUE
426
- local_name(VALUE self)
473
+ local_name(VALUE rb_reader)
427
474
  {
428
- xmlTextReaderPtr reader;
475
+ xmlTextReaderPtr c_reader;
429
476
  const char *name;
430
477
 
431
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
432
- name = (const char *)xmlTextReaderConstLocalName(reader);
478
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
479
+ name = (const char *)xmlTextReaderConstLocalName(c_reader);
433
480
  if (name == NULL) { return Qnil; }
434
481
 
435
482
  return NOKOGIRI_STR_NEW2(name);
@@ -442,13 +489,13 @@ local_name(VALUE self)
442
489
  * Get the name of the node. Returns a utf-8 encoded string.
443
490
  */
444
491
  static VALUE
445
- name(VALUE self)
492
+ name(VALUE rb_reader)
446
493
  {
447
- xmlTextReaderPtr reader;
494
+ xmlTextReaderPtr c_reader;
448
495
  const char *name;
449
496
 
450
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
451
- name = (const char *)xmlTextReaderConstName(reader);
497
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
498
+ name = (const char *)xmlTextReaderConstName(c_reader);
452
499
  if (name == NULL) { return Qnil; }
453
500
 
454
501
  return NOKOGIRI_STR_NEW2(name);
@@ -467,7 +514,7 @@ rb_xml_reader_base_uri(VALUE rb_reader)
467
514
  xmlTextReaderPtr c_reader;
468
515
  xmlChar *c_base_uri;
469
516
 
470
- TypedData_Get_Struct(rb_reader, xmlTextReader, &xml_text_reader_type, c_reader);
517
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
471
518
 
472
519
  c_base_uri = xmlTextReaderBaseUri(c_reader);
473
520
  if (c_base_uri == NULL) {
@@ -487,11 +534,11 @@ rb_xml_reader_base_uri(VALUE rb_reader)
487
534
  * Get the state of the reader
488
535
  */
489
536
  static VALUE
490
- state(VALUE self)
537
+ state(VALUE rb_reader)
491
538
  {
492
- xmlTextReaderPtr reader;
493
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
494
- return INT2NUM(xmlTextReaderReadState(reader));
539
+ xmlTextReaderPtr c_reader;
540
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
541
+ return INT2NUM(xmlTextReaderReadState(c_reader));
495
542
  }
496
543
 
497
544
  /*
@@ -501,11 +548,11 @@ state(VALUE self)
501
548
  * Get the type of readers current node
502
549
  */
503
550
  static VALUE
504
- node_type(VALUE self)
551
+ node_type(VALUE rb_reader)
505
552
  {
506
- xmlTextReaderPtr reader;
507
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
508
- return INT2NUM(xmlTextReaderNodeType(reader));
553
+ xmlTextReaderPtr c_reader;
554
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
555
+ return INT2NUM(xmlTextReaderNodeType(c_reader));
509
556
  }
510
557
 
511
558
  /*
@@ -520,15 +567,19 @@ read_more(VALUE rb_reader)
520
567
  xmlTextReaderPtr c_reader;
521
568
  libxmlStructuredErrorHandlerState handler_state;
522
569
 
523
- TypedData_Get_Struct(rb_reader, xmlTextReader, &xml_text_reader_type, c_reader);
570
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
524
571
 
525
572
  VALUE rb_errors = rb_funcall(rb_reader, rb_intern("errors"), 0);
526
573
  noko__structured_error_func_save_and_set(&handler_state, (void *)rb_errors, noko__error_array_pusher);
527
574
 
575
+ noko_io_read_reset_exception();
528
576
  int status = xmlTextReaderRead(c_reader);
577
+ VALUE rb_io_read_exception = noko_io_read_take_exception();
529
578
 
530
579
  noko__structured_error_func_restore(&handler_state);
531
580
 
581
+ if (!NIL_P(rb_io_read_exception)) { noko_io_read_raise_exception(rb_io_read_exception); }
582
+
532
583
  xmlDocPtr c_document = xmlTextReaderCurrentDoc(c_reader);
533
584
  if (c_document && c_document->encoding == NULL) {
534
585
  VALUE constructor_encoding = rb_iv_get(rb_reader, "@encoding");
@@ -560,15 +611,28 @@ read_more(VALUE rb_reader)
560
611
  * Returns a utf-8 encoded string.
561
612
  */
562
613
  static VALUE
563
- inner_xml(VALUE self)
614
+ inner_xml(VALUE rb_reader)
564
615
  {
565
- xmlTextReaderPtr reader;
616
+ xmlTextReaderPtr c_reader;
566
617
  xmlChar *value;
567
618
  VALUE str;
619
+ libxmlStructuredErrorHandlerState handler_state;
620
+
621
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
622
+
623
+ VALUE rb_errors = rb_funcall(rb_reader, rb_intern("errors"), 0);
624
+ noko__structured_error_func_save_and_set(&handler_state, (void *)rb_errors, noko__error_array_pusher);
568
625
 
569
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
626
+ noko_io_read_reset_exception();
627
+ value = xmlTextReaderReadInnerXml(c_reader);
628
+ VALUE rb_io_read_exception = noko_io_read_take_exception();
570
629
 
571
- value = xmlTextReaderReadInnerXml(reader);
630
+ noko__structured_error_func_restore(&handler_state);
631
+
632
+ if (!NIL_P(rb_io_read_exception)) {
633
+ xmlFree(value);
634
+ noko_io_read_raise_exception(rb_io_read_exception);
635
+ }
572
636
 
573
637
  str = Qnil;
574
638
  if (value) {
@@ -587,20 +651,37 @@ inner_xml(VALUE self)
587
651
  * Returns a utf-8 encoded string.
588
652
  */
589
653
  static VALUE
590
- outer_xml(VALUE self)
654
+ outer_xml(VALUE rb_reader)
591
655
  {
592
- xmlTextReaderPtr reader;
593
- xmlChar *value;
594
- VALUE str = Qnil;
656
+ xmlTextReaderPtr c_reader;
657
+ libxmlStructuredErrorHandlerState handler_state;
595
658
 
596
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
659
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
597
660
 
598
- value = xmlTextReaderReadOuterXml(reader);
661
+ VALUE rb_errors = rb_funcall(rb_reader, rb_intern("errors"), 0);
662
+ noko__structured_error_func_save_and_set(&handler_state, (void *)rb_errors, noko__error_array_pusher);
599
663
 
600
- if (value) {
601
- str = NOKOGIRI_STR_NEW2((char *)value);
664
+ noko_io_read_reset_exception();
665
+ xmlChar *value = xmlTextReaderReadOuterXml(c_reader);
666
+ VALUE rb_io_read_exception = noko_io_read_take_exception();
667
+
668
+ noko__structured_error_func_restore(&handler_state);
669
+
670
+ if (!NIL_P(rb_io_read_exception)) {
602
671
  xmlFree(value);
672
+ noko_io_read_raise_exception(rb_io_read_exception);
673
+ }
674
+
675
+ if (value == NULL) {
676
+ VALUE exception = rb_funcall(cNokogiriXmlSyntaxError, rb_intern("aggregate"), 1, rb_errors);
677
+ if (RB_TEST(exception)) {
678
+ rb_exc_raise(exception);
679
+ }
680
+ return Qnil;
603
681
  }
682
+
683
+ VALUE str = NOKOGIRI_STR_NEW2((char *)value);
684
+ xmlFree(value);
604
685
  return str;
605
686
  }
606
687
 
@@ -616,7 +697,7 @@ from_memory(int argc, VALUE *argv, VALUE klass)
616
697
  /* TODO: deprecate this method, since Reader.new can handle both memory and IO. It can then
617
698
  * become private. */
618
699
  VALUE rb_buffer, rb_url, encoding, rb_options;
619
- xmlTextReaderPtr reader;
700
+ xmlTextReaderPtr c_reader;
620
701
  const char *c_url = NULL;
621
702
  const char *c_encoding = NULL;
622
703
  int c_options = 0;
@@ -629,20 +710,23 @@ from_memory(int argc, VALUE *argv, VALUE klass)
629
710
  if (RTEST(encoding)) { c_encoding = StringValueCStr(encoding); }
630
711
  if (RTEST(rb_options)) { c_options = (int)NUM2INT(rb_options); }
631
712
 
632
- reader = xmlReaderForMemory(
633
- StringValuePtr(rb_buffer),
634
- (int)RSTRING_LEN(rb_buffer),
713
+ /* libxml2 < 2.11 reads the buffer without copying it, so hand it a copy the caller cannot change. */
714
+ VALUE rb_frozen_buffer = rb_str_new_frozen(StringValue(rb_buffer));
715
+
716
+ c_reader = xmlReaderForMemory(
717
+ RSTRING_PTR(rb_frozen_buffer),
718
+ (int)RSTRING_LEN(rb_frozen_buffer),
635
719
  c_url,
636
720
  c_encoding,
637
721
  c_options
638
722
  );
639
723
 
640
- if (reader == NULL) {
641
- xmlFreeTextReader(reader);
724
+ if (c_reader == NULL) {
725
+ xmlFreeTextReader(c_reader);
642
726
  rb_raise(rb_eRuntimeError, "couldn't create a parser");
643
727
  }
644
728
 
645
- rb_reader = TypedData_Wrap_Struct(klass, &xml_text_reader_type, reader);
729
+ rb_reader = _noko_xml_reader_wrap(klass, c_reader, rb_frozen_buffer);
646
730
  args[0] = rb_buffer;
647
731
  args[1] = rb_url;
648
732
  args[2] = encoding;
@@ -663,7 +747,7 @@ from_io(int argc, VALUE *argv, VALUE klass)
663
747
  /* TODO: deprecate this method, since Reader.new can handle both memory and IO. It can then
664
748
  * become private. */
665
749
  VALUE rb_io, rb_url, encoding, rb_options;
666
- xmlTextReaderPtr reader;
750
+ xmlTextReaderPtr c_reader;
667
751
  const char *c_url = NULL;
668
752
  const char *c_encoding = NULL;
669
753
  int c_options = 0;
@@ -676,21 +760,28 @@ from_io(int argc, VALUE *argv, VALUE klass)
676
760
  if (RTEST(encoding)) { c_encoding = StringValueCStr(encoding); }
677
761
  if (RTEST(rb_options)) { c_options = (int)NUM2INT(rb_options); }
678
762
 
679
- reader = xmlReaderForIO(
680
- (xmlInputReadCallback)noko_io_read,
763
+ noko_io_read_reset_exception();
764
+ c_reader = xmlReaderForIO(
765
+ (xmlInputReadCallback)noko_io_read_protected,
681
766
  (xmlInputCloseCallback)noko_io_close,
682
767
  (void *)rb_io,
683
768
  c_url,
684
769
  c_encoding,
685
770
  c_options
686
771
  );
772
+ VALUE rb_io_read_exception = noko_io_read_take_exception();
773
+
774
+ if (!NIL_P(rb_io_read_exception)) {
775
+ xmlFreeTextReader(c_reader);
776
+ noko_io_read_raise_exception(rb_io_read_exception);
777
+ }
687
778
 
688
- if (reader == NULL) {
689
- xmlFreeTextReader(reader);
779
+ if (c_reader == NULL) {
780
+ xmlFreeTextReader(c_reader);
690
781
  rb_raise(rb_eRuntimeError, "couldn't create a parser");
691
782
  }
692
783
 
693
- rb_reader = TypedData_Wrap_Struct(klass, &xml_text_reader_type, reader);
784
+ rb_reader = _noko_xml_reader_wrap(klass, c_reader, rb_io);
694
785
  args[0] = rb_io;
695
786
  args[1] = rb_url;
696
787
  args[2] = encoding;
@@ -706,13 +797,13 @@ from_io(int argc, VALUE *argv, VALUE klass)
706
797
  * Returns true if the current node is empty, otherwise false.
707
798
  */
708
799
  static VALUE
709
- empty_element_p(VALUE self)
800
+ empty_element_p(VALUE rb_reader)
710
801
  {
711
- xmlTextReaderPtr reader;
802
+ xmlTextReaderPtr c_reader;
712
803
 
713
- TypedData_Get_Struct(self, xmlTextReader, &xml_text_reader_type, reader);
804
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
714
805
 
715
- if (xmlTextReaderIsEmptyElement(reader)) {
806
+ if (xmlTextReaderIsEmptyElement(c_reader)) {
716
807
  return Qtrue;
717
808
  }
718
809
 
@@ -726,7 +817,7 @@ rb_xml_reader_encoding(VALUE rb_reader)
726
817
  const char *parser_encoding;
727
818
  VALUE constructor_encoding;
728
819
 
729
- TypedData_Get_Struct(rb_reader, xmlTextReader, &xml_text_reader_type, c_reader);
820
+ c_reader = _noko_xml_reader_unwrap(rb_reader);
730
821
  parser_encoding = (const char *)xmlTextReaderConstEncoding(c_reader);
731
822
  if (parser_encoding) {
732
823
  return NOKOGIRI_STR_NEW2(parser_encoding);
@@ -121,7 +121,7 @@ noko_xml_sax_parser_end_element_callback(void *ctx, const xmlChar *name)
121
121
  static VALUE
122
122
  xml_sax_parser_marshal_attributes(int attributes_len, const xmlChar **c_attributes)
123
123
  {
124
- VALUE rb_array = rb_ary_new2((long)attributes_len);
124
+ VALUE rb_array = rb_ary_new2((rb_len_t)attributes_len);
125
125
  VALUE cNokogiriXmlSaxParserAttribute;
126
126
 
127
127
  cNokogiriXmlSaxParserAttribute = rb_const_get_at(cNokogiriXmlSaxParser, rb_intern("Attribute"));
@@ -165,13 +165,13 @@ noko_xml_sax_parser_start_element_ns_callback(
165
165
 
166
166
  VALUE attribute_ary = xml_sax_parser_marshal_attributes(nb_attributes, attributes);
167
167
 
168
- VALUE ns_list = rb_ary_new2((long)nb_namespaces);
168
+ VALUE ns_list = rb_ary_new2((rb_len_t)nb_namespaces);
169
169
 
170
170
  if (namespaces) {
171
171
  int i;
172
172
  for (i = 0; i < nb_namespaces * 2; i += 2) {
173
173
  rb_ary_push(ns_list,
174
- rb_ary_new3((long)2,
174
+ rb_ary_new3((rb_len_t)2,
175
175
  RBSTR_OR_QNIL(namespaces[i + 0]),
176
176
  RBSTR_OR_QNIL(namespaces[i + 1])
177
177
  )