nokolexbor 0.2.2 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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);
@@ -285,12 +284,12 @@ mark_node_orders(lxb_dom_node_t *root)
285
284
  void sort_nodes_if_necessary(VALUE selector, lxb_dom_document_t *doc, lexbor_array_t *array)
286
285
  {
287
286
  // No need to sort if there's only one selector, the results are natually in document traversal order
288
- if (strstr(RSTRING_PTR(selector), ",") != NULL)
287
+ if (strchr(RSTRING_PTR(selector), ',') != NULL)
289
288
  {
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)