nokolexbor 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5eb708d3b21135112c1e1f373b89f94b83c4926043da9743aff108f4d4eed72
4
- data.tar.gz: 5ba497f52ea19c49816e1ec9c2b5e12449ae4f812cb011f2953ba7cf1a0b971b
3
+ metadata.gz: 7e93c293e8d506960077c772b822d4f75103d6583b8864e56f343a8ad6229c7a
4
+ data.tar.gz: 1baaaed733eae123b895e21021709fed7a7e185a10e8c27cf0d43105e7e4a272
5
5
  SHA512:
6
- metadata.gz: ff508a1599f36608c4c7ae0b360d4f2eb6f4740c059a945215dcdbc27a457a74293a2de6ba4043b5db5601dacccd4befac396b85a824e615163ab36f2a603bcb
7
- data.tar.gz: 1699d675b60d76a12da000e6bc0844842a31f910b80350a5e87bedaf4474e8078099623eeaeb1e1169c16ec23a51a4d0112aebf76c9ef25ac358a347992f32da
6
+ metadata.gz: 665232217ba5f1b0a53ad67dfcbb38244685fab9242bf718b1364b59c3b623e5150bdd471284c3424fb2c319761c30f1022d7792e1edf848e3c4c0a41de89806
7
+ data.tar.gz: 81cc64f435de161807ce0a6d3a0c8b0875a51f0f49307a763be8be4c70b3eefd0a5ea36fb364d2fec2e37b6b3307d549fc0f0bbd3afe35f47b6b797ea5998b96
@@ -5,7 +5,7 @@ extern VALUE cNokolexborNode;
5
5
  VALUE cNokolexborDocument;
6
6
 
7
7
  static void
8
- free_nl_document(lxb_dom_document_t *document)
8
+ free_nl_document(lxb_html_document_t *document)
9
9
  {
10
10
  lxb_html_document_destroy(document);
11
11
  }
@@ -25,7 +25,7 @@ static VALUE
25
25
  nl_document_parse(VALUE self, VALUE rb_html)
26
26
  {
27
27
  const char *html_c = StringValuePtr(rb_html);
28
- int html_len = RSTRING_LEN(rb_html);
28
+ size_t html_len = RSTRING_LEN(rb_html);
29
29
 
30
30
  lxb_html_document_t *document;
31
31
 
@@ -35,13 +35,13 @@ nl_document_parse(VALUE self, VALUE rb_html)
35
35
  rb_raise(rb_eRuntimeError, "Error creating document");
36
36
  }
37
37
 
38
- lxb_status_t status = lxb_html_document_parse(document, html_c, html_len);
38
+ lxb_status_t status = lxb_html_document_parse(document, (const lxb_char_t *)html_c, html_len);
39
39
  if (status != LXB_STATUS_OK)
40
40
  {
41
41
  nl_raise_lexbor_error(status);
42
42
  }
43
43
 
44
- return TypedData_Wrap_Struct(cNokolexborDocument, &nl_document_type, &document->dom_document);
44
+ return TypedData_Wrap_Struct(cNokolexborDocument, &nl_document_type, document);
45
45
  }
46
46
 
47
47
  static VALUE
@@ -50,6 +50,14 @@ nl_document_new(VALUE self)
50
50
  return nl_document_parse(self, rb_str_new("", 0));
51
51
  }
52
52
 
53
+ lxb_dom_document_t *
54
+ nl_rb_document_unwrap(VALUE rb_doc)
55
+ {
56
+ lxb_dom_document_t *doc;
57
+ TypedData_Get_Struct(rb_doc, lxb_dom_document_t, &nl_document_type, doc);
58
+ return doc;
59
+ }
60
+
53
61
  void Init_nl_document(void)
54
62
  {
55
63
  cNokolexborDocument = rb_define_class_under(mNokolexbor, "Document", cNokolexborNode);
@@ -43,7 +43,7 @@ nl_rb_node_unwrap(VALUE rb_node)
43
43
  lxb_dom_node_t *node;
44
44
  if (rb_obj_class(rb_node) == cNokolexborDocument)
45
45
  {
46
- TypedData_Get_Struct(rb_node, lxb_dom_document_t, &nl_document_type, node);
46
+ TypedData_Get_Struct(rb_node, lxb_dom_node_t, &nl_document_type, node);
47
47
  }
48
48
  else
49
49
  {
@@ -56,7 +56,6 @@ static VALUE
56
56
  nl_node_new(int argc, VALUE *argv, VALUE klass)
57
57
  {
58
58
  lxb_dom_document_t *document;
59
- lxb_dom_node_t *node;
60
59
  VALUE rb_name;
61
60
  VALUE rb_document;
62
61
  VALUE rest;
@@ -68,9 +67,9 @@ nl_node_new(int argc, VALUE *argv, VALUE klass)
68
67
  rb_raise(rb_eArgError, "Document must be a Nokolexbor::Document");
69
68
  }
70
69
 
71
- TypedData_Get_Struct(rb_document, lxb_dom_document_t, &nl_document_type, document);
70
+ document = nl_rb_document_unwrap(rb_document);
72
71
 
73
- lxb_dom_element_t *element = lxb_dom_document_create_element(document, StringValueCStr(rb_name), RSTRING_LEN(rb_name), NULL);
72
+ lxb_dom_element_t *element = lxb_dom_document_create_element(document, (const lxb_char_t *)StringValueCStr(rb_name), RSTRING_LEN(rb_name), NULL);
74
73
  if (element == NULL)
75
74
  {
76
75
  rb_raise(rb_eRuntimeError, "Error creating element");
@@ -97,7 +96,7 @@ nl_node_content(VALUE self)
97
96
  {
98
97
  return rb_str_new("", 0);
99
98
  }
100
- VALUE rb_str = rb_utf8_str_new(text, str_len);
99
+ VALUE rb_str = rb_utf8_str_new((char *)text, str_len);
101
100
  lxb_dom_document_destroy_text(node->owner_document, text);
102
101
 
103
102
  return rb_str;
@@ -115,19 +114,19 @@ nl_node_get_attr(VALUE self, VALUE rb_attr)
115
114
 
116
115
  VALUE rb_attr_s = rb_String(rb_attr);
117
116
  const char *attr_c = RSTRING_PTR(rb_attr_s);
118
- int attr_len = RSTRING_LEN(rb_attr_s);
117
+ size_t attr_len = RSTRING_LEN(rb_attr_s);
119
118
 
120
- lxb_dom_element_t *element = lxb_html_interface_element(node);
119
+ lxb_dom_element_t *element = lxb_dom_interface_element(node);
121
120
 
122
- if (!lxb_dom_element_has_attribute(element, attr_c, attr_len))
121
+ if (!lxb_dom_element_has_attribute(element, (const lxb_char_t *)attr_c, attr_len))
123
122
  {
124
123
  return Qnil;
125
124
  }
126
125
 
127
126
  size_t attr_value_len;
128
- char *attr_value = lxb_dom_element_get_attribute(element, attr_c, attr_len, &attr_value_len);
127
+ const lxb_char_t *attr_value = lxb_dom_element_get_attribute(element, (const lxb_char_t *)attr_c, attr_len, &attr_value_len);
129
128
 
130
- return rb_utf8_str_new(attr_value, attr_value_len);
129
+ return rb_utf8_str_new((const char *)attr_value, attr_value_len);
131
130
  }
132
131
 
133
132
  static VALUE
@@ -144,13 +143,13 @@ nl_node_set_attr(VALUE self, VALUE rb_attr, VALUE rb_value)
144
143
  VALUE rb_value_s = rb_String(rb_value);
145
144
 
146
145
  const char *attr_c = RSTRING_PTR(rb_attr_s);
147
- int attr_len = RSTRING_LEN(rb_attr_s);
146
+ size_t attr_len = RSTRING_LEN(rb_attr_s);
148
147
  const char *value_c = RSTRING_PTR(rb_value_s);
149
- int value_len = RSTRING_LEN(rb_value_s);
148
+ size_t value_len = RSTRING_LEN(rb_value_s);
150
149
 
151
- lxb_dom_element_t *element = lxb_html_interface_element(node);
150
+ lxb_dom_element_t *element = lxb_dom_interface_element(node);
152
151
 
153
- lxb_dom_element_set_attribute(element, attr_c, attr_len, value_c, value_len);
152
+ lxb_dom_element_set_attribute(element, (const lxb_char_t *)attr_c, attr_len, (const lxb_char_t *)value_c, value_len);
154
153
 
155
154
  return rb_value;
156
155
  }
@@ -168,14 +167,14 @@ nl_node_remove_attr(VALUE self, VALUE rb_attr)
168
167
  VALUE rb_attr_s = rb_String(rb_attr);
169
168
 
170
169
  const char *attr_c = RSTRING_PTR(rb_attr_s);
171
- int attr_len = RSTRING_LEN(rb_attr_s);
170
+ size_t attr_len = RSTRING_LEN(rb_attr_s);
172
171
 
173
- lxb_dom_element_t *element = lxb_html_interface_element(node);
172
+ lxb_dom_element_t *element = lxb_dom_interface_element(node);
174
173
 
175
- return lxb_dom_element_remove_attribute(element, attr_c, attr_len) == LXB_STATUS_OK ? Qtrue : Qfalse;
174
+ return lxb_dom_element_remove_attribute(element, (const lxb_char_t *)attr_c, attr_len) == LXB_STATUS_OK ? Qtrue : Qfalse;
176
175
  }
