nokolexbor 0.3.1 → 0.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bfa3062e8718581cd8aabef75f0084a6626bd90301c9db4957ee975215edec1
4
- data.tar.gz: 243f5c217c85750f63bfc0dcb8af575c019d3f2fd920f41769c0affc8a219802
3
+ metadata.gz: 042127a2ed4027c52d3718c148921604cae07c274dddb7f3702c7caf0708863f
4
+ data.tar.gz: 60230b55b773ef41abdca313adc3ffdba38a0b8462c9d23c3365e57c68b63bd5
5
5
  SHA512:
6
- metadata.gz: e66b390ef696ed5cafa480065e8ac8fc66ce98d86a7cb15f2f59d8acb7df21381942e5fe6f0244e3b9c7bf54787131c5241a49faeaba328eb49e65af0ac3216c
7
- data.tar.gz: d266e2a7c49a202aec4112667807158b54878cc014b42fc32492fc0977c06db76b1a5ded827d9810f2e7966ba3e5068fe54ab89915a4c56e499181ddc190b6d7
6
+ metadata.gz: f06063b84e62e23ba093a397ba6ffdbd802480e711ca24966d5b78be8bc8a7299754ab8bb4cd5d77d6dfe39efa7c21c705b105fe9d626d62eddc5e2e5a6ec9fb
7
+ data.tar.gz: 86ddfdb650b78827071385cfca708ddbffcd35204a71f439315f800e8e60ee73c2d49ce46e28192ac454df8bab7ef8cbc937b97830e0b488290dbadccd8e51d6
@@ -477,11 +477,10 @@ XMLPUBFUN xmlXPathParserContextPtr XMLCALL
477
477
  XMLPUBFUN void XMLCALL
478
478
  nl_xmlXPathFreeParserContext (xmlXPathParserContextPtr ctxt);
479
479
 
