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).content = content; (*elem).attributes = ptr::null_mut();
647 (*elem).prefix = ptr::null_mut();
648 (*elem).next = ptr::null_mut();
649 (*elem)._private = 0;
650
651 let ret = hash::hash_add_entry(
653 d.elements as *mut hash::HashTable,
654 name,
655 elem as *mut c_void,
656 );
657 if ret != 0 {
658 free_element(elem);
660 return ptr::null_mut();
661 }
662
663 elem
664 }
665}
666
667pub unsafe fn get_element_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlElement {
680 if dtd.is_null() || name.is_null() {
681 return ptr::null_mut();
682 }
683
684 unsafe {
685 let d = &*dtd;
686 let payload = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
687 payload as *mut _xmlElement
688 }
689}
690
691pub unsafe fn copy_element(elem: *mut _xmlElement) -> *mut _xmlElement {
703 if elem.is_null() {
704 return ptr::null_mut();
705 }
706
707 unsafe {
708 let e = &*elem;
709
710 let copy = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
712 if copy.is_null() {
713 return ptr::null_mut();
714 }
715
716 (*copy).name = string::xml_strdup(e.name);
717 (*copy).type_ = e.type_;
718 (*copy).content = copy_content_model(e.content);
719 (*copy).prefix = string::xml_strdup(e.prefix);
720 (*copy)._private = e._private;
721
722 if !e.attributes.is_null() {
724 let mut src_attr = e.attributes;
727 let mut prev_copy: *mut _xmlAttribute = ptr::null_mut();
728 let mut first_copy: *mut _xmlAttribute = ptr::null_mut();
729
730 while !src_attr.is_null() {
731 let attr_copy = copy_attribute_decl(src_attr);
732 if attr_copy.is_null() {
733 let mut to_free = first_copy;
735 while !to_free.is_null() {
736 let next = (*to_free).nexth;
737 free_attribute(to_free);
738 to_free = next;
739 }
740 allocator::xmlFree(copy as *mut c_void);
741 return ptr::null_mut();
742 }
743
744 if prev_copy.is_null() {
745 first_copy = attr_copy;
746 } else {
747 (*prev_copy).nexth = attr_copy;
748 }
749 prev_copy = attr_copy;
750 src_attr = (*src_attr).nexth;
751 }
752
753 (*copy).attributes = first_copy;
754 }
755
756 copy
757 }
758}
759
760pub unsafe fn free_element(elem: *mut _xmlElement) {
775 if elem.is_null() {
776 return;
777 }
778
779 unsafe {
780 if !(*elem).name.is_null() {
782 allocator::xmlFree((*elem).name as *mut c_void);
783 }
784
785 if !(*elem).prefix.is_null() {
787 allocator::xmlFree((*elem).prefix as *mut c_void);
788 }
789
790 if !(*elem).content.is_null() {
792 free_content_model((*elem).content);
793 }
794
795 (*elem).attributes = ptr::null_mut();
801
802 allocator::xmlFree(elem as *mut c_void);
803 }
804}
805
806unsafe fn free_enumeration(tree: *mut _xmlEnumeration) {
816 if tree.is_null() {
817 return;
818 }
819
820 unsafe {
821 let mut cur = tree;
822 while !cur.is_null() {
823 let next = (*cur).next;
824 if !(*cur).name.is_null() {
825 allocator::xmlFree((*cur).name as *mut c_void);
826 }
827 allocator::xmlFree(cur as *mut c_void);
828 cur = next;
829 }
830 }
831}
832
833unsafe fn copy_enumeration(tree: *mut _xmlEnumeration) -> *mut _xmlEnumeration {
839 if tree.is_null() {
840 return ptr::null_mut();
841 }
842
843 unsafe {
844 let mut src = tree;
845 let mut first_copy: *mut _xmlEnumeration = ptr::null_mut();
846 let mut prev_copy: *mut _xmlEnumeration = ptr::null_mut();
847
848 while !src.is_null() {
849 let copy = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
850 as *mut _xmlEnumeration;
851 if copy.is_null() {
852 let mut to_free = first_copy;
854 while !to_free.is_null() {
855 let next = (*to_free).next;
856 if !(*to_free).name.is_null() {
857 allocator::xmlFree((*to_free).name as *mut c_void);
858 }
859 allocator::xmlFree(to_free as *mut c_void);
860 to_free = next;
861 }
862 return ptr::null_mut();
863 }
864
865 (*copy).name = string::xml_strdup((*src).name);
866 (*copy).next = ptr::null_mut();
867
868 if prev_copy.is_null() {
869 first_copy = copy;
870 } else {
871 (*prev_copy).next = copy;
872 }
873 prev_copy = copy;
874 src = (*src).next;
875 }
876
877 first_copy
878 }
879}
880
881pub unsafe fn add_attribute_decl(
903 dtd: *mut _xmlDtd,
904 elem: *mut _xmlElement,
905 name: *const xmlChar,
906 type_: c_int,
907 def: c_int,
908 defaultValue: *const xmlChar,
909 tree: *mut _xmlEnumeration,
910) -> *mut _xmlAttribute {
911 if dtd.is_null() || name.is_null() {
912 return ptr::null_mut();
913 }
914
915 unsafe {
916 let d = &*dtd;
917 let elem_name = if elem.is_null() {
918 ptr::null()
919 } else {
920 (*elem).name
921 };
922
923 let existing = hash::hash_lookup2(d.attributes as *mut hash::HashTable, elem_name, name);
925 if !existing.is_null() {
926 return existing as *mut _xmlAttribute;
927 }
928
929 let attr =
931 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
932 if attr.is_null() {
933 return ptr::null_mut();
934 }
935
936 (*attr).type_ = XML_ATTRIBUTE_DECL as c_int;
937 (*attr).name = string::xml_strdup(name);
938 (*attr).parent = dtd;
939 (*attr).doc = d.doc;
940 (*attr).nexth = ptr::null_mut();
941 (*attr).atype = type_;
942 (*attr).def = def;
943 (*attr).defaultValue = string::xml_strdup(defaultValue);
944 (*attr).tree = tree; (*attr).prefix = ptr::null_mut();
946 (*attr).elem = string::xml_strdup(elem_name);
947
948 let ret = hash::hash_add_entry2(
950 d.attributes as *mut hash::HashTable,
951 elem_name,
952 name,
953 attr as *mut c_void,
954 );
955 if ret != 0 {
956 if !(*attr).defaultValue.is_null() {
958 allocator::xmlFree((*attr).defaultValue as *mut c_void);
959 }
960 if !(*attr).name.is_null() {
961 allocator::xmlFree((*attr).name as *mut c_void);
962 }
963 if !(*attr).elem.is_null() {
964 allocator::xmlFree((*attr).elem as *mut c_void);
965 }
966 allocator::xmlFree(attr as *mut c_void);
967 return ptr::null_mut();
969 }
970
971 if !elem.is_null() {
973 (*attr).nexth = (*elem).attributes;
974 (*elem).attributes = attr;
975 }
976
977 attr
978 }
979}
980
981pub unsafe fn get_attribute_decl(
999 dtd: *mut _xmlDtd,
1000 elem: *mut _xmlElement,
1001 name: *const xmlChar,
1002 _namePrefix: c_int,
1003) -> *mut _xmlAttribute {
1004 if dtd.is_null() || name.is_null() {
1005 return ptr::null_mut();
1006 }
1007
1008 unsafe {
1009 let d = &*dtd;
1010 let elem_name = if elem.is_null() {
1011 ptr::null()
1012 } else {
1013 (*elem).name
1014 };
1015
1016 let payload = hash::hash_lookup2(d.attributes as *mut hash::HashTable, elem_name, name);
1017 payload as *mut _xmlAttribute
1018 }
1019}
1020
1021pub unsafe fn copy_attribute_decl(attr: *mut _xmlAttribute) -> *mut _xmlAttribute {
1033 if attr.is_null() {
1034 return ptr::null_mut();
1035 }
1036
1037 unsafe {
1038 let a = &*attr;
1039
1040 let copy =
1042 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
1043 if copy.is_null() {
1044 return ptr::null_mut();
1045 }
1046
1047 (*copy).type_ = a.type_;
1048 (*copy).name = string::xml_strdup(a.name);
1049 (*copy).parent = a.parent;
1050 (*copy).doc = a.doc;
1051 (*copy).nexth = ptr::null_mut();
1052 (*copy).atype = a.atype;
1053 (*copy).def = a.def;
1054 (*copy).defaultValue = string::xml_strdup(a.defaultValue);
1055 (*copy).tree = copy_enumeration(a.tree);
1056 (*copy).prefix = string::xml_strdup(a.prefix);
1057 (*copy).elem = string::xml_strdup(a.elem);
1058
1059 copy
1060 }
1061}
1062
1063pub unsafe fn free_attribute(attr: *mut _xmlAttribute) {
1075 if attr.is_null() {
1076 return;
1077 }
1078
1079 unsafe {
1080 let a = &*attr;
1081
1082 if !a.name.is_null() {
1083 allocator::xmlFree(a.name as *mut c_void);
1084 }
1085 if !a.defaultValue.is_null() {
1086 allocator::xmlFree(a.defaultValue as *mut c_void);
1087 }
1088 if !a.prefix.is_null() {
1089 allocator::xmlFree(a.prefix as *mut c_void);
1090 }
1091 if !a.elem.is_null() {
1092 allocator::xmlFree(a.elem as *mut c_void);
1093 }
1094 if !a.tree.is_null() {
1095 free_enumeration(a.tree);
1096 }
1097
1098 allocator::xmlFree(attr as *mut c_void);
1099 }
1100}
1101
1102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1108pub enum ContentModelResult {
1109 Valid,
1111 Invalid,
1113 Indeterminate,
1115}
1116
1117pub unsafe fn valid_content_model(
1138 model: *mut _xmlElementContent,
1139 names: &[*const xmlChar],
1140) -> ContentModelResult {
1141 if model.is_null() {
1142 return ContentModelResult::Invalid;
1143 }
1144
1145 unsafe {
1146 let m = &*model;
1147
1148 match m.ocur as u32 {
1150 o if o == XML_ELEMENT_CONTENT_OPT as u32 => {
1151 if names.is_empty() {
1153 return ContentModelResult::Valid;
1154 }
1155 return valid_content_model_inner(model, names);
1156 }
1157 o if o == XML_ELEMENT_CONTENT_MULT as u32 => {
1158 if names.is_empty() {
1160 return ContentModelResult::Valid;
1161 }
1162 return valid_content_model_zero_or_more(model, names);
1163 }
1164 o if o == XML_ELEMENT_CONTENT_PLUS as u32 => {
1165 if names.is_empty() {
1167 return ContentModelResult::Invalid;
1168 }
1169 return valid_content_model_one_or_more(model, names);
1170 }
1171 _ => {}
1172 }
1173
1174 valid_content_model_inner(model, names)
1175 }
1176}
1177
1178unsafe fn valid_content_model_inner(
1180 model: *mut _xmlElementContent,
1181 names: &[*const xmlChar],
1182) -> ContentModelResult {
1183 unsafe {
1184 let m = &*model;
1185
1186 match m.type_ as u32 {
1187 t if t == XML_ELEMENT_CONTENT_PCDATA as u32 => {
1188 if names.is_empty() {
1190 ContentModelResult::Valid
1191 } else {
1192 ContentModelResult::Invalid
1193 }
1194 }
1195 t if t == XML_ELEMENT_CONTENT_ELEMENT as u32 => {
1196 if names.len() != 1 {
1198 return ContentModelResult::Invalid;
1199 }
1200 if names[0].is_null() {
1201 return ContentModelResult::Invalid;
1202 }
1203 if string::xml_strcmp(names[0], m.name) != 0 {
1205 return ContentModelResult::Invalid;
1206 }
1207 ContentModelResult::Valid
1208 }
1209 t if t == XML_ELEMENT_CONTENT_SEQ as u32 => {
1210 valid_content_model_seq(m, names)
1212 }
1213 t if t == XML_ELEMENT_CONTENT_OR as u32 => {
1214 valid_content_model_or(m, names)
1216 }
1217 _ => ContentModelResult::Invalid,
1218 }
1219 }
1220}
1221
1222unsafe fn valid_content_model_zero_or_more(
1224 model: *mut _xmlElementContent,
1225 names: &[*const xmlChar],
1226) -> ContentModelResult {
1227 let mut i = 0;
1229 while i <= names.len() {
1230 let consumed = &names[..i];
1231 let remaining = &names[i..];
1232
1233 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1234 if consumed_valid == ContentModelResult::Valid {
1235 if remaining.is_empty() {
1236 return ContentModelResult::Valid;
1237 }
1238 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1240 if remaining_valid == ContentModelResult::Valid {
1241 return ContentModelResult::Valid;
1242 }
1243 }
1244
1245 i += 1;
1246 }
1247 ContentModelResult::Invalid
1248}
1249
1250unsafe fn valid_content_model_one_or_more(
1252 model: *mut _xmlElementContent,
1253 names: &[*const xmlChar],
1254) -> ContentModelResult {
1255 let mut i = 1;
1257 while i <= names.len() {
1258 let consumed = &names[..i];
1259 let remaining = &names[i..];
1260
1261 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1262 if consumed_valid == ContentModelResult::Valid {
1263 if remaining.is_empty() {
1264 return ContentModelResult::Valid;
1265 }
1266 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1267 if remaining_valid == ContentModelResult::Valid {
1268 return ContentModelResult::Valid;
1269 }
1270 }
1271
1272 i += 1;
1273 }
1274 ContentModelResult::Invalid
1275}
1276
1277unsafe fn valid_content_model_seq(
1279 model: &_xmlElementContent,
1280 names: &[*const xmlChar],
1281) -> ContentModelResult {
1282 let c1 = model.c1;
1287 let c2 = model.c2;
1288
1289 if c1.is_null() && c2.is_null() {
1290 return ContentModelResult::Valid;
1291 }
1292
1293 if c1.is_null() {
1294 return unsafe { valid_content_model(c2, names) };
1295 }
1296
1297 if c2.is_null() {
1298 return unsafe { valid_content_model(c1, names) };
1299 }
1300
1301 for split in 0..=names.len() {
1304 let left = &names[..split];
1305 let right = &names[split..];
1306
1307 let left_valid = unsafe { valid_content_model(c1, left) };
1308 if left_valid != ContentModelResult::Valid {
1309 continue;
1310 }
1311
1312 let right_valid = unsafe { valid_content_model(c2, right) };
1313 if right_valid == ContentModelResult::Valid {
1314 return ContentModelResult::Valid;
1315 }
1316 }
1317
1318 ContentModelResult::Invalid
1319}
1320
1321unsafe fn valid_content_model_or(
1323 model: &_xmlElementContent,
1324 names: &[*const xmlChar],
1325) -> ContentModelResult {
1326 let c1 = model.c1;
1327 let c2 = model.c2;
1328
1329 if c1.is_null() && c2.is_null() {
1330 return ContentModelResult::Invalid;
1331 }
1332
1333 if !c1.is_null() {
1334 let result = unsafe { valid_content_model(c1, names) };
1335 if result == ContentModelResult::Valid {
1336 return ContentModelResult::Valid;
1337 }
1338 }
1339
1340 if !c2.is_null() {
1341 let result = unsafe { valid_content_model(c2, names) };
1342 if result == ContentModelResult::Valid {
1343 return ContentModelResult::Valid;
1344 }
1345 }
1346
1347 ContentModelResult::Invalid
1348}
1349
1350#[cfg(test)]
1355mod tests {
1356 use super::*;
1357 use crate::abi::allocator::xmlFree;
1358 use crate::abi::structs::*;
1359 use core::ffi::c_void;
1360 use core::ptr;
1361
1362 unsafe fn c_str(s: &[u8]) -> *const xmlChar {
1365 let len = s.len();
1367 let buf = allocator::xmlMalloc(len + 1) as *mut xmlChar;
1368 assert!(!buf.is_null());
1369 ptr::copy_nonoverlapping(s.as_ptr(), buf, len);
1370 *buf.add(len) = 0;
1371 buf as *const xmlChar
1372 }
1373
1374 unsafe fn make_doc_and_dtd() -> (*mut _xmlDoc, *mut _xmlDtd) {
1375 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1376 assert!(!doc.is_null());
1377 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1378 (*doc).doc = doc;
1379 let dtd = create_int_subset(doc, c_str(b"root"), ptr::null(), ptr::null());
1380 assert!(!dtd.is_null());
1381 (doc, dtd)
1382 }
1383
1384 #[test]
1387 fn test_get_int_subset_null() {
1388 unsafe {
1389 assert!(get_int_subset(ptr::null()).is_null());
1390 }
1391 }
1392
1393 #[test]
1394 fn test_create_int_subset() {
1395 unsafe {
1396 let (doc, dtd) = make_doc_and_dtd();
1397 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1398 assert!(!(*dtd).name.is_null());
1399 assert_eq!((*doc).intSubset, dtd);
1400
1401 free_dtd(dtd);
1403 allocator::xmlFree(doc as *mut c_void);
1404 }
1405 }
1406
1407 #[test]
1408 fn test_create_int_subset_null_doc() {
1409 unsafe {
1410 let dtd = create_int_subset(ptr::null_mut(), c_str(b"root"), ptr::null(), ptr::null());
1411 assert!(dtd.is_null());
1412 }
1413 }
1414
1415 #[test]
1416 fn test_new_dtd() {
1417 unsafe {
1418 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1419 assert!(!doc.is_null());
1420 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1421 (*doc).doc = doc;
1422
1423 let dtd = new_dtd(doc, c_str(b"test"), c_str(b"-//TEST//"), c_str(b"test.dtd"));
1424 assert!(!dtd.is_null());
1425 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1426 assert_eq!((*doc).intSubset, dtd);
1427
1428 free_dtd(dtd);
1429 allocator::xmlFree(doc as *mut c_void);
1430 }
1431 }
1432
1433 #[test]
1434 fn test_new_dtd_no_doc() {
1435 unsafe {
1436 let dtd = new_dtd(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1437 assert!(!dtd.is_null());
1438 free_dtd(dtd);
1439 }
1440 }
1441
1442 #[test]
1445 fn test_add_get_notation() {
1446 unsafe {
1447 let (doc, dtd) = make_doc_and_dtd();
1448 let name = c_str(b"note");
1449 let pubid = c_str(b"-//TEST//NOTATION");
1450 let sysid = c_str(b"note.ent");
1451
1452 let n = add_notation_decl(dtd, name, pubid, sysid);
1453 assert!(!n.is_null());
1454 assert_eq!(string::xml_strcmp((*n).name, name), 0);
1455
1456 let found = get_notation_decl(dtd, name);
1458 assert_eq!(found, n);
1459
1460 let not_found = get_notation_decl(dtd, c_str(b"nonexistent"));
1462 assert!(not_found.is_null());
1463
1464 free_dtd(dtd);
1465 allocator::xmlFree(doc as *mut c_void);
1466 }
1467 }
1468
1469 #[test]
1470 fn test_add_notation_null_dtd() {
1471 unsafe {
1472 let n = add_notation_decl(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1473 assert!(n.is_null());
1474 }
1475 }
1476
1477 #[test]
1478 fn test_copy_notation() {
1479 unsafe {
1480 let (doc, dtd) = make_doc_and_dtd();
1481 let name = c_str(b"note1");
1482 let pubid = c_str(b"public");
1483 let sysid = c_str(b"system");
1484
1485 let n = add_notation_decl(dtd, name, pubid, sysid);
1486 assert!(!n.is_null());
1487
1488 let copy = copy_notation(n);
1489 assert!(!copy.is_null());
1490 assert_ne!(copy, n);
1491 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1492 assert_eq!(string::xml_strcmp((*copy).PublicID, pubid), 0);
1493 assert_eq!(string::xml_strcmp((*copy).SystemID, sysid), 0);
1494
1495 free_notation(copy);
1496 free_dtd(dtd);
1497 allocator::xmlFree(doc as *mut c_void);
1498 }
1499 }
1500
1501 #[test]
1502 fn test_copy_notation_null() {
1503 unsafe {
1504 assert!(copy_notation(ptr::null_mut()).is_null());
1505 }
1506 }
1507
1508 #[test]
1509 fn test_free_notation_null() {
1510 unsafe {
1511 free_notation(ptr::null_mut()); }
1513 }
1514
1515 #[test]
1518 fn test_create_free_content_model() {
1519 unsafe {
1520 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1521 assert!(!cm.is_null());
1522 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1523 assert_eq!((*cm).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1524
1525 free_content_model(cm);
1526 }
1527 }
1528
1529 #[test]
1530 fn test_create_content_model_pcdata() {
1531 unsafe {
1532 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1533 assert!(!cm.is_null());
1534 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_PCDATA as c_int);
1535 free_content_model(cm);
1536 }
1537 }
1538
1539 #[test]
1540 fn test_copy_content_model() {
1541 unsafe {
1542 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1543 assert!(!cm.is_null());
1544
1545 let copy = copy_content_model(cm);
1546 assert!(!copy.is_null());
1547 assert_ne!(copy, cm);
1548 assert_eq!((*copy).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1549 assert_eq!((*copy).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1550 assert_eq!(string::xml_strcmp((*copy).name, (*cm).name), 0);
1551
1552 free_content_model(cm);
1553 free_content_model(copy);
1554 }
1555 }
1556
1557 #[test]
1558 fn test_copy_content_model_null() {
1559 unsafe {
1560 assert!(copy_content_model(ptr::null_mut()).is_null());
1561 }
1562 }
1563
1564 #[test]
1565 fn test_free_content_model_null() {
1566 unsafe {
1567 free_content_model(ptr::null_mut()); }
1569 }
1570
1571 #[test]
1572 fn test_create_sequence_content_model() {
1573 unsafe {
1574 let c1 = create_content_model(c_str(b"a"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1575 let c2 = create_content_model(c_str(b"b"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1576 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1577 assert!(!seq.is_null());
1578 (*seq).c1 = c1;
1579 (*seq).c2 = c2;
1580 (*c1).parent = seq;
1581 (*c2).parent = seq;
1582
1583 free_content_model(seq);
1584 }
1585 }
1586
1587 #[test]
1590 fn test_add_get_element() {
1591 unsafe {
1592 let (doc, dtd) = make_doc_and_dtd();
1593 let name = c_str(b"myElement");
1594
1595 let elem =
1596 add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1597 assert!(!elem.is_null());
1598 assert_eq!((*elem).type_, XML_ELEMENT_TYPE_EMPTY as c_int);
1599
1600 let found = get_element_decl(dtd, name);
1601 assert_eq!(found, elem);
1602
1603 let not_found = get_element_decl(dtd, c_str(b"nonexistent"));
1604 assert!(not_found.is_null());
1605
1606 free_dtd(dtd);
1607 allocator::xmlFree(doc as *mut c_void);
1608 }
1609 }
1610
1611 #[test]
1612 fn test_add_element_duplicate() {
1613 unsafe {
1614 let (doc, dtd) = make_doc_and_dtd();
1615 let name = c_str(b"dup");
1616
1617 let e1 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1618 assert!(!e1.is_null());
1619
1620 let e2 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ANY as c_int, ptr::null_mut());
1621 assert_eq!(e1, e2); assert_eq!((*e2).type_, XML_ELEMENT_TYPE_EMPTY as c_int); free_dtd(dtd);
1625 allocator::xmlFree(doc as *mut c_void);
1626 }
1627 }
1628
1629 #[test]
1630 fn test_add_element_null_dtd() {
1631 unsafe {
1632 let elem = add_element_decl(
1633 ptr::null_mut(),
1634 c_str(b"test"),
1635 XML_ELEMENT_TYPE_EMPTY as c_int,
1636 ptr::null_mut(),
1637 );
1638 assert!(elem.is_null());
1639 }
1640 }
1641
1642 #[test]
1643 fn test_copy_element() {
1644 unsafe {
1645 let (doc, dtd) = make_doc_and_dtd();
1646 let name = c_str(b"source");
1647 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1648
1649 let elem = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ELEMENT as c_int, cm);
1650 assert!(!elem.is_null());
1651
1652 let copy = copy_element(elem);
1653 assert!(!copy.is_null());
1654 assert_ne!(copy, elem);
1655 assert_eq!((*copy).type_, XML_ELEMENT_TYPE_ELEMENT as c_int);
1656 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1657 assert!(!(*copy).content.is_null());
1658 assert_ne!((*copy).content, cm);
1659
1660 free_element(copy);
1661 free_dtd(dtd);
1662 allocator::xmlFree(doc as *mut c_void);
1663 }
1664 }
1665
1666 #[test]
1667 fn test_free_element_null() {
1668 unsafe {
1669 free_element(ptr::null_mut()); }
1671 }
1672
1673 #[test]
1676 fn test_add_get_attribute() {
1677 unsafe {
1678 let (doc, dtd) = make_doc_and_dtd();
1679 let elem_name = c_str(b"elem");
1680 let attr_name = c_str(b"attr1");
1681
1682 let elem = add_element_decl(
1683 dtd,
1684 elem_name,
1685 XML_ELEMENT_TYPE_EMPTY as c_int,
1686 ptr::null_mut(),
1687 );
1688 assert!(!elem.is_null());
1689
1690 let attr = add_attribute_decl(
1691 dtd,
1692 elem,
1693 attr_name,
1694 XML_ATTRIBUTE_CDATA as c_int,
1695 XML_ATTRIBUTE_IMPLIED as c_int,
1696 ptr::null(),
1697 ptr::null_mut(),
1698 );
1699 assert!(!attr.is_null());
1700 assert_eq!((*attr).atype, XML_ATTRIBUTE_CDATA as c_int);
1701 assert_eq!((*attr).def, XML_ATTRIBUTE_IMPLIED as c_int);
1702
1703 let found = get_attribute_decl(dtd, elem, attr_name, 0);
1705 assert_eq!(found, attr);
1706
1707 let not_found = get_attribute_decl(dtd, elem, c_str(b"nonexistent"), 0);
1709 assert!(not_found.is_null());
1710
1711 free_dtd(dtd);
1712 allocator::xmlFree(doc as *mut c_void);
1713 }
1714 }
1715
1716 #[test]
1717 fn test_add_attribute_with_default() {
1718 unsafe {
1719 let (doc, dtd) = make_doc_and_dtd();
1720 let elem_name = c_str(b"elem");
1721 let attr_name = c_str(b"color");
1722 let default_val = c_str(b"red");
1723
1724 let elem = add_element_decl(
1725 dtd,
1726 elem_name,
1727 XML_ELEMENT_TYPE_EMPTY as c_int,
1728 ptr::null_mut(),
1729 );
1730
1731 let attr = add_attribute_decl(
1732 dtd,
1733 elem,
1734 attr_name,
1735 XML_ATTRIBUTE_CDATA as c_int,
1736 XML_ATTRIBUTE_FIXED as c_int,
1737 default_val,
1738 ptr::null_mut(),
1739 );
1740 assert!(!attr.is_null());
1741 assert_eq!((*attr).def, XML_ATTRIBUTE_FIXED as c_int);
1742 assert_eq!(string::xml_strcmp((*attr).defaultValue, default_val), 0);
1743
1744 free_dtd(dtd);
1745 allocator::xmlFree(doc as *mut c_void);
1746 }
1747 }
1748
1749 #[test]
1750 fn test_add_attribute_enumeration() {
1751 unsafe {
1752 let (doc, dtd) = make_doc_and_dtd();
1753 let elem_name = c_str(b"elem");
1754 let attr_name = c_str(b"size");
1755
1756 let v3 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1758 as *mut _xmlEnumeration;
1759 (*v3).name = string::xml_strdup(c_str(b"large"));
1760 let v2 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1761 as *mut _xmlEnumeration;
1762 (*v2).name = string::xml_strdup(c_str(b"medium"));
1763 (*v2).next = v3;
1764 let v1 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1765 as *mut _xmlEnumeration;
1766 (*v1).name = string::xml_strdup(c_str(b"small"));
1767 (*v1).next = v2;
1768
1769 let elem = add_element_decl(
1770 dtd,
1771 elem_name,
1772 XML_ELEMENT_TYPE_EMPTY as c_int,
1773 ptr::null_mut(),
1774 );
1775 let attr = add_attribute_decl(
1776 dtd,
1777 elem,
1778 attr_name,
1779 XML_ATTRIBUTE_ENUMERATION as c_int,
1780 XML_ATTRIBUTE_REQUIRED as c_int,
1781 ptr::null(),
1782 v1,
1783 );
1784 assert!(!attr.is_null());
1785 assert_eq!((*attr).atype, XML_ATTRIBUTE_ENUMERATION as c_int);
1786
1787 free_dtd(dtd);
1788 allocator::xmlFree(doc as *mut c_void);
1789 }
1790 }
1791
1792 #[test]
1793 fn test_add_attribute_null_dtd() {
1794 unsafe {
1795 let attr = add_attribute_decl(
1796 ptr::null_mut(),
1797 ptr::null_mut(),
1798 c_str(b"test"),
1799 XML_ATTRIBUTE_CDATA as c_int,
1800 XML_ATTRIBUTE_IMPLIED as c_int,
1801 ptr::null(),
1802 ptr::null_mut(),
1803 );
1804 assert!(attr.is_null());
1805 }
1806 }
1807
1808 #[test]
1809 fn test_copy_attribute() {
1810 unsafe {
1811 let (doc, dtd) = make_doc_and_dtd();
1812 let elem_name = c_str(b"elem");
1813 let attr_name = c_str(b"id");
1814 let default_val = c_str(b"default");
1815
1816 let elem = add_element_decl(
1817 dtd,
1818 elem_name,
1819 XML_ELEMENT_TYPE_EMPTY as c_int,
1820 ptr::null_mut(),
1821 );
1822 let attr = add_attribute_decl(
1823 dtd,
1824 elem,
1825 attr_name,
1826 XML_ATTRIBUTE_ID as c_int,
1827 XML_ATTRIBUTE_IMPLIED as c_int,
1828 default_val,
1829 ptr::null_mut(),
1830 );
1831 assert!(!attr.is_null());
1832
1833 let copy = copy_attribute_decl(attr);
1834 assert!(!copy.is_null());
1835 assert_ne!(copy, attr);
1836 assert_eq!((*copy).atype, XML_ATTRIBUTE_ID as c_int);
1837 assert_eq!(string::xml_strcmp((*copy).name, attr_name), 0);
1838
1839 free_attribute(copy);
1840 free_dtd(dtd);
1841 allocator::xmlFree(doc as *mut c_void);
1842 }
1843 }
1844
1845 #[test]
1846 fn test_free_attribute_null() {
1847 unsafe {
1848 free_attribute(ptr::null_mut()); }
1850 }
1851
1852 #[test]
1855 fn test_valid_content_model_null() {
1856 unsafe {
1857 assert_eq!(
1858 valid_content_model(ptr::null_mut(), &[]),
1859 ContentModelResult::Invalid
1860 );
1861 }
1862 }
1863
1864 #[test]
1865 fn test_valid_content_model_pcdata() {
1866 unsafe {
1867 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1868 assert!(!cm.is_null());
1869
1870 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Valid);
1872
1873 let name = c_str(b"child");
1875 assert_eq!(
1876 valid_content_model(cm, &[name]),
1877 ContentModelResult::Invalid
1878 );
1879
1880 free_content_model(cm);
1881 }
1882 }
1883
1884 #[test]
1885 fn test_valid_content_model_element() {
1886 unsafe {
1887 let child_name = c_str(b"child");
1888 let cm = create_content_model(child_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1889 assert!(!cm.is_null());
1890
1891 assert_eq!(
1893 valid_content_model(cm, &[child_name]),
1894 ContentModelResult::Valid
1895 );
1896
1897 let other = c_str(b"other");
1899 assert_eq!(
1900 valid_content_model(cm, &[other]),
1901 ContentModelResult::Invalid
1902 );
1903
1904 assert_eq!(
1906 valid_content_model(cm, &[child_name, child_name]),
1907 ContentModelResult::Invalid
1908 );
1909
1910 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Invalid);
1912
1913 free_content_model(cm);
1914 }
1915 }
1916
1917 #[test]
1918 fn test_valid_content_model_seq() {
1919 unsafe {
1920 let a_name = c_str(b"a");
1921 let b_name = c_str(b"b");
1922
1923 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1924 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1925 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1926 (*seq).c1 = c1;
1927 (*seq).c2 = c2;
1928 (*c1).parent = seq;
1929 (*c2).parent = seq;
1930
1931 assert_eq!(
1933 valid_content_model(seq, &[a_name, b_name]),
1934 ContentModelResult::Valid
1935 );
1936
1937 assert_eq!(
1939 valid_content_model(seq, &[b_name, a_name]),
1940 ContentModelResult::Invalid
1941 );
1942
1943 assert_eq!(
1945 valid_content_model(seq, &[a_name]),
1946 ContentModelResult::Invalid
1947 );
1948
1949 free_content_model(seq);
1950 }
1951 }
1952
1953 #[test]
1954 fn test_valid_content_model_or() {
1955 unsafe {
1956 let a_name = c_str(b"a");
1957 let b_name = c_str(b"b");
1958
1959 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1960 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1961 let choice = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_OR as c_int);
1962 (*choice).c1 = c1;
1963 (*choice).c2 = c2;
1964 (*c1).parent = choice;
1965 (*c2).parent = choice;
1966
1967 assert_eq!(
1969 valid_content_model(choice, &[a_name]),
1970 ContentModelResult::Valid
1971 );
1972
1973 assert_eq!(
1975 valid_content_model(choice, &[b_name]),
1976 ContentModelResult::Valid
1977 );
1978
1979 let other = c_str(b"other");
1981 assert_eq!(
1982 valid_content_model(choice, &[other]),
1983 ContentModelResult::Invalid
1984 );
1985
1986 free_content_model(choice);
1987 }
1988 }
1989
1990 #[test]
1991 fn test_valid_content_model_optional() {
1992 unsafe {
1993 let a_name = c_str(b"a");
1994
1995 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1996 (*c1).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
1997
1998 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2000
2001 assert_eq!(
2003 valid_content_model(c1, &[a_name]),
2004 ContentModelResult::Valid
2005 );
2006
2007 free_content_model(c1);
2008 }
2009 }
2010
2011 #[test]
2012 fn test_valid_content_model_zero_or_more() {
2013 unsafe {
2014 let a_name = c_str(b"a");
2015
2016 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2017 (*c1).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2018
2019 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2021
2022 assert_eq!(
2024 valid_content_model(c1, &[a_name]),
2025 ContentModelResult::Valid
2026 );
2027
2028 assert_eq!(
2030 valid_content_model(c1, &[a_name, a_name, a_name]),
2031 ContentModelResult::Valid
2032 );
2033
2034 free_content_model(c1);
2035 }
2036 }
2037
2038 #[test]
2039 fn test_valid_content_model_one_or_more() {
2040 unsafe {
2041 let a_name = c_str(b"a");
2042
2043 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2044 (*c1).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2045
2046 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Invalid);
2048
2049 assert_eq!(
2051 valid_content_model(c1, &[a_name]),
2052 ContentModelResult::Valid
2053 );
2054
2055 assert_eq!(
2057 valid_content_model(c1, &[a_name, a_name]),
2058 ContentModelResult::Valid
2059 );
2060
2061 free_content_model(c1);
2062 }
2063 }
2064}