177
176
 
178
- static lxb_status_t
177
+ lxb_status_t
179
178
  nl_node_at_css_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *spec, void *ctx)
180
179
  {
181
180
  lexbor_array_t *array = (lexbor_array_t *)ctx;
@@ -188,7 +187,7 @@ nl_node_at_css_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *sp
188
187
  return LXB_STATUS_STOP;
189
188
  }
190
189
 
191
- static lxb_status_t
190
+ lxb_status_t
192
191
  nl_node_css_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *spec, void *ctx)
193
192
  {
194
193
  lexbor_array_t *array = (lexbor_array_t *)ctx;
@@ -200,11 +199,11 @@ nl_node_css_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *spec,
200
199
  return LXB_STATUS_OK;
201
200
  }
202
201
 
203
- static void
202
+ void
204
203
  nl_node_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void *ctx)
205
204
  {
206
205
  const char *selector_c = StringValuePtr(selector);
207
- int selector_len = RSTRING_LEN(selector);
206
+ size_t selector_len = RSTRING_LEN(selector);
208
207
 
209
208
  lxb_dom_node_t *node = nl_rb_node_unwrap(self);
210
209
 
@@ -226,7 +225,7 @@ nl_node_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void *ctx)
226
225
 
227
226
  /* Parse and get the log. */
228
227
  // TODO: Cache the list for reuse, improves performance
229
- lxb_css_selector_list_t *list = lxb_css_selectors_parse_relative_list(parser, selector_c, selector_len);
228
+ lxb_css_selector_list_t *list = lxb_css_selectors_parse_relative_list(parser, (const lxb_char_t *)selector_c, selector_len);
230
229
  if (parser->status != LXB_STATUS_OK)
231
230
  {
232
231
  nl_raise_lexbor_error(parser->status);
@@ -252,15 +251,15 @@ nl_node_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void *ctx)
252
251
  static void
253
252
  mark_node_orders(lxb_dom_node_t *root)
254
253
  {
255
- int count = 1;
256
- root->user = count;
254
+ size_t count = 1;
255
+ root->user = (void *)count;
257
256
  lxb_dom_node_t *node = root;
258
257
  do
259
258
  {
260
259
  if (node->first_child != NULL)
261
260
  {
262
261
  node = node->first_child;
263
- node->user = ++count;
262
+ node->user = (void *)++count;
264
263
  }
265
264
  else
266
265
  {
@@ -275,7 +274,7 @@ mark_node_orders(lxb_dom_node_t *root)
275
274
  }
276
275
 
277
276
  node = node->next;
278
- node->user = ++count;
277
+ node->user = (void *)++count;
279
278
  }
280
279
 
281
280
  } while (true);
@@ -290,7 +289,7 @@ void sort_nodes_if_necessary(VALUE selector, lxb_dom_document_t *doc, lexbor_arr
290
289
  int need_order = 0;
291
290
  // Check if we have already markded orders, note that
292
291
  // we need to order again if new nodes are added to the document
293
- for (int i = 0; i < array->length; i++)
292
+ for (size_t i = 0; i < array->length; i++)
294
293
  {
295
294
  if (((lxb_dom_node_t *)array->list[i])->user == 0)
296
295
  {
@@ -300,13 +299,13 @@ void sort_nodes_if_necessary(VALUE selector, lxb_dom_document_t *doc, lexbor_arr
300
299
  }
301
300
  if (need_order)
302
301
  {
303
- mark_node_orders(doc);
302
+ mark_node_orders(&doc->node);
304
303
  }
305
- css_result_tim_sort(&array->list[0], array->length);
304
+ css_result_tim_sort((lxb_dom_node_t **)&array->list[0], array->length);
306
305
  }
307
306
  }
308
307
 
309
- VALUE
308
+ static VALUE
310
309
  nl_node_at_css(VALUE self, VALUE selector)
311
310
  {
312
311
  lxb_dom_node_t *node = nl_rb_node_unwrap(self);
@@ -321,10 +320,14 @@ nl_node_at_css(VALUE self, VALUE selector)
321
320
 
322
321
  sort_nodes_if_necessary(selector, node->owner_document, array);
323
322
 
324
- return nl_rb_node_create(array->list[0], nl_rb_document_get(self));
323
+ VALUE ret = nl_rb_node_create(array->list[0], nl_rb_document_get(self));
324
+
325
+ lexbor_array_destroy(array, true);
326
+
327
+ return ret;
325
328
  }
326
329
 
327
- VALUE
330
+ static VALUE
328
331
  nl_node_css(VALUE self, VALUE selector)
329
332
  {
330
333
  lxb_dom_node_t *node = nl_rb_node_unwrap(self);
@@ -354,7 +357,7 @@ nl_node_inner_html(VALUE self)
354
357
 
355
358
  if (str.data != NULL)
356
359
  {
357
- VALUE ret = rb_utf8_str_new(str.data, str.length);
360
+ VALUE ret = rb_utf8_str_new((const char *)str.data, str.length);
358
361
  lexbor_str_destroy(&str, node->owner_document->text, false);
359
362
  return ret;
360
363
  }
@@ -379,7 +382,7 @@ nl_node_outer_html(VALUE self)
379
382
 
380
383
  if (str.data != NULL)
381
384
  {
382
- VALUE ret = rb_utf8_str_new(str.data, str.length);
385
+ VALUE ret = rb_utf8_str_new((const char *)str.data, str.length);
383
386
  lexbor_str_destroy(&str, node->owner_document->text, false);
384
387
  return ret;
385
388
  }
@@ -399,11 +402,11 @@ nl_node_has_key(VALUE self, VALUE rb_attr)
399
402
 
400
403
  VALUE rb_attr_s = rb_String(rb_attr);
401
404
  const char *attr_c = RSTRING_PTR(rb_attr_s);
402
- int attr_len = RSTRING_LEN(rb_attr_s);
405
+ size_t attr_len = RSTRING_LEN(rb_attr_s);
403
406
 
404
- lxb_dom_element_t *element = lxb_html_interface_element(node);
407
+ lxb_dom_element_t *element = lxb_dom_interface_element(node);
405
408
 
406
- return lxb_dom_element_has_attribute(element, attr_c, attr_len) ? Qtrue : Qfalse;
409
+ return lxb_dom_element_has_attribute(element, (const lxb_char_t *)attr_c, attr_len) ? Qtrue : Qfalse;
407
410
  }
408
411
 
409
412
  static VALUE
@@ -417,13 +420,13 @@ nl_node_keys(VALUE self)
417
420
  return ary_keys;
418
421
  }
