1use core::ffi::c_void;
11use core::ptr;
12use std::os::raw::{c_char, c_int, c_uint, c_ulong};
13
14use crate::abi::allocator;
15use crate::abi::structs::*;
16use crate::abi::types::xmlAttributeDefault::*;
17use crate::abi::types::xmlAttributeType::*;
18use crate::abi::types::xmlElementContentOccur::*;
19use crate::abi::types::xmlElementContentType::*;
20use crate::abi::types::xmlElementType::*;
21use crate::abi::types::xmlElementTypeVal::*;
22use crate::abi::types::*;
23use crate::xml::hash;
24use crate::xml::string;
25
26pub fn get_int_subset(doc: *const _xmlDoc) -> *mut _xmlDtd {
40 if doc.is_null() {
41 return ptr::null_mut();
42 }
43 unsafe { (*doc).intSubset }
44}
45
46pub unsafe fn create_int_subset(
63 doc: *mut _xmlDoc,
64 name: *const xmlChar,
65 ExternalID: *const xmlChar,
66 SystemID: *const xmlChar,
67) -> *mut _xmlDtd {
68 if doc.is_null() {
69 return ptr::null_mut();
70 }
71
72 let dtd = allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd;
74 if dtd.is_null() {
75 return ptr::null_mut();
76 }
77
78 unsafe {
79 (*dtd).type_ = XML_DTD_NODE as c_int;
80 (*dtd).name = string::xml_strdup(name);
81 (*dtd).ExternalID = string::xml_strdup(ExternalID);
82 (*dtd).SystemID = string::xml_strdup(SystemID);
83 (*dtd).parent = doc;
84 (*dtd).doc = doc;
85
86 (*dtd).notations = hash::hash_create(8) as *mut c_void;
88 (*dtd).elements = hash::hash_create(16) as *mut c_void;
89 (*dtd).attributes = hash::hash_create(16) as *mut c_void;
90 (*dtd).entities = hash::hash_create(8) as *mut c_void;
91 (*dtd).pentities = hash::hash_create(8) as *mut c_void;
92
93 (*doc).intSubset = dtd;
95 }
96
97 dtd
98}
99
100pub unsafe fn new_dtd(
117 doc: *mut _xmlDoc,
118 name: *const xmlChar,
119 ExternalID: *const xmlChar,
120 SystemID: *const xmlChar,
121) -> *mut _xmlDtd {
122 let dtd = allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd;
124 if dtd.is_null() {
125 return ptr::null_mut();
126 }
127
128 unsafe {
129 (*dtd).type_ = XML_DTD_NODE as c_int;
130 (*dtd).name = string::xml_strdup(name);
131 (*dtd).ExternalID = string::xml_strdup(ExternalID);
132 (*dtd).SystemID = string::xml_strdup(SystemID);
133 (*dtd).parent = doc;
134 (*dtd).doc = doc;
135
136 (*dtd).notations = hash::hash_create(8) as *mut c_void;
138 (*dtd).elements = hash::hash_create(16) as *mut c_void;
139 (*dtd).attributes = hash::hash_create(16) as *mut c_void;
140 (*dtd).entities = hash::hash_create(8) as *mut c_void;
141 (*dtd).pentities = hash::hash_create(8) as *mut c_void;
142
143 if !doc.is_null() && (*doc).intSubset.is_null() {
145 (*doc).intSubset = dtd;
146 }
147 }
148
149 dtd
150}
151
152unsafe extern "C" fn copy_elem_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
154 unsafe { copy_element(payload as *mut _xmlElement) as *mut c_void }
155}
156
157unsafe extern "C" fn copy_attr_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
158 unsafe { copy_attribute_decl(payload as *mut _xmlAttribute) as *mut c_void }
159}
160
161unsafe extern "C" fn copy_ent_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
162 unsafe { crate::xml::entities::copy_entity(payload as *mut _xmlEntity) as *mut c_void }
163}
164
165unsafe extern "C" fn copy_notation_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
166 unsafe { copy_notation(payload as *mut _xmlNotation) as *mut c_void }
167}
168
169pub unsafe fn copy_dtd(dtd: *const _xmlDtd) -> *mut _xmlDtd {
179 if dtd.is_null() {
180 return ptr::null_mut();
181 }
182 let d = unsafe { &*dtd };
183
184 let copy = unsafe { allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd };
185 if copy.is_null() {
186 return ptr::null_mut();
187 }
188
189 unsafe {
190 (*copy).type_ = d.type_;
191 (*copy).name = string::xml_strdup(d.name);
192 (*copy).ExternalID = string::xml_strdup(d.ExternalID);
193 (*copy).SystemID = string::xml_strdup(d.SystemID);
194 (*copy).notations =
195 hash::hash_copy(d.notations as *mut hash::HashTable, Some(copy_notation_cb))
196 as *mut c_void;
197 (*copy).elements =
198 hash::hash_copy(d.elements as *mut hash::HashTable, Some(copy_elem_cb)) as *mut c_void;
199 (*copy).attributes =
200 hash::hash_copy(d.attributes as *mut hash::HashTable, Some(copy_attr_cb))
201 as *mut c_void;
202 (*copy).entities =
203 hash::hash_copy(d.entities as *mut hash::HashTable, Some(copy_ent_cb)) as *mut c_void;
204 (*copy).pentities =
205 hash::hash_copy(d.pentities as *mut hash::HashTable, Some(copy_ent_cb)) as *mut c_void;
206 }
207
208 copy
209}
210
211pub unsafe fn free_dtd(dtd: *mut _xmlDtd) {
223 if dtd.is_null() {
224 return;
225 }
226
227 unsafe {
228 let d = &mut *dtd;
229
230 if !d.notations.is_null() {
232 hash::hash_free(
233 d.notations as *mut hash::HashTable,
234 Some(notation_deallocator),
235 );
236 d.notations = ptr::null_mut();
237 }
238 if !d.elements.is_null() {
239 hash::hash_free(
240 d.elements as *mut hash::HashTable,
241 Some(element_deallocator),
242 );
243 d.elements = ptr::null_mut();
244 }
245 if !d.attributes.is_null() {
246 hash::hash_free(
247 d.attributes as *mut hash::HashTable,
248 Some(attribute_deallocator),
249 );
250 d.attributes = ptr::null_mut();
251 }
252 if !d.entities.is_null() {
253 hash::hash_free(d.entities as *mut hash::HashTable, Some(entity_deallocator));
254 d.entities = ptr::null_mut();
255 }
256 if !d.pentities.is_null() {
257 hash::hash_free(
258 d.pentities as *mut hash::HashTable,
259 Some(entity_deallocator),
260 );
261 d.pentities = ptr::null_mut();
262 }
263
264 if !d.name.is_null() {
266 allocator::xmlFree(d.name as *mut c_void);
267 }
268 if !d.ExternalID.is_null() {
269 allocator::xmlFree(d.ExternalID as *mut c_void);
270 }
271 if !d.SystemID.is_null() {
272 allocator::xmlFree(d.SystemID as *mut c_void);
273 }
274
275 if !d.children.is_null() {
277 }
282
283 allocator::xmlFree(dtd as *mut c_void);
284 }
285}
286
287unsafe extern "C" fn notation_deallocator(payload: *mut c_void, _name: *mut u8) {
292 if !payload.is_null() {
293 free_notation(payload as *mut _xmlNotation);
294 }
295}
296
297unsafe extern "C" fn element_deallocator(payload: *mut c_void, _name: *mut u8) {
298 if !payload.is_null() {
299 free_element(payload as *mut _xmlElement);
300 }
301}
302
303unsafe extern "C" fn attribute_deallocator(payload: *mut c_void, _name: *mut u8) {
304 if !payload.is_null() {
305 free_attribute(payload as *mut _xmlAttribute);
306 }
307}
308
309unsafe extern "C" fn entity_deallocator(payload: *mut c_void, _name: *mut u8) {
310 if !payload.is_null() {
311 crate::xml::entities::free_entity(payload as *mut _xmlEntity);
312 }
313}
314
315pub unsafe fn add_notation_decl(
335 dtd: *mut _xmlDtd,
336 name: *const xmlChar,
337 PublicID: *const xmlChar,
338 SystemID: *const xmlChar,
339) -> *mut _xmlNotation {
340 if dtd.is_null() || name.is_null() {
341 return ptr::null_mut();
342 }
343
344 unsafe {
345 let d = &*dtd;
346
347 let existing = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
349 if !existing.is_null() {
350 return existing as *mut _xmlNotation;
351 }
352
353 let not = allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
355 if not.is_null() {
356 return ptr::null_mut();
357 }
358
359 (*not).name = string::xml_strdup(name);
360 (*not).PublicID = string::xml_strdup(PublicID);
361 (*not).SystemID = string::xml_strdup(SystemID);
362
363 let ret = hash::hash_add_entry(
365 d.notations as *mut hash::HashTable,
366 name,
367 not as *mut c_void,
368 );
369 if ret != 0 {
370 free_notation(not);
372 return ptr::null_mut();
373 }
374
375 not
376 }
377}
378
379pub unsafe fn get_notation_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlNotation {
392 if dtd.is_null() || name.is_null() {
393 return ptr::null_mut();
394 }
395
396 unsafe {
397 let d = &*dtd;
398 let payload = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
399 payload as *mut _xmlNotation
400 }
401}
402
403pub unsafe fn copy_notation(notation: *mut _xmlNotation) -> *mut _xmlNotation {
415 if notation.is_null() {
416 return ptr::null_mut();
417 }
418
419 unsafe {
420 let n = &*notation;
421 let copy =
423 allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
424 if copy.is_null() {
425 return ptr::null_mut();
426 }
427
428 (*copy).name = string::xml_strdup(n.name);
429 (*copy).PublicID = string::xml_strdup(n.PublicID);
430 (*copy).SystemID = string::xml_strdup(n.SystemID);
431
432 copy
433 }
434}
435
436pub unsafe fn free_notation(notation: *mut _xmlNotation) {
448 if notation.is_null() {
449 return;
450 }
451
452 unsafe {
453 let n = &*notation;
454 if !n.name.is_null() {
455 allocator::xmlFree(n.name as *mut c_void);
456 }
457 if !n.PublicID.is_null() {
458 allocator::xmlFree(n.PublicID as *mut c_void);
459 }
460 if !n.SystemID.is_null() {
461 allocator::xmlFree(n.SystemID as *mut c_void);
462 }
463 allocator::xmlFree(notation as *mut c_void);
464 }
465}
466
467pub unsafe fn create_content_model(name: *const xmlChar, type_: c_int) -> *mut _xmlElementContent {
486 let content = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
488 as *mut _xmlElementContent;
489 if content.is_null() {
490 return ptr::null_mut();
491 }
492
493 unsafe {
494 (*content).type_ = type_;
495 (*content).ocur = XML_ELEMENT_CONTENT_ONCE as c_int;
496 (*content).name = string::xml_strdup(name);
497 (*content).c1 = ptr::null_mut();
498 (*content).c2 = ptr::null_mut();
499 (*content).parent = ptr::null_mut();
500 (*content).prefix = ptr::null_mut();
501 }
502
503 content
504}
505
506pub unsafe fn free_content_model(cur: *mut _xmlElementContent) {
520 if cur.is_null() {
521 return;
522 }
523
524 unsafe {
525 let c = &*cur;
526
527 if !c.c1.is_null() {
529 free_content_model(c.c1);
530 }
531 if !c.c2.is_null() {
532 free_content_model(c.c2);
533 }
534
535 if !c.name.is_null() {
537 allocator::xmlFree(c.name as *mut c_void);
538 }
539 if !c.prefix.is_null() {
540 allocator::xmlFree(c.prefix as *mut c_void);
541 }
542
543 allocator::xmlFree(cur as *mut c_void);
544 }
545}
546
547pub unsafe fn copy_content_model(content: *mut _xmlElementContent) -> *mut _xmlElementContent {
561 if content.is_null() {
562 return ptr::null_mut();
563 }
564
565 unsafe {
566 let c = &*content;
567
568 let copy = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
570 as *mut _xmlElementContent;
571 if copy.is_null() {
572 return ptr::null_mut();
573 }
574
575 (*copy).type_ = c.type_;
576 (*copy).ocur = c.ocur;
577 (*copy).name = string::xml_strdup(c.name);
578 (*copy).prefix = string::xml_strdup(c.prefix);
579
580 if !c.c1.is_null() {
582 (*copy).c1 = copy_content_model(c.c1);
583 if !(*copy).c1.is_null() {
584 (*(*copy).c1).parent = copy;
585 }
586 }
587 if !c.c2.is_null() {
588 (*copy).c2 = copy_content_model(c.c2);
589 if !(*copy).c2.is_null() {
590 (*(*copy).c2).parent = copy;
591 }
592 }
593
594 copy
595 }
596}
597
598pub unsafe fn add_element_decl(
619 dtd: *mut _xmlDtd,
620 name: *const xmlChar,
621 type_: c_int,
622 content: *mut _xmlElementContent,
623) -> *mut _xmlElement {
624 if dtd.is_null() || name.is_null() {
625 return ptr::null_mut();
626 }
627
628 unsafe {
629 let d = &*dtd;
630
631 let existing = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
633 if !existing.is_null() {
634 return existing as *mut _xmlElement;
635 }
636
637 let elem = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
639 if elem.is_null() {
640 return ptr::null_mut();
641 }
642
643 (*elem).name = string::xml_strdup(name);
644 (*elem).type_ = type_;
645 (*elem).etype = type_; (*elem).content = content; (*elem).attributes = ptr::null_mut();
648 (*elem).prefix = ptr::null_mut();
649 (*elem).children = ptr::null_mut();
650 (*elem).last = ptr::null_mut();
651 (*elem).parent = dtd;
652 (*elem).next = ptr::null_mut();
653 (*elem).prev = ptr::null_mut();
654 (*elem).doc = ptr::null_mut();
655 (*elem).cont_model = ptr::null_mut();
656
657 let ret = hash::hash_add_entry(
659 d.elements as *mut hash::HashTable,
660 name,
661 elem as *mut c_void,
662 );
663 if ret != 0 {
664 free_element(elem);
666 return ptr::null_mut();
667 }
668
669 elem
670 }
671}
672
673pub unsafe fn get_element_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlElement {
686 if dtd.is_null() || name.is_null() {
687 return ptr::null_mut();
688 }
689
690 unsafe {
691 let d = &*dtd;
692 let payload = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
693 payload as *mut _xmlElement
694 }
695}
696
697pub unsafe fn copy_element(elem: *mut _xmlElement) -> *mut _xmlElement {
709 if elem.is_null() {
710 return ptr::null_mut();
711 }
712
713 unsafe {
714 let e = &*elem;
715
716 let copy = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
718 if copy.is_null() {
719 return ptr::null_mut();
720 }
721
722 (*copy).name = string::xml_strdup(e.name);
723 (*copy).type_ = e.type_;
724 (*copy).etype = e.etype;
725 (*copy).content = copy_content_model(e.content);
726 (*copy).prefix = string::xml_strdup(e.prefix);
727 (*copy)._private = e._private;
728 (*copy).parent = e.parent;
729 (*copy).doc = e.doc;
730
731 if !e.attributes.is_null() {
733 let mut src_attr = e.attributes;
736 let mut prev_copy: *mut _xmlAttribute = ptr::null_mut();
737 let mut first_copy: *mut _xmlAttribute = ptr::null_mut();
738
739 while !src_attr.is_null() {
740 let attr_copy = copy_attribute_decl(src_attr);
741 if attr_copy.is_null() {
742 let mut to_free = first_copy;
744 while !to_free.is_null() {
745 let next = (*to_free).nexth;
746 free_attribute(to_free);
747 to_free = next;
748 }
749 allocator::xmlFree(copy as *mut c_void);
750 return ptr::null_mut();
751 }
752
753 if prev_copy.is_null() {
754 first_copy = attr_copy;
755 } else {
756 (*prev_copy).nexth = attr_copy;
757 }
758 prev_copy = attr_copy;
759 src_attr = (*src_attr).nexth;
760 }
761
762 (*copy).attributes = first_copy;
763 }
764
765 copy
766 }
767}
768
769pub unsafe fn free_element(elem: *mut _xmlElement) {
784 if elem.is_null() {
785 return;
786 }
787
788 unsafe {
789 if !(*elem).name.is_null() {
791 allocator::xmlFree((*elem).name as *mut c_void);
792 }
793
794 if !(*elem).prefix.is_null() {
796 allocator::xmlFree((*elem).prefix as *mut c_void);
797 }
798
799 if !(*elem).content.is_null() {
801 free_content_model((*elem).content);
802 }
803
804 if !(*elem).cont_model.is_null() {
807 crate::xml::validation::free_content_model_nfa(
808 (*elem).cont_model as *mut crate::xml::validation::ContentModelNfa,
809 );
810 }
811
812 (*elem).attributes = ptr::null_mut();
818
819 allocator::xmlFree(elem as *mut c_void);
820 }
821}
822
823unsafe fn free_enumeration(tree: *mut _xmlEnumeration) {
833 if tree.is_null() {
834 return;
835 }
836
837 unsafe {
838 let mut cur = tree;
839 while !cur.is_null() {
840 let next = (*cur).next;
841 if !(*cur).name.is_null() {
842 allocator::xmlFree((*cur).name as *mut c_void);
843 }
844 allocator::xmlFree(cur as *mut c_void);
845 cur = next;
846 }
847 }
848}
849
850unsafe fn copy_enumeration(tree: *mut _xmlEnumeration) -> *mut _xmlEnumeration {
856 if tree.is_null() {
857 return ptr::null_mut();
858 }
859
860 unsafe {
861 let mut src = tree;
862 let mut first_copy: *mut _xmlEnumeration = ptr::null_mut();
863 let mut prev_copy: *mut _xmlEnumeration = ptr::null_mut();
864
865 while !src.is_null() {
866 let copy = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
867 as *mut _xmlEnumeration;
868 if copy.is_null() {
869 let mut to_free = first_copy;
871 while !to_free.is_null() {
872 let next = (*to_free).next;
873 if !(*to_free).name.is_null() {
874 allocator::xmlFree((*to_free).name as *mut c_void);
875 }
876 allocator::xmlFree(to_free as *mut c_void);
877 to_free = next;
878 }
879 return ptr::null_mut();
880 }
881
882 (*copy).name = string::xml_strdup((*src).name);
883 (*copy).next = ptr::null_mut();
884
885 if prev_copy.is_null() {
886 first_copy = copy;
887 } else {
888 (*prev_copy).next = copy;
889 }
890 prev_copy = copy;
891 src = (*src).next;
892 }
893
894 first_copy
895 }
896}
897
898pub unsafe fn add_attribute_decl(
920 dtd: *mut _xmlDtd,
921 elem: *mut _xmlElement,
922 name: *const xmlChar,
923 type_: c_int,
924 def: c_int,
925 defaultValue: *const xmlChar,
926 tree: *mut _xmlEnumeration,
927) -> *mut _xmlAttribute {
928 if dtd.is_null() || name.is_null() {
929 return ptr::null_mut();
930 }
931
932 unsafe {
933 let d = &*dtd;
934 let elem_name = if elem.is_null() {
935 ptr::null()
936 } else {
937 (*elem).name
938 };
939
940 let existing = hash::hash_lookup2(d.attributes as *mut hash::HashTable, elem_name, name);
942 if !existing.is_null() {
943 return existing as *mut _xmlAttribute;
944 }
945
946 let attr =
948 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
949 if attr.is_null() {
950 return ptr::null_mut();
951 }
952
953 (*attr).type_ = XML_ATTRIBUTE_DECL as c_int;
954 (*attr).name = string::xml_strdup(name);
955 (*attr).parent = dtd;
956 (*attr).doc = d.doc;
957 (*attr).nexth = ptr::null_mut();
958 (*attr).atype = type_;
959 (*attr).def = def;
960 (*attr).defaultValue = string::xml_strdup(defaultValue);
961 (*attr).tree = tree; (*attr).prefix = ptr::null_mut();
963 (*attr).elem = string::xml_strdup(elem_name);
964
965 let ret = hash::hash_add_entry2(
967 d.attributes as *mut hash::HashTable,
968 elem_name,
969 name,
970 attr as *mut c_void,
971 );
972 if ret != 0 {
973 if !(*attr).defaultValue.is_null() {
975 allocator::xmlFree((*attr).defaultValue as *mut c_void);
976 }
977 if !(*attr).name.is_null() {
978 allocator::xmlFree((*attr).name as *mut c_void);
979 }
980 if !(*attr).elem.is_null() {
981 allocator::xmlFree((*attr).elem as *mut c_void);
982 }
983 allocator::xmlFree(attr as *mut c_void);
984 return ptr::null_mut();
986 }
987
988 if !elem.is_null() {
990 (*attr).nexth = (*elem).attributes;
991 (*elem).attributes = attr;
992 }
993
994 attr
995 }
996}
997
998pub unsafe fn get_attribute_decl(
1016 dtd: *mut _xmlDtd,
1017 elem: *mut _xmlElement,
1018 name: *const xmlChar,
1019 _namePrefix: c_int,
1020) -> *mut _xmlAttribute {
1021 if dtd.is_null() || name.is_null() {
1022 return ptr::null_mut();
1023 }
1024
1025 unsafe {
1026 let d = &*dtd;
1027 let elem_name = if elem.is_null() {
1028 ptr::null()
1029 } else {
1030 (*elem).name
1031 };
1032
1033 let payload = hash::hash_lookup2(d.attributes as *mut hash::HashTable, elem_name, name);
1034 payload as *mut _xmlAttribute
1035 }
1036}
1037
1038pub unsafe fn copy_attribute_decl(attr: *mut _xmlAttribute) -> *mut _xmlAttribute {
1050 if attr.is_null() {
1051 return ptr::null_mut();
1052 }
1053
1054 unsafe {
1055 let a = &*attr;
1056
1057 let copy =
1059 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
1060 if copy.is_null() {
1061 return ptr::null_mut();
1062 }
1063
1064 (*copy).type_ = a.type_;
1065 (*copy).name = string::xml_strdup(a.name);
1066 (*copy).parent = a.parent;
1067 (*copy).doc = a.doc;
1068 (*copy).nexth = ptr::null_mut();
1069 (*copy).atype = a.atype;
1070 (*copy).def = a.def;
1071 (*copy).defaultValue = string::xml_strdup(a.defaultValue);
1072 (*copy).tree = copy_enumeration(a.tree);
1073 (*copy).prefix = string::xml_strdup(a.prefix);
1074 (*copy).elem = string::xml_strdup(a.elem);
1075
1076 copy
1077 }
1078}
1079
1080pub unsafe fn free_attribute(attr: *mut _xmlAttribute) {
1092 if attr.is_null() {
1093 return;
1094 }
1095
1096 unsafe {
1097 let a = &*attr;
1098
1099 if !a.name.is_null() {
1100 allocator::xmlFree(a.name as *mut c_void);
1101 }
1102 if !a.defaultValue.is_null() {
1103 allocator::xmlFree(a.defaultValue as *mut c_void);
1104 }
1105 if !a.prefix.is_null() {
1106 allocator::xmlFree(a.prefix as *mut c_void);
1107 }
1108 if !a.elem.is_null() {
1109 allocator::xmlFree(a.elem as *mut c_void);
1110 }
1111 if !a.tree.is_null() {
1112 free_enumeration(a.tree);
1113 }
1114
1115 allocator::xmlFree(attr as *mut c_void);
1116 }
1117}
1118
1119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1125pub enum ContentModelResult {
1126 Valid,
1128 Invalid,
1130 Indeterminate,
1132}
1133
1134pub unsafe fn valid_content_model(
1155 model: *mut _xmlElementContent,
1156 names: &[*const xmlChar],
1157) -> ContentModelResult {
1158 if model.is_null() {
1159 return ContentModelResult::Invalid;
1160 }
1161
1162 unsafe {
1163 let m = &*model;
1164
1165 match m.ocur as u32 {
1167 o if o == XML_ELEMENT_CONTENT_OPT as u32 => {
1168 if names.is_empty() {
1170 return ContentModelResult::Valid;
1171 }
1172 return valid_content_model_inner(model, names);
1173 }
1174 o if o == XML_ELEMENT_CONTENT_MULT as u32 => {
1175 if names.is_empty() {
1177 return ContentModelResult::Valid;
1178 }
1179 return valid_content_model_zero_or_more(model, names);
1180 }
1181 o if o == XML_ELEMENT_CONTENT_PLUS as u32 => {
1182 if names.is_empty() {
1184 return ContentModelResult::Invalid;
1185 }
1186 return valid_content_model_one_or_more(model, names);
1187 }
1188 _ => {}
1189 }
1190
1191 valid_content_model_inner(model, names)
1192 }
1193}
1194
1195unsafe fn valid_content_model_inner(
1197 model: *mut _xmlElementContent,
1198 names: &[*const xmlChar],
1199) -> ContentModelResult {
1200 unsafe {
1201 let m = &*model;
1202
1203 match m.type_ as u32 {
1204 t if t == XML_ELEMENT_CONTENT_PCDATA as u32 => {
1205 if names.is_empty() {
1207 ContentModelResult::Valid
1208 } else {
1209 ContentModelResult::Invalid
1210 }
1211 }
1212 t if t == XML_ELEMENT_CONTENT_ELEMENT as u32 => {
1213 if names.len() != 1 {
1215 return ContentModelResult::Invalid;
1216 }
1217 if names[0].is_null() {
1218 return ContentModelResult::Invalid;
1219 }
1220 if string::xml_strcmp(names[0], m.name) != 0 {
1222 return ContentModelResult::Invalid;
1223 }
1224 ContentModelResult::Valid
1225 }
1226 t if t == XML_ELEMENT_CONTENT_SEQ as u32 => {
1227 valid_content_model_seq(m, names)
1229 }
1230 t if t == XML_ELEMENT_CONTENT_OR as u32 => {
1231 valid_content_model_or(m, names)
1233 }
1234 _ => ContentModelResult::Invalid,
1235 }
1236 }
1237}
1238
1239unsafe fn valid_content_model_zero_or_more(
1241 model: *mut _xmlElementContent,
1242 names: &[*const xmlChar],
1243) -> ContentModelResult {
1244 let mut i = 0;
1246 while i <= names.len() {
1247 let consumed = &names[..i];
1248 let remaining = &names[i..];
1249
1250 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1251 if consumed_valid == ContentModelResult::Valid {
1252 if remaining.is_empty() {
1253 return ContentModelResult::Valid;
1254 }
1255 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1257 if remaining_valid == ContentModelResult::Valid {
1258 return ContentModelResult::Valid;
1259 }
1260 }
1261
1262 i += 1;
1263 }
1264 ContentModelResult::Invalid
1265}
1266
1267unsafe fn valid_content_model_one_or_more(
1269 model: *mut _xmlElementContent,
1270 names: &[*const xmlChar],
1271) -> ContentModelResult {
1272 let mut i = 1;
1274 while i <= names.len() {
1275 let consumed = &names[..i];
1276 let remaining = &names[i..];
1277
1278 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1279 if consumed_valid == ContentModelResult::Valid {
1280 if remaining.is_empty() {
1281 return ContentModelResult::Valid;
1282 }
1283 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1284 if remaining_valid == ContentModelResult::Valid {
1285 return ContentModelResult::Valid;
1286 }
1287 }
1288
1289 i += 1;
1290 }
1291 ContentModelResult::Invalid
1292}
1293
1294unsafe fn valid_content_model_seq(
1296 model: &_xmlElementContent,
1297 names: &[*const xmlChar],
1298) -> ContentModelResult {
1299 let c1 = model.c1;
1304 let c2 = model.c2;
1305
1306 if c1.is_null() && c2.is_null() {
1307 return ContentModelResult::Valid;
1308 }
1309
1310 if c1.is_null() {
1311 return unsafe { valid_content_model(c2, names) };
1312 }
1313
1314 if c2.is_null() {
1315 return unsafe { valid_content_model(c1, names) };
1316 }
1317
1318 for split in 0..=names.len() {
1321 let left = &names[..split];
1322 let right = &names[split..];
1323
1324 let left_valid = unsafe { valid_content_model(c1, left) };
1325 if left_valid != ContentModelResult::Valid {
1326 continue;
1327 }
1328
1329 let right_valid = unsafe { valid_content_model(c2, right) };
1330 if right_valid == ContentModelResult::Valid {
1331 return ContentModelResult::Valid;
1332 }
1333 }
1334
1335 ContentModelResult::Invalid
1336}
1337
1338unsafe fn valid_content_model_or(
1340 model: &_xmlElementContent,
1341 names: &[*const xmlChar],
1342) -> ContentModelResult {
1343 let c1 = model.c1;
1344 let c2 = model.c2;
1345
1346 if c1.is_null() && c2.is_null() {
1347 return ContentModelResult::Invalid;
1348 }
1349
1350 if !c1.is_null() {
1351 let result = unsafe { valid_content_model(c1, names) };
1352 if result == ContentModelResult::Valid {
1353 return ContentModelResult::Valid;
1354 }
1355 }
1356
1357 if !c2.is_null() {
1358 let result = unsafe { valid_content_model(c2, names) };
1359 if result == ContentModelResult::Valid {
1360 return ContentModelResult::Valid;
1361 }
1362 }
1363
1364 ContentModelResult::Invalid
1365}
1366
1367#[cfg(test)]
1372mod tests {
1373 use super::*;
1374 use crate::abi::allocator::xmlFree;
1375 use crate::abi::structs::*;
1376 use core::ffi::c_void;
1377 use core::ptr;
1378
1379 unsafe fn c_str(s: &[u8]) -> *const xmlChar {
1382 let len = s.len();
1384 let buf = allocator::xmlMalloc(len + 1) as *mut xmlChar;
1385 assert!(!buf.is_null());
1386 ptr::copy_nonoverlapping(s.as_ptr(), buf, len);
1387 *buf.add(len) = 0;
1388 buf as *const xmlChar
1389 }
1390
1391 unsafe fn make_doc_and_dtd() -> (*mut _xmlDoc, *mut _xmlDtd) {
1392 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1393 assert!(!doc.is_null());
1394 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1395 (*doc).doc = doc;
1396 let dtd = create_int_subset(doc, c_str(b"root"), ptr::null(), ptr::null());
1397 assert!(!dtd.is_null());
1398 (doc, dtd)
1399 }
1400
1401 #[test]
1404 fn test_get_int_subset_null() {
1405 unsafe {
1406 assert!(get_int_subset(ptr::null()).is_null());
1407 }
1408 }
1409
1410 #[test]
1411 fn test_create_int_subset() {
1412 unsafe {
1413 let (doc, dtd) = make_doc_and_dtd();
1414 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1415 assert!(!(*dtd).name.is_null());
1416 assert_eq!((*doc).intSubset, dtd);
1417
1418 free_dtd(dtd);
1420 allocator::xmlFree(doc as *mut c_void);
1421 }
1422 }
1423
1424 #[test]
1425 fn test_create_int_subset_null_doc() {
1426 unsafe {
1427 let dtd = create_int_subset(ptr::null_mut(), c_str(b"root"), ptr::null(), ptr::null());
1428 assert!(dtd.is_null());
1429 }
1430 }
1431
1432 #[test]
1433 fn test_new_dtd() {
1434 unsafe {
1435 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1436 assert!(!doc.is_null());
1437 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1438 (*doc).doc = doc;
1439
1440 let dtd = new_dtd(doc, c_str(b"test"), c_str(b"-//TEST//"), c_str(b"test.dtd"));
1441 assert!(!dtd.is_null());
1442 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1443 assert_eq!((*doc).intSubset, dtd);
1444
1445 free_dtd(dtd);
1446 allocator::xmlFree(doc as *mut c_void);
1447 }
1448 }
1449
1450 #[test]
1451 fn test_new_dtd_no_doc() {
1452 unsafe {
1453 let dtd = new_dtd(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1454 assert!(!dtd.is_null());
1455 free_dtd(dtd);
1456 }
1457 }
1458
1459 #[test]
1462 fn test_add_get_notation() {
1463 unsafe {
1464 let (doc, dtd) = make_doc_and_dtd();
1465 let name = c_str(b"note");
1466 let pubid = c_str(b"-//TEST//NOTATION");
1467 let sysid = c_str(b"note.ent");
1468
1469 let n = add_notation_decl(dtd, name, pubid, sysid);
1470 assert!(!n.is_null());
1471 assert_eq!(string::xml_strcmp((*n).name, name), 0);
1472
1473 let found = get_notation_decl(dtd, name);
1475 assert_eq!(found, n);
1476
1477 let not_found = get_notation_decl(dtd, c_str(b"nonexistent"));
1479 assert!(not_found.is_null());
1480
1481 free_dtd(dtd);
1482 allocator::xmlFree(doc as *mut c_void);
1483 }
1484 }
1485
1486 #[test]
1487 fn test_add_notation_null_dtd() {
1488 unsafe {
1489 let n = add_notation_decl(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1490 assert!(n.is_null());
1491 }
1492 }
1493
1494 #[test]
1495 fn test_copy_notation() {
1496 unsafe {
1497 let (doc, dtd) = make_doc_and_dtd();
1498 let name = c_str(b"note1");
1499 let pubid = c_str(b"public");
1500 let sysid = c_str(b"system");
1501
1502 let n = add_notation_decl(dtd, name, pubid, sysid);
1503 assert!(!n.is_null());
1504
1505 let copy = copy_notation(n);
1506 assert!(!copy.is_null());
1507 assert_ne!(copy, n);
1508 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1509 assert_eq!(string::xml_strcmp((*copy).PublicID, pubid), 0);
1510 assert_eq!(string::xml_strcmp((*copy).SystemID, sysid), 0);
1511
1512 free_notation(copy);
1513 free_dtd(dtd);
1514 allocator::xmlFree(doc as *mut c_void);
1515 }
1516 }
1517
1518 #[test]
1519 fn test_copy_notation_null() {
1520 unsafe {
1521 assert!(copy_notation(ptr::null_mut()).is_null());
1522 }
1523 }
1524
1525 #[test]
1526 fn test_free_notation_null() {
1527 unsafe {
1528 free_notation(ptr::null_mut()); }
1530 }
1531
1532 #[test]
1535 fn test_create_free_content_model() {
1536 unsafe {
1537 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1538 assert!(!cm.is_null());
1539 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1540 assert_eq!((*cm).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1541
1542 free_content_model(cm);
1543 }
1544 }
1545
1546 #[test]
1547 fn test_create_content_model_pcdata() {
1548 unsafe {
1549 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1550 assert!(!cm.is_null());
1551 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_PCDATA as c_int);
1552 free_content_model(cm);
1553 }
1554 }
1555
1556 #[test]
1557 fn test_copy_content_model() {
1558 unsafe {
1559 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1560 assert!(!cm.is_null());
1561
1562 let copy = copy_content_model(cm);
1563 assert!(!copy.is_null());
1564 assert_ne!(copy, cm);
1565 assert_eq!((*copy).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1566 assert_eq!((*copy).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1567 assert_eq!(string::xml_strcmp((*copy).name, (*cm).name), 0);
1568
1569 free_content_model(cm);
1570 free_content_model(copy);
1571 }
1572 }
1573
1574 #[test]
1575 fn test_copy_content_model_null() {
1576 unsafe {
1577 assert!(copy_content_model(ptr::null_mut()).is_null());
1578 }
1579 }
1580
1581 #[test]
1582 fn test_free_content_model_null() {
1583 unsafe {
1584 free_content_model(ptr::null_mut()); }
1586 }
1587
1588 #[test]
1589 fn test_create_sequence_content_model() {
1590 unsafe {
1591 let c1 = create_content_model(c_str(b"a"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1592 let c2 = create_content_model(c_str(b"b"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1593 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1594 assert!(!seq.is_null());
1595 (*seq).c1 = c1;
1596 (*seq).c2 = c2;
1597 (*c1).parent = seq;
1598 (*c2).parent = seq;
1599
1600 free_content_model(seq);
1601 }
1602 }
1603
1604 #[test]
1607 fn test_add_get_element() {
1608 unsafe {
1609 let (doc, dtd) = make_doc_and_dtd();
1610 let name = c_str(b"myElement");
1611
1612 let elem =
1613 add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1614 assert!(!elem.is_null());
1615 assert_eq!((*elem).etype, XML_ELEMENT_TYPE_EMPTY as c_int);
1616
1617 let found = get_element_decl(dtd, name);
1618 assert_eq!(found, elem);
1619
1620 let not_found = get_element_decl(dtd, c_str(b"nonexistent"));
1621 assert!(not_found.is_null());
1622
1623 free_dtd(dtd);
1624 allocator::xmlFree(doc as *mut c_void);
1625 }
1626 }
1627
1628 #[test]
1629 fn test_add_element_duplicate() {
1630 unsafe {
1631 let (doc, dtd) = make_doc_and_dtd();
1632 let name = c_str(b"dup");
1633
1634 let e1 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1635 assert!(!e1.is_null());
1636
1637 let e2 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ANY as c_int, ptr::null_mut());
1638 assert_eq!(e1, e2); assert_eq!((*e2).type_, XML_ELEMENT_TYPE_EMPTY as c_int); free_dtd(dtd);
1642 allocator::xmlFree(doc as *mut c_void);
1643 }
1644 }
1645
1646 #[test]
1647 fn test_add_element_null_dtd() {
1648 unsafe {
1649 let elem = add_element_decl(
1650 ptr::null_mut(),
1651 c_str(b"test"),
1652 XML_ELEMENT_TYPE_EMPTY as c_int,
1653 ptr::null_mut(),
1654 );
1655 assert!(elem.is_null());
1656 }
1657 }
1658
1659 #[test]
1660 fn test_copy_element() {
1661 unsafe {
1662 let (doc, dtd) = make_doc_and_dtd();
1663 let name = c_str(b"source");
1664 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1665
1666 let elem = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ELEMENT as c_int, cm);
1667 assert!(!elem.is_null());
1668
1669 let copy = copy_element(elem);
1670 assert!(!copy.is_null());
1671 assert_ne!(copy, elem);
1672 assert_eq!((*copy).type_, XML_ELEMENT_TYPE_ELEMENT as c_int);
1673 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1674 assert!(!(*copy).content.is_null());
1675 assert_ne!((*copy).content, cm);
1676
1677 free_element(copy);
1678 free_dtd(dtd);
1679 allocator::xmlFree(doc as *mut c_void);
1680 }
1681 }
1682
1683 #[test]
1684 fn test_free_element_null() {
1685 unsafe {
1686 free_element(ptr::null_mut()); }
1688 }
1689
1690 #[test]
1693 fn test_add_get_attribute() {
1694 unsafe {
1695 let (doc, dtd) = make_doc_and_dtd();
1696 let elem_name = c_str(b"elem");
1697 let attr_name = c_str(b"attr1");
1698
1699 let elem = add_element_decl(
1700 dtd,
1701 elem_name,
1702 XML_ELEMENT_TYPE_EMPTY as c_int,
1703 ptr::null_mut(),
1704 );
1705 assert!(!elem.is_null());
1706
1707 let attr = add_attribute_decl(
1708 dtd,
1709 elem,
1710 attr_name,
1711 XML_ATTRIBUTE_CDATA as c_int,
1712 XML_ATTRIBUTE_IMPLIED as c_int,
1713 ptr::null(),
1714 ptr::null_mut(),
1715 );
1716 assert!(!attr.is_null());
1717 assert_eq!((*attr).atype, XML_ATTRIBUTE_CDATA as c_int);
1718 assert_eq!((*attr).def, XML_ATTRIBUTE_IMPLIED as c_int);
1719
1720 let found = get_attribute_decl(dtd, elem, attr_name, 0);
1722 assert_eq!(found, attr);
1723
1724 let not_found = get_attribute_decl(dtd, elem, c_str(b"nonexistent"), 0);
1726 assert!(not_found.is_null());
1727
1728 free_dtd(dtd);
1729 allocator::xmlFree(doc as *mut c_void);
1730 }
1731 }
1732
1733 #[test]
1734 fn test_add_attribute_with_default() {
1735 unsafe {
1736 let (doc, dtd) = make_doc_and_dtd();
1737 let elem_name = c_str(b"elem");
1738 let attr_name = c_str(b"color");
1739 let default_val = c_str(b"red");
1740
1741 let elem = add_element_decl(
1742 dtd,
1743 elem_name,
1744 XML_ELEMENT_TYPE_EMPTY as c_int,
1745 ptr::null_mut(),
1746 );
1747
1748 let attr = add_attribute_decl(
1749 dtd,
1750 elem,
1751 attr_name,
1752 XML_ATTRIBUTE_CDATA as c_int,
1753 XML_ATTRIBUTE_FIXED as c_int,
1754 default_val,
1755 ptr::null_mut(),
1756 );
1757 assert!(!attr.is_null());
1758 assert_eq!((*attr).def, XML_ATTRIBUTE_FIXED as c_int);
1759 assert_eq!(string::xml_strcmp((*attr).defaultValue, default_val), 0);
1760
1761 free_dtd(dtd);
1762 allocator::xmlFree(doc as *mut c_void);
1763 }
1764 }
1765
1766 #[test]
1767 fn test_add_attribute_enumeration() {
1768 unsafe {
1769 let (doc, dtd) = make_doc_and_dtd();
1770 let elem_name = c_str(b"elem");
1771 let attr_name = c_str(b"size");
1772
1773 let v3 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1775 as *mut _xmlEnumeration;
1776 (*v3).name = string::xml_strdup(c_str(b"large"));
1777 let v2 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1778 as *mut _xmlEnumeration;
1779 (*v2).name = string::xml_strdup(c_str(b"medium"));
1780 (*v2).next = v3;
1781 let v1 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1782 as *mut _xmlEnumeration;
1783 (*v1).name = string::xml_strdup(c_str(b"small"));
1784 (*v1).next = v2;
1785
1786 let elem = add_element_decl(
1787 dtd,
1788 elem_name,
1789 XML_ELEMENT_TYPE_EMPTY as c_int,
1790 ptr::null_mut(),
1791 );
1792 let attr = add_attribute_decl(
1793 dtd,
1794 elem,
1795 attr_name,
1796 XML_ATTRIBUTE_ENUMERATION as c_int,
1797 XML_ATTRIBUTE_REQUIRED as c_int,
1798 ptr::null(),
1799 v1,
1800 );
1801 assert!(!attr.is_null());
1802 assert_eq!((*attr).atype, XML_ATTRIBUTE_ENUMERATION as c_int);
1803
1804 free_dtd(dtd);
1805 allocator::xmlFree(doc as *mut c_void);
1806 }
1807 }
1808
1809 #[test]
1810 fn test_add_attribute_null_dtd() {
1811 unsafe {
1812 let attr = add_attribute_decl(
1813 ptr::null_mut(),
1814 ptr::null_mut(),
1815 c_str(b"test"),
1816 XML_ATTRIBUTE_CDATA as c_int,
1817 XML_ATTRIBUTE_IMPLIED as c_int,
1818 ptr::null(),
1819 ptr::null_mut(),
1820 );
1821 assert!(attr.is_null());
1822 }
1823 }
1824
1825 #[test]
1826 fn test_copy_attribute() {
1827 unsafe {
1828 let (doc, dtd) = make_doc_and_dtd();
1829 let elem_name = c_str(b"elem");
1830 let attr_name = c_str(b"id");
1831 let default_val = c_str(b"default");
1832
1833 let elem = add_element_decl(
1834 dtd,
1835 elem_name,
1836 XML_ELEMENT_TYPE_EMPTY as c_int,
1837 ptr::null_mut(),
1838 );
1839 let attr = add_attribute_decl(
1840 dtd,
1841 elem,
1842 attr_name,
1843 XML_ATTRIBUTE_ID as c_int,
1844 XML_ATTRIBUTE_IMPLIED as c_int,
1845 default_val,
1846 ptr::null_mut(),
1847 );
1848 assert!(!attr.is_null());
1849
1850 let copy = copy_attribute_decl(attr);
1851 assert!(!copy.is_null());
1852 assert_ne!(copy, attr);
1853 assert_eq!((*copy).atype, XML_ATTRIBUTE_ID as c_int);
1854 assert_eq!(string::xml_strcmp((*copy).name, attr_name), 0);
1855
1856 free_attribute(copy);
1857 free_dtd(dtd);
1858 allocator::xmlFree(doc as *mut c_void);
1859 }
1860 }
1861
1862 #[test]
1863 fn test_free_attribute_null() {
1864 unsafe {
1865 free_attribute(ptr::null_mut()); }
1867 }
1868
1869 #[test]
1872 fn test_valid_content_model_null() {
1873 unsafe {
1874 assert_eq!(
1875 valid_content_model(ptr::null_mut(), &[]),
1876 ContentModelResult::Invalid
1877 );
1878 }
1879 }
1880
1881 #[test]
1882 fn test_valid_content_model_pcdata() {
1883 unsafe {
1884 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1885 assert!(!cm.is_null());
1886
1887 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Valid);
1889
1890 let name = c_str(b"child");
1892 assert_eq!(
1893 valid_content_model(cm, &[name]),
1894 ContentModelResult::Invalid
1895 );
1896
1897 free_content_model(cm);
1898 }
1899 }
1900
1901 #[test]
1902 fn test_valid_content_model_element() {
1903 unsafe {
1904 let child_name = c_str(b"child");
1905 let cm = create_content_model(child_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1906 assert!(!cm.is_null());
1907
1908 assert_eq!(
1910 valid_content_model(cm, &[child_name]),
1911 ContentModelResult::Valid
1912 );
1913
1914 let other = c_str(b"other");
1916 assert_eq!(
1917 valid_content_model(cm, &[other]),
1918 ContentModelResult::Invalid
1919 );
1920
1921 assert_eq!(
1923 valid_content_model(cm, &[child_name, child_name]),
1924 ContentModelResult::Invalid
1925 );
1926
1927 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Invalid);
1929
1930 free_content_model(cm);
1931 }
1932 }
1933
1934 #[test]
1935 fn test_valid_content_model_seq() {
1936 unsafe {
1937 let a_name = c_str(b"a");
1938 let b_name = c_str(b"b");
1939
1940 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1941 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1942 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1943 (*seq).c1 = c1;
1944 (*seq).c2 = c2;
1945 (*c1).parent = seq;
1946 (*c2).parent = seq;
1947
1948 assert_eq!(
1950 valid_content_model(seq, &[a_name, b_name]),
1951 ContentModelResult::Valid
1952 );
1953
1954 assert_eq!(
1956 valid_content_model(seq, &[b_name, a_name]),
1957 ContentModelResult::Invalid
1958 );
1959
1960 assert_eq!(
1962 valid_content_model(seq, &[a_name]),
1963 ContentModelResult::Invalid
1964 );
1965
1966 free_content_model(seq);
1967 }
1968 }
1969
1970 #[test]
1971 fn test_valid_content_model_or() {
1972 unsafe {
1973 let a_name = c_str(b"a");
1974 let b_name = c_str(b"b");
1975
1976 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1977 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1978 let choice = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_OR as c_int);
1979 (*choice).c1 = c1;
1980 (*choice).c2 = c2;
1981 (*c1).parent = choice;
1982 (*c2).parent = choice;
1983
1984 assert_eq!(
1986 valid_content_model(choice, &[a_name]),
1987 ContentModelResult::Valid
1988 );
1989
1990 assert_eq!(
1992 valid_content_model(choice, &[b_name]),
1993 ContentModelResult::Valid
1994 );
1995
1996 let other = c_str(b"other");
1998 assert_eq!(
1999 valid_content_model(choice, &[other]),
2000 ContentModelResult::Invalid
2001 );
2002
2003 free_content_model(choice);
2004 }
2005 }
2006
2007 #[test]
2008 fn test_valid_content_model_optional() {
2009 unsafe {
2010 let a_name = c_str(b"a");
2011
2012 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2013 (*c1).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
2014
2015 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2017
2018 assert_eq!(
2020 valid_content_model(c1, &[a_name]),
2021 ContentModelResult::Valid
2022 );
2023
2024 free_content_model(c1);
2025 }
2026 }
2027
2028 #[test]
2029 fn test_valid_content_model_zero_or_more() {
2030 unsafe {
2031 let a_name = c_str(b"a");
2032
2033 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2034 (*c1).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2035
2036 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2038
2039 assert_eq!(
2041 valid_content_model(c1, &[a_name]),
2042 ContentModelResult::Valid
2043 );
2044
2045 assert_eq!(
2047 valid_content_model(c1, &[a_name, a_name, a_name]),
2048 ContentModelResult::Valid
2049 );
2050
2051 free_content_model(c1);
2052 }
2053 }
2054
2055 #[test]
2056 fn test_valid_content_model_one_or_more() {
2057 unsafe {
2058 let a_name = c_str(b"a");
2059
2060 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2061 (*c1).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2062
2063 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Invalid);
2065
2066 assert_eq!(
2068 valid_content_model(c1, &[a_name]),
2069 ContentModelResult::Valid
2070 );
2071
2072 assert_eq!(
2074 valid_content_model(c1, &[a_name, a_name]),
2075 ContentModelResult::Valid
2076 );
2077
2078 free_content_model(c1);
2079 }
2080 }
2081}