480
- /* TODO: remap to xmlXPathValuePop and Push. */
481
- static xmlXPathObjectPtr XMLCALL
482
- valuePop (xmlXPathParserContextPtr ctxt);
483
- static int XMLCALL
484
- valuePush (xmlXPathParserContextPtr ctxt,
480
+ XMLPUBFUN xmlXPathObjectPtr XMLCALL
481
+ nl_xmlXPathValuePop (xmlXPathParserContextPtr ctxt);
482
+ XMLPUBFUN int XMLCALL
483
+ nl_xmlXPathValuePush (xmlXPathParserContextPtr ctxt,
485
484
  xmlXPathObjectPtr value);
486
485
 
487
486
  XMLPUBFUN xmlXPathObjectPtr XMLCALL
@@ -20,7 +20,7 @@ nl_cdata_new(int argc, VALUE *argv, VALUE klass)
20
20
 
21
21
  document = nl_rb_document_unwrap(rb_document);
22
22
 
23
- const char* c_content = StringValuePtr(rb_content);
23
+ const char *c_content = StringValuePtr(rb_content);
24
24
  size_t content_len = RSTRING_LEN(rb_content);
25
25
  lxb_dom_cdata_section_t *element = lxb_dom_document_create_cdata_section(document, (const lxb_char_t *)c_content, content_len);
26
26
  if (element == NULL) {
@@ -20,7 +20,7 @@ nl_comment_new(int argc, VALUE *argv, VALUE klass)
20
20
 
21
21
  document = nl_rb_document_unwrap(rb_document);
22
22
 
23
- const char* c_content = StringValuePtr(rb_content);
23
+ const char *c_content = StringValuePtr(rb_content);
24
24
  size_t content_len = RSTRING_LEN(rb_content);
25
25
  lxb_dom_comment_t *element = lxb_dom_document_create_comment(document, (const lxb_char_t *)c_content, content_len);
26
26
  if (element == NULL) {
@@ -41,6 +41,8 @@ nl_document_parse(VALUE self, VALUE rb_string_or_io)
41
41
  rb_raise(rb_eRuntimeError, "Error creating document");
42
42
  }
43
43
 
44
+ lxb_dom_document_scripting_set(lxb_dom_interface_document(document), true);
45
+
44
46
  lxb_status_t status = lxb_html_document_parse(document, (const lxb_char_t *)html_c, html_len);
45
47
  if (status != LXB_STATUS_OK) {
46
48
  nl_raise_lexbor_error(status);
@@ -0,0 +1,39 @@
1
+ #include "nokolexbor.h"
2
+
3
+ VALUE cNokolexborDocumentFragment;
4
+ extern VALUE cNokolexborNode;
5
+ extern VALUE mNokolexbor;
6
+
7
+ static VALUE
8
+ nl_document_fragment_new(int argc, VALUE *argv, VALUE klass)
9
+ {
10
+ lxb_dom_document_t *document;
11
+ VALUE rb_document;
12
+ VALUE rest;
13
+
14
+ rb_scan_args(argc, argv, "1*", &rb_document, &rest);
15
+
16
+ if (!rb_obj_is_kind_of(rb_document, cNokolexborDocument)) {
17
+ rb_raise(rb_eArgError, "Document must be a Nokolexbor::Document");
18
+ }
19
+
20
+ document = nl_rb_document_unwrap(rb_document);
21
+
22
+ lxb_dom_document_fragment_t *node = lxb_dom_document_create_document_fragment(document);
23
+ if (node == NULL) {
24
+ rb_raise(rb_eRuntimeError, "Error creating document fragment");
25
+ }
26
+
27
+ VALUE rb_node = nl_rb_node_create(&node->node, rb_document);
28
+
29
+ rb_obj_call_init(rb_node, argc, argv);
30
+
31
+ return rb_node;
32
+ }
33
+
34
+ void Init_nl_document_fragment(void)
35
+ {
36
+ cNokolexborDocumentFragment = rb_define_class_under(mNokolexbor, "DocumentFragment", cNokolexborNode);
37
+
38
+ rb_define_singleton_method(cNokolexborDocumentFragment, "new", nl_document_fragment_new, -1);
39
+ }
@@ -0,0 +1,93 @@
1
+ #include "nokolexbor.h"
2
+
3
+ VALUE eLexborError;
4
+ VALUE eLexborMemoryAllocationError;
5
+ VALUE eLexborSmallBufferError;
6
+ VALUE eLexborObjectIsNullError;
7
+ VALUE eLexborIncompleteObjectError;
8
+ VALUE eLexborNoFreeSlotError;
9
+ VALUE eLexborTooSmallSizeError;
10
+ VALUE eLexborNotExistsError;
11
+ VALUE eLexborWrongArgsError;
12
+ VALUE eLexborWrongStageError;
13
+ VALUE eLexborUnexpectedResultError;
14
+ VALUE eLexborUnexpectedDataError;
15
+ VALUE eLexborOverflowError;
16
+ VALUE eLexborContinueStatus;
17
+ VALUE eLexborSmallBufferStatus;
18
+ VALUE eLexborAbortedStatus;
19
+ VALUE eLexborStoppedStatus;
20
+ VALUE eLexborNextStatus;
21
+ VALUE eLexborStopStatus;
22
+ extern VALUE mNokolexbor;
23
+
24
+ void nl_raise_lexbor_error(lxb_status_t error)
25
+ {
26
+ switch (error) {
27
+ case LXB_STATUS_ERROR:
28
+ rb_exc_raise(eLexborError);
29
+ case LXB_STATUS_ERROR_MEMORY_ALLOCATION:
30
+ rb_exc_raise(eLexborMemoryAllocationError);
31
+ case LXB_STATUS_ERROR_OBJECT_IS_NULL:
32
+ rb_exc_raise(eLexborObjectIsNullError);
33
+ case LXB_STATUS_ERROR_SMALL_BUFFER:
34
+ rb_exc_raise(eLexborSmallBufferError);
35
+ case LXB_STATUS_ERROR_INCOMPLETE_OBJECT:
36
+ rb_exc_raise(eLexborIncompleteObjectError);
37
+ case LXB_STATUS_ERROR_NO_FREE_SLOT:
38
+ rb_exc_raise(eLexborNoFreeSlotError);
39
+ case LXB_STATUS_ERROR_TOO_SMALL_SIZE:
40
+ rb_exc_raise(eLexborTooSmallSizeError);
41
+ case LXB_STATUS_ERROR_NOT_EXISTS:
42
+ rb_exc_raise(eLexborNotExistsError);
43
+ case LXB_STATUS_ERROR_WRONG_ARGS:
44
+ rb_exc_raise(eLexborWrongArgsError);
45
+ case LXB_STATUS_ERROR_WRONG_STAGE:
46
+ rb_exc_raise(eLexborWrongStageError);
47
+ case LXB_STATUS_ERROR_UNEXPECTED_RESULT:
48
+ rb_exc_raise(eLexborUnexpectedResultError);
49
+ case LXB_STATUS_ERROR_UNEXPECTED_DATA:
50
+ rb_raise(eLexborUnexpectedDataError, "Invalid syntax");
51
+ case LXB_STATUS_ERROR_OVERFLOW:
52
+ rb_exc_raise(eLexborOverflowError);
53
+ case LXB_STATUS_CONTINUE:
54
+ rb_exc_raise(eLexborContinueStatus);
55
+ case LXB_STATUS_SMALL_BUFFER:
56
+ rb_exc_raise(eLexborSmallBufferStatus);
57
+ case LXB_STATUS_ABORTED:
58
+ rb_exc_raise(eLexborAbortedStatus);
59
+ case LXB_STATUS_STOPPED:
60
+ rb_exc_raise(eLexborStoppedStatus);
61
+ case LXB_STATUS_NEXT:
62
+ rb_exc_raise(eLexborNextStatus);
63
+ case LXB_STATUS_STOP:
64
+ rb_exc_raise(eLexborStopStatus);
65
+ case LXB_STATUS_OK:
66
+ return;
67
+ default:
68
+ rb_raise(eLexborError, "Unknown error (%d)", error);
69
+ }
70
+ }
71
+
72
+ void Init_nl_error(void)
73
+ {
74
+ eLexborError = rb_define_class_under(mNokolexbor, "LexborError", rb_eStandardError);
75
+ eLexborMemoryAllocationError = rb_define_class_under(mNokolexbor, "LexborMemoryAllocationError", eLexborError);
76
+ eLexborSmallBufferError = rb_define_class_under(mNokolexbor, "LexborSmallBufferError", eLexborError);
77
+ eLexborObjectIsNullError = rb_define_class_under(mNokolexbor, "LexborObjectIsNullError", eLexborError);
78
+ eLexborIncompleteObjectError = rb_define_class_under(mNokolexbor, "LexborIncompleteObjectError", eLexborError);
79
+ eLexborNoFreeSlotError = rb_define_class_under(mNokolexbor, "LexborNoFreeSlotError", eLexborError);
80
+ eLexborTooSmallSizeError = rb_define_class_under(mNokolexbor, "LexborTooSmallSizeError", eLexborError);
81
+ eLexborNotExistsError = rb_define_class_under(mNokolexbor, "LexborNotExistsError", eLexborError);
82
+ eLexborWrongArgsError = rb_define_class_under(mNokolexbor, "LexborWrongArgsError", eLexborError);
83
+ eLexborWrongStageError = rb_define_class_under(mNokolexbor, "LexborWrongStageError", eLexborError);
84
+ eLexborUnexpectedResultError = rb_define_class_under(mNokolexbor, "LexborUnexpectedResultError", eLexborError);
85
+ eLexborUnexpectedDataError = rb_define_class_under(mNokolexbor, "LexborUnexpectedDataError", eLexborError);
86
+ eLexborOverflowError = rb_define_class_under(mNokolexbor, "LexborOverflowError", eLexborError);
87
+ eLexborContinueStatus = rb_define_class_under(mNokolexbor, "LexborContinueStatus", eLexborError);
88
+ eLexborSmallBufferStatus = rb_define_class_under(mNokolexbor, "LexborSmallBufferStatus", eLexborError);
89
+ eLexborAbortedStatus = rb_define_class_under(mNokolexbor, "LexborAbortedStatus", eLexborError);
90
+ eLexborStoppedStatus = rb_define_class_under(mNokolexbor, "LexborStoppedStatus", eLexborError);
91
+ eLexborNextStatus = rb_define_class_under(mNokolexbor, "LexborNextStatus", eLexborError);
92
+ eLexborStopStatus = rb_define_class_under(mNokolexbor, "LexborStopStatus", eLexborError);
93
+ }
@@ -9,7 +9,9 @@ extern VALUE mNokolexbor;
9
9
  extern VALUE cNokolexborDocument;
10
10
  extern VALUE cNokolexborText;
11
11
  extern VALUE cNokolexborComment;
12
+ extern VALUE cNokolexborProcessingInstruction;
12
13
  extern VALUE cNokolexborNodeSet;
14
+ extern VALUE cNokolexborDocumentFragment;
13
15
  extern VALUE eLexborError;
14
16
  VALUE cNokolexborNode;
15
17
  VALUE cNokolexborElement;
@@ -41,8 +43,9 @@ nl_rb_node_create(lxb_dom_node_t *node, VALUE rb_document)
41
43
  // break;
42
44
  // case LXB_DOM_NODE_TYPE_ENTITY:
43
45
  // break;
44
- // case LXB_DOM_NODE_TYPE_PROCESSING_INSTRUCTION:
45
- // break;
46
+ case LXB_DOM_NODE_TYPE_PROCESSING_INSTRUCTION:
47
+ rb_class = cNokolexborProcessingInstruction;
48
+ break;
46
49
  case LXB_DOM_NODE_TYPE_COMMENT:
47
50
  rb_class = cNokolexborComment;
48
51
  break;
@@ -50,8 +53,9 @@ nl_rb_node_create(lxb_dom_node_t *node, VALUE rb_document)
50
53
  // break;
51
54
  // case LXB_DOM_NODE_TYPE_DOCUMENT_TYPE:
52
55
  // break;
53
- // case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
54
- // break;
56
+ case LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT:
57
+ rb_class = cNokolexborDocumentFragment;
58
+ break;
55
59
  // case LXB_DOM_NODE_TYPE_NOTATION:
56
60
  // break;
57
61
  default:
@@ -91,7 +95,7 @@ nl_node_new(int argc, VALUE *argv, VALUE klass)
91
95
 
92
96
  document = nl_rb_document_unwrap(rb_document);
93
97
 
94
- const char* c_name = StringValuePtr(rb_name);
98
+ const char *c_name = StringValuePtr(rb_name);
95
99
  size_t name_len = RSTRING_LEN(rb_name);
96
100
  lxb_dom_element_t *element = lxb_dom_document_create_element(document, (const lxb_char_t *)c_name, name_len, NULL);
97
101
  if (element == NULL) {
@@ -657,17 +661,19 @@ nl_node_name(VALUE self)
657
661
  }
658
662
 
659
663
  static lxb_dom_node_t *
660
- nl_node_parse_fragment(lxb_dom_document_t *doc, lxb_char_t *html, size_t size)
664
+ nl_node_parse_fragment(lxb_dom_document_t *doc, lxb_dom_element_t *element, lxb_char_t *html, size_t size)
661
665
  {
662
666
  size_t tag_name_len;
663
667
  lxb_html_document_t *html_doc = lxb_html_interface_document(doc);
664
- const lxb_char_t *tag_name = lxb_tag_name_by_id(lxb_html_document_tags(html_doc), LXB_TAG__UNDEF, &tag_name_len);
665
- if (tag_name == NULL) {
666
- rb_raise(rb_eRuntimeError, "Error getting tag name");
667
- }
668
- lxb_dom_element_t *element = lxb_dom_document_create_element(doc, tag_name, tag_name_len, NULL);
669
668
  if (element == NULL) {
670
- rb_raise(rb_eRuntimeError, "Error creating element");
669
+ const lxb_char_t *tag_name = lxb_tag_name_by_id(lxb_html_document_tags(html_doc), LXB_TAG__UNDEF, &tag_name_len);
670
+ if (tag_name == NULL) {
671
+ rb_raise(rb_eRuntimeError, "Error getting tag name");
672
+ }
673
+ element = lxb_dom_document_create_element(doc, tag_name, tag_name_len, NULL);
674
+ if (element == NULL) {
675
+ rb_raise(rb_eRuntimeError, "Error creating element");
676
+ }
671
677
  }
672
678
  lxb_dom_node_t *frag_root = lxb_html_document_parse_fragment(html_doc, element, html, size);
673
679
  if (frag_root == NULL) {
@@ -677,14 +683,22 @@ nl_node_parse_fragment(lxb_dom_document_t *doc, lxb_char_t *html, size_t size)
677
683
  }
678
684
 
679
685
  static VALUE
680
- nl_node_fragment(VALUE self, VALUE html)
686
+ nl_node_parse(VALUE self, VALUE html)
681
687
  {
682
688
  Check_Type(html, T_STRING);
683
689
  lxb_dom_node_t *node = nl_rb_node_unwrap(self);
684
690
  lxb_dom_document_t *doc = node->owner_document;
685
691
 
686
- lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, (lxb_char_t *)RSTRING_PTR(html), RSTRING_LEN(html));
687
- return nl_rb_node_create(frag_root, nl_rb_document_get(self));
692
+ lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, lxb_dom_interface_element(node), (lxb_char_t *)RSTRING_PTR(html), RSTRING_LEN(html));
693
+ lexbor_array_t *array = lexbor_array_create();
694
+
695
+ while (frag_root->first_child != NULL) {
696
+ lxb_dom_node_t *child = frag_root->first_child;
697
+ lxb_dom_node_remove(child);
698
+ lexbor_array_push(array, child);
699
+ }
700
+ lxb_dom_node_destroy(frag_root);
701
+ return nl_rb_node_set_create_with_data(array, nl_rb_document_get(self));
688
702
  }
689
703
 
690
704
  static VALUE
@@ -703,7 +717,7 @@ nl_node_add_sibling(VALUE self, VALUE next_or_previous, VALUE new)
703
717
  }
704
718
 
705
719
  if (TYPE(new) == T_STRING) {
706
- lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
720
+ lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, NULL, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
707
721
  lexbor_array_t *array = lexbor_array_create();
708
722
 
709
723
  while (frag_root->first_child != NULL) {
@@ -734,7 +748,7 @@ nl_node_add_child(VALUE self, VALUE new)
734
748
  lxb_dom_document_t *doc = node->owner_document;
735
749
 
736
750
  if (TYPE(new) == T_STRING) {
737
- lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
751
+ lxb_dom_node_t *frag_root = nl_node_parse_fragment(doc, NULL, (lxb_char_t *)RSTRING_PTR(new), RSTRING_LEN(new));
738
752
  lexbor_array_t *array = lexbor_array_create();
739
753
 
740
754
  while (frag_root->first_child != NULL) {
@@ -859,7 +873,7 @@ void Init_nl_node(void)
859
873
  rb_define_method(cNokolexborNode, "destroy", nl_node_destroy, 0);
860
874
  rb_define_method(cNokolexborNode, "attrs", nl_node_attrs, 0);
861
875
  rb_define_method(cNokolexborNode, "name", nl_node_name, 0);
862
- rb_define_method(cNokolexborNode, "fragment", nl_node_fragment, 1);
876
+ rb_define_method(cNokolexborNode, "parse", nl_node_parse, 1);
863
877
  rb_define_method(cNokolexborNode, "add_sibling", nl_node_add_sibling, 2);
864
878
  rb_define_method(cNokolexborNode, "add_child", nl_node_add_child, 1);
865
879
  rb_define_method(cNokolexborNode, "node_type", nl_node_get_type, 0);
@@ -0,0 +1,47 @@
1
+ #include "nokolexbor.h"
2
+
3
+ VALUE cNokolexborProcessingInstruction;
4
+ extern VALUE cNokolexborNode;
5
+ extern VALUE mNokolexbor;
6
+
7
+ static VALUE
8
+ nl_processing_instruction_new(int argc, VALUE *argv, VALUE klass)
9
+ {
10
+ lxb_dom_document_t *document;
11
+ VALUE rb_name;
12
+ VALUE rb_content;
13
+ VALUE rb_document;
14
+ VALUE rest;
15
+
16
+ rb_scan_args(argc, argv, "3*", &rb_name, &rb_content, &rb_document, &rest);
17
+
18
+ if (!rb_obj_is_kind_of(rb_document, cNokolexborDocument)) {
19
+ rb_raise(rb_eArgError, "Document must be a Nokolexbor::Document");
20
+ }
21
+
22
+ document = nl_rb_document_unwrap(rb_document);
23
+
24
+ const char *c_name = StringValuePtr(rb_name);
25
+ size_t name_len = RSTRING_LEN(rb_name);
26
+ const char *c_content = StringValuePtr(rb_content);
27
+ size_t content_len = RSTRING_LEN(rb_content);
28
+ lxb_dom_processing_instruction_t *node = lxb_dom_document_create_processing_instruction(document, (const lxb_char_t *)c_name, name_len, (const lxb_char_t *)c_content, content_len);
29
+ if (node == NULL) {
30
+ rb_raise(rb_eRuntimeError, "Error creating processing instruction");
31
+ }
32
+
33
+ VALUE rb_node = nl_rb_node_create(&node->char_data.node, rb_document);
34
+
35
+ if (rb_block_given_p()) {
36
+ rb_yield(rb_node);
37
+ }
38
+
39
+ return rb_node;
40
+ }
41
+
42
+ void Init_nl_processing_instruction(void)
43
+ {
44
+ cNokolexborProcessingInstruction = rb_define_class_under(mNokolexbor, "ProcessingInstruction", cNokolexborNode);
45
+
46
+ rb_define_singleton_method(cNokolexborProcessingInstruction, "new", nl_processing_instruction_new, -1);
47
+ }
@@ -20,7 +20,7 @@ nl_text_new(int argc, VALUE *argv, VALUE klass)
20
20
 
21
21
  document = nl_rb_document_unwrap(rb_document);
22
22
 
23
- const char* c_text = StringValuePtr(rb_text);
23
+ const char *c_text = StringValuePtr(rb_text);
24
24
  size_t text_len = RSTRING_LEN(rb_text);
25
25
  lxb_dom_text_t *element = lxb_dom_document_create_text_node(document, (const lxb_char_t *)c_text, text_len);
26
26
  if (element == NULL) {
@@ -15,12 +15,110 @@ VALUE cNokolexborXpathContext;
15
15
  VALUE mNokolexborXpath;
16
16
  VALUE cNokolexborXpathSyntaxError;
17
17
 
18
+ static const xmlChar *NOKOGIRI_PREFIX = (const xmlChar *)"nokogiri";
19
+ static const xmlChar *NOKOGIRI_URI = (const xmlChar *)"http://www.nokogiri.org/default_ns/ruby/extensions_functions";
20
+ static const xmlChar *NOKOGIRI_BUILTIN_PREFIX = (const xmlChar *)"nokogiri-builtin";
21
+ static const xmlChar *NOKOGIRI_BUILTIN_URI = (const xmlChar *)"https://www.nokogiri.org/default_ns/ruby/builtins";
22
+
18
23
  static void
19
24
  free_xml_xpath_context(xmlXPathContextPtr ctx)
20
25
  {
21
26
  nl_xmlXPathFreeContext(ctx);
22
27
  }
23
28
 
29
+ /* find a CSS class in an HTML element's `class` attribute */
30
+ static const xmlChar *
31
+ builtin_css_class(const xmlChar *str, const xmlChar *val)
32
+ {
33
+ int val_len;
34
+
35
+ if (str == NULL) {
36
+ return (NULL);
37
+ }
38
+ if (val == NULL) {
39
+ return (NULL);
40
+ }
41
+
42
+ val_len = nl_xmlStrlen(val);
43
+ if (val_len == 0) {
44
+ return (str);
45
+ }
46
+
47
+ while (*str != 0) {
48
+ if ((*str == *val) && !nl_xmlStrncmp(str, val, val_len)) {
49
+ const xmlChar *next_byte = str + val_len;
50
+
51
+ /* only match if the next byte is whitespace or end of string */
52
+ if ((*next_byte == 0) || (IS_BLANK_CH(*next_byte))) {
53
+ return ((const xmlChar *)str);
54
+ }
55
+ }
56
+
57
+ /* advance str to whitespace */
58
+ while ((*str != 0) && !IS_BLANK_CH(*str)) {
59
+ str++;
60
+ }
61
+
62
+ /* advance str to start of next word or end of string */
63
+ while ((*str != 0) && IS_BLANK_CH(*str)) {
64
+ str++;
65
+ }
66
+ }
67
+
68
+ return (NULL);
69
+ }
70
+
71
+ /* xmlXPathFunction to wrap builtin_css_class() */
72
+ static void
73
+ xpath_builtin_css_class(xmlXPathParserContextPtr ctxt, int nargs)
74
+ {
75
+ xmlXPathObjectPtr hay, needle;
76
+
77
+ CHECK_ARITY(2);
78
+
79
+ CAST_TO_STRING;
80
+ needle = nl_xmlXPathValuePop(ctxt);
81
+ if ((needle == NULL) || (needle->type != XPATH_STRING)) {
82
+ nl_xmlXPathFreeObject(needle);
83
+ XP_ERROR(XPATH_INVALID_TYPE);
84
+ }
85
+
86
+ CAST_TO_STRING;
87
+ hay = nl_xmlXPathValuePop(ctxt);
88
+ if ((hay == NULL) || (hay->type != XPATH_STRING)) {
89
+ nl_xmlXPathFreeObject(hay);
90
+ nl_xmlXPathFreeObject(needle);
91
+ XP_ERROR(XPATH_INVALID_TYPE);
92
+ }
93
+
94
+ if (builtin_css_class(hay->stringval, needle->stringval)) {
95
+ nl_xmlXPathValuePush(ctxt, nl_xmlXPathNewBoolean(1));
96
+ } else {
97
+ nl_xmlXPathValuePush(ctxt, nl_xmlXPathNewBoolean(0));
98
+ }
99
+
100
+ nl_xmlXPathFreeObject(hay);
101
+ nl_xmlXPathFreeObject(needle);
102
+ }
103
+
104
+ /* xmlXPathFunction to select nodes whose local name matches, for HTML5 CSS queries that should ignore namespaces */
105
+ static void
106
+ xpath_builtin_local_name_is(xmlXPathParserContextPtr ctxt, int nargs)
107
+ {
108
+ xmlXPathObjectPtr element_name;
109
+ size_t tmp_len;
110
+
111
+ CHECK_ARITY(1);
112
+ CAST_TO_STRING;
113
+ CHECK_TYPE(XPATH_STRING);
114
+ element_name = nl_xmlXPathValuePop(ctxt);
115
+
116
+ const lxb_char_t *node_name = lxb_dom_node_name_qualified(ctxt->context->node, &tmp_len);
117
+ nl_xmlXPathValuePush(ctxt, nl_xmlXPathNewBoolean(nl_xmlStrEqual((xmlChar *)node_name, element_name->stringval)));
118
+
119
+ nl_xmlXPathFreeObject(element_name);
120
+ }
121
+
24
122
  /*
25
123
  * call-seq:
26
124
  * register_ns(prefix, uri)
@@ -228,6 +326,13 @@ nl_xpath_context_new(VALUE klass, VALUE rb_node)
228
326
  ctx = nl_xmlXPathNewContext(node->owner_document);
229
327
  ctx->node = node;
230
328
 
329
+ nl_xmlXPathRegisterNs(ctx, NOKOGIRI_PREFIX, NOKOGIRI_URI);
330
+ nl_xmlXPathRegisterNs(ctx, NOKOGIRI_BUILTIN_PREFIX, NOKOGIRI_BUILTIN_URI);
331
+ nl_xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"css-class", NOKOGIRI_BUILTIN_URI,
332
+ xpath_builtin_css_class);
333
+ nl_xmlXPathRegisterFuncNS(ctx, (const xmlChar *)"local-name-is", NOKOGIRI_BUILTIN_URI,
334
+ xpath_builtin_local_name_is);
335
+
231
336
  self = Data_Wrap_Struct(klass, 0, free_xml_xpath_context, ctx);
232
337
  rb_iv_set(self, "@document", nl_rb_document_get(rb_node));
233
338
 
@@ -1,67 +1,21 @@
1
1
  #include "nokolexbor.h"
2
2
 
3
3
  VALUE mNokolexbor;
4
- VALUE eLexborError;
5
- VALUE eLexborSyntaxError;
6
-
7
- void nl_raise_lexbor_error(lxb_status_t error)
8
- {
9
- switch (error) {
10
- case LXB_STATUS_ERROR:
11
- rb_raise(eLexborError, "LXB_STATUS_ERROR");
12
- case LXB_STATUS_ERROR_MEMORY_ALLOCATION:
13
- rb_raise(eLexborError, "LXB_STATUS_ERROR_MEMORY_ALLOCATION");
14
- case LXB_STATUS_ERROR_OBJECT_IS_NULL:
15
- rb_raise(eLexborError, "LXB_STATUS_ERROR_OBJECT_IS_NULL");
16
- case LXB_STATUS_ERROR_SMALL_BUFFER:
17
- rb_raise(eLexborError, "LXB_STATUS_ERROR_SMALL_BUFFER");
18
- case LXB_STATUS_ERROR_INCOMPLETE_OBJECT:
19
- rb_raise(eLexborError, "LXB_STATUS_ERROR_INCOMPLETE_OBJECT");
20
- case LXB_STATUS_ERROR_NO_FREE_SLOT:
21
- rb_raise(eLexborError, "LXB_STATUS_ERROR_NO_FREE_SLOT");
22
- case LXB_STATUS_ERROR_TOO_SMALL_SIZE:
23
- rb_raise(eLexborError, "LXB_STATUS_ERROR_TOO_SMALL_SIZE");
24
- case LXB_STATUS_ERROR_NOT_EXISTS:
25
- rb_raise(eLexborError, "LXB_STATUS_ERROR_NOT_EXISTS");
26
- case LXB_STATUS_ERROR_WRONG_ARGS:
27
- rb_raise(eLexborError, "LXB_STATUS_ERROR_WRONG_ARGS");
28
- case LXB_STATUS_ERROR_WRONG_STAGE:
29
- rb_raise(eLexborError, "LXB_STATUS_ERROR_WRONG_STAGE");
30
- case LXB_STATUS_ERROR_UNEXPECTED_RESULT:
31
- rb_raise(eLexborError, "LXB_STATUS_ERROR_UNEXPECTED_RESULT");
32
- case LXB_STATUS_ERROR_UNEXPECTED_DATA:
33
- rb_raise(eLexborSyntaxError, "LXB_STATUS_ERROR_UNEXPECTED_DATA");
34
- case LXB_STATUS_ERROR_OVERFLOW:
35
- rb_raise(eLexborError, "LXB_STATUS_ERROR_OVERFLOW");
36
- case LXB_STATUS_CONTINUE:
37
- rb_raise(eLexborError, "LXB_STATUS_CONTINUE");
38
- case LXB_STATUS_SMALL_BUFFER:
39
- rb_raise(eLexborError, "LXB_STATUS_SMALL_BUFFER");
40
- case LXB_STATUS_ABORTED:
41
- rb_raise(eLexborError, "LXB_STATUS_ABORTED");
42
- case LXB_STATUS_STOPPED:
43
- rb_raise(eLexborError, "LXB_STATUS_STOPPED");
44
- case LXB_STATUS_NEXT:
45
- rb_raise(eLexborError, "LXB_STATUS_NEXT");
46
- case LXB_STATUS_STOP:
47
- rb_raise(eLexborError, "LXB_STATUS_STOP");
48
- case LXB_STATUS_OK:
49
- return;
50
- default:
51
- rb_raise(eLexborError, "LXB_ERROR_UKNOWN(%d)", error);
52
- }
53
- }
54
4
 
55
5
  void Init_nokolexbor(void)
56
6
  {
7
+ #ifndef NOKOLEXBOR_ASAN
8
+ lexbor_memory_setup(ruby_xmalloc, ruby_xrealloc, ruby_xcalloc, ruby_xfree);
9
+ #endif
57
10
  mNokolexbor = rb_define_module("Nokolexbor");
58
- eLexborError = rb_define_class_under(mNokolexbor, "LexborError", rb_eStandardError);
59
- eLexborSyntaxError = rb_define_class_under(mNokolexbor, "LexborSyntaxError", eLexborError);
11
+ Init_nl_error();
60
12
  Init_nl_node();
61
13
  Init_nl_document();
62
14
  Init_nl_text();
63
15
  Init_nl_comment();
64
16
  Init_nl_cdata();
17
+ Init_nl_processing_instruction();
65
18
  Init_nl_node_set();
19
+ Init_nl_document_fragment();
66
20
  Init_nl_xpath_context();
67
21
  }
@@ -9,12 +9,15 @@
9
9
 
10
10
  extern VALUE cNokolexborDocument;
11
11
 
12
+ void Init_nl_error(void);
12
13
  void Init_nl_document(void);
13
14
  void Init_nl_node(void);
14
- void Init_nl_node_set(void);
15
15
  void Init_nl_text(void);
16
16
  void Init_nl_comment(void);
17
17
  void Init_nl_cdata(void);
18
+ void Init_nl_processing_instruction(void);
19
+ void Init_nl_node_set(void);
20
+ void Init_nl_document_fragment(void);
18
21
  void Init_nl_xpath_context(void);
19
22
 
20
23
  void nl_raise_lexbor_error(lxb_status_t error);
@@ -2897,6 +2897,10 @@ valuePop(xmlXPathParserContextPtr ctxt)
2897
2897
  ctxt->valueTab[ctxt->valueNr] = NULL;
2898
2898
  return (ret);
2899
2899
  }
2900
+
2901
+ xmlXPathObjectPtr
2902
+ nl_xmlXPathValuePop(xmlXPathParserContextPtr ctxt) { return valuePop(ctxt); }
2903
+
2900
2904
  /**
2901
2905
  * valuePush:
2902
2906
  * @ctxt: an XPath evaluation context
@@ -2941,6 +2945,9 @@ valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
2941
2945
  return (ctxt->valueNr++);
2942
2946
  }
2943
2947
 
2948
+ int
2949
+ nl_xmlXPathValuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value) { return valuePush(ctxt, value); }
2950
+
2944
2951
  /**
2945
2952
  * nl_xmlXPathPopBoolean:
2946
2953
  * @ctxt: an XPath parser context
@@ -93,5 +93,9 @@ module Nokolexbor
93
93
  head.prepend_child(element)
94
94
  end
95
95
  end
96
+
97
+ private
98
+
99
+ IMPLIED_XPATH_CONTEXTS = ["//"].freeze # :nodoc:
96
100
  end
97
101
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nokolexbor
4
+ class DocumentFragment < Nokolexbor::Node
5
+ def self.parse(tags)
6
+ new(Nokolexbor::Document.new, tags, nil)
7
+ end
8
+
9
+ def initialize(document, tags = nil, ctx = nil)
10
+ return self unless tags
11
+
12
+ ctx ||= document
13
+ node_set = ctx.parse(tags)
14
+ node_set.each { |child| child.parent = self } unless node_set.empty?
15
+ nil
16
+ end
17
+
18
+ def name
19
+ "#document-fragment"
20
+ end
21
+
22
+ alias_method :outer_html, :inner_html
23
+ alias_method :to_html, :outer_html
24
+ alias_method :to_s, :outer_html
25
+ alias_method :serialize, :outer_html
26
+
27
+ def fragment(data)
28
+ document.fragment(data)
29
+ end
30
+ end
31
+ end
@@ -182,6 +182,10 @@ module Nokolexbor
182
182
  end
183
183
  end
184
184
 
185
+ def fragment(tags)
186
+ Nokolexbor::DocumentFragment.new(document, tags, self)
187
+ end
188
+
185
189
  alias_method :inner_html=, :children=
186
190
 
187
191
  def css(*args)
@@ -192,6 +196,16 @@ module Nokolexbor
192
196
  at_css_impl(args.join(', '))
193
197
  end
194
198
 
199
+ def nokogiri_css(*args)
200
+ rules, handler, ns, _ = extract_params(args)
201
+
202
+ nokogiri_css_internal(self, rules, handler, ns)
203
+ end
204
+
205
+ def nokogiri_at_css(*args)
206
+ nokogiri_css(*args).first
207
+ end
208
+
195
209
  def xpath(*args)
196
210
  paths, handler, ns, binds = extract_params(args)
197
211
 
@@ -299,6 +313,10 @@ module Nokolexbor
299
313
 
300
314
  private
301
315
 
316
+ def nokogiri_css_internal(node, rules, handler, ns)
317
+ xpath_internal(node, css_rules_to_xpath(rules, ns), handler, ns, nil)
318
+ end
319
+
302
320
  def xpath_internal(node, paths, handler, ns, binds)
303
321
  # document = node.document
304
322
  # return NodeSet.new(document) unless document
@@ -326,6 +344,34 @@ module Nokolexbor
326
344
  ctx.evaluate(path, handler)
327
345
  end
328
346
 
347
+ def css_rules_to_xpath(rules, ns)
348
+ rules.map { |rule| xpath_query_from_css_rule(rule, ns) }
349
+ end
350
+
351
+ def ensure_nokogiri
352
+ unless defined?(Nokogiri) && defined?(Nokogiri::CSS)
353
+ require 'nokogiri'
354
+ end
355
+ rescue LoadError
356
+ fail('nokogiri_css and nokogiri_at_css require Nokogiri to be installed')
357
+ end
358
+
359
+ def xpath_query_from_css_rule(rule, ns)
360
+ ensure_nokogiri
361
+ if defined? Nokogiri::CSS::XPathVisitor::BuiltinsConfig
362
+ visitor = Nokogiri::CSS::XPathVisitor.new(
363
+ builtins: Nokogiri::CSS::XPathVisitor::BuiltinsConfig::OPTIMAL,
364
+ doctype: :html4,
365
+ )
366
+ else
367
+ visitor = Nokogiri::CSS::XPathVisitorOptimallyUseBuiltins.new
368
+ end
369
+ self.class::IMPLIED_XPATH_CONTEXTS.map do |implied_xpath_context|
370
+ Nokogiri::CSS.xpath_for(rule.to_s, { prefix: implied_xpath_context, ns: ns,
371
+ visitor: visitor, })
372
+ end.join(" | ")
373
+ end
374
+
329
375
  def extract_params(params)
330
376
  handler = params.find do |param|
331
377
  ![Hash, String, Symbol].include?(param.class)
@@ -344,5 +390,7 @@ module Nokolexbor
344
390
 
345
391
  [params, handler, ns, binds]
346
392
  end
393
+
394
+ IMPLIED_XPATH_CONTEXTS = [".//"].freeze
347
395
  end
348
- end
396
+ end
@@ -126,6 +126,23 @@ module Nokolexbor
126
126
  end
127
127
  end
128
128
  end
129
+
130
+ def nokogiri_css(*args)
131
+ rules, handler, ns, _ = extract_params(args)
132
+ paths = css_rules_to_xpath(rules, ns)
133
+
134
+ NodeSet.new(@document) do |set|
135
+ each do |node|
136
+ node.send(:xpath_internal, node, paths, handler, ns, nil).each do |inner_node|
137
+ set << inner_node
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ private
144
+
145
+ IMPLIED_XPATH_CONTEXTS = [".//", "self::"].freeze # :nodoc:
129
146
 
130
147
  end
131
148
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nokolexbor
4
- VERSION = '0.3.1'
4
+ VERSION = '0.3.3'
5
5
  end
data/lib/nokolexbor.rb CHANGED
@@ -25,6 +25,7 @@ require 'nokolexbor/version'
25
25
  require 'nokolexbor/node'
26
26
  require 'nokolexbor/document'
27
27
  require 'nokolexbor/node_set'
28
+ require 'nokolexbor/document_fragment'
28
29
  require 'nokolexbor/attribute'
29
30
  require 'nokolexbor/xpath'
30
31
  require 'nokolexbor/xpath_context'
@@ -13,7 +13,7 @@ index 2b19f18..5e56181 100644
13
13
  lxb_css_selector_pseudo_element_id_t;
14
14
 
15
15
  diff --git i/source/lexbor/css/selectors/pseudo_res.h w/source/lexbor/css/selectors/pseudo_res.h
16
- index 398d1bb..b35bfab 100644
16
+ index 398d1bb..ddd5f3e 100644
17
17
  --- i/source/lexbor/css/selectors/pseudo_res.h
18
18
  +++ w/source/lexbor/css/selectors/pseudo_res.h
19
19
  @@ -124,7 +124,8 @@ static const lxb_css_selectors_pseudo_data_t lxb_css_selectors_pseudo_data_pseud
@@ -36,7 +36,7 @@ index 398d1bb..b35bfab 100644
36
36
  {"grammar-error", (void *) &lxb_css_selectors_pseudo_data_pseudo_element[LXB_CSS_SELECTOR_PSEUDO_ELEMENT_GRAMMAR_ERROR], 13, 0},
37
37
  {"before", (void *) &lxb_css_selectors_pseudo_data_pseudo_element[LXB_CSS_SELECTOR_PSEUDO_ELEMENT_BEFORE], 6, 0},
38
38
  diff --git i/source/lexbor/selectors/selectors.c w/source/lexbor/selectors/selectors.c
39
- index c2d18ea..84b5b14 100644
39
+ index fef05d3..1ceaa19 100644
40
40
  --- i/source/lexbor/selectors/selectors.c
41
41
  +++ w/source/lexbor/selectors/selectors.c
42
42
  @@ -156,6 +156,12 @@ lxb_selectors_descendant(lxb_selectors_t *selectors, lxb_selectors_entry_t *entr
@@ -91,16 +91,7 @@ index c2d18ea..84b5b14 100644
91
91
 
92
92
  node = node->next;
93
93
  }
94
- @@ -262,6 +286,8 @@ lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
95
- {
96
- node = node->next;
97
-
98
- + if (node == NULL) return NULL;
99
- +
100
- do {
101
- if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) {
102
- if (lxb_selectors_match(selectors, entry, selector, node)) {
103
- @@ -290,6 +316,12 @@ lxb_selectors_following(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry
94
+ @@ -289,6 +313,12 @@ lxb_selectors_following(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry
104
95
  {
105
96
  return node;
106
97
  }
@@ -113,7 +104,7 @@ index c2d18ea..84b5b14 100644
113
104
 
114
105
  node = node->next;
115
106
  }
116
- @@ -1429,6 +1461,8 @@ lxb_selectors_pseudo_element(lxb_selectors_t *selectors,
107
+ @@ -1428,6 +1458,8 @@ lxb_selectors_pseudo_element(lxb_selectors_t *selectors,
117
108
  lxb_css_selector_pseudo_t *pseudo = &selector->u.pseudo;
118
109
 
119
110
  switch (pseudo->type) {
@@ -2,7 +2,7 @@ diff --git i/source/lexbor/selectors/selectors.c w/source/lexbor/selectors/selec
2
2
  index c2d18ea..84b5b14 100644
3
3
  --- i/source/lexbor/selectors/selectors.c
4
4
  +++ w/source/lexbor/selectors/selectors.c
5
- @@ -751,7 +783,7 @@ lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
5
+ @@ -750,7 +780,7 @@ lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
6
6
  src = &selector->name;
7
7
 
8
8
  if (trg->length == src->length
@@ -11,7 +11,7 @@ index c2d18ea..84b5b14 100644
11
11
  {
12
12
  return true;
13
13
  }
14
- @@ -766,7 +798,7 @@ lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
14
+ @@ -765,7 +795,7 @@ lxb_selectors_match(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
15
15
  }
16
16
 
17
17
  return lxb_selectors_match_class(element->attr_class->value,
@@ -13,6 +13,10 @@ extern "C" {
13
13
 
14
14
  #include "lexbor/core/def.h"
15
15
 
16
+ typedef void *(*lexbor_memory_malloc_f)(size_t size);
17
+ typedef void *(*lexbor_memory_realloc_f)(void *dst, size_t size);
18
+ typedef void *(*lexbor_memory_calloc_f)(size_t num, size_t size);
19
+ typedef void (*lexbor_memory_free_f)(void *dst);
16
20
 
17
21
  LXB_API void *
18
22
  lexbor_malloc(size_t size);
@@ -26,6 +30,10 @@ lexbor_calloc(size_t num, size_t size);
26
30
  LXB_API void *
27
31
  lexbor_free(void *dst);
28
32
 
33
+ LXB_API lxb_status_t
34
+ lexbor_memory_setup(lexbor_memory_malloc_f new_malloc, lexbor_memory_realloc_f new_realloc,
35
+ lexbor_memory_calloc_f new_calloc, lexbor_memory_free_f new_free);
36
+
29
37
 
30
38
  #ifdef __cplusplus
31
39
  } /* extern "C" */
@@ -6,28 +6,48 @@
6
6
 
7
7
  #include "lexbor/core/base.h"
8
8
 
9
+ static lexbor_memory_malloc_f lexbor_memory_malloc = malloc;
10
+ static lexbor_memory_realloc_f lexbor_memory_realloc = realloc;
11
+ static lexbor_memory_calloc_f lexbor_memory_calloc = calloc;
12
+ static lexbor_memory_free_f lexbor_memory_free = free;
9
13
 
10
14
  void *
11
15
  lexbor_malloc(size_t size)
12
16
  {
13
- return malloc(size);
17
+ return lexbor_memory_malloc(size);
14
18
  }
15
19
 
16
20
  void *
17
21
  lexbor_realloc(void *dst, size_t size)
18
22
  {
19
- return realloc(dst, size);
23
+ return lexbor_memory_realloc(dst, size);
20
24
  }
21
25
 
22
26
  void *
23
27
  lexbor_calloc(size_t num, size_t size)
24
28
  {
25
- return calloc(num, size);
29
+ return lexbor_memory_calloc(num, size);
26
30
  }
27
31
 
28
32
  void *
29
33
  lexbor_free(void *dst)
30
34
  {
31
- free(dst);
35
+ lexbor_memory_free(dst);
32
36
  return NULL;
33
37
  }
38
+
39
+ lxb_status_t
40
+ lexbor_memory_setup(lexbor_memory_malloc_f new_malloc, lexbor_memory_realloc_f new_realloc,
41
+ lexbor_memory_calloc_f new_calloc, lexbor_memory_free_f new_free)
42
+ {
43
+ if (new_malloc == NULL || new_realloc == NULL || new_calloc == NULL || new_free == NULL) {
44
+ return LXB_STATUS_ERROR_OBJECT_IS_NULL;
45
+ }
46
+
47
+ lexbor_memory_malloc = new_malloc;
48
+ lexbor_memory_realloc = new_realloc;
49
+ lexbor_memory_calloc = new_calloc;
50
+ lexbor_memory_free = new_free;
51
+
52
+ return LXB_STATUS_OK;
53
+ }
@@ -6,28 +6,48 @@
6
6
 
7
7
  #include "lexbor/core/base.h"
8
8
 
9
+ static lexbor_memory_malloc_f lexbor_memory_malloc = malloc;
10
+ static lexbor_memory_realloc_f lexbor_memory_realloc = realloc;
11
+ static lexbor_memory_calloc_f lexbor_memory_calloc = calloc;
12
+ static lexbor_memory_free_f lexbor_memory_free = free;
9
13
 
10
14
  void *
11
15
  lexbor_malloc(size_t size)
12
16
  {
13
- return malloc(size);
17
+ return lexbor_memory_malloc(size);
14
18
  }
15
19
 
16
20
  void *
17
21
  lexbor_realloc(void *dst, size_t size)
18
22
  {
19
- return realloc(dst, size);
23
+ return lexbor_memory_realloc(dst, size);
20
24
  }
21
25
 
22
26
  void *
23
27
  lexbor_calloc(size_t num, size_t size)
24
28
  {
25
- return calloc(num, size);
29
+ return lexbor_memory_calloc(num, size);
26
30
  }
27
31
 
28
32
  void *
29
33
  lexbor_free(void *dst)
30
34
  {
31
- free(dst);
35
+ lexbor_memory_free(dst);
32
36
  return NULL;
33
37
  }
38
+
39
+ lxb_status_t
40
+ lexbor_memory_setup(lexbor_memory_malloc_f new_malloc, lexbor_memory_realloc_f new_realloc,
41
+ lexbor_memory_calloc_f new_calloc, lexbor_memory_free_f new_free)
42
+ {
43
+ if (new_malloc == NULL || new_realloc == NULL || new_calloc == NULL || new_free == NULL) {
44
+ return LXB_STATUS_ERROR_OBJECT_IS_NULL;
45
+ }
46
+
47
+ lexbor_memory_malloc = new_malloc;
48
+ lexbor_memory_realloc = new_realloc;
49
+ lexbor_memory_calloc = new_calloc;
50
+ lexbor_memory_free = new_free;
51
+
52
+ return LXB_STATUS_OK;
53
+ }
@@ -262,7 +262,7 @@ lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
262
262
  {
263
263
  node = node->next;
264
264
 
265
- do {
265
+ while (node != NULL) {
266
266
  if (node->type == LXB_DOM_NODE_TYPE_ELEMENT) {
267
267
  if (lxb_selectors_match(selectors, entry, selector, node)) {
268
268
  return node;
@@ -273,7 +273,6 @@ lxb_selectors_sibling(lxb_selectors_t *selectors, lxb_selectors_entry_t *entry,
273
273
 
274
274
  node = node->next;
275
275
  }
276
- while (node != NULL);
277
276
 
278
277
  return NULL;
279
278
  }
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.3.1
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yicheng Zhou
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-31 00:00:00.000000000 Z
11
+ date: 2023-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -78,12 +78,14 @@ files:
78
78
  - ext/nokolexbor/libxml/xpath.h
79
79
  - ext/nokolexbor/libxml/xpathInternals.h
80
80
  - ext/nokolexbor/libxml/xpointer.h
81
- - ext/nokolexbor/memory.c
82
81
  - ext/nokolexbor/nl_cdata.c
83
82
  - ext/nokolexbor/nl_comment.c
84
83
  - ext/nokolexbor/nl_document.c
84
+ - ext/nokolexbor/nl_document_fragment.c
85
+ - ext/nokolexbor/nl_error.c
85
86
  - ext/nokolexbor/nl_node.c
86
87
  - ext/nokolexbor/nl_node_set.c
88
+ - ext/nokolexbor/nl_processing_instruction.c
87
89
  - ext/nokolexbor/nl_text.c
88
90
  - ext/nokolexbor/nl_xpath_context.c
89
91
  - ext/nokolexbor/nokolexbor.c
@@ -119,6 +121,7 @@ files:
119
121
  - lib/nokolexbor.rb
120
122
  - lib/nokolexbor/attribute.rb
121
123
  - lib/nokolexbor/document.rb
124
+ - lib/nokolexbor/document_fragment.rb
122
125
  - lib/nokolexbor/node.rb
123
126
  - lib/nokolexbor/node_set.rb
124
127
  - lib/nokolexbor/version.rb
@@ -1,46 +0,0 @@
1
- /*
2
- * This file overrides the default `lexbor_malloc` and other
3
- * related functions to reduce memory bloat and allow Ruby to
4
- * GC more often.
5
- * By calling `ruby_xmalloc` instead of `malloc`, Ruby can
6
- * count the memory usage of the C extension and run GC
7
- * whenever `malloc_increase_byte` exceeds the limit. Similar
8
- * to Nokogiri's solution by calling `xmlMemSetup`.
9
- * The downside will be the downgrade of performance because
10
- * of more frequent GC.
11
- */
12
-
13
- #include "lexbor/core/base.h"
14
- #include <ruby.h>
15
-
16
- // Disable using ruby memory functions when ASAN is enabled,
17
- // otherwise memory leak info will be all about ruby which
18
- // is useless.
19
- #ifndef NOKOLEXBOR_ASAN
20
-
21
- void *
22
- lexbor_malloc(size_t size)
23
- {
24
- return ruby_xmalloc(size);
25
- }
26
-
27
- void *
28
- lexbor_realloc(void *dst, size_t size)
29
- {
30
- return ruby_xrealloc(dst, size);
31
- }
32
-
33
- void *
34
- lexbor_calloc(size_t num, size_t size)
35
- {
36
- return ruby_xcalloc(num, size);
37
- }
38
-
39
- void *
40
- lexbor_free(void *dst)
41
- {
42
- ruby_xfree(dst);
43
- return NULL;
44
- }
45
-
46
- #endif