419
422
 
420
- lxb_dom_attr_t *attr = lxb_dom_element_first_attribute(lxb_html_interface_element(node));
423
+ lxb_dom_attr_t *attr = lxb_dom_element_first_attribute(lxb_dom_interface_element(node));
421
424
 
422
425
  while (attr != NULL)
423
426
  {
424
427
  size_t tmp_len;
425
- lxb_char_t *tmp = lxb_dom_attr_qualified_name(attr, &tmp_len);
426
- rb_ary_push(ary_keys, rb_utf8_str_new(tmp, tmp_len));
428
+ const lxb_char_t *tmp = lxb_dom_attr_qualified_name(attr, &tmp_len);
429
+ rb_ary_push(ary_keys, rb_utf8_str_new((const char *)tmp, tmp_len));
427
430
 
428
431
  attr = lxb_dom_element_next_attribute(attr);
429
432
  }
@@ -442,15 +445,19 @@ nl_node_values(VALUE self)
442
445
  return ary_values;
443
446
  }
444
447
 
445
- lxb_dom_attr_t *attr = lxb_dom_element_first_attribute(lxb_html_interface_element(node));
448
+ lxb_dom_attr_t *attr = lxb_dom_element_first_attribute(lxb_dom_interface_element(node));
446
449
 
447
450
  while (attr != NULL)
448
451
  {
449
452
  size_t tmp_len;
450
- lxb_char_t *tmp = lxb_dom_attr_value(attr, &tmp_len);
453
+ const lxb_char_t *tmp = lxb_dom_attr_value(attr, &tmp_len);
451
454
  if (tmp != NULL)
452
455
  {
453
- rb_ary_push(ary_values, rb_utf8_str_new(tmp, tmp_len));
456
+ rb_ary_push(ary_values, rb_utf8_str_new((const char *)tmp, tmp_len));
457
+ }
458
+ else
459
+ {
460
+ rb_ary_push(ary_values, rb_str_new("", 0));
454
461
  }
455
462
 
456
463
  attr = lxb_dom_element_next_attribute(attr);
@@ -470,16 +477,16 @@ nl_node_attrs(VALUE self)
470
477
  return rb_hash;
471
478
  }
472
479
 
473
- lxb_dom_attr_t *attr = lxb_dom_element_first_attribute(lxb_html_interface_element(node));
480
+ lxb_dom_attr_t *attr = lxb_dom_element_first_attribute(lxb_dom_interface_element(node));
474
481
 
475
482
  while (attr != NULL)
