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
152pub unsafe fn free_dtd(dtd: *mut _xmlDtd) {
164 if dtd.is_null() {
165 return;
166 }
167
168 unsafe {
169 let d = &mut *dtd;
170
171 if !d.notations.is_null() {
173 hash::hash_free(
174 d.notations as *mut hash::HashTable,
175 Some(notation_deallocator),
176 );
177 d.notations = ptr::null_mut();
178 }
179 if !d.elements.is_null() {
180 hash::hash_free(
181 d.elements as *mut hash::HashTable,
182 Some(element_deallocator),
183 );
184 d.elements = ptr::null_mut();
185 }
186 if !d.attributes.is_null() {
187 hash::hash_free(
188 d.attributes as *mut hash::HashTable,
189 Some(attribute_deallocator),
190 );
191 d.attributes = ptr::null_mut();
192 }
193 if !d.entities.is_null() {
194 hash::hash_free(d.entities as *mut hash::HashTable, Some(entity_deallocator));
195 d.entities = ptr::null_mut();
196 }
197 if !d.pentities.is_null() {
198 hash::hash_free(
199 d.pentities as *mut hash::HashTable,
200 Some(entity_deallocator),
201 );
202 d.pentities = ptr::null_mut();
203 }
204
205 if !d.name.is_null() {
207 allocator::xmlFree(d.name as *mut c_void);
208 }
209 if !d.ExternalID.is_null() {
210 allocator::xmlFree(d.ExternalID as *mut c_void);
211 }
212 if !d.SystemID.is_null() {
213 allocator::xmlFree(d.SystemID as *mut c_void);
214 }
215
216 if !d.children.is_null() {
218 }
223
224 allocator::xmlFree(dtd as *mut c_void);
225 }
226}
227
228unsafe extern "C" fn notation_deallocator(payload: *mut c_void, _name: *mut u8) {
233 if !payload.is_null() {
234 free_notation(payload as *mut _xmlNotation);
235 }
236}
237
238unsafe extern "C" fn element_deallocator(payload: *mut c_void, _name: *mut u8) {
239 if !payload.is_null() {
240 free_element(payload as *mut _xmlElement);
241 }
242}
243
244unsafe extern "C" fn attribute_deallocator(payload: *mut c_void, _name: *mut u8) {
245 if !payload.is_null() {
246 free_attribute(payload as *mut _xmlAttribute);
247 }
248}
249
250unsafe extern "C" fn entity_deallocator(payload: *mut c_void, _name: *mut u8) {
251 if !payload.is_null() {
252 crate::xml::entities::free_entity(payload as *mut _xmlEntity);
253 }
254}
255
256pub unsafe fn add_notation_decl(
276 dtd: *mut _xmlDtd,
277 name: *const xmlChar,
278 PublicID: *const xmlChar,
279 SystemID: *const xmlChar,
280) -> *mut _xmlNotation {
281 if dtd.is_null() || name.is_null() {
282 return ptr::null_mut();
283 }
284
285 unsafe {
286 let d = &*dtd;
287
288 let existing = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
290 if !existing.is_null() {
291 return existing as *mut _xmlNotation;
292 }
293
294 let not = allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
296 if not.is_null() {
297 return ptr::null_mut();
298 }
299
300 (*not).name = string::xml_strdup(name);
301 (*not).PublicID = string::xml_strdup(PublicID);
302 (*not).SystemID = string::xml_strdup(SystemID);
303
304 let ret = hash::hash_add_entry(
306 d.notations as *mut hash::HashTable,
307 name,
308 not as *mut c_void,
309 );
310 if ret != 0 {
311 free_notation(not);
313 return ptr::null_mut();
314 }
315
316 not
317 }
318}
319
320pub unsafe fn get_notation_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlNotation {
333 if dtd.is_null() || name.is_null() {
334 return ptr::null_mut();
335 }
336
337 unsafe {
338 let d = &*dtd;
339 let payload = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
340 payload as *mut _xmlNotation
341 }
342}
343
344pub unsafe fn copy_notation(notation: *mut _xmlNotation) -> *mut _xmlNotation {
356 if notation.is_null() {
357 return ptr::null_mut();
358 }
359
360 unsafe {
361 let n = &*notation;
362 let copy =
364 allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
365 if copy.is_null() {
366 return ptr::null_mut();
367 }
368
369 (*copy).name = string::xml_strdup(n.name);
370 (*copy).PublicID = string::xml_strdup(n.PublicID);
371 (*copy).SystemID = string::xml_strdup(n.SystemID);
372
373 copy
374 }
375}
376
377pub unsafe fn free_notation(notation: *mut _xmlNotation) {
389 if notation.is_null() {
390 return;
391 }
392
393 unsafe {
394 let n = &*notation;
395 if !n.name.is_null() {
396 allocator::xmlFree(n.name as *mut c_void);
397 }
398 if !n.PublicID.is_null() {
399 allocator::xmlFree(n.PublicID as *mut c_void);
400 }
401 if !n.SystemID.is_null() {
402 allocator::xmlFree(n.SystemID as *mut c_void);
403 }
404 allocator::xmlFree(notation as *mut c_void);
405 }
406}
407
408pub unsafe fn create_content_model(name: *const xmlChar, type_: c_int) -> *mut _xmlElementContent {
427 let content = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
429 as *mut _xmlElementContent;
430 if content.is_null() {
431 return ptr::null_mut();
432 }
433
434 unsafe {
435 (*content).type_ = type_;
436 (*content).ocur = XML_ELEMENT_CONTENT_ONCE as c_int;
437 (*content).name = string::xml_strdup(name);
438 (*content).c1 = ptr::null_mut();
439 (*content).c2 = ptr::null_mut();
440 (*content).parent = ptr::null_mut();
441 (*content).prefix = ptr::null_mut();
442 }
443
444 content
445}
446
447pub unsafe fn free_content_model(cur: *mut _xmlElementContent) {
461 if cur.is_null() {
462 return;
463 }
464
465 unsafe {
466 let c = &*cur;
467
468 if !c.c1.is_null() {
470 free_content_model(c.c1);
471 }
472 if !c.c2.is_null() {
473 free_content_model(c.c2);
474 }
475
476 if !c.name.is_null() {
478 allocator::xmlFree(c.name as *mut c_void);
479 }
480 if !c.prefix.is_null() {
481 allocator::xmlFree(c.prefix as *mut c_void);
482 }
483
484 allocator::xmlFree(cur as *mut c_void);
485 }
486}
487
488pub unsafe fn copy_content_model(content: *mut _xmlElementContent) -> *mut _xmlElementContent {
502 if content.is_null() {
503 return ptr::null_mut();
504 }
505
506 unsafe {
507 let c = &*content;
508
509 let copy = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
511 as *mut _xmlElementContent;
512 if copy.is_null() {
513 return ptr::null_mut();
514 }
515
516 (*copy).type_ = c.type_;
517 (*copy).ocur = c.ocur;
518 (*copy).name = string::xml_strdup(c.name);
519 (*copy).prefix = string::xml_strdup(c.prefix);
520
521 if !c.c1.is_null() {
523 (*copy).c1 = copy_content_model(c.c1);
524 if !(*copy).c1.is_null() {
525 (*(*copy).c1).parent = copy;
526 }
527 }
528 if !c.c2.is_null() {
529 (*copy).c2 = copy_content_model(c.c2);
530 if !(*copy).c2.is_null() {
531 (*(*copy).c2).parent = copy;
532 }
533 }
534
535 copy
536 }
537}
538
539pub unsafe fn add_element_decl(
560 dtd: *mut _xmlDtd,
561 name: *const xmlChar,
562 type_: c_int,
563 content: *mut _xmlElementContent,
564) -> *mut _xmlElement {
565 if dtd.is_null() || name.is_null() {
566 return ptr::null_mut();
567 }
568
569 unsafe {
570 let d = &*dtd;
571
572 let existing = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
574 if !existing.is_null() {
575 return existing as *mut _xmlElement;
576 }
577
578 let elem = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
580 if elem.is_null() {
581 return ptr::null_mut();
582 }
583
584 (*elem).name = string::xml_strdup(name);
585 (*elem).type_ = type_;
586 (*elem).content = content; (*elem).attributes = ptr::null_mut();
588 (*elem).prefix = ptr::null_mut();
589 (*elem).next = ptr::null_mut();
590 (*elem)._private = 0;
591
592 let ret = hash::hash_add_entry(
594 d.elements as *mut hash::HashTable,
595 name,
596 elem as *mut c_void,
597 );
598 if ret != 0 {
599 free_element(elem);
601 return ptr::null_mut();
602 }
603
604 elem
605 }
606}
607
608pub unsafe fn get_element_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlElement {
621 if dtd.is_null() || name.is_null() {
622 return ptr::null_mut();
623 }
624
625 unsafe {
626 let d = &*dtd;
627 let payload = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
628 payload as *mut _xmlElement
629 }
630}
631
632pub unsafe fn copy_element(elem: *mut _xmlElement) -> *mut _xmlElement {
644 if elem.is_null() {
645 return ptr::null_mut();
646 }
647
648 unsafe {
649 let e = &*elem;
650
651 let copy = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
653 if copy.is_null() {
654 return ptr::null_mut();
655 }
656
657 (*copy).name = string::xml_strdup(e.name);
658 (*copy).type_ = e.type_;
659 (*copy).content = copy_content_model(e.content);
660 (*copy).prefix = string::xml_strdup(e.prefix);
661 (*copy)._private = e._private;
662
663 if !e.attributes.is_null() {
665 let mut src_attr = e.attributes;
668 let mut prev_copy: *mut _xmlAttribute = ptr::null_mut();
669 let mut first_copy: *mut _xmlAttribute = ptr::null_mut();
670
671 while !src_attr.is_null() {
672 let attr_copy = copy_attribute_decl(src_attr);
673 if attr_copy.is_null() {
674 let mut to_free = first_copy;
676 while !to_free.is_null() {
677 let next = (*to_free).nexth;
678 free_attribute(to_free);
679 to_free = next;
680 }
681 allocator::xmlFree(copy as *mut c_void);
682 return ptr::null_mut();
683 }
684
685 if prev_copy.is_null() {
686 first_copy = attr_copy;
687 } else {
688 (*prev_copy).nexth = attr_copy;
689 }
690 prev_copy = attr_copy;
691 src_attr = (*src_attr).nexth;
692 }
693
694 (*copy).attributes = first_copy;
695 }
696
697 copy
698 }
699}
700
701pub unsafe fn free_element(elem: *mut _xmlElement) {
716 if elem.is_null() {
717 return;
718 }
719
720 unsafe {
721 if !(*elem).name.is_null() {
723 allocator::xmlFree((*elem).name as *mut c_void);
724 }
725
726 if !(*elem).prefix.is_null() {
728 allocator::xmlFree((*elem).prefix as *mut c_void);
729 }
730
731 if !(*elem).content.is_null() {
733 free_content_model((*elem).content);
734 }
735
736 (*elem).attributes = ptr::null_mut();
742
743 allocator::xmlFree(elem as *mut c_void);
744 }
745}
746
747unsafe fn free_enumeration(tree: *mut _xmlEnumeration) {
757 if tree.is_null() {
758 return;
759 }
760
761 unsafe {
762 let mut cur = tree;
763 while !cur.is_null() {
764 let next = (*cur).next;
765 if !(*cur).name.is_null() {
766 allocator::xmlFree((*cur).name as *mut c_void);
767 }
768 allocator::xmlFree(cur as *mut c_void);
769 cur = next;
770 }
771 }
772}
773
774unsafe fn copy_enumeration(tree: *mut _xmlEnumeration) -> *mut _xmlEnumeration {
780 if tree.is_null() {
781 return ptr::null_mut();
782 }
783
784 unsafe {
785 let mut src = tree;
786 let mut first_copy: *mut _xmlEnumeration = ptr::null_mut();
787 let mut prev_copy: *mut _xmlEnumeration = ptr::null_mut();
788
789 while !src.is_null() {
790 let copy = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
791 as *mut _xmlEnumeration;
792 if copy.is_null() {
793 let mut to_free = first_copy;
795 while !to_free.is_null() {
796 let next = (*to_free).next;
797 if !(*to_free).name.is_null() {
798 allocator::xmlFree((*to_free).name as *mut c_void);
799 }
800 allocator::xmlFree(to_free as *mut c_void);
801 to_free = next;
802 }
803 return ptr::null_mut();
804 }
805
806 (*copy).name = string::xml_strdup((*src).name);
807 (*copy).next = ptr::null_mut();
808
809 if prev_copy.is_null() {
810 first_copy = copy;
811 } else {
812 (*prev_copy).next = copy;
813 }
814 prev_copy = copy;
815 src = (*src).next;
816 }
817
818 first_copy
819 }
820}
821
822pub unsafe fn add_attribute_decl(
844 dtd: *mut _xmlDtd,
845 elem: *mut _xmlElement,
846 name: *const xmlChar,
847 type_: c_int,
848 def: c_int,
849 defaultValue: *const xmlChar,
850 tree: *mut _xmlEnumeration,
851) -> *mut _xmlAttribute {
852 if dtd.is_null() || name.is_null() {
853 return ptr::null_mut();
854 }
855
856 unsafe {
857 let d = &*dtd;
858 let elem_name = if elem.is_null() {
859 ptr::null()
860 } else {
861 (*elem).name
862 };
863
864 let existing = hash::hash_lookup2(d.attributes as *mut hash::HashTable, elem_name, name);
866 if !existing.is_null() {
867 return existing as *mut _xmlAttribute;
868 }
869
870 let attr =
872 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
873 if attr.is_null() {
874 return ptr::null_mut();
875 }
876
877 (*attr).type_ = XML_ATTRIBUTE_DECL as c_int;
878 (*attr).name = string::xml_strdup(name);
879 (*attr).parent = dtd;
880 (*attr).doc = d.doc;
881 (*attr).nexth = ptr::null_mut();
882 (*attr).atype = type_;
883 (*attr).def = def;
884 (*attr).defaultValue = string::xml_strdup(defaultValue);
885 (*attr).tree = tree; (*attr).prefix = ptr::null_mut();
887 (*attr).elem = string::xml_strdup(elem_name);
888
889 let ret = hash::hash_add_entry2(
891 d.attributes as *mut hash::HashTable,
892 elem_name,
893 name,
894 attr as *mut c_void,
895 );
896 if ret != 0 {
897 if !(*attr).defaultValue.is_null() {
899 allocator::xmlFree((*attr).defaultValue as *mut c_void);
900 }
901 if !(*attr).name.is_null() {
902 allocator::xmlFree((*attr).name as *mut c_void);
903 }
904 if !(*attr).elem.is_null() {
905 allocator::xmlFree((*attr).elem as *mut c_void);
906 }
907 allocator::xmlFree(attr as *mut c_void);
908 return ptr::null_mut();
910 }
911
912 if !elem.is_null() {
914 (*attr).nexth = (*elem).attributes;
915 (*elem).attributes = attr;
916 }
917
918 attr
919 }
920}
921
922pub unsafe fn get_attribute_decl(
940 dtd: *mut _xmlDtd,
941 elem: *mut _xmlElement,
942 name: *const xmlChar,
943 _namePrefix: c_int,
944) -> *mut _xmlAttribute {
945 if dtd.is_null() || name.is_null() {
946 return ptr::null_mut();
947 }
948
949 unsafe {
950 let d = &*dtd;
951 let elem_name = if elem.is_null() {
952 ptr::null()
953 } else {
954 (*elem).name
955 };
956
957 let payload = hash::hash_lookup2(d.attributes as *mut hash::HashTable, elem_name, name);
958 payload as *mut _xmlAttribute
959 }
960}
961
962pub unsafe fn copy_attribute_decl(attr: *mut _xmlAttribute) -> *mut _xmlAttribute {
974 if attr.is_null() {
975 return ptr::null_mut();
976 }
977
978 unsafe {
979 let a = &*attr;
980
981 let copy =
983 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
984 if copy.is_null() {
985 return ptr::null_mut();
986 }
987
988 (*copy).type_ = a.type_;
989 (*copy).name = string::xml_strdup(a.name);
990 (*copy).parent = a.parent;
991 (*copy).doc = a.doc;
992 (*copy).nexth = ptr::null_mut();
993 (*copy).atype = a.atype;
994 (*copy).def = a.def;
995 (*copy).defaultValue = string::xml_strdup(a.defaultValue);
996 (*copy).tree = copy_enumeration(a.tree);
997 (*copy).prefix = string::xml_strdup(a.prefix);
998 (*copy).elem = string::xml_strdup(a.elem);
999
1000 copy
1001 }
1002}
1003
1004pub unsafe fn free_attribute(attr: *mut _xmlAttribute) {
1016 if attr.is_null() {
1017 return;
1018 }
1019
1020 unsafe {
1021 let a = &*attr;
1022
1023 if !a.name.is_null() {
1024 allocator::xmlFree(a.name as *mut c_void);
1025 }
1026 if !a.defaultValue.is_null() {
1027 allocator::xmlFree(a.defaultValue as *mut c_void);
1028 }
1029 if !a.prefix.is_null() {
1030 allocator::xmlFree(a.prefix as *mut c_void);
1031 }
1032 if !a.elem.is_null() {
1033 allocator::xmlFree(a.elem as *mut c_void);
1034 }
1035 if !a.tree.is_null() {
1036 free_enumeration(a.tree);
1037 }
1038
1039 allocator::xmlFree(attr as *mut c_void);
1040 }
1041}
1042
1043#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1049pub enum ContentModelResult {
1050 Valid,
1052 Invalid,
1054 Indeterminate,
1056}
1057
1058pub unsafe fn valid_content_model(
1079 model: *mut _xmlElementContent,
1080 names: &[*const xmlChar],
1081) -> ContentModelResult {
1082 if model.is_null() {
1083 return ContentModelResult::Invalid;
1084 }
1085
1086 unsafe {
1087 let m = &*model;
1088
1089 match m.ocur as u32 {
1091 o if o == XML_ELEMENT_CONTENT_OPT as u32 => {
1092 if names.is_empty() {
1094 return ContentModelResult::Valid;
1095 }
1096 return valid_content_model_inner(model, names);
1097 }
1098 o if o == XML_ELEMENT_CONTENT_MULT as u32 => {
1099 if names.is_empty() {
1101 return ContentModelResult::Valid;
1102 }
1103 return valid_content_model_zero_or_more(model, names);
1104 }
1105 o if o == XML_ELEMENT_CONTENT_PLUS as u32 => {
1106 if names.is_empty() {
1108 return ContentModelResult::Invalid;
1109 }
1110 return valid_content_model_one_or_more(model, names);
1111 }
1112 _ => {}
1113 }
1114
1115 valid_content_model_inner(model, names)
1116 }
1117}
1118
1119unsafe fn valid_content_model_inner(
1121 model: *mut _xmlElementContent,
1122 names: &[*const xmlChar],
1123) -> ContentModelResult {
1124 unsafe {
1125 let m = &*model;
1126
1127 match m.type_ as u32 {
1128 t if t == XML_ELEMENT_CONTENT_PCDATA as u32 => {
1129 if names.is_empty() {
1131 ContentModelResult::Valid
1132 } else {
1133 ContentModelResult::Invalid
1134 }
1135 }
1136 t if t == XML_ELEMENT_CONTENT_ELEMENT as u32 => {
1137 if names.len() != 1 {
1139 return ContentModelResult::Invalid;
1140 }
1141 if names[0].is_null() {
1142 return ContentModelResult::Invalid;
1143 }
1144 if string::xml_strcmp(names[0], m.name) != 0 {
1146 return ContentModelResult::Invalid;
1147 }
1148 ContentModelResult::Valid
1149 }
1150 t if t == XML_ELEMENT_CONTENT_SEQ as u32 => {
1151 valid_content_model_seq(m, names)
1153 }
1154 t if t == XML_ELEMENT_CONTENT_OR as u32 => {
1155 valid_content_model_or(m, names)
1157 }
1158 _ => ContentModelResult::Invalid,
1159 }
1160 }
1161}
1162
1163unsafe fn valid_content_model_zero_or_more(
1165 model: *mut _xmlElementContent,
1166 names: &[*const xmlChar],
1167) -> ContentModelResult {
1168 let mut i = 0;
1170 while i <= names.len() {
1171 let consumed = &names[..i];
1172 let remaining = &names[i..];
1173
1174 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1175 if consumed_valid == ContentModelResult::Valid {
1176 if remaining.is_empty() {
1177 return ContentModelResult::Valid;
1178 }
1179 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1181 if remaining_valid == ContentModelResult::Valid {
1182 return ContentModelResult::Valid;
1183 }
1184 }
1185
1186 i += 1;
1187 }
1188 ContentModelResult::Invalid
1189}
1190
1191unsafe fn valid_content_model_one_or_more(
1193 model: *mut _xmlElementContent,
1194 names: &[*const xmlChar],
1195) -> ContentModelResult {
1196 let mut i = 1;
1198 while i <= names.len() {
1199 let consumed = &names[..i];
1200 let remaining = &names[i..];
1201
1202 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1203 if consumed_valid == ContentModelResult::Valid {
1204 if remaining.is_empty() {
1205 return ContentModelResult::Valid;
1206 }
1207 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1208 if remaining_valid == ContentModelResult::Valid {
1209 return ContentModelResult::Valid;
1210 }
1211 }
1212
1213 i += 1;
1214 }
1215 ContentModelResult::Invalid
1216}
1217
1218unsafe fn valid_content_model_seq(
1220 model: &_xmlElementContent,
1221 names: &[*const xmlChar],
1222) -> ContentModelResult {
1223 let c1 = model.c1;
1228 let c2 = model.c2;
1229
1230 if c1.is_null() && c2.is_null() {
1231 return ContentModelResult::Valid;
1232 }
1233
1234 if c1.is_null() {
1235 return unsafe { valid_content_model(c2, names) };
1236 }
1237
1238 if c2.is_null() {
1239 return unsafe { valid_content_model(c1, names) };
1240 }
1241
1242 for split in 0..=names.len() {
1245 let left = &names[..split];
1246 let right = &names[split..];
1247
1248 let left_valid = unsafe { valid_content_model(c1, left) };
1249 if left_valid != ContentModelResult::Valid {
1250 continue;
1251 }
1252
1253 let right_valid = unsafe { valid_content_model(c2, right) };
1254 if right_valid == ContentModelResult::Valid {
1255 return ContentModelResult::Valid;
1256 }
1257 }
1258
1259 ContentModelResult::Invalid
1260}
1261
1262unsafe fn valid_content_model_or(
1264 model: &_xmlElementContent,
1265 names: &[*const xmlChar],
1266) -> ContentModelResult {
1267 let c1 = model.c1;
1268 let c2 = model.c2;
1269
1270 if c1.is_null() && c2.is_null() {
1271 return ContentModelResult::Invalid;
1272 }
1273
1274 if !c1.is_null() {
1275 let result = unsafe { valid_content_model(c1, names) };
1276 if result == ContentModelResult::Valid {
1277 return ContentModelResult::Valid;
1278 }
1279 }
1280
1281 if !c2.is_null() {
1282 let result = unsafe { valid_content_model(c2, names) };
1283 if result == ContentModelResult::Valid {
1284 return ContentModelResult::Valid;
1285 }
1286 }
1287
1288 ContentModelResult::Invalid
1289}
1290
1291#[cfg(test)]
1296mod tests {
1297 use super::*;
1298 use crate::abi::allocator::xmlFree;
1299 use crate::abi::structs::*;
1300 use core::ffi::c_void;
1301 use core::ptr;
1302
1303 unsafe fn c_str(s: &[u8]) -> *const xmlChar {
1306 let len = s.len();
1308 let buf = allocator::xmlMalloc(len + 1) as *mut xmlChar;
1309 assert!(!buf.is_null());
1310 ptr::copy_nonoverlapping(s.as_ptr(), buf, len);
1311 *buf.add(len) = 0;
1312 buf as *const xmlChar
1313 }
1314
1315 unsafe fn make_doc_and_dtd() -> (*mut _xmlDoc, *mut _xmlDtd) {
1316 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1317 assert!(!doc.is_null());
1318 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1319 (*doc).doc = doc;
1320 let dtd = create_int_subset(doc, c_str(b"root"), ptr::null(), ptr::null());
1321 assert!(!dtd.is_null());
1322 (doc, dtd)
1323 }
1324
1325 #[test]
1328 fn test_get_int_subset_null() {
1329 unsafe {
1330 assert!(get_int_subset(ptr::null()).is_null());
1331 }
1332 }
1333
1334 #[test]
1335 fn test_create_int_subset() {
1336 unsafe {
1337 let (doc, dtd) = make_doc_and_dtd();
1338 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1339 assert!(!(*dtd).name.is_null());
1340 assert_eq!((*doc).intSubset, dtd);
1341
1342 free_dtd(dtd);
1344 allocator::xmlFree(doc as *mut c_void);
1345 }
1346 }
1347
1348 #[test]
1349 fn test_create_int_subset_null_doc() {
1350 unsafe {
1351 let dtd = create_int_subset(ptr::null_mut(), c_str(b"root"), ptr::null(), ptr::null());
1352 assert!(dtd.is_null());
1353 }
1354 }
1355
1356 #[test]
1357 fn test_new_dtd() {
1358 unsafe {
1359 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1360 assert!(!doc.is_null());
1361 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1362 (*doc).doc = doc;
1363
1364 let dtd = new_dtd(doc, c_str(b"test"), c_str(b"-//TEST//"), c_str(b"test.dtd"));
1365 assert!(!dtd.is_null());
1366 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1367 assert_eq!((*doc).intSubset, dtd);
1368
1369 free_dtd(dtd);
1370 allocator::xmlFree(doc as *mut c_void);
1371 }
1372 }
1373
1374 #[test]
1375 fn test_new_dtd_no_doc() {
1376 unsafe {
1377 let dtd = new_dtd(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1378 assert!(!dtd.is_null());
1379 free_dtd(dtd);
1380 }
1381 }
1382
1383 #[test]
1386 fn test_add_get_notation() {
1387 unsafe {
1388 let (doc, dtd) = make_doc_and_dtd();
1389 let name = c_str(b"note");
1390 let pubid = c_str(b"-//TEST//NOTATION");
1391 let sysid = c_str(b"note.ent");
1392
1393 let n = add_notation_decl(dtd, name, pubid, sysid);
1394 assert!(!n.is_null());
1395 assert_eq!(string::xml_strcmp((*n).name, name), 0);
1396
1397 let found = get_notation_decl(dtd, name);
1399 assert_eq!(found, n);
1400
1401 let not_found = get_notation_decl(dtd, c_str(b"nonexistent"));
1403 assert!(not_found.is_null());
1404
1405 free_dtd(dtd);
1406 allocator::xmlFree(doc as *mut c_void);
1407 }
1408 }
1409
1410 #[test]
1411 fn test_add_notation_null_dtd() {
1412 unsafe {
1413 let n = add_notation_decl(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1414 assert!(n.is_null());
1415 }
1416 }
1417
1418 #[test]
1419 fn test_copy_notation() {
1420 unsafe {
1421 let (doc, dtd) = make_doc_and_dtd();
1422 let name = c_str(b"note1");
1423 let pubid = c_str(b"public");
1424 let sysid = c_str(b"system");
1425
1426 let n = add_notation_decl(dtd, name, pubid, sysid);
1427 assert!(!n.is_null());
1428
1429 let copy = copy_notation(n);
1430 assert!(!copy.is_null());
1431 assert_ne!(copy, n);
1432 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1433 assert_eq!(string::xml_strcmp((*copy).PublicID, pubid), 0);
1434 assert_eq!(string::xml_strcmp((*copy).SystemID, sysid), 0);
1435
1436 free_notation(copy);
1437 free_dtd(dtd);
1438 allocator::xmlFree(doc as *mut c_void);
1439 }
1440 }
1441
1442 #[test]
1443 fn test_copy_notation_null() {
1444 unsafe {
1445 assert!(copy_notation(ptr::null_mut()).is_null());
1446 }
1447 }
1448
1449 #[test]
1450 fn test_free_notation_null() {
1451 unsafe {
1452 free_notation(ptr::null_mut()); }
1454 }
1455
1456 #[test]
1459 fn test_create_free_content_model() {
1460 unsafe {
1461 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1462 assert!(!cm.is_null());
1463 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1464 assert_eq!((*cm).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1465
1466 free_content_model(cm);
1467 }
1468 }
1469
1470 #[test]
1471 fn test_create_content_model_pcdata() {
1472 unsafe {
1473 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1474 assert!(!cm.is_null());
1475 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_PCDATA as c_int);
1476 free_content_model(cm);
1477 }
1478 }
1479
1480 #[test]
1481 fn test_copy_content_model() {
1482 unsafe {
1483 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1484 assert!(!cm.is_null());
1485
1486 let copy = copy_content_model(cm);
1487 assert!(!copy.is_null());
1488 assert_ne!(copy, cm);
1489 assert_eq!((*copy).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1490 assert_eq!((*copy).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1491 assert_eq!(string::xml_strcmp((*copy).name, (*cm).name), 0);
1492
1493 free_content_model(cm);
1494 free_content_model(copy);
1495 }
1496 }
1497
1498 #[test]
1499 fn test_copy_content_model_null() {
1500 unsafe {
1501 assert!(copy_content_model(ptr::null_mut()).is_null());
1502 }
1503 }
1504
1505 #[test]
1506 fn test_free_content_model_null() {
1507 unsafe {
1508 free_content_model(ptr::null_mut()); }
1510 }
1511
1512 #[test]
1513 fn test_create_sequence_content_model() {
1514 unsafe {
1515 let c1 = create_content_model(c_str(b"a"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1516 let c2 = create_content_model(c_str(b"b"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1517 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1518 assert!(!seq.is_null());
1519 (*seq).c1 = c1;
1520 (*seq).c2 = c2;
1521 (*c1).parent = seq;
1522 (*c2).parent = seq;
1523
1524 free_content_model(seq);
1525 }
1526 }
1527
1528 #[test]
1531 fn test_add_get_element() {
1532 unsafe {
1533 let (doc, dtd) = make_doc_and_dtd();
1534 let name = c_str(b"myElement");
1535
1536 let elem =
1537 add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1538 assert!(!elem.is_null());
1539 assert_eq!((*elem).type_, XML_ELEMENT_TYPE_EMPTY as c_int);
1540
1541 let found = get_element_decl(dtd, name);
1542 assert_eq!(found, elem);
1543
1544 let not_found = get_element_decl(dtd, c_str(b"nonexistent"));
1545 assert!(not_found.is_null());
1546
1547 free_dtd(dtd);
1548 allocator::xmlFree(doc as *mut c_void);
1549 }
1550 }
1551
1552 #[test]
1553 fn test_add_element_duplicate() {
1554 unsafe {
1555 let (doc, dtd) = make_doc_and_dtd();
1556 let name = c_str(b"dup");
1557
1558 let e1 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1559 assert!(!e1.is_null());
1560
1561 let e2 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ANY as c_int, ptr::null_mut());
1562 assert_eq!(e1, e2); assert_eq!((*e2).type_, XML_ELEMENT_TYPE_EMPTY as c_int); free_dtd(dtd);
1566 allocator::xmlFree(doc as *mut c_void);
1567 }
1568 }
1569
1570 #[test]
1571 fn test_add_element_null_dtd() {
1572 unsafe {
1573 let elem = add_element_decl(
1574 ptr::null_mut(),
1575 c_str(b"test"),
1576 XML_ELEMENT_TYPE_EMPTY as c_int,
1577 ptr::null_mut(),
1578 );
1579 assert!(elem.is_null());
1580 }
1581 }
1582
1583 #[test]
1584 fn test_copy_element() {
1585 unsafe {
1586 let (doc, dtd) = make_doc_and_dtd();
1587 let name = c_str(b"source");
1588 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1589
1590 let elem = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ELEMENT as c_int, cm);
1591 assert!(!elem.is_null());
1592
1593 let copy = copy_element(elem);
1594 assert!(!copy.is_null());
1595 assert_ne!(copy, elem);
1596 assert_eq!((*copy).type_, XML_ELEMENT_TYPE_ELEMENT as c_int);
1597 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1598 assert!(!(*copy).content.is_null());
1599 assert_ne!((*copy).content, cm);
1600
1601 free_element(copy);
1602 free_dtd(dtd);
1603 allocator::xmlFree(doc as *mut c_void);
1604 }
1605 }
1606
1607 #[test]
1608 fn test_free_element_null() {
1609 unsafe {
1610 free_element(ptr::null_mut()); }
1612 }
1613
1614 #[test]
1617 fn test_add_get_attribute() {
1618 unsafe {
1619 let (doc, dtd) = make_doc_and_dtd();
1620 let elem_name = c_str(b"elem");
1621 let attr_name = c_str(b"attr1");
1622
1623 let elem = add_element_decl(
1624 dtd,
1625 elem_name,
1626 XML_ELEMENT_TYPE_EMPTY as c_int,
1627 ptr::null_mut(),
1628 );
1629 assert!(!elem.is_null());
1630
1631 let attr = add_attribute_decl(
1632 dtd,
1633 elem,
1634 attr_name,
1635 XML_ATTRIBUTE_CDATA as c_int,
1636 XML_ATTRIBUTE_IMPLIED as c_int,
1637 ptr::null(),
1638 ptr::null_mut(),
1639 );
1640 assert!(!attr.is_null());
1641 assert_eq!((*attr).atype, XML_ATTRIBUTE_CDATA as c_int);
1642 assert_eq!((*attr).def, XML_ATTRIBUTE_IMPLIED as c_int);
1643
1644 let found = get_attribute_decl(dtd, elem, attr_name, 0);
1646 assert_eq!(found, attr);
1647
1648 let not_found = get_attribute_decl(dtd, elem, c_str(b"nonexistent"), 0);
1650 assert!(not_found.is_null());
1651
1652 free_dtd(dtd);
1653 allocator::xmlFree(doc as *mut c_void);
1654 }
1655 }
1656
1657 #[test]
1658 fn test_add_attribute_with_default() {
1659 unsafe {
1660 let (doc, dtd) = make_doc_and_dtd();
1661 let elem_name = c_str(b"elem");
1662 let attr_name = c_str(b"color");
1663 let default_val = c_str(b"red");
1664
1665 let elem = add_element_decl(
1666 dtd,
1667 elem_name,
1668 XML_ELEMENT_TYPE_EMPTY as c_int,
1669 ptr::null_mut(),
1670 );
1671
1672 let attr = add_attribute_decl(
1673 dtd,
1674 elem,
1675 attr_name,
1676 XML_ATTRIBUTE_CDATA as c_int,
1677 XML_ATTRIBUTE_FIXED as c_int,
1678 default_val,
1679 ptr::null_mut(),
1680 );
1681 assert!(!attr.is_null());
1682 assert_eq!((*attr).def, XML_ATTRIBUTE_FIXED as c_int);
1683 assert_eq!(string::xml_strcmp((*attr).defaultValue, default_val), 0);
1684
1685 free_dtd(dtd);
1686 allocator::xmlFree(doc as *mut c_void);
1687 }
1688 }
1689
1690 #[test]
1691 fn test_add_attribute_enumeration() {
1692 unsafe {
1693 let (doc, dtd) = make_doc_and_dtd();
1694 let elem_name = c_str(b"elem");
1695 let attr_name = c_str(b"size");
1696
1697 let v3 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1699 as *mut _xmlEnumeration;
1700 (*v3).name = string::xml_strdup(c_str(b"large"));
1701 let v2 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1702 as *mut _xmlEnumeration;
1703 (*v2).name = string::xml_strdup(c_str(b"medium"));
1704 (*v2).next = v3;
1705 let v1 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1706 as *mut _xmlEnumeration;
1707 (*v1).name = string::xml_strdup(c_str(b"small"));
1708 (*v1).next = v2;
1709
1710 let elem = add_element_decl(
1711 dtd,
1712 elem_name,
1713 XML_ELEMENT_TYPE_EMPTY as c_int,
1714 ptr::null_mut(),
1715 );
1716 let attr = add_attribute_decl(
1717 dtd,
1718 elem,
1719 attr_name,
1720 XML_ATTRIBUTE_ENUMERATION as c_int,
1721 XML_ATTRIBUTE_REQUIRED as c_int,
1722 ptr::null(),
1723 v1,
1724 );
1725 assert!(!attr.is_null());
1726 assert_eq!((*attr).atype, XML_ATTRIBUTE_ENUMERATION as c_int);
1727
1728 free_dtd(dtd);
1729 allocator::xmlFree(doc as *mut c_void);
1730 }
1731 }
1732
1733 #[test]
1734 fn test_add_attribute_null_dtd() {
1735 unsafe {
1736 let attr = add_attribute_decl(
1737 ptr::null_mut(),
1738 ptr::null_mut(),
1739 c_str(b"test"),
1740 XML_ATTRIBUTE_CDATA as c_int,
1741 XML_ATTRIBUTE_IMPLIED as c_int,
1742 ptr::null(),
1743 ptr::null_mut(),
1744 );
1745 assert!(attr.is_null());
1746 }
1747 }
1748
1749 #[test]
1750 fn test_copy_attribute() {
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"id");
1755 let default_val = c_str(b"default");
1756
1757 let elem = add_element_decl(
1758 dtd,
1759 elem_name,
1760 XML_ELEMENT_TYPE_EMPTY as c_int,
1761 ptr::null_mut(),
1762 );
1763 let attr = add_attribute_decl(
1764 dtd,
1765 elem,
1766 attr_name,
1767 XML_ATTRIBUTE_ID as c_int,
1768 XML_ATTRIBUTE_IMPLIED as c_int,
1769 default_val,
1770 ptr::null_mut(),
1771 );
1772 assert!(!attr.is_null());
1773
1774 let copy = copy_attribute_decl(attr);
1775 assert!(!copy.is_null());
1776 assert_ne!(copy, attr);
1777 assert_eq!((*copy).atype, XML_ATTRIBUTE_ID as c_int);
1778 assert_eq!(string::xml_strcmp((*copy).name, attr_name), 0);
1779
1780 free_attribute(copy);
1781 free_dtd(dtd);
1782 allocator::xmlFree(doc as *mut c_void);
1783 }
1784 }
1785
1786 #[test]
1787 fn test_free_attribute_null() {
1788 unsafe {
1789 free_attribute(ptr::null_mut()); }
1791 }
1792
1793 #[test]
1796 fn test_valid_content_model_null() {
1797 unsafe {
1798 assert_eq!(
1799 valid_content_model(ptr::null_mut(), &[]),
1800 ContentModelResult::Invalid
1801 );
1802 }
1803 }
1804
1805 #[test]
1806 fn test_valid_content_model_pcdata() {
1807 unsafe {
1808 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1809 assert!(!cm.is_null());
1810
1811 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Valid);
1813
1814 let name = c_str(b"child");
1816 assert_eq!(
1817 valid_content_model(cm, &[name]),
1818 ContentModelResult::Invalid
1819 );
1820
1821 free_content_model(cm);
1822 }
1823 }
1824
1825 #[test]
1826 fn test_valid_content_model_element() {
1827 unsafe {
1828 let child_name = c_str(b"child");
1829 let cm = create_content_model(child_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1830 assert!(!cm.is_null());
1831
1832 assert_eq!(
1834 valid_content_model(cm, &[child_name]),
1835 ContentModelResult::Valid
1836 );
1837
1838 let other = c_str(b"other");
1840 assert_eq!(
1841 valid_content_model(cm, &[other]),
1842 ContentModelResult::Invalid
1843 );
1844
1845 assert_eq!(
1847 valid_content_model(cm, &[child_name, child_name]),
1848 ContentModelResult::Invalid
1849 );
1850
1851 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Invalid);
1853
1854 free_content_model(cm);
1855 }
1856 }
1857
1858 #[test]
1859 fn test_valid_content_model_seq() {
1860 unsafe {
1861 let a_name = c_str(b"a");
1862 let b_name = c_str(b"b");
1863
1864 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1865 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1866 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1867 (*seq).c1 = c1;
1868 (*seq).c2 = c2;
1869 (*c1).parent = seq;
1870 (*c2).parent = seq;
1871
1872 assert_eq!(
1874 valid_content_model(seq, &[a_name, b_name]),
1875 ContentModelResult::Valid
1876 );
1877
1878 assert_eq!(
1880 valid_content_model(seq, &[b_name, a_name]),
1881 ContentModelResult::Invalid
1882 );
1883
1884 assert_eq!(
1886 valid_content_model(seq, &[a_name]),
1887 ContentModelResult::Invalid
1888 );
1889
1890 free_content_model(seq);
1891 }
1892 }
1893
1894 #[test]
1895 fn test_valid_content_model_or() {
1896 unsafe {
1897 let a_name = c_str(b"a");
1898 let b_name = c_str(b"b");
1899
1900 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1901 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1902 let choice = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_OR as c_int);
1903 (*choice).c1 = c1;
1904 (*choice).c2 = c2;
1905 (*c1).parent = choice;
1906 (*c2).parent = choice;
1907
1908 assert_eq!(
1910 valid_content_model(choice, &[a_name]),
1911 ContentModelResult::Valid
1912 );
1913
1914 assert_eq!(
1916 valid_content_model(choice, &[b_name]),
1917 ContentModelResult::Valid
1918 );
1919
1920 let other = c_str(b"other");
1922 assert_eq!(
1923 valid_content_model(choice, &[other]),
1924 ContentModelResult::Invalid
1925 );
1926
1927 free_content_model(choice);
1928 }
1929 }
1930
1931 #[test]
1932 fn test_valid_content_model_optional() {
1933 unsafe {
1934 let a_name = c_str(b"a");
1935
1936 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1937 (*c1).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
1938
1939 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
1941
1942 assert_eq!(
1944 valid_content_model(c1, &[a_name]),
1945 ContentModelResult::Valid
1946 );
1947
1948 free_content_model(c1);
1949 }
1950 }
1951
1952 #[test]
1953 fn test_valid_content_model_zero_or_more() {
1954 unsafe {
1955 let a_name = c_str(b"a");
1956
1957 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1958 (*c1).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
1959
1960 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
1962
1963 assert_eq!(
1965 valid_content_model(c1, &[a_name]),
1966 ContentModelResult::Valid
1967 );
1968
1969 assert_eq!(
1971 valid_content_model(c1, &[a_name, a_name, a_name]),
1972 ContentModelResult::Valid
1973 );
1974
1975 free_content_model(c1);
1976 }
1977 }
1978
1979 #[test]
1980 fn test_valid_content_model_one_or_more() {
1981 unsafe {
1982 let a_name = c_str(b"a");
1983
1984 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1985 (*c1).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
1986
1987 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Invalid);
1989
1990 assert_eq!(
1992 valid_content_model(c1, &[a_name]),
1993 ContentModelResult::Valid
1994 );
1995
1996 assert_eq!(
1998 valid_content_model(c1, &[a_name, a_name]),
1999 ContentModelResult::Valid
2000 );
2001
2002 free_content_model(c1);
2003 }
2004 }
2005}