nokolexbor 0.2.2 → 0.2.4
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.
- checksums.yaml +4 -4
- data/ext/nokolexbor/CMakeLists.txt +92 -0
- data/ext/nokolexbor/config.h.cmake.in +26 -0
- data/ext/nokolexbor/extconf.rb +17 -8
- data/ext/nokolexbor/libxml/{xmlversion.h → xmlversion.h.in} +41 -41
- data/ext/nokolexbor/nl_document.c +12 -4
- data/ext/nokolexbor/nl_node.c +66 -56
- data/ext/nokolexbor/nl_node_set.c +43 -22
- data/ext/nokolexbor/nl_xpath_context.c +78 -18
- data/ext/nokolexbor/nokolexbor.h +2 -0
- data/ext/nokolexbor/xml_error.c +225 -27
- data/lib/nokolexbor/node.rb +2 -2
- data/lib/nokolexbor/node_set.rb +5 -1
- data/lib/nokolexbor/version.rb +1 -1
- data/lib/nokolexbor/xpath.rb +69 -0
- data/lib/nokolexbor.rb +1 -0
- metadata +26 -9
- data/ext/nokolexbor/config.h +0 -186
data/ext/nokolexbor/nl_node.c
CHANGED
@@ -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,
|
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
|
-
|
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
|
-
|
117
|
+
size_t attr_len = RSTRING_LEN(rb_attr_s);
|
119
118
|
|
120
|
-
lxb_dom_element_t *element =
|
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
|
-
|
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
|
-
|
146
|
+
size_t attr_len = RSTRING_LEN(rb_attr_s);
|
148
147
|
const char *value_c = RSTRING_PTR(rb_value_s);
|
149
|
-
|
148
|
+
size_t value_len = RSTRING_LEN(rb_value_s);
|
150
149
|
|
151
|
-
lxb_dom_element_t *element =
|
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
|
-
|
170
|
+
size_t attr_len = RSTRING_LEN(rb_attr_s);
|
172
171
|
|
173
|
-
lxb_dom_element_t *element =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 (
|
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 (
|
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
|
-
|
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
|
-
|
405
|
+
size_t attr_len = RSTRING_LEN(rb_attr_s);
|
403
406
|
|
404
|
-
lxb_dom_element_t *element =
|
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(
|
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(
|
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(
|
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) :
|
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(
|
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
|
-
|
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(
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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 (
|
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
|
-
|
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 (
|
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 (
|
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
|
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 (
|
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 (
|
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
|
279
|
-
nl_node_set_find(VALUE self, VALUE selector,
|
278
|
+
static void
|
279
|
+
nl_node_set_find(VALUE self, VALUE selector, lxb_selectors_cb_f cb, void* ctx)
|
280
280
|
{
|
281
|
-
|
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 (
|
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
|
-
|
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 (
|
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
|
-
|
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
|
-
|
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)
|