476
483
  {
477
484
  size_t tmp_len;
478
- lxb_char_t *tmp = lxb_dom_attr_qualified_name(attr, &tmp_len);
479
- VALUE rb_key = rb_utf8_str_new(tmp, tmp_len);
485
+ const lxb_char_t *tmp = lxb_dom_attr_qualified_name(attr, &tmp_len);
486
+ VALUE rb_key = rb_utf8_str_new((const char *)tmp, tmp_len);
480
487
 
481
488
  tmp = lxb_dom_attr_value(attr, &tmp_len);
482
- VALUE rb_value = tmp != NULL ? rb_utf8_str_new(tmp, tmp_len) : Qnil;
489
+ VALUE rb_value = tmp != NULL ? rb_utf8_str_new((const char *)tmp, tmp_len) : rb_str_new("", 0);
483
490
 
484
491
  rb_hash_aset(rb_hash, rb_key, rb_value);
485
492
 
@@ -604,15 +611,16 @@ nl_node_name(VALUE self)
604
611
  {
605
612
  lxb_dom_node_t *node = nl_rb_node_unwrap(self);
606
613
  size_t len;
607
- lxb_char_t *name = lxb_dom_node_name_qualified(node, &len);
608
- return rb_utf8_str_new(name, len);
614
+ const lxb_char_t *name = lxb_dom_node_name_qualified(node, &len);
615
+ return rb_utf8_str_new((const char *)name, len);
609
616
  }
610
617
 
611
618
  static lxb_dom_node_t *
612
- nl_node_parse_fragment(lxb_html_document_t *doc, lxb_char_t *html, size_t size)
619
+ nl_node_parse_fragment(lxb_dom_document_t *doc, lxb_char_t *html, size_t size)
613
620
  {
614
621
  size_t tag_name_len;
615
- lxb_char_t *tag_name = lxb_tag_name_by_id(lxb_html_document_tags(doc), LXB_TAG__UNDEF, &tag_name_len);
622
+ lxb_html_document_t *html_doc = lxb_html_interface_document(doc);
623
+ const lxb_char_t *tag_name = lxb_tag_name_by_id(lxb_html_document_tags(html_doc), LXB_TAG__UNDEF, &tag_name_len);
616
624
  if (tag_name == NULL)
617
625
  {
618
626
  rb_raise(rb_eRuntimeError, "Error getting tag name");
@@ -622,7 +630,7 @@ nl_node_parse_fragment(lxb_html_document_t *doc, lxb_char_t *html, size_t size)
622
630
  {
623
631
  rb_raise(rb_eRuntimeError, "Error creating element");
624
632
  }
625
- lxb_dom_node_t *frag_root = lxb_html_document_parse_fragment(doc, element, html, size);
633
+ lxb_dom_node_t *frag_root = lxb_html_document_parse_fragment(html_doc, element, html, size);
626
634
  if (frag_root == NULL)
627
635
  {
628
636
  rb_raise(rb_eArgError, "Error parsing HTML");
@@ -637,7 +645,7 @@ nl_node_fragment(VALUE self, VALUE html)
637
645
  lxb_dom_node_t *node = nl_rb_node_unwrap(self);
638
646
  lxb_dom_document_t *doc = node->owner_document;
639
647
 
640
- lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, RSTRING_PTR(html), RSTRING_LEN(html));
648
+ lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, (lxb_char_t *)RSTRING_PTR(html), RSTRING_LEN(html));
641
649
  return nl_rb_node_create(frag_root, nl_rb_document_get(self));
642
650
  }
643
651
 
@@ -663,7 +671,7 @@ nl_node_add_sibling(VALUE self, VALUE next_or_previous, VALUE new)
663
671
 
664
672
  if (TYPE(new) == T_STRING)
665
673
  {
666
- lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, RSTRING_PTR(new), RSTRING_LEN(new));
674
+ lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
667
675
 
668
676
  while (frag_root->first_child != NULL)
669
677
  {
@@ -694,7 +702,7 @@ nl_node_add_child(VALUE self, VALUE new)
694
702
 
695
703
  if (TYPE(new) == T_STRING)
696
704
  {
697
- lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, RSTRING_PTR(new), RSTRING_LEN(new));
705
+ lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
698
706
 
699
707
  while (frag_root->first_child != NULL)
700
708
  {
@@ -832,11 +840,13 @@ void Init_nl_node(void)
832
840
 
833
841
  rb_define_alias(cNokolexborNode, "attr", "[]");
834
842
  rb_define_alias(cNokolexborNode, "set_attr", "[]=");
843
+ rb_define_alias(cNokolexborNode, "delete", "remove_attr");
835
844
  rb_define_alias(cNokolexborNode, "text", "content");
836
845
  rb_define_alias(cNokolexborNode, "inner_text", "content");
837
846
  rb_define_alias(cNokolexborNode, "to_str", "content");
838
847
  rb_define_alias(cNokolexborNode, "to_html", "outer_html");
839
848
  rb_define_alias(cNokolexborNode, "to_s", "outer_html");
849
+ rb_define_alias(cNokolexborNode, "unlink", "remove");
840
850
  rb_define_alias(cNokolexborNode, "type", "node_type");
841
851
  rb_define_alias(cNokolexborNode, "dup", "clone");
842
852
  }
@@ -5,15 +5,15 @@ extern VALUE cNokolexborNode;
5
5
  VALUE cNokolexborNodeSet;
6
6
  extern rb_data_type_t nl_document_type;
7
7
 
8
- VALUE nl_node_at_css(VALUE self, VALUE selector);
9
- VALUE nl_node_css(VALUE self, VALUE selector);
10
-
11
- typedef VALUE (*nl_node_find_f)(VALUE self, VALUE selector);
8
+ void nl_node_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void *ctx);
9
+ void sort_nodes_if_necessary(VALUE selector, lxb_dom_document_t *doc, lexbor_array_t *array);
10
+ lxb_status_t nl_node_at_css_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *spec, void *ctx);
11
+ lxb_status_t nl_node_css_callback(lxb_dom_node_t *node, lxb_css_selector_specificity_t *spec, void *ctx);
12
12
 
13
13
  lxb_status_t
14
14
  lexbor_array_push_unique(lexbor_array_t *array, void *value)
15
15
  {
16
- for (int i = 0; i < array->length; i++)
16
+ for (size_t i = 0; i < array->length; i++)
17
17
  if (array->list[i] == value)
18
18
  return LXB_STATUS_STOPPED;
19
19
 
@@ -91,7 +91,7 @@ nl_node_set_delete(VALUE self, VALUE rb_node)
91
91
  lexbor_array_t *array = nl_rb_node_set_unwrap(self);
92
92
  lxb_dom_node_t *node = nl_rb_node_unwrap(rb_node);
93
93
 
94
- int i;
94
+ size_t i;
95
95
  for (i = 0; i < array->length; i++)
96
96
  if (array->list[i] == node)
97
97
  {
@@ -113,7 +113,7 @@ nl_node_set_is_include(VALUE self, VALUE rb_node)
113
113
  lexbor_array_t *array = nl_rb_node_set_unwrap(self);
114
114
  lxb_dom_node_t *node = nl_rb_node_unwrap(rb_node);
115
115
 
116
- for (int i = 0; i < array->length; i++)
116
+ for (size_t i = 0; i < array->length; i++)
117
117
  if (array->list[i] == node)
118
118
  {
119
119
  return Qtrue;
@@ -169,7 +169,7 @@ nl_node_set_subseq(VALUE self, long beg, long len)
169
169
  }
170
170
  }
171
171
 
172
- for (int j = beg; j < beg + len; ++j)
172
+ for (long j = beg; j < beg + len; ++j)
173
173
  {
174
174
  lxb_status_t status = lexbor_array_push(new_array, old_array->list[j]);
175
175
  if (status != LXB_STATUS_OK)
@@ -177,7 +177,7 @@ nl_node_set_subseq(VALUE self, long beg, long len)
177
177
  nl_raise_lexbor_error(status);
178
178
  }
179
179
  }
180
- return TypedData_Wrap_Struct(cNokolexborNodeSet, &nl_node_set_type, new_array);
180
+ return nl_rb_node_set_create_with_data(new_array, nl_rb_document_get(self));
181
181
  }
182
182
 
183
183
  static VALUE
@@ -231,7 +231,7 @@ nl_node_set_to_array(VALUE self)
231
231
 
232
232
  VALUE list = rb_ary_new2(array->length);
233
233
  VALUE doc = nl_rb_document_get(self);
234
- for (int i = 0; i < array->length; i++)
234
+ for (size_t i = 0; i < array->length; i++)
235
235
  {
236
236
  lxb_dom_node_t *node = (lxb_dom_node_t *)array->list[i];
237
237
  VALUE rb_node = nl_rb_node_create(node, doc);
@@ -267,7 +267,7 @@ nl_node_set_union(VALUE self, VALUE other)
267
267
  memcpy(new_array->list, self_array->list, sizeof(lxb_dom_node_t *) * self_array->length);
268
268
  new_array->length = self_array->length;
269
269
 
270
- for (int i = 0; i < other_array->length; i++)
270
+ for (size_t i = 0; i < other_array->length; i++)
271
271
  {
272
272
  lexbor_array_push_unique(new_array, other_array->list[i]);
273
273
  }
@@ -275,16 +275,15 @@ nl_node_set_union(VALUE self, VALUE other)
275
275
  return nl_rb_node_set_create_with_data(new_array, nl_rb_document_get(self));
276
276
  }
277
277
 
