php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
node.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2018-2022 Alexander Borisov
3 *
4 * Author: Alexander Borisov <borisov@lexbor.com>
5 */
6
13
14
16
17typedef bool
19
31
32
35 const lxb_char_t *name, size_t length);
36
39 const lxb_char_t *name, size_t length);
40
42lxb_ns_append(lexbor_hash_t *hash, const lxb_char_t *link, size_t length);
43
44static lexbor_action_t
45lxb_dom_node_by_tag_name_cb(lxb_dom_node_t *node, void *ctx);
46
47static lexbor_action_t
48lxb_dom_node_by_tag_name_cb_all(lxb_dom_node_t *node, void *ctx);
49
50static lexbor_action_t
51lxb_dom_node_by_class_name_cb(lxb_dom_node_t *node, void *ctx);
52
53static lexbor_action_t
54lxb_dom_node_by_attr_cb(lxb_dom_node_t *node, void *ctx);
55
56static bool
57lxb_dom_node_by_attr_cmp_full(lxb_dom_node_cb_ctx_t *ctx,
59static bool
60lxb_dom_node_by_attr_cmp_full_case(lxb_dom_node_cb_ctx_t *ctx,
62static bool
63lxb_dom_node_by_attr_cmp_begin(lxb_dom_node_cb_ctx_t *ctx,
65static bool
66lxb_dom_node_by_attr_cmp_begin_case(lxb_dom_node_cb_ctx_t *ctx,
68static bool
69lxb_dom_node_by_attr_cmp_end(lxb_dom_node_cb_ctx_t *ctx,
71static bool
72lxb_dom_node_by_attr_cmp_end_case(lxb_dom_node_cb_ctx_t *ctx,
74static bool
75lxb_dom_node_by_attr_cmp_contain(lxb_dom_node_cb_ctx_t *ctx,
77static bool
78lxb_dom_node_by_attr_cmp_contain_case(lxb_dom_node_cb_ctx_t *ctx,
80
81static lexbor_action_t
82lxb_dom_node_text_content_size(lxb_dom_node_t *node, void *ctx);
83
84static lexbor_action_t
85lxb_dom_node_text_content_concatenate(lxb_dom_node_t *node, void *ctx);
86
87
90{
91 lxb_dom_node_t *element;
92
93 element = lexbor_mraw_calloc(document->mraw,
94 sizeof(lxb_dom_node_t));
95 if (element == NULL) {
96 return NULL;
97 }
98
99 element->owner_document = lxb_dom_document_owner(document);
100 element->type = LXB_DOM_NODE_TYPE_UNDEF;
101
102 return element;
103}
104
107 const lxb_dom_node_t *node, bool is_attr)
108{
109 lxb_dom_node_t *new;
110
111 new = lxb_dom_node_interface_create(document);
112 if (new == NULL) {
113 return NULL;
114 }
115
116 if (lxb_dom_node_interface_copy(new, node, is_attr) != LXB_STATUS_OK) {
118 }
119
120 return new;
121}
122
125{
127
128 if (doc->ev_destroy != NULL) {
129 doc->ev_destroy(node);
130 }
131
132 return lexbor_mraw_free(node->owner_document->mraw, node);
133}
134
137 const lxb_dom_node_t *src, bool is_attr)
138{
139 lxb_dom_document_t *from, *to;
140 const lxb_ns_data_t *ns;
141 const lxb_tag_data_t *tag;
143 const lexbor_hash_entry_t *entry;
145
146 dst->type = src->type;
147 dst->user = src->user;
148
149 if (dst->owner_document == src->owner_document) {
150 dst->local_name = src->local_name;
151 dst->ns = src->ns;
152 dst->prefix = src->prefix;
153
154 return LXB_STATUS_OK;
155 }
156
157 from = src->owner_document;
158 to = dst->owner_document;
159
160 if (is_attr) {
162 dst->local_name = src->local_name;
163 }
164 else {
166 if (data == NULL) {
168 }
169
170 entry = &data->entry;
171
174 entry->length);
175 if (data == NULL) {
177 }
178
180 }
181 }
182 else {
183 if (src->local_name < LXB_TAG__LAST_ENTRY) {
184 dst->local_name = src->local_name;
185 }
186 else {
187 tag = lxb_tag_data_by_id(src->local_name);
188 if (tag == NULL) {
190 }
191
192 entry = &tag->entry;
193
195 lexbor_hash_entry_str(entry), entry->length);
196 if (tag == NULL) {
198 }
199
200 dst->local_name = (lxb_dom_attr_id_t) tag;
201 }
202 }
203
204 if (src->ns < LXB_NS__LAST_ENTRY) {
205 dst->ns = src->ns;
206 }
207 else {
208 ns = lxb_ns_data_by_id(from->ns, src->ns);
209 if (ns == NULL) {
211 }
212
213 entry = &ns->entry;
214
215 ns = lxb_ns_append(to->ns, lexbor_hash_entry_str(entry),
216 entry->length);
217 if (ns == NULL) {
219 }
220
221 dst->ns = (lxb_ns_id_t) ns;
222 }
223
224 if (src->prefix < LXB_NS__LAST_ENTRY) {
225 dst->prefix = src->prefix;
226 }
227 else {
229 if (prefix == NULL) {
231 }
232
233 entry = &prefix->entry;
234
236 entry->length);
237 if (prefix == NULL) {
238 return LXB_STATUS_ERROR;
239 }
240
242 }
243
244 return LXB_STATUS_OK;
245}
246
249{
251
252 if (node->owner_document->ev_destroy != NULL) {
253 node->owner_document->ev_destroy(node);
254 }
255
257}
258
261{
262 lxb_dom_node_t *tmp;
263 lxb_dom_node_t *node = root;
264
265 while (node != NULL) {
266 if (node->first_child != NULL) {
267 node = node->first_child;
268 }
269 else {
270 while(node != root && node->next == NULL) {
271 tmp = node->parent;
272
274
275 node = tmp;
276 }
277
278 if (node == root) {
280
281 break;
282 }
283
284 tmp = node->next;
285
287
288 node = tmp;
289 }
290 }
291
292 return NULL;
293}
294
297{
298 return lxb_dom_document_import_node(node->owner_document, node, deep);
299}
300
301const lxb_char_t *
303{
304 switch (node->type) {
307 len);
308
311 len);
312
314 if (len != NULL) {
315 *len = sizeof("#text") - 1;
316 }
317
318 return (const lxb_char_t *) "#text";
319
321 if (len != NULL) {
322 *len = sizeof("#cdata-section") - 1;
323 }
324
325 return (const lxb_char_t *) "#cdata-section";
326
329 len);
330
332 if (len != NULL) {
333 *len = sizeof("#comment") - 1;
334 }
335
336 return (const lxb_char_t *) "#comment";
337
339 if (len != NULL) {
340 *len = sizeof("#document") - 1;
341 }
342
343 return (const lxb_char_t *) "#document";
344
347 len);
348
350 if (len != NULL) {
351 *len = sizeof("#document-fragment") - 1;
352 }
353
354 return (const lxb_char_t *) "#document-fragment";
355
356 default:
357 break;
358 }
359
360 if (len != NULL) {
361 *len = 0;
362 }
363
364 return NULL;
365}
366
367void
369{
370 if (to->last_child != NULL) {
371 to->last_child->next = node;
372 }
373 else {
374 to->first_child = node;
375 }
376
377 node->parent = to;
378 node->next = NULL;
379 node->prev = to->last_child;
380
381 to->last_child = node;
382}
383
384void
386{
388
389 if (node->owner_document->ev_insert != NULL) {
390 node->owner_document->ev_insert(node);
391 }
392}
393
394void
396{
397 if (to->prev != NULL) {
398 to->prev->next = node;
399 }
400 else {
401 if (to->parent != NULL) {
402 to->parent->first_child = node;
403 }
404 }
405
406 node->parent = to->parent;
407 node->next = to;
408 node->prev = to->prev;
409
410 to->prev = node;
411}
412
413void
422
423void
425{
426 if (to->next != NULL) {
427 to->next->prev = node;
428 }
429 else {
430 if (to->parent != NULL) {
431 to->parent->last_child = node;
432 }
433 }
434
435 node->parent = to->parent;
436 node->next = to->next;
437 node->prev = to;
438 to->next = node;
439}
440
441void
443{
445
446 if (node->owner_document->ev_insert != NULL) {
447 node->owner_document->ev_insert(node);
448 }
449}
450
451void
453{
454 if (node->parent != NULL) {
455 if (node->parent->first_child == node) {
456 node->parent->first_child = node->next;
457 }
458
459 if (node->parent->last_child == node) {
460 node->parent->last_child = node->prev;
461 }
462 }
463
464 if (node->next != NULL) {
465 node->next->prev = node->prev;
466 }
467
468 if (node->prev != NULL) {
469 node->prev->next = node->next;
470 }
471
472 node->parent = NULL;
473 node->next = NULL;
474 node->prev = NULL;
475}
476
477void
479{
480 if (node->owner_document->ev_remove != NULL) {
481 node->owner_document->ev_remove(node);
482 }
483
485}
486
489{
490 while (parent->first_child != NULL) {
491 lxb_dom_node_destroy_deep(parent->first_child);
492 }
493
494 lxb_dom_node_insert_child(parent, node);
495
496 return LXB_STATUS_OK;
497}
498
499void
501 lxb_dom_node_simple_walker_f walker_cb, void *ctx)
502{
503 lexbor_action_t action;
504 lxb_dom_node_t *node = root->first_child;
505
506 while (node != NULL) {
507 action = walker_cb(node, ctx);
508 if (action == LEXBOR_ACTION_STOP) {
509 return;
510 }
511
512 if (node->first_child != NULL && action != LEXBOR_ACTION_NEXT) {
513 node = node->first_child;
514 }
515 else {
516 while(node != root && node->next == NULL) {
517 node = node->parent;
518 }
519
520 if (node == root) {
521 break;
522 }
523
524 node = node->next;
525 }
526 }
527}
528
531 lxb_dom_node_cb_ctx_t *cb_ctx,
532 const lxb_char_t *qname, size_t qlen)
533{
534 size_t length;
535 const lxb_char_t *prefix_end;
536 const lxb_dom_attr_data_t *attr_data;
537 const lxb_ns_prefix_data_t *prefix_data;
538
539 cb_ctx->prefix_id = LXB_NS__UNDEF;
540
541 prefix_end = memchr(qname, ':', qlen);
542
543 if (prefix_end != NULL) {
544 length = prefix_end - qname;
545
546 if (length == 0) {
548 }
549
550 prefix_data = lxb_ns_prefix_data_by_name(document->prefix, qname, qlen);
551 if (prefix_data == NULL) {
552 return LXB_STATUS_STOP;
553 }
554
555 cb_ctx->prefix_id = prefix_data->prefix_id;
556
557 length += 1;
558
559 if (length >= qlen) {
561 }
562
563 qname += length;
564 qlen -= length;
565 }
566
567 attr_data = lxb_dom_attr_data_by_local_name(document->attrs, qname, qlen);
568 if (attr_data == NULL) {
569 return LXB_STATUS_STOP;
570 }
571
572 cb_ctx->name_id = attr_data->attr_id;
573
574 return LXB_STATUS_OK;
575}
576
579 lxb_dom_node_cb_ctx_t *cb_ctx,
580 const lxb_char_t *qname, size_t qlen)
581{
582 size_t length;
583 const lxb_char_t *prefix_end;
584 const lxb_tag_data_t *tag_data;
585 const lxb_ns_prefix_data_t *prefix_data;
586
587 cb_ctx->prefix_id = LXB_NS__UNDEF;
588
589 prefix_end = memchr(qname, ':', qlen);
590
591 if (prefix_end != NULL) {
592 length = prefix_end - qname;
593
594 if (length == 0) {
596 }
597
598 prefix_data = lxb_ns_prefix_data_by_name(document->prefix, qname, qlen);
599 if (prefix_data == NULL) {
600 return LXB_STATUS_STOP;
601 }
602
603 cb_ctx->prefix_id = prefix_data->prefix_id;
604
605 length += 1;
606
607 if (length >= qlen) {
609 }
610
611 qname += length;
612 qlen -= length;
613 }
614
615 tag_data = lxb_tag_data_by_name(document->tags, qname, qlen);
616 if (tag_data == NULL) {
617 return LXB_STATUS_STOP;
618 }
619
620 cb_ctx->name_id = tag_data->tag_id;
621
622 return LXB_STATUS_OK;
623}
624
627 lxb_dom_collection_t *collection,
628 const lxb_char_t *qualified_name, size_t len)
629{
631 lxb_dom_node_cb_ctx_t cb_ctx = {0};
632
633 cb_ctx.col = collection;
634
635 /* "*" (U+002A) */
636 if (len == 1 && *qualified_name == 0x2A) {
637 lxb_dom_node_simple_walk(root, lxb_dom_node_by_tag_name_cb_all,
638 &cb_ctx);
639 return cb_ctx.status;
640 }
641
643 qualified_name, len);
644 if (status != LXB_STATUS_OK) {
645 if (status == LXB_STATUS_STOP) {
646 return LXB_STATUS_OK;
647 }
648
649 return status;
650 }
651
653 lxb_dom_node_by_tag_name_cb, &cb_ctx);
654
655 return cb_ctx.status;
656}
657
658static lexbor_action_t
659lxb_dom_node_by_tag_name_cb_all(lxb_dom_node_t *node, void *ctx)
660{
661 if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
662 return LEXBOR_ACTION_OK;
663 }
664
665 lxb_dom_node_cb_ctx_t *cb_ctx = ctx;
666
667 cb_ctx->status = lxb_dom_collection_append(cb_ctx->col, node);
668 if (cb_ctx->status != LXB_STATUS_OK) {
669 return LEXBOR_ACTION_STOP;
670 }
671
672 return LEXBOR_ACTION_OK;
673}
674
675static lexbor_action_t
676lxb_dom_node_by_tag_name_cb(lxb_dom_node_t *node, void *ctx)
677{
678 if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
679 return LEXBOR_ACTION_OK;
680 }
681
682 lxb_dom_node_cb_ctx_t *cb_ctx = ctx;
683
684 if (node->local_name == cb_ctx->name_id
685 && node->prefix == cb_ctx->prefix_id)
686 {
687 cb_ctx->status = lxb_dom_collection_append(cb_ctx->col, node);
688 if (cb_ctx->status != LXB_STATUS_OK) {
689 return LEXBOR_ACTION_STOP;
690 }
691 }
692
693 return LEXBOR_ACTION_OK;
694}
695
698 lxb_dom_collection_t *collection,
699 const lxb_char_t *class_name, size_t len)
700{
701 if (class_name == NULL || len == 0) {
702 return LXB_STATUS_OK;
703 }
704
705 lxb_dom_node_cb_ctx_t cb_ctx = {0};
706
707 cb_ctx.col = collection;
708 cb_ctx.value = class_name;
709 cb_ctx.value_length = len;
710
712 lxb_dom_node_by_class_name_cb, &cb_ctx);
713
714 return cb_ctx.status;
715}
716
717static lexbor_action_t
718lxb_dom_node_by_class_name_cb(lxb_dom_node_t *node, void *ctx)
719{
720 if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
721 return LEXBOR_ACTION_OK;
722 }
723
724 lxb_dom_node_cb_ctx_t *cb_ctx = ctx;
726
727 if (el->attr_class == NULL
728 || el->attr_class->value == NULL
729 || el->attr_class->value->length < cb_ctx->value_length)
730 {
731 return LEXBOR_ACTION_OK;
732 }
733
734 const lxb_char_t *data = el->attr_class->value->data;
735 size_t length = el->attr_class->value->length;
736
737 bool is_it = false;
738 const lxb_char_t *pos = data;
739 const lxb_char_t *end = data + length;
740
742
743 for (; data < end; data++) {
744 if (lexbor_utils_whitespace(*data, ==, ||)) {
745
746 if (pos != data && (size_t) (data - pos) == cb_ctx->value_length) {
748 is_it = lexbor_str_data_ncasecmp(pos, cb_ctx->value,
749 cb_ctx->value_length);
750 }
751 else {
752 is_it = lexbor_str_data_ncmp(pos, cb_ctx->value,
753 cb_ctx->value_length);
754 }
755
756 if (is_it) {
757 cb_ctx->status = lxb_dom_collection_append(cb_ctx->col,
758 node);
759 if (cb_ctx->status != LXB_STATUS_OK) {
760 return LEXBOR_ACTION_STOP;
761 }
762
763 return LEXBOR_ACTION_OK;
764 }
765 }
766
767 if ((size_t) (end - data) < cb_ctx->value_length) {
768 return LEXBOR_ACTION_OK;
769 }
770
771 pos = data + 1;
772 }
773 }
774
775 if ((size_t) (end - pos) == cb_ctx->value_length) {
777 is_it = lexbor_str_data_ncasecmp(pos, cb_ctx->value,
778 cb_ctx->value_length);
779 }
780 else {
781 is_it = lexbor_str_data_ncmp(pos, cb_ctx->value,
782 cb_ctx->value_length);
783 }
784
785 if (is_it) {
786 cb_ctx->status = lxb_dom_collection_append(cb_ctx->col, node);
787 if (cb_ctx->status != LXB_STATUS_OK) {
788 return LEXBOR_ACTION_STOP;
789 }
790 }
791 }
792
793 return LEXBOR_ACTION_OK;
794}
795
798 lxb_dom_collection_t *collection,
799 const lxb_char_t *qualified_name, size_t qname_len,
800 const lxb_char_t *value, size_t value_len,
801 bool case_insensitive)
802{
804 lxb_dom_node_cb_ctx_t cb_ctx = {0};
805
806 cb_ctx.col = collection;
807 cb_ctx.value = value;
808 cb_ctx.value_length = value_len;
809
811 qualified_name, qname_len);
812 if (status != LXB_STATUS_OK) {
813 if (status == LXB_STATUS_STOP) {
814 return LXB_STATUS_OK;
815 }
816
817 return status;
818 }
819
820 if (case_insensitive) {
821 cb_ctx.cmp_func = lxb_dom_node_by_attr_cmp_full_case;
822 }
823 else {
824 cb_ctx.cmp_func = lxb_dom_node_by_attr_cmp_full;
825 }
826
827 lxb_dom_node_simple_walk(root, lxb_dom_node_by_attr_cb, &cb_ctx);
828
829 return cb_ctx.status;
830}
831
834 lxb_dom_collection_t *collection,
835 const lxb_char_t *qualified_name, size_t qname_len,
836 const lxb_char_t *value, size_t value_len,
837 bool case_insensitive)
838{
840 lxb_dom_node_cb_ctx_t cb_ctx = {0};
841
842 cb_ctx.col = collection;
843 cb_ctx.value = value;
844 cb_ctx.value_length = value_len;
845
847 qualified_name, qname_len);
848 if (status != LXB_STATUS_OK) {
849 if (status == LXB_STATUS_STOP) {
850 return LXB_STATUS_OK;
851 }
852
853 return status;
854 }
855
856 if (case_insensitive) {
857 cb_ctx.cmp_func = lxb_dom_node_by_attr_cmp_begin_case;
858 }
859 else {
860 cb_ctx.cmp_func = lxb_dom_node_by_attr_cmp_begin;
861 }
862
864 lxb_dom_node_by_attr_cb, &cb_ctx);
865
866 return cb_ctx.status;
867}
868
871 const lxb_char_t *qualified_name, size_t qname_len,
872 const lxb_char_t *value, size_t value_len,
873 bool case_insensitive)
874{
876 lxb_dom_node_cb_ctx_t cb_ctx = {0};
877
878 cb_ctx.col = collection;
879 cb_ctx.value = value;
880 cb_ctx.value_length = value_len;
881
883 qualified_name, qname_len);
884 if (status != LXB_STATUS_OK) {
885 if (status == LXB_STATUS_STOP) {
886 return LXB_STATUS_OK;
887 }
888
889 return status;
890 }
891
892 if (case_insensitive) {
893 cb_ctx.cmp_func = lxb_dom_node_by_attr_cmp_end_case;
894 }
895 else {
896 cb_ctx.cmp_func = lxb_dom_node_by_attr_cmp_end;
897 }
898
899 lxb_dom_node_simple_walk(root, lxb_dom_node_by_attr_cb, &cb_ctx);
900
901 return cb_ctx.status;
902}
903
906 lxb_dom_collection_t *collection,
907 const lxb_char_t *qualified_name, size_t qname_len,
908 const lxb_char_t *value, size_t value_len,
909 bool case_insensitive)
910{
912 lxb_dom_node_cb_ctx_t cb_ctx = {0};
913
914 cb_ctx.col = collection;
915 cb_ctx.value = value;
916 cb_ctx.value_length = value_len;
917
919 qualified_name, qname_len);
920 if (status != LXB_STATUS_OK) {
921 if (status == LXB_STATUS_STOP) {
922 return LXB_STATUS_OK;
923 }
924
925 return status;
926 }
927
928 if (case_insensitive) {
929 cb_ctx.cmp_func = lxb_dom_node_by_attr_cmp_contain_case;
930 }
931 else {
932 cb_ctx.cmp_func = lxb_dom_node_by_attr_cmp_contain;
933 }
934
935 lxb_dom_node_simple_walk(root, lxb_dom_node_by_attr_cb, &cb_ctx);
936
937 return cb_ctx.status;
938}
939
940static lexbor_action_t
941lxb_dom_node_by_attr_cb(lxb_dom_node_t *node, void *ctx)
942{
943 if (node->type != LXB_DOM_NODE_TYPE_ELEMENT) {
944 return LEXBOR_ACTION_OK;
945 }
946
948 lxb_dom_node_cb_ctx_t *cb_ctx = ctx;
950
952 if (attr == NULL) {
953 return LEXBOR_ACTION_OK;
954 }
955
956 if ((cb_ctx->value_length == 0 && (attr->value == NULL || attr->value->length == 0))
957 || cb_ctx->cmp_func(cb_ctx, attr))
958 {
959 cb_ctx->status = lxb_dom_collection_append(cb_ctx->col, node);
960
961 if (cb_ctx->status != LXB_STATUS_OK) {
962 return LEXBOR_ACTION_STOP;
963 }
964 }
965
966 return LEXBOR_ACTION_OK;
967}
968
969static bool
970lxb_dom_node_by_attr_cmp_full(lxb_dom_node_cb_ctx_t *ctx, lxb_dom_attr_t *attr)
971{
972 if (attr->value != NULL && ctx->value_length == attr->value->length
973 && lexbor_str_data_ncmp(attr->value->data, ctx->value,
974 ctx->value_length))
975 {
976 return true;
977 }
978
979 return attr->value == NULL && ctx->value_length == 0;
980}
981
982static bool
983lxb_dom_node_by_attr_cmp_full_case(lxb_dom_node_cb_ctx_t *ctx,
985{
986 if (attr->value != NULL && ctx->value_length == attr->value->length
987 && lexbor_str_data_ncasecmp(attr->value->data, ctx->value,
988 ctx->value_length))
989 {
990 return true;
991 }
992
993 return attr->value == NULL && ctx->value_length == 0;
994}
995
996static bool
997lxb_dom_node_by_attr_cmp_begin(lxb_dom_node_cb_ctx_t *ctx, lxb_dom_attr_t *attr)
998{
999 if (attr->value != NULL && ctx->value_length <= attr->value->length
1000 && lexbor_str_data_ncmp(attr->value->data, ctx->value,
1001 ctx->value_length))
1002 {
1003 return true;
1004 }
1005
1006 return attr->value == NULL && ctx->value_length == 0;
1007}
1008
1009static bool
1010lxb_dom_node_by_attr_cmp_begin_case(lxb_dom_node_cb_ctx_t *ctx,
1012{
1013 if (attr->value != NULL && ctx->value_length <= attr->value->length
1014 && lexbor_str_data_ncasecmp(attr->value->data,
1015 ctx->value, ctx->value_length))
1016 {
1017 return true;
1018 }
1019
1020 return attr->value == NULL && ctx->value_length == 0;
1021}
1022
1023static bool
1024lxb_dom_node_by_attr_cmp_end(lxb_dom_node_cb_ctx_t *ctx, lxb_dom_attr_t *attr)
1025{
1026 if (attr->value != NULL && ctx->value_length <= attr->value->length) {
1027 size_t dif = attr->value->length - ctx->value_length;
1028
1029 if (lexbor_str_data_ncmp_end(&attr->value->data[dif],
1030 ctx->value, ctx->value_length))
1031 {
1032 return true;
1033 }
1034 }
1035
1036 return attr->value == NULL && ctx->value_length == 0;
1037}
1038
1039static bool
1040lxb_dom_node_by_attr_cmp_end_case(lxb_dom_node_cb_ctx_t *ctx,
1042{
1043 if (attr->value != NULL && ctx->value_length <= attr->value->length) {
1044 size_t dif = attr->value->length - ctx->value_length;
1045
1046 if (lexbor_str_data_ncasecmp_end(&attr->value->data[dif],
1047 ctx->value, ctx->value_length))
1048 {
1049 return true;
1050 }
1051 }
1052
1053 return attr->value == NULL && ctx->value_length == 0;
1054}
1055
1056static bool
1057lxb_dom_node_by_attr_cmp_contain(lxb_dom_node_cb_ctx_t *ctx,
1059{
1060 if (attr->value != NULL && ctx->value_length <= attr->value->length
1061 && lexbor_str_data_ncmp_contain(attr->value->data, attr->value->length,
1062 ctx->value, ctx->value_length))
1063 {
1064 return true;
1065 }
1066
1067 return attr->value == NULL && ctx->value_length == 0;
1068}
1069
1070static bool
1071lxb_dom_node_by_attr_cmp_contain_case(lxb_dom_node_cb_ctx_t *ctx,
1073{
1074 if (attr->value != NULL && ctx->value_length <= attr->value->length
1075 && lexbor_str_data_ncasecmp_contain(attr->value->data, attr->value->length,
1076 ctx->value, ctx->value_length))
1077 {
1078 return true;
1079 }
1080
1081 return attr->value == NULL && ctx->value_length == 0;
1082}
1083
1084lxb_char_t *
1086{
1088 size_t length = 0;
1089
1090 switch (node->type) {
1093 lxb_dom_node_simple_walk(node, lxb_dom_node_text_content_size,
1094 &length);
1095
1097 (length + 1));
1098 if (text == NULL) {
1099 goto failed;
1100 }
1101
1102 lxb_dom_node_simple_walk(node, lxb_dom_node_text_content_concatenate,
1103 &text);
1104
1105 text -= length;
1106
1107 break;
1108
1110 const lxb_char_t *attr_text;
1111
1112 attr_text = lxb_dom_attr_value(lxb_dom_interface_attr(node), &length);
1113 if (attr_text == NULL) {
1114 goto failed;
1115 }
1116
1118 (length + 1));
1119 if (text == NULL) {
1120 goto failed;
1121 }
1122
1123 /* +1 == with null '\0' */
1124 memcpy(text, attr_text, sizeof(lxb_char_t) * (length + 1));
1125
1126 break;
1127 }
1128
1132 lxb_dom_character_data_t *ch_data;
1133
1134 ch_data = lxb_dom_interface_character_data(node);
1135 length = ch_data->data.length;
1136
1138 (length + 1));
1139 if (text == NULL) {
1140 goto failed;
1141 }
1142
1143 /* +1 == with null '\0' */
1144 memcpy(text, ch_data->data.data, sizeof(lxb_char_t) * (length + 1));
1145
1146 break;
1147 }
1148
1149 default:
1150 goto failed;
1151 }
1152
1153 if (len != NULL) {
1154 *len = length;
1155 }
1156
1157 text[length] = 0x00;
1158
1159 return text;
1160
1161failed:
1162
1163 if (len != NULL) {
1164 *len = 0;
1165 }
1166
1167 return NULL;
1168}
1169
1170static lexbor_action_t
1171lxb_dom_node_text_content_size(lxb_dom_node_t *node, void *ctx)
1172{
1173 if (node->type == LXB_DOM_NODE_TYPE_TEXT) {
1174 *((size_t *) ctx) += lxb_dom_interface_text(node)->char_data.data.length;
1175 }
1176
1177 return LEXBOR_ACTION_OK;
1178}
1179
1180static lexbor_action_t
1181lxb_dom_node_text_content_concatenate(lxb_dom_node_t *node, void *ctx)
1182{
1183 if (node->type != LXB_DOM_NODE_TYPE_TEXT) {
1184 return LEXBOR_ACTION_OK;
1185 }
1186
1187 lxb_char_t **text = (lxb_char_t **) ctx;
1188 lxb_dom_character_data_t *ch_data = &lxb_dom_interface_text(node)->char_data;
1189
1190 memcpy(*text, ch_data->data.data, sizeof(lxb_char_t) * ch_data->data.length);
1191
1192 *text = *text + ch_data->data.length;
1193
1194 return LEXBOR_ACTION_OK;
1195}
1196
1199 const lxb_char_t *content, size_t len)
1200{
1202
1203 switch (node->type) {
1207
1209 content, len);
1210 if (text == NULL) {
1212 }
1213
1215 if (status != LXB_STATUS_OK) {
1217
1218 return status;
1219 }
1220
1221 break;
1222 }
1223
1226 content, len);
1227
1232 content, len, 0, 0);
1233
1234 default:
1235 return LXB_STATUS_OK;
1236 }
1237
1238 return LXB_STATUS_OK;
1239}
1240
1241bool
1243{
1245 lexbor_str_t *str;
1246 const lxb_char_t *data, *end;
1247 lxb_dom_node_t *node = root->first_child;
1248
1249 while (node != NULL) {
1250 if(node->local_name != LXB_TAG__EM_COMMENT) {
1251 if(node->local_name != LXB_TAG__TEXT)
1252 return false;
1253
1254 str = &lxb_dom_interface_text(node)->char_data.data;
1255 data = str->data;
1256 end = data + str->length;
1257
1258 while (data < end) {
1259 chr = *data++;
1260
1261 if (lexbor_utils_whitespace(chr, !=, &&)) {
1262 return false;
1263 }
1264 }
1265 }
1266
1267 if(node->first_child != NULL) {
1268 node = node->first_child;
1269 }
1270 else {
1271 while(node != root && node->next == NULL) {
1272 node = node->parent;
1273 }
1274
1275 if(node == root) {
1276 break;
1277 }
1278
1279 node = node->next;
1280 }
1281 }
1282
1283 return true;
1284}
1285
1288{
1289 return lxb_dom_node_tag_id(node);
1290}
1291
1294{
1295 return lxb_dom_node_next(node);
1296}
1297
1300{
1301 return lxb_dom_node_prev(node);
1302}
1303
1306{
1307 return lxb_dom_node_parent(node);
1308}
1309
1315
size_t len
Definition apprentice.c:174
lxb_inline const lxb_char_t * lxb_dom_attr_value(lxb_dom_attr_t *attr, size_t *len)
Definition attr.h:124
uintptr_t lxb_dom_attr_id_t
Definition attr_const.h:18
@ LXB_DOM_ATTR__LAST_ENTRY
Definition attr_const.h:57
chr(int $codepoint)
link(string $target, string $link)
lxb_status_t lxb_dom_character_data_replace(lxb_dom_character_data_t *ch_data, const lxb_char_t *data, size_t len, size_t offset, size_t count)
lxb_inline lxb_status_t lxb_dom_collection_append(lxb_dom_collection_t *col, void *value)
Definition collection.h:63
@ LXB_STATUS_ERROR_MEMORY_ALLOCATION
Definition base.h:51
@ LXB_STATUS_STOP
Definition base.h:68
@ LXB_STATUS_ERROR_WRONG_ARGS
Definition base.h:58
@ LXB_STATUS_OK
Definition base.h:49
@ LXB_STATUS_ERROR_NOT_EXISTS
Definition base.h:57
@ LXB_STATUS_ERROR
Definition base.h:50
lexbor_action_t
Definition base.h:73
@ LEXBOR_ACTION_NEXT
Definition base.h:76
@ LEXBOR_ACTION_OK
Definition base.h:74
@ LEXBOR_ACTION_STOP
Definition base.h:75
#define LXB_API
Definition def.h:48
DNS_STATUS status
Definition dns_win32.c:49
lxb_inline const lxb_char_t * lxb_dom_document_type_name(lxb_dom_document_type_t *doc_type, size_t *len)
struct lxb_dom_document lxb_dom_document_t
Definition interface.h:41
#define lxb_dom_interface_element(obj)
Definition interface.h:28
#define lxb_dom_interface_attr(obj)
Definition interface.h:29
#define lxb_dom_interface_node(obj)
Definition interface.h:31
#define lxb_dom_interface_processing_instruction(obj)
Definition interface.h:32
struct lxb_dom_node lxb_dom_node_t
Definition interface.h:38
struct lxb_dom_character_data lxb_dom_character_data_t
Definition interface.h:45
#define lxb_dom_interface_document_type(obj)
Definition interface.h:27
struct lxb_dom_attr lxb_dom_attr_t
Definition interface.h:40
struct lxb_dom_text lxb_dom_text_t
Definition interface.h:46
#define lxb_dom_interface_character_data(obj)
Definition interface.h:23
struct lxb_dom_element lxb_dom_element_t
Definition interface.h:39
#define lxb_dom_interface_text(obj)
Definition interface.h:34
lxb_inline lxb_char_t * lxb_dom_document_create_text(lxb_dom_document_t *document, size_t len)
Definition document.h:167
lxb_inline lxb_dom_document_t * lxb_dom_document_owner(lxb_dom_document_t *document)
Definition document.h:198
@ LXB_DOM_DOCUMENT_CMODE_QUIRKS
Definition document.h:23
lxb_inline lxb_dom_interface_t * lxb_dom_document_destroy_interface(lxb_dom_interface_t *intrfc)
Definition document.h:149
lxb_inline lxb_dom_node_t * lxb_dom_node_prev(lxb_dom_node_t *node)
Definition node.h:188
lxb_inline lxb_tag_id_t lxb_dom_node_tag_id(lxb_dom_node_t *node)
Definition node.h:176
lexbor_action_t(* lxb_dom_node_simple_walker_f)(lxb_dom_node_t *node, void *ctx)
Definition node.h:20
@ LXB_DOM_NODE_TYPE_COMMENT
Definition node.h:32
@ LXB_DOM_NODE_TYPE_CDATA_SECTION
Definition node.h:28
@ LXB_DOM_NODE_TYPE_PROCESSING_INSTRUCTION
Definition node.h:31
@ LXB_DOM_NODE_TYPE_UNDEF
Definition node.h:24
@ LXB_DOM_NODE_TYPE_DOCUMENT
Definition node.h:33
@ LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT
Definition node.h:35
@ LXB_DOM_NODE_TYPE_DOCUMENT_TYPE
Definition node.h:34
@ LXB_DOM_NODE_TYPE_ATTRIBUTE
Definition node.h:26
@ LXB_DOM_NODE_TYPE_ELEMENT
Definition node.h:25
@ LXB_DOM_NODE_TYPE_TEXT
Definition node.h:27
lxb_inline lxb_dom_node_t * lxb_dom_node_parent(lxb_dom_node_t *node)
Definition node.h:194
lxb_inline lxb_dom_node_t * lxb_dom_node_last_child(lxb_dom_node_t *node)
Definition node.h:206
lxb_inline lxb_dom_node_t * lxb_dom_node_first_child(lxb_dom_node_t *node)
Definition node.h:200
lxb_inline lxb_dom_node_t * lxb_dom_node_next(lxb_dom_node_t *node)
Definition node.h:182
memcpy(ptr1, ptr2, size)
new_type attr
Definition ffi.c:4364
#define NULL
Definition gdcache.h:45
#define prefix
lxb_inline lxb_char_t * lexbor_hash_entry_str(const lexbor_hash_entry_t *entry)
Definition hash.h:161
struct lexbor_hash lexbor_hash_t
Definition hash.h:41
struct lexbor_hash_entry lexbor_hash_entry_t
Definition hash.h:42
hash(string $algo, string $data, bool $binary=false, array $options=[])
Definition hash.stub.php:12
const lxb_char_t * lxb_dom_attr_qualified_name(lxb_dom_attr_t *attr, size_t *len)
Definition attr.c:463
lxb_status_t lxb_dom_attr_set_existing_value(lxb_dom_attr_t *attr, const lxb_char_t *value, size_t value_len)
Definition attr.c:278
const lxb_dom_attr_data_t * lxb_dom_attr_data_by_local_name(lexbor_hash_t *hash, const lxb_char_t *name, size_t length)
Definition attr.c:425
const lxb_dom_attr_data_t * lxb_dom_attr_data_by_id(lexbor_hash_t *hash, lxb_dom_attr_id_t attr_id)
Definition attr.c:411
lxb_dom_node_t * lxb_dom_document_import_node(lxb_dom_document_t *doc, lxb_dom_node_t *node, bool deep)
Definition document.c:432
lxb_dom_text_t * lxb_dom_document_create_text_node(lxb_dom_document_t *document, const lxb_char_t *data, size_t len)
Definition document.c:275
const lxb_char_t * lxb_dom_element_tag_name(lxb_dom_element_t *element, size_t *len)
Definition element.c:769
lxb_dom_attr_t * lxb_dom_element_attr_by_id(lxb_dom_element_t *element, lxb_dom_attr_id_t attr_id)
Definition element.c:460
lxb_inline lxb_status_t lxb_dom_node_prepare_by_attr(lxb_dom_document_t *document, lxb_dom_node_cb_ctx_t *cb_ctx, const lxb_char_t *qname, size_t qlen)
Definition node.c:530
LXB_API lxb_dom_attr_data_t * lxb_dom_attr_local_name_append(lexbor_hash_t *hash, const lxb_char_t *name, size_t length)
Definition attr.c:358
struct lxb_dom_node_cb_ctx lxb_dom_node_cb_ctx_t
Definition node.c:15
lxb_status_t lxb_dom_node_text_content_set(lxb_dom_node_t *node, const lxb_char_t *content, size_t len)
Definition node.c:1198
lxb_dom_node_t * lxb_dom_node_prev_noi(lxb_dom_node_t *node)
Definition node.c:1299
lxb_dom_node_t * lxb_dom_node_interface_create(lxb_dom_document_t *document)
Definition node.c:89
void lxb_dom_node_remove_wo_events(lxb_dom_node_t *node)
Definition node.c:452
lxb_dom_node_t * lxb_dom_node_clone(lxb_dom_node_t *node, bool deep)
Definition node.c:296
void lxb_dom_node_remove(lxb_dom_node_t *node)
Definition node.c:478
lxb_dom_node_t * lxb_dom_node_interface_clone(lxb_dom_document_t *document, const lxb_dom_node_t *node, bool is_attr)
Definition node.c:106
lxb_dom_node_t * lxb_dom_node_destroy_deep(lxb_dom_node_t *root)
Definition node.c:260
lxb_status_t lxb_dom_node_by_attr_begin(lxb_dom_node_t *root, lxb_dom_collection_t *collection, const lxb_char_t *qualified_name, size_t qname_len, const lxb_char_t *value, size_t value_len, bool case_insensitive)
Definition node.c:833
lxb_status_t lxb_dom_node_by_attr_end(lxb_dom_node_t *root, lxb_dom_collection_t *collection, const lxb_char_t *qualified_name, size_t qname_len, const lxb_char_t *value, size_t value_len, bool case_insensitive)
Definition node.c:870
lxb_dom_node_t * lxb_dom_node_first_child_noi(lxb_dom_node_t *node)
Definition node.c:1311
void lxb_dom_node_insert_after_wo_events(lxb_dom_node_t *to, lxb_dom_node_t *node)
Definition node.c:424
void lxb_dom_node_simple_walk(lxb_dom_node_t *root, lxb_dom_node_simple_walker_f walker_cb, void *ctx)
Definition node.c:500
lxb_status_t lxb_dom_node_interface_copy(lxb_dom_node_t *dst, const lxb_dom_node_t *src, bool is_attr)
Definition node.c:136
LXB_API const lxb_tag_data_t * lxb_tag_append(lexbor_hash_t *hash, lxb_tag_id_t tag_id, const lxb_char_t *name, size_t length)
Definition tag.c:13
void lxb_dom_node_insert_child(lxb_dom_node_t *to, lxb_dom_node_t *node)
Definition node.c:385
lxb_status_t lxb_dom_node_by_tag_name(lxb_dom_node_t *root, lxb_dom_collection_t *collection, const lxb_char_t *qualified_name, size_t len)
Definition node.c:626
lxb_status_t lxb_dom_node_by_class_name(lxb_dom_node_t *root, lxb_dom_collection_t *collection, const lxb_char_t *class_name, size_t len)
Definition node.c:697
lxb_char_t * lxb_dom_node_text_content(lxb_dom_node_t *node, size_t *len)
Definition node.c:1085
lxb_status_t lxb_dom_node_replace_all(lxb_dom_node_t *parent, lxb_dom_node_t *node)
Definition node.c:488
const lxb_char_t * lxb_dom_node_name(lxb_dom_node_t *node, size_t *len)
Definition node.c:302
lxb_inline lxb_status_t lxb_dom_node_prepare_by(lxb_dom_document_t *document, lxb_dom_node_cb_ctx_t *cb_ctx, const lxb_char_t *qname, size_t qlen)
Definition node.c:578
LXB_API const lxb_ns_data_t * lxb_ns_append(lexbor_hash_t *hash, const lxb_char_t *link, size_t length)
Definition ns.c:17
void lxb_dom_node_insert_after(lxb_dom_node_t *to, lxb_dom_node_t *node)
Definition node.c:442
bool(* lxb_dom_node_attr_cmp_f)(lxb_dom_node_cb_ctx_t *ctx, lxb_dom_attr_t *attr)
Definition node.c:18
lxb_dom_node_t * lxb_dom_node_destroy(lxb_dom_node_t *node)
Definition node.c:248
lxb_dom_node_t * lxb_dom_node_next_noi(lxb_dom_node_t *node)
Definition node.c:1293
lxb_status_t lxb_dom_node_by_attr(lxb_dom_node_t *root, lxb_dom_collection_t *collection, const lxb_char_t *qualified_name, size_t qname_len, const lxb_char_t *value, size_t value_len, bool case_insensitive)
Definition node.c:797
lxb_status_t lxb_dom_node_by_attr_contain(lxb_dom_node_t *root, lxb_dom_collection_t *collection, const lxb_char_t *qualified_name, size_t qname_len, const lxb_char_t *value, size_t value_len, bool case_insensitive)
Definition node.c:905
lxb_dom_node_t * lxb_dom_node_last_child_noi(lxb_dom_node_t *node)
Definition node.c:1317
void lxb_dom_node_insert_before_wo_events(lxb_dom_node_t *to, lxb_dom_node_t *node)
Definition node.c:395
void lxb_dom_node_insert_child_wo_events(lxb_dom_node_t *to, lxb_dom_node_t *node)
Definition node.c:368
bool lxb_dom_node_is_empty(const lxb_dom_node_t *root)
Definition node.c:1242
void lxb_dom_node_insert_before(lxb_dom_node_t *to, lxb_dom_node_t *node)
Definition node.c:414
lxb_tag_id_t lxb_dom_node_tag_id_noi(lxb_dom_node_t *node)
Definition node.c:1287
lxb_dom_node_t * lxb_dom_node_interface_destroy(lxb_dom_node_t *node)
Definition node.c:124
lxb_dom_node_t * lxb_dom_node_parent_noi(lxb_dom_node_t *node)
Definition node.c:1305
void * lexbor_mraw_free(lexbor_mraw_t *mraw, void *data)
Definition mraw.c:392
void * lexbor_mraw_calloc(lexbor_mraw_t *mraw, size_t size)
Definition mraw.c:227
uintptr_t lxb_ns_prefix_id_t
Definition const.h:21
uintptr_t lxb_ns_id_t
Definition const.h:20
@ LXB_NS__UNDEF
Definition const.h:24
@ LXB_NS__LAST_ENTRY
Definition const.h:32
const lxb_ns_prefix_data_t * lxb_ns_prefix_append(lexbor_hash_t *hash, const lxb_char_t *prefix, size_t length)
Definition ns.c:97
const lxb_ns_prefix_data_t * lxb_ns_prefix_data_by_name(lexbor_hash_t *hash, const lxb_char_t *prefix, size_t length)
Definition ns.c:138
const lxb_ns_data_t * lxb_ns_data_by_id(lexbor_hash_t *hash, lxb_ns_id_t ns_id)
Definition ns.c:64
const lxb_ns_prefix_data_t * lxb_ns_prefix_data_by_id(lexbor_hash_t *hash, lxb_ns_prefix_id_t prefix_id)
Definition ns.c:124
unsigned const char * end
Definition php_ffi.h:51
unsigned const char * pos
Definition php_ffi.h:52
unsigned const char * text
Definition php_ffi.h:53
zend_constant * data
lxb_inline const lxb_char_t * lxb_dom_processing_instruction_target(lxb_dom_processing_instruction_t *pi, size_t *len)
bool lexbor_str_data_ncmp_contain(const lxb_char_t *where, size_t where_size, const lxb_char_t *what, size_t what_size)
Definition str.c:510
bool lexbor_str_data_ncasecmp(const lxb_char_t *first, const lxb_char_t *sec, size_t size)
Definition str.c:435
bool lexbor_str_data_ncmp_end(const lxb_char_t *first, const lxb_char_t *sec, size_t size)
Definition str.c:495
bool lexbor_str_data_ncasecmp_end(const lxb_char_t *first, const lxb_char_t *sec, size_t size)
Definition str.c:405
bool lexbor_str_data_ncmp(const lxb_char_t *first, const lxb_char_t *sec, size_t size)
Definition str.c:523
bool lexbor_str_data_ncasecmp_contain(const lxb_char_t *where, size_t where_size, const lxb_char_t *what, size_t what_size)
Definition str.c:422
size_t length
Definition hash.h:61
lxb_char_t * data
Definition str.h:47
size_t length
Definition str.h:48
lxb_dom_attr_id_t attr_id
Definition attr.h:27
lexbor_str_t * value
Definition attr.h:42
lexbor_hash_t * ns
Definition document.h:58
lxb_dom_document_cmode_t compat_mode
Definition document.h:38
lexbor_mraw_t * mraw
Definition document.h:53
lexbor_hash_t * tags
Definition document.h:55
lxb_dom_event_remove_f ev_remove
Definition document.h:49
lexbor_hash_t * attrs
Definition document.h:56
lexbor_hash_t * prefix
Definition document.h:57
lxb_dom_event_insert_f ev_insert
Definition document.h:48
lxb_dom_event_destroy_f ev_destroy
Definition document.h:50
lxb_dom_attr_t * attr_class
Definition element.h:49
lxb_dom_node_t node
Definition element.h:33
lxb_ns_prefix_id_t prefix_id
Definition node.c:26
lxb_status_t status
Definition node.c:22
lxb_dom_node_attr_cmp_f cmp_func
Definition node.c:23
const lxb_char_t * value
Definition node.c:28
lxb_dom_collection_t * col
Definition node.c:21
lxb_dom_attr_id_t name_id
Definition node.c:25
size_t value_length
Definition node.c:29
lxb_dom_node_t * prev
Definition node.h:53
void * user
Definition node.h:57
uintptr_t ns
Definition node.h:48
lxb_dom_node_t * first_child
Definition node.h:55
lxb_dom_document_t * owner_document
Definition node.h:50
uintptr_t prefix
Definition node.h:47
lxb_dom_node_t * last_child
Definition node.h:56
lxb_dom_node_type_t type
Definition node.h:59
uintptr_t local_name
Definition node.h:46
lxb_dom_node_t * parent
Definition node.h:54
lxb_dom_node_t * next
Definition node.h:52
lexbor_hash_entry_t entry
Definition ns.h:21
lxb_ns_prefix_id_t prefix_id
Definition ns.h:32
lexbor_hash_entry_t entry
Definition tag.h:23
lxb_tag_id_t tag_id
Definition tag.h:24
@ LXB_TAG__EM_COMMENT
Definition const.h:28
@ LXB_TAG__LAST_ENTRY
Definition const.h:220
@ LXB_TAG__TEXT
Definition const.h:26
@ LXB_TAG__UNDEF
Definition const.h:24
uintptr_t lxb_tag_id_t
Definition const.h:21
const lxb_tag_data_t * lxb_tag_data_by_name(lexbor_hash_t *hash, const lxb_char_t *name, size_t len)
Definition tag.c:77
const lxb_tag_data_t * lxb_tag_data_by_id(lxb_tag_id_t tag_id)
Definition tag.c:63
unsigned int lxb_status_t
Definition types.h:28
#define lxb_inline
Definition types.h:21
unsigned char lxb_char_t
Definition types.h:27
#define lexbor_utils_whitespace(onechar, action, logic)
Definition utils.h:17
zend_string * name
value