278
- static VALUE
279
- nl_node_set_find(VALUE self, VALUE selector, nl_node_find_f finder)
278
+ static void
279
+ nl_node_set_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void* ctx)
280
280
  {
281
- VALUE rb_doc = nl_rb_document_get(self);
282
- lxb_dom_document_t *doc;
283
- TypedData_Get_Struct(rb_doc, lxb_dom_document_t, &nl_document_type, doc);
281
+ lxb_dom_document_t *doc = nl_rb_document_unwrap(nl_rb_document_get(self));
284
282
  if (doc == NULL)
285
283
  {
286
284
  rb_raise(rb_eRuntimeError, "Error getting document");
287
285
  }
286
+ // Wrap direct children with a temporary fragment so that they can be searched
288
287
  lxb_dom_document_fragment_t *frag = lxb_dom_document_fragment_interface_create(doc);
289
288
  if (frag == NULL)
290
289
  {
@@ -302,7 +301,7 @@ nl_node_set_find(VALUE self, VALUE selector, nl_node_find_f finder)
302
301
  }
303
302
  }
304
303
  // Backup original node data and re-group them into a fragment
305
- for (int i = 0; i < array->length; i++)
304
+ for (size_t i = 0; i < array->length; i++)
306
305
  {
307
306
  lxb_dom_node_t *node = (lxb_dom_node_t *)array->list[i];
308
307
  lxb_dom_node_t *backup_node = malloc(sizeof(lxb_dom_node_t));
@@ -320,29 +319,51 @@ nl_node_set_find(VALUE self, VALUE selector, nl_node_find_f finder)
320
319
  }
321
320
  VALUE rb_frag = nl_rb_node_create(&frag->node, nl_rb_document_get(self));
322
321
 
323
- VALUE ret = finder(rb_frag, selector);
322
+ nl_node_find(rb_frag, selector, cb, ctx);
324
323
 
325
324
  lxb_dom_document_fragment_interface_destroy(frag);
326
325
  // Restore original node data
327
- for (int i = 0; i < array->length; i++)
326
+ for (size_t i = 0; i < array->length; i++)
328
327
  {
329
328
  memcpy(array->list[i], backup_array->list[i], sizeof(lxb_dom_node_t));
330
329
  free(backup_array->list[i]);
331
330
  }
332
331
  lexbor_array_destroy(backup_array, true);
333
- return ret;
334
332
  }
335
333
 
336
334
  static VALUE
337
335
  nl_node_set_at_css(VALUE self, VALUE selector)
338
336
  {
339
- return nl_node_set_find(self, selector, nl_node_at_css);
337
+ lexbor_array_t *array = lexbor_array_create();
338
+ lxb_dom_document_t *doc = nl_rb_document_unwrap(nl_rb_document_get(self));
339
+
340
+ nl_node_set_find(self, selector, nl_node_at_css_callback, array);
341
+
342
+ if (array->length == 0)
343
+ {
344
+ return Qnil;
345
+ }
346
+
347
+ sort_nodes_if_necessary(selector, doc, array);
348
+
349
+ VALUE ret = nl_rb_node_create(array->list[0], nl_rb_document_get(self));
350
+
351
+ lexbor_array_destroy(array, true);
352
+
353
+ return ret;
340
354
  }
341
355
 
342
356
  static VALUE
343
357
  nl_node_set_css(VALUE self, VALUE selector)
344
358
  {
345
- return nl_node_set_find(self, selector, nl_node_css);
359
+ lexbor_array_t *array = lexbor_array_create();
360
+ lxb_dom_document_t *doc = nl_rb_document_unwrap(nl_rb_document_get(self));
361
+
362
+ nl_node_set_find(self, selector, nl_node_css_callback, array);
363
+
364
+ sort_nodes_if_necessary(selector, doc, array);
365
+
366
+ return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
346
367
  }
347
368
 
348
369
  void Init_nl_node_set(void)
@@ -7,9 +7,13 @@
7
7
  #include "libxml/xpathInternals.h"
8
8
  #include "libxml/parserInternals.h"
9
9
 
10
+ #define RBSTR_OR_QNIL(_str) (_str ? rb_utf8_str_new_cstr(_str) : Qnil)
11
+
10
12
  extern VALUE mNokolexbor;
11
13
  extern VALUE cNokolexborNodeSet;
12
- VALUE cNokoLexborXpathContext;
14
+ VALUE cNokolexborXpathContext;
15
+ VALUE mNokolexborXpath;
16
+ VALUE cNokolexborXpathSyntaxError;
13
17
 
14
18
  static void
15
19
  free_xml_xpath_context(xmlXPathContextPtr ctx)
@@ -24,7 +28,7 @@ free_xml_xpath_context(xmlXPathContextPtr ctx)
24
28
  * Register the namespace with +prefix+ and +uri+.
25
29
  */
26
30
  static VALUE
27
- rb_xml_xpath_context_register_ns(VALUE self, VALUE prefix, VALUE uri)
31
+ nl_xpath_context_register_ns(VALUE self, VALUE prefix, VALUE uri)
28
32
  {
29
33
  xmlXPathContextPtr ctx;
30
34
  Data_Get_Struct(self, xmlXPathContext, ctx);
@@ -42,7 +46,7 @@ rb_xml_xpath_context_register_ns(VALUE self, VALUE prefix, VALUE uri)
42
46
  * Register the variable +name+ with +value+.
43
47
  */
44
48
  static VALUE
45
- rb_xml_xpath_context_register_variable(VALUE self, VALUE name, VALUE value)
49
+ nl_xpath_context_register_variable(VALUE self, VALUE name, VALUE value)
46
50
  {
47
51
  xmlXPathContextPtr ctx;
48
52
  xmlXPathObjectPtr xmlValue;
@@ -69,7 +73,7 @@ xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr ctx, VALUE rb_do
69
73
  switch (c_xpath_object->type)
70
74
  {
71
75
  case XPATH_STRING:
72
- rb_retval = rb_utf8_str_new_cstr(c_xpath_object->stringval);
76
+ rb_retval = rb_utf8_str_new_cstr((const char *)c_xpath_object->stringval);
73
77
  xmlFree(c_xpath_object->stringval);
74
78
  return rb_retval;
75
79
 
@@ -106,6 +110,60 @@ xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr ctx, VALUE rb_do
106
110
  }
107
111
  }
108
112
 
113
+ static VALUE
114
+ nl_xpath_wrap_syntax_error(xmlErrorPtr error)
115
+ {
116
+ VALUE msg, e;
117
+
118
+ msg = (error && error->message) ? rb_utf8_str_new_cstr(error->message) : Qnil;
119
+
120
+ e = rb_class_new_instance(
121
+ 1,
122
+ &msg,
123
+ cNokolexborXpathSyntaxError);
124
+
125
+ if (error)
126
+ {
127
+ rb_iv_set(e, "@domain", INT2NUM(error->domain));
128
+ rb_iv_set(e, "@code", INT2NUM(error->code));
129
+ rb_iv_set(e, "@level", INT2NUM((short)error->level));
130
+ rb_iv_set(e, "@file", RBSTR_OR_QNIL(error->file));
131
+ rb_iv_set(e, "@line", INT2NUM(error->line));
132
+ rb_iv_set(e, "@str1", RBSTR_OR_QNIL(error->str1));
133
+ rb_iv_set(e, "@str2", RBSTR_OR_QNIL(error->str2));
134
+ rb_iv_set(e, "@str3", RBSTR_OR_QNIL(error->str3));
135
+ rb_iv_set(e, "@int1", INT2NUM(error->int1));
136
+ rb_iv_set(e, "@column", INT2NUM(error->int2));
137
+ }
138
+
139
+ return e;
140
+ }
141
+
142
+ static void nl_xpath_error_array_pusher(void *ctx, xmlErrorPtr error)
143
+ {
144
+ VALUE list = (VALUE)ctx;
145
+ Check_Type(list, T_ARRAY);
146
+ rb_ary_push(list, nl_xpath_wrap_syntax_error(error));
147
+ }
148
+
149
+ static void
150
+ nl_xpath_generic_exception_pusher(void *ctx, const char *msg, ...)
151
+ {
152
+ VALUE rb_errors = (VALUE)ctx;
153
+ VALUE rb_message;
154
+ VALUE rb_exception;
155
+
156
+ Check_Type(rb_errors, T_ARRAY);
157
+
158
+ va_list args;
159
+ va_start(args, msg);
160
+ rb_message = rb_vsprintf(msg, args);
161
+ va_end(args);
162
+
163
+ rb_exception = rb_exc_new_str(cNokolexborXpathSyntaxError, rb_message);
164
+ rb_ary_push(rb_errors, rb_exception);
165
+ }
166
+
109
167
  /*
110
168
  * call-seq:
111
169
  * evaluate(search_path, handler = nil)
@@ -113,7 +171,7 @@ xpath2ruby(xmlXPathObjectPtr c_xpath_object, xmlXPathContextPtr ctx, VALUE rb_do
113
171
  * Evaluate the +search_path+ returning an XML::XPath object.
114
172
  */
115
173
  static VALUE
116
- rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
174
+ nl_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
117
175
  {
118
176
  VALUE search_path, xpath_handler;
119
177
  VALUE retval = Qnil;
@@ -137,13 +195,13 @@ rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
137
195
  // xmlXPathRegisterFuncLookup(ctx, handler_lookup, (void *)xpath_handler);
138
196
  // }
139
197
 
140
- // xmlSetStructuredErrorFunc((void *)errors, Nokogiri_error_array_pusher);
141
- // xmlSetGenericErrorFunc((void *)errors, generic_exception_pusher);
198
+ xmlSetStructuredErrorFunc((void *)errors, nl_xpath_error_array_pusher);
199
+ xmlSetGenericErrorFunc((void *)errors, nl_xpath_generic_exception_pusher);
142
200
 
143
201
  xpath = xmlXPathEvalExpression(query, ctx);
144
202
 
145
- // xmlSetStructuredErrorFunc(NULL, NULL);
146
- // xmlSetGenericErrorFunc(NULL, NULL);
203
+ xmlSetStructuredErrorFunc(NULL, NULL);
204
+ xmlSetGenericErrorFunc(NULL, NULL);
147
205
 
148
206
  if (xpath == NULL)
149
207
  {
@@ -156,7 +214,7 @@ rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
156
214
  retval = rb_funcall(cNokolexborNodeSet, rb_intern("new"), 1, rb_ary_new());
157
215
  }
158
216
 
159
- // xmlXPathFreeNodeSetList(xpath);
217
+ xmlXPathFreeNodeSetList(xpath);
160
218
 
161
219
  return retval;
162
220
  }
@@ -168,7 +226,7 @@ rb_xml_xpath_context_evaluate(int argc, VALUE *argv, VALUE self)
168
226
  * Create a new XPathContext with +node+ as the reference point.
169
227
  */
170
228
  static VALUE
171
- rb_xml_xpath_context_new(VALUE klass, VALUE rb_node)
229
+ nl_xpath_context_new(VALUE klass, VALUE rb_node)
172
230
  {
173
231
  xmlXPathContextPtr ctx;
174
232
  VALUE self;
@@ -188,13 +246,15 @@ void Init_nl_xpath_context(void)
188
246
  {
189
247
  xmlMemSetup((xmlFreeFunc)ruby_xfree, (xmlMallocFunc)ruby_xmalloc, (xmlReallocFunc)ruby_xrealloc, ruby_strdup);
190
248
 
191
- cNokoLexborXpathContext = rb_define_class_under(mNokolexbor, "XPathContext", rb_cObject);
249
+ cNokolexborXpathContext = rb_define_class_under(mNokolexbor, "XPathContext", rb_cObject);
250
+ mNokolexborXpath = rb_define_module_under(mNokolexbor, "XPath");
251
+ cNokolexborXpathSyntaxError = rb_define_class_under(mNokolexborXpath, "SyntaxError", rb_eStandardError);
192
252
 
193
- rb_undef_alloc_func(cNokoLexborXpathContext);
253
+ rb_undef_alloc_func(cNokolexborXpathContext);
194
254
 
195
- rb_define_singleton_method(cNokoLexborXpathContext, "new", rb_xml_xpath_context_new, 1);
255
+ rb_define_singleton_method(cNokolexborXpathContext, "new", nl_xpath_context_new, 1);
196
256
 
197
- rb_define_method(cNokoLexborXpathContext, "evaluate", rb_xml_xpath_context_evaluate, -1);
198
- rb_define_method(cNokoLexborXpathContext, "register_variable", rb_xml_xpath_context_register_variable, 2);
199
- rb_define_method(cNokoLexborXpathContext, "register_ns", rb_xml_xpath_context_register_ns, 2);
257
+ rb_define_method(cNokolexborXpathContext, "evaluate", nl_xpath_context_evaluate, -1);
258
+ rb_define_method(cNokolexborXpathContext, "register_variable", nl_xpath_context_register_variable, 2);
259
+ rb_define_method(cNokolexborXpathContext, "register_ns", nl_xpath_context_register_ns, 2);
200
260
  }
@@ -28,6 +28,8 @@ lxb_inline VALUE nl_rb_document_get(VALUE rb_node_or_doc)
28
28
  return rb_iv_get(rb_node_or_doc, "@document");
29
29
  }
30
30
 
31
+ lxb_dom_document_t * nl_rb_document_unwrap(VALUE rb_doc);
32
+
31
33
  const lxb_char_t *
32
34
  lxb_dom_node_name_qualified(lxb_dom_node_t *node, size_t *len);
33
35
 
@@ -3,12 +3,38 @@
3
3
  #include <stdarg.h>
4
4
  #include "libxml/xmlerror.h"
5
5
 
6
- void *_xmlGenericErrorContext = NULL;
7
-
8
- // void * *
9
- // __xmlGenericErrorContext(void) {
10
- // return (&_xmlGenericErrorContext);
11
- // }
6
+ #define XML_GET_VAR_STR(msg, str) { \
7
+ int size, prev_size = -1; \
8
+ int chars; \
9
+ char *larger; \
10
+ va_list ap; \
11
+ \
12
+ str = (char *) xmlMalloc(150); \
13
+ if (str != NULL) { \
14
+ \
15
+ size = 150; \
16
+ \
17
+ while (size < 64000) { \
18
+ va_start(ap, msg); \
19
+ chars = vsnprintf(str, size, msg, ap); \
20
+ va_end(ap); \
21
+ if ((chars > -1) && (chars < size)) { \
22
+ if (prev_size == chars) { \
23
+ break; \
24
+ } else { \
25
+ prev_size = chars; \
26
+ } \
27
+ } \
28
+ if (chars > -1) \
29
+ size += chars + 1; \
30
+ else \
31
+ size += 100; \
32
+ if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
33
+ break; \
34
+ } \
35
+ str = larger; \
36
+ }} \
37
+ }
12
38
 
13
39
  /**
14
40
  * xmlGenericErrorDefaultFunc:
@@ -20,22 +46,57 @@ void *_xmlGenericErrorContext = NULL;
20
46
  */
21
47
  void XMLCDECL
22
48
  xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
23
- va_list args;
49
+ }
24
50
 
25
- if (_xmlGenericErrorContext == NULL)
26
- _xmlGenericErrorContext = (void *) stderr;
51
+ /**
52
+ * xmlCopyError:
53
+ * @from: a source error
54
+ * @to: a target error
55
+ *
56
+ * Save the original error to the new place.
57
+ *
58
+ * Returns 0 in case of success and -1 in case of error.
59
+ */
60
+ int
61
+ xmlCopyError(xmlErrorPtr from, xmlErrorPtr to) {
62
+ char *message, *file, *str1, *str2, *str3;
27
63
 
28
- va_start(args, msg);
29
- vfprintf((FILE *)_xmlGenericErrorContext, msg, args);
30
- va_end(args);
31
- }
64
+ if ((from == NULL) || (to == NULL))
65
+ return(-1);
66
+
67
+ message = (char *) xmlStrdup((xmlChar *) from->message);
68
+ file = (char *) xmlStrdup ((xmlChar *) from->file);
69
+ str1 = (char *) xmlStrdup ((xmlChar *) from->str1);
70
+ str2 = (char *) xmlStrdup ((xmlChar *) from->str2);
71
+ str3 = (char *) xmlStrdup ((xmlChar *) from->str3);
32
72
 
33
- // xmlGenericErrorFunc _xmlGenericError = xmlGenericErrorDefaultFunc;
73
+ if (to->message != NULL)
74
+ xmlFree(to->message);
75
+ if (to->file != NULL)
76
+ xmlFree(to->file);
77
+ if (to->str1 != NULL)
78
+ xmlFree(to->str1);
79
+ if (to->str2 != NULL)
80
+ xmlFree(to->str2);
81
+ if (to->str3 != NULL)
82
+ xmlFree(to->str3);
83
+ to->domain = from->domain;
84
+ to->code = from->code;
85
+ to->level = from->level;
86
+ to->line = from->line;
87
+ to->node = from->node;
88
+ to->int1 = from->int1;
89
+ to->int2 = from->int2;
90
+ to->node = from->node;
91
+ to->ctxt = from->ctxt;
92
+ to->message = message;
93
+ to->file = file;
94
+ to->str1 = str1;
95
+ to->str2 = str2;
96
+ to->str3 = str3;
34
97
 
35
- // xmlGenericErrorFunc *
36
- // __xmlGenericError(void) {
37
- // return (&_xmlGenericError);
38
- // }
98
+ return 0;
99
+ }
39
100
 
40
101
  /**
41
102
  * __xmlRaiseError:
@@ -63,16 +124,112 @@ xmlGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
63
124
  */
64
125
  void XMLCDECL
65
126
  __xmlRaiseError(xmlStructuredErrorFunc schannel,
66
- xmlGenericErrorFunc channel, void *data, void *ctx,
67
- void *nod, int domain, int code, xmlErrorLevel level,
68
- const char *file, int line, const char *str1,
69
- const char *str2, const char *str3, int int1, int col,
70
- const char *msg, ...)
127
+ xmlGenericErrorFunc channel, void *data, void *ctx,
128
+ void *nod, int domain, int code, xmlErrorLevel level,
129
+ const char *file, int line, const char *str1,
130
+ const char *str2, const char *str3, int int1, int col,
131
+ const char *msg, ...)
71
132
  {
72
- va_list args;
73
- va_start(args, msg);
74
- vfprintf(stderr, msg, args);
75
- va_end(args);
133
+ xmlParserCtxtPtr ctxt = NULL;
134
+ lxb_dom_node_t_ptr node = (lxb_dom_node_t_ptr)nod;
135
+ char *str = NULL;
136
+ xmlParserInputPtr input = NULL;
137
+ xmlErrorPtr to = &xmlLastError;
138
+ lxb_dom_node_t_ptr baseptr = NULL;
139
+
140
+ if (code == XML_ERR_OK)
141
+ return;
142
+ if ((xmlGetWarningsDefaultValue == 0) && (level == XML_ERR_WARNING))
143
+ return;
144
+ if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
145
+ (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
146
+ (domain == XML_FROM_IO) || (domain == XML_FROM_VALID))
147
+ {
148
+ ctxt = (xmlParserCtxtPtr)ctx;
149
+ if ((schannel == NULL) && (ctxt != NULL) && (ctxt->sax != NULL) &&
150
+ (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
151
+ (ctxt->sax->serror != NULL))
152
+ {
153
+ schannel = ctxt->sax->serror;
154
+ data = ctxt->userData;
155
+ }
156
+ }
157
+ /*
158
+ * Check if structured error handler set
159
+ */
160
+ if (schannel == NULL)
161
+ {
162
+ schannel = xmlStructuredError;
163
+ /*
164
+ * if user has defined handler, change data ptr to user's choice
165
+ */
166
+ if (schannel != NULL)
167
+ data = xmlStructuredErrorContext;
168
+ }
169
+ /*
170
+ * Formatting the message
171
+ */
172
+ if (msg == NULL)
173
+ {
174
+ str = (char *)xmlStrdup(BAD_CAST "No error message provided");
175
+ }
176
+ else
177
+ {
178
+ XML_GET_VAR_STR(msg, str);
179
+ }
180
+
181
+ /*
182
+ * specific processing if a parser context is provided
183
+ */
184
+ if (ctxt != NULL)
185
+ {
186
+ if (file == NULL)
187
+ {
188
+ input = ctxt->input;
189
+ if ((input != NULL) && (input->filename == NULL) &&
190
+ (ctxt->inputNr > 1))
191
+ {
192
+ input = ctxt->inputTab[ctxt->inputNr - 2];
193
+ }
194
+ if (input != NULL)
195
+ {
196
+ file = input->filename;
197
+ line = input->line;
198
+ col = input->col;
199
+ }
200
+ }
201
+ to = &ctxt->lastError;
202
+ }
203
+
204
+ /*
205
+ * Save the information about the error
206
+ */
207
+ xmlResetError(to);
208
+ to->domain = domain;
209
+ to->code = code;
210
+ to->message = str;
211
+ to->level = level;
212
+ if (file != NULL)
213
+ to->file = (char *)xmlStrdup((const xmlChar *)file);
214
+ to->line = line;
215
+ if (str1 != NULL)
216
+ to->str1 = (char *)xmlStrdup((const xmlChar *)str1);
217
+ if (str2 != NULL)
218
+ to->str2 = (char *)xmlStrdup((const xmlChar *)str2);
219
+ if (str3 != NULL)
220
+ to->str3 = (char *)xmlStrdup((const xmlChar *)str3);
221
+ to->int1 = int1;
222
+ to->int2 = col;
223
+ to->node = node;
224
+ to->ctxt = ctx;
225
+
226
+ if (to != &xmlLastError)
227
+ xmlCopyError(to, &xmlLastError);
228
+
229
+ if (schannel != NULL)
230
+ {
231
+ schannel(data, to);
232
+ }
76
233
  }
77
234
 
78
235
  /**
@@ -131,4 +288,45 @@ __xmlSimpleError(int domain, int code, lxb_dom_node_t_ptr node,
131
288
  code, XML_ERR_ERROR, NULL, 0, extra,
132
289
  NULL, NULL, 0, 0, msg, extra);
133
290
  }
291
+ }
292
+
293
+ /**
294
+ * xmlSetGenericErrorFunc:
295
+ * @ctx: the new error handling context
296
+ * @handler: the new handler function
297
+ *
298
+ * Function to reset the handler and the error context for out of
299
+ * context error messages.
300
+ * This simply means that @handler will be called for subsequent
301
+ * error messages while not parsing nor validating. And @ctx will
302
+ * be passed as first argument to @handler
303
+ * One can simply force messages to be emitted to another FILE * than
304
+ * stderr by setting @ctx to this file handle and @handler to NULL.
305
+ * For multi-threaded applications, this must be set separately for each thread.
306
+ */
307
+ void
308
+ xmlSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
309
+ xmlGenericErrorContext = ctx;
310
+ if (handler != NULL)
311
+ xmlGenericError = handler;
312
+ else
313
+ xmlGenericError = xmlGenericErrorDefaultFunc;
314
+ }
315
+
316
+ /**
317
+ * xmlSetStructuredErrorFunc:
318
+ * @ctx: the new error handling context
319
+ * @handler: the new handler function
320
+ *
321
+ * Function to reset the handler and the error context for out of
322
+ * context structured error messages.
323
+ * This simply means that @handler will be called for subsequent
324
+ * error messages while not parsing nor validating. And @ctx will
325
+ * be passed as first argument to @handler
326
+ * For multi-threaded applications, this must be set separately for each thread.
327
+ */
328
+ void
329
+ xmlSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
330
+ xmlStructuredErrorContext = ctx;
331
+ xmlStructuredError = handler;
134
332
  }
@@ -119,8 +119,8 @@ module Nokolexbor
119
119
  end
120
120
 
121
121
  def each
122
- attributes.each do |node|
123
- yield [node.name, node.value]
122
+ attributes.each do |name, node|
123
+ yield [name, node.value]
124
124
  end
125
125
  end
126
126
 
@@ -69,9 +69,13 @@ module Nokolexbor
69
69
  self.each(&:remove)
70
70
  end
71
71
 
72
- alias_method :destroy, :remove
72
+ alias_method :unlink, :remove
73
73
  alias_method :to_ary, :to_a
74
74
 
75
+ def destroy
76
+ self.each(&:destroy)
77
+ end
78
+
75
79
  def pop
76
80
  return nil if length == 0
77
81
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nokolexbor
4
- VERSION = '0.2.3'
4
+ VERSION = '0.2.4'
5
5
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nokolexbor
4
+ module XPath
5
+ class SyntaxError < StandardError
6
+ attr_reader :domain
7
+ attr_reader :code
8
+ attr_reader :level
9
+ attr_reader :file
10
+ attr_reader :line
11
+ attr_reader :str1
12
+ attr_reader :str2
13
+ attr_reader :str3
14
+ attr_reader :int1
15
+ attr_reader :column
16
+
17
+ ###
18
+ # return true if this is a non error
19
+ def none?
20
+ level == 0
21
+ end
22
+
23
+ ###
24
+ # return true if this is a warning
25
+ def warning?
26
+ level == 1
27
+ end
28
+
29
+ ###
30
+ # return true if this is an error
31
+ def error?
32
+ level == 2
33
+ end
34
+
35
+ ###
36
+ # return true if this error is fatal
37
+ def fatal?
38
+ level == 3
39
+ end
40
+
41
+ def to_s
42
+ message = super.chomp
43
+ [location_to_s, level_to_s, message]
44
+ .compact.join(": ")
45
+ .force_encoding(message.encoding)
46
+ end
47
+
48
+ private
49
+
50
+ def level_to_s
51
+ case level
52
+ when 3 then "FATAL"
53
+ when 2 then "ERROR"
54
+ when 1 then "WARNING"
55
+ end
56
+ end
57
+
58
+ def nil_or_zero?(attribute)
59
+ attribute.nil? || attribute.zero?
60
+ end
61
+
62
+ def location_to_s
63
+ return nil if nil_or_zero?(line) && nil_or_zero?(column)
64
+
65
+ "#{line}:#{column}"
66
+ end
67
+ end
68
+ end
69
+ end
data/lib/nokolexbor.rb CHANGED
@@ -6,6 +6,7 @@ require 'nokolexbor/node'
6
6
  require 'nokolexbor/document'
7
7
  require 'nokolexbor/node_set'
8
8
  require 'nokolexbor/attribute'
9
+ require 'nokolexbor/xpath'
9
10
  require 'nokolexbor/xpath_context'
10
11
 
11
12
  module Nokolexbor
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nokolexbor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yicheng Zhou
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-16 00:00:00.000000000 Z
11
+ date: 2022-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
27
41
  description: Nokolexbor is a high performance HTML5 parser, with support for both
28
42
  CSS selectors and XPath. It's API is designed to be compatible with Nokogiri.
29
43
  email: zyc9012@gmail.com
@@ -105,6 +119,7 @@ files:
105
119
  - lib/nokolexbor/node.rb
106
120
  - lib/nokolexbor/node_set.rb
107
121
  - lib/nokolexbor/version.rb
122
+ - lib/nokolexbor/xpath.rb
108
123
  - lib/nokolexbor/xpath_context.rb
109
124
  - patches/0001-lexbor-support-text-pseudo-element.patch
110
125
  - patches/0002-lexbor-match-id-class-case-sensitive.patch
@@ -522,7 +537,7 @@ licenses:
522
537
  - MIT
523
538
  metadata:
524
539
  msys2_mingw_dependencies: cmake
525
- post_install_message:
540
+ post_install_message:
526
541
  rdoc_options: []
527
542
  require_paths:
528
543
  - lib
@@ -537,8 +552,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
537
552
  - !ruby/object:Gem::Version
538
553
  version: '0'
539
554
  requirements: []
540
- rubygems_version: 3.1.4
541
- signing_key:
555
+ rubygems_version: 3.0.3.1
556
+ signing_key:
542
557
  specification_version: 4
543
558
  summary: High performance HTML5 parser, with support for both CSS selectors and XPath.
544
559
  test_files: []