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 (*doc).intSubset = dtd;
92
93 let doc_children = (*doc).children;
97 if doc_children.is_null() {
98 (*doc).children = dtd as *mut _xmlNode;
99 (*doc).last = dtd as *mut _xmlNode;
100 } else {
101 let mut next = doc_children;
102 while !next.is_null() && (*next).type_ != XML_ELEMENT_NODE as c_int {
103 next = (*next).next;
104 }
105 if next.is_null() {
106 (*dtd).prev = (*doc).last;
107 (*(*doc).last).next = dtd as *mut _xmlNode;
108 (*doc).last = dtd as *mut _xmlNode;
109 } else {
110 (*dtd).next = next;
111 (*dtd).prev = (*next).prev;
112 if (*dtd).prev.is_null() {
113 (*doc).children = dtd as *mut _xmlNode;
114 } else {
115 (*(*dtd).prev).next = dtd as *mut _xmlNode;
116 }
117 (*next).prev = dtd as *mut _xmlNode;
118 }
119 }
120 }
121
122 dtd
123}
124
125pub unsafe fn new_dtd(
142 doc: *mut _xmlDoc,
143 name: *const xmlChar,
144 ExternalID: *const xmlChar,
145 SystemID: *const xmlChar,
146) -> *mut _xmlDtd {
147 let dtd = allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd;
149 if dtd.is_null() {
150 return ptr::null_mut();
151 }
152
153 unsafe {
154 (*dtd).type_ = XML_DTD_NODE as c_int;
155 (*dtd).name = string::xml_strdup(name);
156 (*dtd).ExternalID = string::xml_strdup(ExternalID);
157 (*dtd).SystemID = string::xml_strdup(SystemID);
158 (*dtd).parent = doc;
159 (*dtd).doc = doc;
160
161 if !doc.is_null() && (*doc).intSubset.is_null() {
166 (*doc).intSubset = dtd;
167 }
168 }
169
170 dtd
171}
172
173unsafe extern "C" fn copy_elem_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
175 unsafe { copy_element(payload as *mut _xmlElement) as *mut c_void }
176}
177
178unsafe extern "C" fn copy_attr_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
179 unsafe { copy_attribute_decl(payload as *mut _xmlAttribute) as *mut c_void }
180}
181
182unsafe extern "C" fn copy_ent_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
183 unsafe { crate::xml::entities::copy_entity(payload as *mut _xmlEntity) as *mut c_void }
184}
185
186unsafe extern "C" fn copy_notation_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
187 unsafe { copy_notation(payload as *mut _xmlNotation) as *mut c_void }
188}
189
190pub unsafe fn copy_dtd(dtd: *const _xmlDtd) -> *mut _xmlDtd {
200 if dtd.is_null() {
201 return ptr::null_mut();
202 }
203 let d = unsafe { &*dtd };
204
205 let copy = unsafe { allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd };
206 if copy.is_null() {
207 return ptr::null_mut();
208 }
209
210 unsafe {
211 (*copy).type_ = d.type_;
212 (*copy).name = string::xml_strdup(d.name);
213 (*copy).ExternalID = string::xml_strdup(d.ExternalID);
214 (*copy).SystemID = string::xml_strdup(d.SystemID);
215 (*copy).notations =
216 hash::hash_copy(d.notations as *mut hash::HashTable, Some(copy_notation_cb))
217 as *mut c_void;
218 (*copy).elements =
219 hash::hash_copy(d.elements as *mut hash::HashTable, Some(copy_elem_cb)) as *mut c_void;
220 (*copy).attributes =
221 hash::hash_copy(d.attributes as *mut hash::HashTable, Some(copy_attr_cb))
222 as *mut c_void;
223 (*copy).entities =
224 hash::hash_copy(d.entities as *mut hash::HashTable, Some(copy_ent_cb)) as *mut c_void;
225 (*copy).pentities =
226 hash::hash_copy(d.pentities as *mut hash::HashTable, Some(copy_ent_cb)) as *mut c_void;
227 }
228
229 copy
230}
231
232pub unsafe fn free_dtd(dtd: *mut _xmlDtd) {
244 if dtd.is_null() {
245 return;
246 }
247
248 unsafe {
249 let d = &mut *dtd;
250
251 if !d.children.is_null() {
258 let mut c = d.children;
259 while !c.is_null() {
260 let next = (*c).next;
261 let t = (*c).type_;
262 if t != XML_ELEMENT_DECL as c_int
263 && t != XML_ATTRIBUTE_DECL as c_int
264 && t != XML_ENTITY_DECL as c_int
265 {
266 crate::xml::tree::free_node(c);
267 }
268 c = next;
269 }
270 }
271
272 if !d.notations.is_null() {
274 hash::hash_free(
275 d.notations as *mut hash::HashTable,
276 Some(notation_deallocator),
277 );
278 d.notations = ptr::null_mut();
279 }
280 if !d.elements.is_null() {
281 hash::hash_free(
282 d.elements as *mut hash::HashTable,
283 Some(element_deallocator),
284 );
285 d.elements = ptr::null_mut();
286 }
287 if !d.attributes.is_null() {
288 hash::hash_free(
289 d.attributes as *mut hash::HashTable,
290 Some(attribute_deallocator),
291 );
292 d.attributes = ptr::null_mut();
293 }
294 if !d.entities.is_null() {
295 hash::hash_free(d.entities as *mut hash::HashTable, Some(entity_deallocator));
296 d.entities = ptr::null_mut();
297 }
298 if !d.pentities.is_null() {
299 hash::hash_free(
300 d.pentities as *mut hash::HashTable,
301 Some(entity_deallocator),
302 );
303 d.pentities = ptr::null_mut();
304 }
305
306 if !d.name.is_null() {
308 allocator::xmlFreeImpl(d.name as *mut c_void);
309 }
310 if !d.ExternalID.is_null() {
311 allocator::xmlFreeImpl(d.ExternalID as *mut c_void);
312 }
313 if !d.SystemID.is_null() {
314 allocator::xmlFreeImpl(d.SystemID as *mut c_void);
315 }
316
317 allocator::xmlFreeImpl(dtd as *mut c_void);
318 }
319}
320
321unsafe extern "C" fn notation_deallocator(payload: *mut c_void, _name: *mut u8) {
326 if !payload.is_null() {
327 free_notation(payload as *mut _xmlNotation);
328 }
329}
330
331unsafe extern "C" fn element_deallocator(payload: *mut c_void, _name: *mut u8) {
332 if !payload.is_null() {
333 free_element(payload as *mut _xmlElement);
334 }
335}
336
337unsafe extern "C" fn attribute_deallocator(payload: *mut c_void, _name: *mut u8) {
338 if !payload.is_null() {
339 free_attribute(payload as *mut _xmlAttribute);
340 }
341}
342
343unsafe extern "C" fn entity_deallocator(payload: *mut c_void, _name: *mut u8) {
344 if !payload.is_null() {
345 crate::xml::entities::free_entity(payload as *mut _xmlEntity);
346 }
347}
348
349pub unsafe fn add_notation_decl(
369 dtd: *mut _xmlDtd,
370 name: *const xmlChar,
371 PublicID: *const xmlChar,
372 SystemID: *const xmlChar,
373) -> *mut _xmlNotation {
374 if dtd.is_null() || name.is_null() {
375 return ptr::null_mut();
376 }
377
378 unsafe {
379 if (*dtd).notations.is_null() {
382 (*dtd).notations = hash::hash_create(8) as *mut c_void;
383 }
384 let d = &*dtd;
385
386 let existing = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
388 if !existing.is_null() {
389 return existing as *mut _xmlNotation;
390 }
391
392 let not = allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
394 if not.is_null() {
395 return ptr::null_mut();
396 }
397
398 (*not).name = string::xml_strdup(name);
399 (*not).PublicID = string::xml_strdup(PublicID);
400 (*not).SystemID = string::xml_strdup(SystemID);
401
402 let ret = hash::hash_add_entry(
404 d.notations as *mut hash::HashTable,
405 name,
406 not as *mut c_void,
407 );
408 if ret != 0 {
409 free_notation(not);
411 return ptr::null_mut();
412 }
413
414 not
415 }
416}
417
418pub unsafe fn get_notation_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlNotation {
431 if dtd.is_null() || name.is_null() {
432 return ptr::null_mut();
433 }
434
435 unsafe {
436 let d = &*dtd;
437 let payload = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
438 payload as *mut _xmlNotation
439 }
440}
441
442pub unsafe fn copy_notation(notation: *mut _xmlNotation) -> *mut _xmlNotation {
454 if notation.is_null() {
455 return ptr::null_mut();
456 }
457
458 unsafe {
459 let n = &*notation;
460 let copy =
462 allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
463 if copy.is_null() {
464 return ptr::null_mut();
465 }
466
467 (*copy).name = string::xml_strdup(n.name);
468 (*copy).PublicID = string::xml_strdup(n.PublicID);
469 (*copy).SystemID = string::xml_strdup(n.SystemID);
470
471 copy
472 }
473}
474
475pub unsafe fn free_notation(notation: *mut _xmlNotation) {
487 if notation.is_null() {
488 return;
489 }
490
491 unsafe {
492 let n = &*notation;
493 if !n.name.is_null() {
494 allocator::xmlFreeImpl(n.name as *mut c_void);
495 }
496 if !n.PublicID.is_null() {
497 allocator::xmlFreeImpl(n.PublicID as *mut c_void);
498 }
499 if !n.SystemID.is_null() {
500 allocator::xmlFreeImpl(n.SystemID as *mut c_void);
501 }
502 allocator::xmlFreeImpl(notation as *mut c_void);
503 }
504}
505
506pub unsafe fn create_content_model(name: *const xmlChar, type_: c_int) -> *mut _xmlElementContent {
525 let content = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
527 as *mut _xmlElementContent;
528 if content.is_null() {
529 return ptr::null_mut();
530 }
531
532 unsafe {
533 (*content).type_ = type_;
534 (*content).ocur = XML_ELEMENT_CONTENT_ONCE as c_int;
535 (*content).name = string::xml_strdup(name);
536 (*content).c1 = ptr::null_mut();
537 (*content).c2 = ptr::null_mut();
538 (*content).parent = ptr::null_mut();
539 (*content).prefix = ptr::null_mut();
540 }
541
542 content
543}
544
545pub unsafe fn free_content_model(cur: *mut _xmlElementContent) {
559 if cur.is_null() {
560 return;
561 }
562
563 unsafe {
564 let c = &*cur;
565
566 if !c.c1.is_null() {
568 free_content_model(c.c1);
569 }
570 if !c.c2.is_null() {
571 free_content_model(c.c2);
572 }
573
574 if !c.name.is_null() {
576 allocator::xmlFreeImpl(c.name as *mut c_void);
577 }
578 if !c.prefix.is_null() {
579 allocator::xmlFreeImpl(c.prefix as *mut c_void);
580 }
581
582 allocator::xmlFreeImpl(cur as *mut c_void);
583 }
584}
585
586pub unsafe fn copy_content_model(content: *mut _xmlElementContent) -> *mut _xmlElementContent {
600 if content.is_null() {
601 return ptr::null_mut();
602 }
603
604 unsafe {
605 let c = &*content;
606
607 let copy = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
609 as *mut _xmlElementContent;
610 if copy.is_null() {
611 return ptr::null_mut();
612 }
613
614 (*copy).type_ = c.type_;
615 (*copy).ocur = c.ocur;
616 (*copy).name = string::xml_strdup(c.name);
617 (*copy).prefix = string::xml_strdup(c.prefix);
618
619 if !c.c1.is_null() {
621 (*copy).c1 = copy_content_model(c.c1);
622 if !(*copy).c1.is_null() {
623 (*(*copy).c1).parent = copy;
624 }
625 }
626 if !c.c2.is_null() {
627 (*copy).c2 = copy_content_model(c.c2);
628 if !(*copy).c2.is_null() {
629 (*(*copy).c2).parent = copy;
630 }
631 }
632
633 copy
634 }
635}
636
637pub unsafe fn add_element_decl(
658 dtd: *mut _xmlDtd,
659 name: *const xmlChar,
660 type_: c_int,
661 content: *mut _xmlElementContent,
662) -> *mut _xmlElement {
663 if dtd.is_null() || name.is_null() {
664 return ptr::null_mut();
665 }
666
667 unsafe {
668 if (*dtd).elements.is_null() {
671 (*dtd).elements = hash::hash_create(8) as *mut c_void;
672 }
673 let d = &*dtd;
674
675 let existing = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
677 if !existing.is_null() {
678 return existing as *mut _xmlElement;
679 }
680
681 let elem = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
683 if elem.is_null() {
684 return ptr::null_mut();
685 }
686
687 (*elem).name = string::xml_strdup(name);
692 (*elem).type_ = XML_ELEMENT_DECL as c_int;
693 (*elem).etype = type_; (*elem).content = content; (*elem).attributes = ptr::null_mut();
696 (*elem).prefix = ptr::null_mut();
697 (*elem).children = ptr::null_mut();
698 (*elem).last = ptr::null_mut();
699 (*elem).parent = dtd;
700 (*elem).next = ptr::null_mut();
701 (*elem).prev = ptr::null_mut();
702 (*elem).doc = (*dtd).doc;
703 (*elem).cont_model = ptr::null_mut();
704
705 let ret = hash::hash_add_entry(
707 d.elements as *mut hash::HashTable,
708 name,
709 elem as *mut c_void,
710 );
711 if ret != 0 {
712 free_element(elem);
714 return ptr::null_mut();
715 }
716
717 if (*dtd).last.is_null() {
720 (*dtd).children = elem as *mut _xmlNode;
721 (*dtd).last = elem as *mut _xmlNode;
722 } else {
723 (*(*dtd).last).next = elem as *mut _xmlNode;
724 (*elem).prev = (*dtd).last;
725 (*dtd).last = elem as *mut _xmlNode;
726 }
727
728 elem
729 }
730}
731
732pub unsafe fn get_element_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlElement {
745 if dtd.is_null() || name.is_null() {
746 return ptr::null_mut();
747 }
748
749 unsafe {
750 let d = &*dtd;
751 if d.elements.is_null() {
752 return ptr::null_mut();
753 }
754 let payload = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
755 payload as *mut _xmlElement
756 }
757}
758
759pub unsafe fn get_element_decl_created(
770 dtd: *mut _xmlDtd,
771 name: *const xmlChar,
772) -> *mut _xmlElement {
773 if dtd.is_null() || name.is_null() {
774 return ptr::null_mut();
775 }
776
777 unsafe {
778 if (*dtd).elements.is_null() {
779 (*dtd).elements = hash::hash_create(8) as *mut c_void;
780 }
781 let existing = hash::hash_lookup((*dtd).elements as *mut hash::HashTable, name);
782 if !existing.is_null() {
783 return existing as *mut _xmlElement;
784 }
785
786 let elem = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
787 if elem.is_null() {
788 return ptr::null_mut();
789 }
790 (*elem).type_ = XML_ELEMENT_DECL as c_int;
791 (*elem).name = string::xml_strdup(name);
792 (*elem).etype = XML_ELEMENT_TYPE_UNDEFINED as c_int;
793 (*elem).doc = (*dtd).doc;
794 (*elem).parent = dtd;
795 if hash::hash_add_entry(
796 (*dtd).elements as *mut hash::HashTable,
797 name,
798 elem as *mut c_void,
799 ) != 0
800 {
801 free_element(elem);
802 return ptr::null_mut();
803 }
804 elem
805 }
806}
807
808pub unsafe fn copy_element(elem: *mut _xmlElement) -> *mut _xmlElement {
820 if elem.is_null() {
821 return ptr::null_mut();
822 }
823
824 unsafe {
825 let e = &*elem;
826
827 let copy = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
829 if copy.is_null() {
830 return ptr::null_mut();
831 }
832
833 (*copy).name = string::xml_strdup(e.name);
834 (*copy).type_ = e.type_;
835 (*copy).etype = e.etype;
836 (*copy).content = copy_content_model(e.content);
837 (*copy).prefix = string::xml_strdup(e.prefix);
838 (*copy)._private = e._private;
839 (*copy).parent = e.parent;
840 (*copy).doc = e.doc;
841
842 if !e.attributes.is_null() {
844 let mut src_attr = e.attributes;
847 let mut prev_copy: *mut _xmlAttribute = ptr::null_mut();
848 let mut first_copy: *mut _xmlAttribute = ptr::null_mut();
849
850 while !src_attr.is_null() {
851 let attr_copy = copy_attribute_decl(src_attr);
852 if attr_copy.is_null() {
853 let mut to_free = first_copy;
855 while !to_free.is_null() {
856 let next = (*to_free).nexth;
857 free_attribute(to_free);
858 to_free = next;
859 }
860 allocator::xmlFreeImpl(copy as *mut c_void);
861 return ptr::null_mut();
862 }
863
864 if prev_copy.is_null() {
865 first_copy = attr_copy;
866 } else {
867 (*prev_copy).nexth = attr_copy;
868 }
869 prev_copy = attr_copy;
870 src_attr = (*src_attr).nexth;
871 }
872
873 (*copy).attributes = first_copy;
874 }
875
876 copy
877 }
878}
879
880pub unsafe fn free_element(elem: *mut _xmlElement) {
895 if elem.is_null() {
896 return;
897 }
898
899 unsafe {
900 if !(*elem).name.is_null() {
902 allocator::xmlFreeImpl((*elem).name as *mut c_void);
903 }
904
905 if !(*elem).prefix.is_null() {
907 allocator::xmlFreeImpl((*elem).prefix as *mut c_void);
908 }
909
910 if !(*elem).content.is_null() {
912 free_content_model((*elem).content);
913 }
914
915 if !(*elem).cont_model.is_null() {
918 crate::xml::validation::free_content_model_nfa(
919 (*elem).cont_model as *mut crate::xml::validation::ContentModelNfa,
920 );
921 }
922
923 (*elem).attributes = ptr::null_mut();
929
930 allocator::xmlFreeImpl(elem as *mut c_void);
931 }
932}
933
934unsafe fn free_enumeration(tree: *mut _xmlEnumeration) {
944 if tree.is_null() {
945 return;
946 }
947
948 unsafe {
949 let mut cur = tree;
950 while !cur.is_null() {
951 let next = (*cur).next;
952 if !(*cur).name.is_null() {
953 allocator::xmlFreeImpl((*cur).name as *mut c_void);
954 }
955 allocator::xmlFreeImpl(cur as *mut c_void);
956 cur = next;
957 }
958 }
959}
960
961unsafe fn copy_enumeration(tree: *mut _xmlEnumeration) -> *mut _xmlEnumeration {
967 if tree.is_null() {
968 return ptr::null_mut();
969 }
970
971 unsafe {
972 let mut src = tree;
973 let mut first_copy: *mut _xmlEnumeration = ptr::null_mut();
974 let mut prev_copy: *mut _xmlEnumeration = ptr::null_mut();
975
976 while !src.is_null() {
977 let copy = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
978 as *mut _xmlEnumeration;
979 if copy.is_null() {
980 let mut to_free = first_copy;
982 while !to_free.is_null() {
983 let next = (*to_free).next;
984 if !(*to_free).name.is_null() {
985 allocator::xmlFreeImpl((*to_free).name as *mut c_void);
986 }
987 allocator::xmlFreeImpl(to_free as *mut c_void);
988 to_free = next;
989 }
990 return ptr::null_mut();
991 }
992
993 (*copy).name = string::xml_strdup((*src).name);
994 (*copy).next = ptr::null_mut();
995
996 if prev_copy.is_null() {
997 first_copy = copy;
998 } else {
999 (*prev_copy).next = copy;
1000 }
1001 prev_copy = copy;
1002 src = (*src).next;
1003 }
1004
1005 first_copy
1006 }
1007}
1008
1009pub unsafe fn add_attribute_decl(
1031 dtd: *mut _xmlDtd,
1032 elem: *mut _xmlElement,
1033 name: *const xmlChar,
1034 type_: c_int,
1035 def: c_int,
1036 defaultValue: *const xmlChar,
1037 tree: *mut _xmlEnumeration,
1038) -> *mut _xmlAttribute {
1039 if dtd.is_null() || name.is_null() {
1040 return ptr::null_mut();
1041 }
1042
1043 unsafe {
1044 if (*dtd).attributes.is_null() {
1047 (*dtd).attributes = hash::hash_create(8) as *mut c_void;
1048 }
1049 let d = &*dtd;
1050 let elem_name = if elem.is_null() {
1051 ptr::null()
1052 } else {
1053 (*elem).name
1054 };
1055
1056 let existing = hash::hash_lookup3(
1060 d.attributes as *mut hash::HashTable,
1061 name,
1062 ptr::null(),
1063 elem_name,
1064 );
1065 if !existing.is_null() {
1066 return existing as *mut _xmlAttribute;
1067 }
1068
1069 let attr =
1071 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
1072 if attr.is_null() {
1073 return ptr::null_mut();
1074 }
1075
1076 (*attr).type_ = XML_ATTRIBUTE_DECL as c_int;
1077 (*attr).name = string::xml_strdup(name);
1078 (*attr).parent = dtd;
1079 (*attr).doc = d.doc;
1080 (*attr).nexth = ptr::null_mut();
1081 (*attr).atype = type_;
1082 (*attr).def = def;
1083 (*attr).defaultValue = string::xml_strdup(defaultValue);
1084 (*attr).tree = tree; (*attr).prefix = ptr::null_mut();
1086 (*attr).elem = string::xml_strdup(elem_name);
1087
1088 let ret = hash::hash_add_entry3(
1091 d.attributes as *mut hash::HashTable,
1092 name,
1093 ptr::null(),
1094 elem_name,
1095 attr as *mut c_void,
1096 );
1097 if ret != 0 {
1098 if !(*attr).defaultValue.is_null() {
1100 allocator::xmlFreeImpl((*attr).defaultValue as *mut c_void);
1101 }
1102 if !(*attr).name.is_null() {
1103 allocator::xmlFreeImpl((*attr).name as *mut c_void);
1104 }
1105 if !(*attr).elem.is_null() {
1106 allocator::xmlFreeImpl((*attr).elem as *mut c_void);
1107 }
1108 allocator::xmlFreeImpl(attr as *mut c_void);
1109 return ptr::null_mut();
1111 }
1112
1113 if !elem.is_null() {
1115 (*attr).nexth = (*elem).attributes;
1116 (*elem).attributes = attr;
1117 }
1118
1119 if (*dtd).last.is_null() {
1122 (*dtd).children = attr as *mut _xmlNode;
1123 (*dtd).last = attr as *mut _xmlNode;
1124 } else {
1125 (*(*dtd).last).next = attr as *mut _xmlNode;
1126 (*attr).prev = (*dtd).last;
1127 (*dtd).last = attr as *mut _xmlNode;
1128 }
1129
1130 attr
1131 }
1132}
1133
1134pub unsafe fn get_attribute_decl(
1152 dtd: *mut _xmlDtd,
1153 elem: *mut _xmlElement,
1154 name: *const xmlChar,
1155 _namePrefix: c_int,
1156) -> *mut _xmlAttribute {
1157 if dtd.is_null() || name.is_null() {
1158 return ptr::null_mut();
1159 }
1160
1161 unsafe {
1162 let d = &*dtd;
1163 let elem_name = if elem.is_null() {
1164 ptr::null()
1165 } else {
1166 (*elem).name
1167 };
1168
1169 let payload = hash::hash_lookup3(
1172 d.attributes as *mut hash::HashTable,
1173 name,
1174 ptr::null(),
1175 elem_name,
1176 );
1177 payload as *mut _xmlAttribute
1178 }
1179}
1180
1181pub unsafe fn copy_attribute_decl(attr: *mut _xmlAttribute) -> *mut _xmlAttribute {
1193 if attr.is_null() {
1194 return ptr::null_mut();
1195 }
1196
1197 unsafe {
1198 let a = &*attr;
1199
1200 let copy =
1202 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
1203 if copy.is_null() {
1204 return ptr::null_mut();
1205 }
1206
1207 (*copy).type_ = a.type_;
1208 (*copy).name = string::xml_strdup(a.name);
1209 (*copy).parent = a.parent;
1210 (*copy).doc = a.doc;
1211 (*copy).nexth = ptr::null_mut();
1212 (*copy).atype = a.atype;
1213 (*copy).def = a.def;
1214 (*copy).defaultValue = string::xml_strdup(a.defaultValue);
1215 (*copy).tree = copy_enumeration(a.tree);
1216 (*copy).prefix = string::xml_strdup(a.prefix);
1217 (*copy).elem = string::xml_strdup(a.elem);
1218
1219 copy
1220 }
1221}
1222
1223pub unsafe fn free_attribute(attr: *mut _xmlAttribute) {
1235 if attr.is_null() {
1236 return;
1237 }
1238
1239 unsafe {
1240 let a = &*attr;
1241
1242 if !a.name.is_null() {
1243 allocator::xmlFreeImpl(a.name as *mut c_void);
1244 }
1245 if !a.defaultValue.is_null() {
1246 allocator::xmlFreeImpl(a.defaultValue as *mut c_void);
1247 }
1248 if !a.prefix.is_null() {
1249 allocator::xmlFreeImpl(a.prefix as *mut c_void);
1250 }
1251 if !a.elem.is_null() {
1252 allocator::xmlFreeImpl(a.elem as *mut c_void);
1253 }
1254 if !a.tree.is_null() {
1255 free_enumeration(a.tree);
1256 }
1257
1258 allocator::xmlFreeImpl(attr as *mut c_void);
1259 }
1260}
1261
1262#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1268pub enum ContentModelResult {
1269 Valid,
1271 Invalid,
1273 Indeterminate,
1275}
1276
1277pub unsafe fn valid_content_model(
1298 model: *mut _xmlElementContent,
1299 names: &[*const xmlChar],
1300) -> ContentModelResult {
1301 if model.is_null() {
1302 return ContentModelResult::Invalid;
1303 }
1304
1305 unsafe {
1306 let m = &*model;
1307
1308 match m.ocur as u32 {
1310 o if o == XML_ELEMENT_CONTENT_OPT as u32 => {
1311 if names.is_empty() {
1313 return ContentModelResult::Valid;
1314 }
1315 return valid_content_model_inner(model, names);
1316 }
1317 o if o == XML_ELEMENT_CONTENT_MULT as u32 => {
1318 if names.is_empty() {
1320 return ContentModelResult::Valid;
1321 }
1322 return valid_content_model_zero_or_more(model, names);
1323 }
1324 o if o == XML_ELEMENT_CONTENT_PLUS as u32 => {
1325 if names.is_empty() {
1327 return ContentModelResult::Invalid;
1328 }
1329 return valid_content_model_one_or_more(model, names);
1330 }
1331 _ => {}
1332 }
1333
1334 valid_content_model_inner(model, names)
1335 }
1336}
1337
1338unsafe fn valid_content_model_inner(
1340 model: *mut _xmlElementContent,
1341 names: &[*const xmlChar],
1342) -> ContentModelResult {
1343 unsafe {
1344 let m = &*model;
1345
1346 match m.type_ as u32 {
1347 t if t == XML_ELEMENT_CONTENT_PCDATA as u32 => {
1348 if names.is_empty() {
1350 ContentModelResult::Valid
1351 } else {
1352 ContentModelResult::Invalid
1353 }
1354 }
1355 t if t == XML_ELEMENT_CONTENT_ELEMENT as u32 => {
1356 if names.len() != 1 {
1358 return ContentModelResult::Invalid;
1359 }
1360 if names[0].is_null() {
1361 return ContentModelResult::Invalid;
1362 }
1363 if string::xml_strcmp(names[0], m.name) != 0 {
1365 return ContentModelResult::Invalid;
1366 }
1367 ContentModelResult::Valid
1368 }
1369 t if t == XML_ELEMENT_CONTENT_SEQ as u32 => {
1370 valid_content_model_seq(m, names)
1372 }
1373 t if t == XML_ELEMENT_CONTENT_OR as u32 => {
1374 valid_content_model_or(m, names)
1376 }
1377 _ => ContentModelResult::Invalid,
1378 }
1379 }
1380}
1381
1382unsafe fn valid_content_model_zero_or_more(
1384 model: *mut _xmlElementContent,
1385 names: &[*const xmlChar],
1386) -> ContentModelResult {
1387 let mut i = 0;
1389 while i <= names.len() {
1390 let consumed = &names[..i];
1391 let remaining = &names[i..];
1392
1393 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1394 if consumed_valid == ContentModelResult::Valid {
1395 if remaining.is_empty() {
1396 return ContentModelResult::Valid;
1397 }
1398 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1400 if remaining_valid == ContentModelResult::Valid {
1401 return ContentModelResult::Valid;
1402 }
1403 }
1404
1405 i += 1;
1406 }
1407 ContentModelResult::Invalid
1408}
1409
1410unsafe fn valid_content_model_one_or_more(
1412 model: *mut _xmlElementContent,
1413 names: &[*const xmlChar],
1414) -> ContentModelResult {
1415 let mut i = 1;
1417 while i <= names.len() {
1418 let consumed = &names[..i];
1419 let remaining = &names[i..];
1420
1421 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1422 if consumed_valid == ContentModelResult::Valid {
1423 if remaining.is_empty() {
1424 return ContentModelResult::Valid;
1425 }
1426 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1427 if remaining_valid == ContentModelResult::Valid {
1428 return ContentModelResult::Valid;
1429 }
1430 }
1431
1432 i += 1;
1433 }
1434 ContentModelResult::Invalid
1435}
1436
1437unsafe fn valid_content_model_seq(
1439 model: &_xmlElementContent,
1440 names: &[*const xmlChar],
1441) -> ContentModelResult {
1442 let c1 = model.c1;
1447 let c2 = model.c2;
1448
1449 if c1.is_null() && c2.is_null() {
1450 return ContentModelResult::Valid;
1451 }
1452
1453 if c1.is_null() {
1454 return unsafe { valid_content_model(c2, names) };
1455 }
1456
1457 if c2.is_null() {
1458 return unsafe { valid_content_model(c1, names) };
1459 }
1460
1461 for split in 0..=names.len() {
1464 let left = &names[..split];
1465 let right = &names[split..];
1466
1467 let left_valid = unsafe { valid_content_model(c1, left) };
1468 if left_valid != ContentModelResult::Valid {
1469 continue;
1470 }
1471
1472 let right_valid = unsafe { valid_content_model(c2, right) };
1473 if right_valid == ContentModelResult::Valid {
1474 return ContentModelResult::Valid;
1475 }
1476 }
1477
1478 ContentModelResult::Invalid
1479}
1480
1481unsafe fn valid_content_model_or(
1483 model: &_xmlElementContent,
1484 names: &[*const xmlChar],
1485) -> ContentModelResult {
1486 let c1 = model.c1;
1487 let c2 = model.c2;
1488
1489 if c1.is_null() && c2.is_null() {
1490 return ContentModelResult::Invalid;
1491 }
1492
1493 if !c1.is_null() {
1494 let result = unsafe { valid_content_model(c1, names) };
1495 if result == ContentModelResult::Valid {
1496 return ContentModelResult::Valid;
1497 }
1498 }
1499
1500 if !c2.is_null() {
1501 let result = unsafe { valid_content_model(c2, names) };
1502 if result == ContentModelResult::Valid {
1503 return ContentModelResult::Valid;
1504 }
1505 }
1506
1507 ContentModelResult::Invalid
1508}
1509
1510#[cfg(test)]
1515mod tests {
1516 use super::*;
1517 use crate::abi::allocator::xmlFreeImpl;
1518 use crate::abi::structs::*;
1519 use core::ffi::c_void;
1520 use core::ptr;
1521
1522 unsafe fn c_str(s: &[u8]) -> *const xmlChar {
1525 let len = s.len();
1527 let buf = allocator::xmlMallocImpl(len + 1) as *mut xmlChar;
1528 assert!(!buf.is_null());
1529 ptr::copy_nonoverlapping(s.as_ptr(), buf, len);
1530 *buf.add(len) = 0;
1531 buf as *const xmlChar
1532 }
1533
1534 unsafe fn make_doc_and_dtd() -> (*mut _xmlDoc, *mut _xmlDtd) {
1535 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1536 assert!(!doc.is_null());
1537 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1538 (*doc).doc = doc;
1539 let dtd = create_int_subset(doc, c_str(b"root"), ptr::null(), ptr::null());
1540 assert!(!dtd.is_null());
1541 (doc, dtd)
1542 }
1543
1544 #[test]
1547 fn test_get_int_subset_null() {
1548 unsafe {
1549 assert!(get_int_subset(ptr::null()).is_null());
1550 }
1551 }
1552
1553 #[test]
1554 fn test_create_int_subset() {
1555 unsafe {
1556 let (doc, dtd) = make_doc_and_dtd();
1557 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1558 assert!(!(*dtd).name.is_null());
1559 assert_eq!((*doc).intSubset, dtd);
1560
1561 free_dtd(dtd);
1563 allocator::xmlFreeImpl(doc as *mut c_void);
1564 }
1565 }
1566
1567 #[test]
1568 fn test_create_int_subset_null_doc() {
1569 unsafe {
1570 let dtd = create_int_subset(ptr::null_mut(), c_str(b"root"), ptr::null(), ptr::null());
1571 assert!(dtd.is_null());
1572 }
1573 }
1574
1575 #[test]
1576 fn test_new_dtd() {
1577 unsafe {
1578 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1579 assert!(!doc.is_null());
1580 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1581 (*doc).doc = doc;
1582
1583 let dtd = new_dtd(doc, c_str(b"test"), c_str(b"-//TEST//"), c_str(b"test.dtd"));
1584 assert!(!dtd.is_null());
1585 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1586 assert_eq!((*doc).intSubset, dtd);
1587
1588 free_dtd(dtd);
1589 allocator::xmlFreeImpl(doc as *mut c_void);
1590 }
1591 }
1592
1593 #[test]
1594 fn test_new_dtd_no_doc() {
1595 unsafe {
1596 let dtd = new_dtd(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1597 assert!(!dtd.is_null());
1598 free_dtd(dtd);
1599 }
1600 }
1601
1602 #[test]
1605 fn test_add_get_notation() {
1606 unsafe {
1607 let (doc, dtd) = make_doc_and_dtd();
1608 let name = c_str(b"note");
1609 let pubid = c_str(b"-//TEST//NOTATION");
1610 let sysid = c_str(b"note.ent");
1611
1612 let n = add_notation_decl(dtd, name, pubid, sysid);
1613 assert!(!n.is_null());
1614 assert_eq!(string::xml_strcmp((*n).name, name), 0);
1615
1616 let found = get_notation_decl(dtd, name);
1618 assert_eq!(found, n);
1619
1620 let not_found = get_notation_decl(dtd, c_str(b"nonexistent"));
1622 assert!(not_found.is_null());
1623
1624 free_dtd(dtd);
1625 allocator::xmlFreeImpl(doc as *mut c_void);
1626 }
1627 }
1628
1629 #[test]
1630 fn test_add_notation_null_dtd() {
1631 unsafe {
1632 let n = add_notation_decl(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1633 assert!(n.is_null());
1634 }
1635 }
1636
1637 #[test]
1638 fn test_copy_notation() {
1639 unsafe {
1640 let (doc, dtd) = make_doc_and_dtd();
1641 let name = c_str(b"note1");
1642 let pubid = c_str(b"public");
1643 let sysid = c_str(b"system");
1644
1645 let n = add_notation_decl(dtd, name, pubid, sysid);
1646 assert!(!n.is_null());
1647
1648 let copy = copy_notation(n);
1649 assert!(!copy.is_null());
1650 assert_ne!(copy, n);
1651 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1652 assert_eq!(string::xml_strcmp((*copy).PublicID, pubid), 0);
1653 assert_eq!(string::xml_strcmp((*copy).SystemID, sysid), 0);
1654
1655 free_notation(copy);
1656 free_dtd(dtd);
1657 allocator::xmlFreeImpl(doc as *mut c_void);
1658 }
1659 }
1660
1661 #[test]
1662 fn test_copy_notation_null() {
1663 unsafe {
1664 assert!(copy_notation(ptr::null_mut()).is_null());
1665 }
1666 }
1667
1668 #[test]
1669 fn test_free_notation_null() {
1670 unsafe {
1671 free_notation(ptr::null_mut()); }
1673 }
1674
1675 #[test]
1678 fn test_create_free_content_model() {
1679 unsafe {
1680 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1681 assert!(!cm.is_null());
1682 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1683 assert_eq!((*cm).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1684
1685 free_content_model(cm);
1686 }
1687 }
1688
1689 #[test]
1690 fn test_create_content_model_pcdata() {
1691 unsafe {
1692 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1693 assert!(!cm.is_null());
1694 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_PCDATA as c_int);
1695 free_content_model(cm);
1696 }
1697 }
1698
1699 #[test]
1700 fn test_copy_content_model() {
1701 unsafe {
1702 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1703 assert!(!cm.is_null());
1704
1705 let copy = copy_content_model(cm);
1706 assert!(!copy.is_null());
1707 assert_ne!(copy, cm);
1708 assert_eq!((*copy).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1709 assert_eq!((*copy).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1710 assert_eq!(string::xml_strcmp((*copy).name, (*cm).name), 0);
1711
1712 free_content_model(cm);
1713 free_content_model(copy);
1714 }
1715 }
1716
1717 #[test]
1718 fn test_copy_content_model_null() {
1719 unsafe {
1720 assert!(copy_content_model(ptr::null_mut()).is_null());
1721 }
1722 }
1723
1724 #[test]
1725 fn test_free_content_model_null() {
1726 unsafe {
1727 free_content_model(ptr::null_mut()); }
1729 }
1730
1731 #[test]
1732 fn test_create_sequence_content_model() {
1733 unsafe {
1734 let c1 = create_content_model(c_str(b"a"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1735 let c2 = create_content_model(c_str(b"b"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1736 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1737 assert!(!seq.is_null());
1738 (*seq).c1 = c1;
1739 (*seq).c2 = c2;
1740 (*c1).parent = seq;
1741 (*c2).parent = seq;
1742
1743 free_content_model(seq);
1744 }
1745 }
1746
1747 #[test]
1750 fn test_add_get_element() {
1751 unsafe {
1752 let (doc, dtd) = make_doc_and_dtd();
1753 let name = c_str(b"myElement");
1754
1755 let elem =
1756 add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1757 assert!(!elem.is_null());
1758 assert_eq!((*elem).etype, XML_ELEMENT_TYPE_EMPTY as c_int);
1759
1760 let found = get_element_decl(dtd, name);
1761 assert_eq!(found, elem);
1762
1763 let not_found = get_element_decl(dtd, c_str(b"nonexistent"));
1764 assert!(not_found.is_null());
1765
1766 free_dtd(dtd);
1767 allocator::xmlFreeImpl(doc as *mut c_void);
1768 }
1769 }
1770
1771 #[test]
1772 fn test_add_element_duplicate() {
1773 unsafe {
1774 let (doc, dtd) = make_doc_and_dtd();
1775 let name = c_str(b"dup");
1776
1777 let e1 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1778 assert!(!e1.is_null());
1779
1780 let e2 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ANY as c_int, ptr::null_mut());
1781 assert_eq!(e1, e2); assert_eq!((*e2).type_, XML_ELEMENT_DECL as c_int); assert_eq!((*e2).etype, XML_ELEMENT_TYPE_EMPTY as c_int); free_dtd(dtd);
1786 allocator::xmlFreeImpl(doc as *mut c_void);
1787 }
1788 }
1789
1790 #[test]
1791 fn test_add_element_null_dtd() {
1792 unsafe {
1793 let elem = add_element_decl(
1794 ptr::null_mut(),
1795 c_str(b"test"),
1796 XML_ELEMENT_TYPE_EMPTY as c_int,
1797 ptr::null_mut(),
1798 );
1799 assert!(elem.is_null());
1800 }
1801 }
1802
1803 #[test]
1804 fn test_copy_element() {
1805 unsafe {
1806 let (doc, dtd) = make_doc_and_dtd();
1807 let name = c_str(b"source");
1808 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1809
1810 let elem = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ELEMENT as c_int, cm);
1811 assert!(!elem.is_null());
1812
1813 let copy = copy_element(elem);
1814 assert!(!copy.is_null());
1815 assert_ne!(copy, elem);
1816 assert_eq!((*copy).type_, XML_ELEMENT_DECL as c_int);
1817 assert_eq!((*copy).etype, XML_ELEMENT_TYPE_ELEMENT as c_int);
1818 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1819 assert!(!(*copy).content.is_null());
1820 assert_ne!((*copy).content, cm);
1821
1822 free_element(copy);
1823 free_dtd(dtd);
1824 allocator::xmlFreeImpl(doc as *mut c_void);
1825 }
1826 }
1827
1828 #[test]
1829 fn test_free_element_null() {
1830 unsafe {
1831 free_element(ptr::null_mut()); }
1833 }
1834
1835 #[test]
1838 fn test_add_get_attribute() {
1839 unsafe {
1840 let (doc, dtd) = make_doc_and_dtd();
1841 let elem_name = c_str(b"elem");
1842 let attr_name = c_str(b"attr1");
1843
1844 let elem = add_element_decl(
1845 dtd,
1846 elem_name,
1847 XML_ELEMENT_TYPE_EMPTY as c_int,
1848 ptr::null_mut(),
1849 );
1850 assert!(!elem.is_null());
1851
1852 let attr = add_attribute_decl(
1853 dtd,
1854 elem,
1855 attr_name,
1856 XML_ATTRIBUTE_CDATA as c_int,
1857 XML_ATTRIBUTE_IMPLIED as c_int,
1858 ptr::null(),
1859 ptr::null_mut(),
1860 );
1861 assert!(!attr.is_null());
1862 assert_eq!((*attr).atype, XML_ATTRIBUTE_CDATA as c_int);
1863 assert_eq!((*attr).def, XML_ATTRIBUTE_IMPLIED as c_int);
1864
1865 let found = get_attribute_decl(dtd, elem, attr_name, 0);
1867 assert_eq!(found, attr);
1868
1869 let not_found = get_attribute_decl(dtd, elem, c_str(b"nonexistent"), 0);
1871 assert!(not_found.is_null());
1872
1873 free_dtd(dtd);
1874 allocator::xmlFreeImpl(doc as *mut c_void);
1875 }
1876 }
1877
1878 #[test]
1879 fn test_add_attribute_with_default() {
1880 unsafe {
1881 let (doc, dtd) = make_doc_and_dtd();
1882 let elem_name = c_str(b"elem");
1883 let attr_name = c_str(b"color");
1884 let default_val = c_str(b"red");
1885
1886 let elem = add_element_decl(
1887 dtd,
1888 elem_name,
1889 XML_ELEMENT_TYPE_EMPTY as c_int,
1890 ptr::null_mut(),
1891 );
1892
1893 let attr = add_attribute_decl(
1894 dtd,
1895 elem,
1896 attr_name,
1897 XML_ATTRIBUTE_CDATA as c_int,
1898 XML_ATTRIBUTE_FIXED as c_int,
1899 default_val,
1900 ptr::null_mut(),
1901 );
1902 assert!(!attr.is_null());
1903 assert_eq!((*attr).def, XML_ATTRIBUTE_FIXED as c_int);
1904 assert_eq!(string::xml_strcmp((*attr).defaultValue, default_val), 0);
1905
1906 free_dtd(dtd);
1907 allocator::xmlFreeImpl(doc as *mut c_void);
1908 }
1909 }
1910
1911 #[test]
1912 fn test_add_attribute_enumeration() {
1913 unsafe {
1914 let (doc, dtd) = make_doc_and_dtd();
1915 let elem_name = c_str(b"elem");
1916 let attr_name = c_str(b"size");
1917
1918 let v3 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1920 as *mut _xmlEnumeration;
1921 (*v3).name = string::xml_strdup(c_str(b"large"));
1922 let v2 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1923 as *mut _xmlEnumeration;
1924 (*v2).name = string::xml_strdup(c_str(b"medium"));
1925 (*v2).next = v3;
1926 let v1 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1927 as *mut _xmlEnumeration;
1928 (*v1).name = string::xml_strdup(c_str(b"small"));
1929 (*v1).next = v2;
1930
1931 let elem = add_element_decl(
1932 dtd,
1933 elem_name,
1934 XML_ELEMENT_TYPE_EMPTY as c_int,
1935 ptr::null_mut(),
1936 );
1937 let attr = add_attribute_decl(
1938 dtd,
1939 elem,
1940 attr_name,
1941 XML_ATTRIBUTE_ENUMERATION as c_int,
1942 XML_ATTRIBUTE_REQUIRED as c_int,
1943 ptr::null(),
1944 v1,
1945 );
1946 assert!(!attr.is_null());
1947 assert_eq!((*attr).atype, XML_ATTRIBUTE_ENUMERATION as c_int);
1948
1949 free_dtd(dtd);
1950 allocator::xmlFreeImpl(doc as *mut c_void);
1951 }
1952 }
1953
1954 #[test]
1955 fn test_add_attribute_null_dtd() {
1956 unsafe {
1957 let attr = add_attribute_decl(
1958 ptr::null_mut(),
1959 ptr::null_mut(),
1960 c_str(b"test"),
1961 XML_ATTRIBUTE_CDATA as c_int,
1962 XML_ATTRIBUTE_IMPLIED as c_int,
1963 ptr::null(),
1964 ptr::null_mut(),
1965 );
1966 assert!(attr.is_null());
1967 }
1968 }
1969
1970 #[test]
1971 fn test_copy_attribute() {
1972 unsafe {
1973 let (doc, dtd) = make_doc_and_dtd();
1974 let elem_name = c_str(b"elem");
1975 let attr_name = c_str(b"id");
1976 let default_val = c_str(b"default");
1977
1978 let elem = add_element_decl(
1979 dtd,
1980 elem_name,
1981 XML_ELEMENT_TYPE_EMPTY as c_int,
1982 ptr::null_mut(),
1983 );
1984 let attr = add_attribute_decl(
1985 dtd,
1986 elem,
1987 attr_name,
1988 XML_ATTRIBUTE_ID as c_int,
1989 XML_ATTRIBUTE_IMPLIED as c_int,
1990 default_val,
1991 ptr::null_mut(),
1992 );
1993 assert!(!attr.is_null());
1994
1995 let copy = copy_attribute_decl(attr);
1996 assert!(!copy.is_null());
1997 assert_ne!(copy, attr);
1998 assert_eq!((*copy).atype, XML_ATTRIBUTE_ID as c_int);
1999 assert_eq!(string::xml_strcmp((*copy).name, attr_name), 0);
2000
2001 free_attribute(copy);
2002 free_dtd(dtd);
2003 allocator::xmlFreeImpl(doc as *mut c_void);
2004 }
2005 }
2006
2007 #[test]
2008 fn test_free_attribute_null() {
2009 unsafe {
2010 free_attribute(ptr::null_mut()); }
2012 }
2013
2014 #[test]
2017 fn test_valid_content_model_null() {
2018 unsafe {
2019 assert_eq!(
2020 valid_content_model(ptr::null_mut(), &[]),
2021 ContentModelResult::Invalid
2022 );
2023 }
2024 }
2025
2026 #[test]
2027 fn test_valid_content_model_pcdata() {
2028 unsafe {
2029 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
2030 assert!(!cm.is_null());
2031
2032 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Valid);
2034
2035 let name = c_str(b"child");
2037 assert_eq!(
2038 valid_content_model(cm, &[name]),
2039 ContentModelResult::Invalid
2040 );
2041
2042 free_content_model(cm);
2043 }
2044 }
2045
2046 #[test]
2047 fn test_valid_content_model_element() {
2048 unsafe {
2049 let child_name = c_str(b"child");
2050 let cm = create_content_model(child_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2051 assert!(!cm.is_null());
2052
2053 assert_eq!(
2055 valid_content_model(cm, &[child_name]),
2056 ContentModelResult::Valid
2057 );
2058
2059 let other = c_str(b"other");
2061 assert_eq!(
2062 valid_content_model(cm, &[other]),
2063 ContentModelResult::Invalid
2064 );
2065
2066 assert_eq!(
2068 valid_content_model(cm, &[child_name, child_name]),
2069 ContentModelResult::Invalid
2070 );
2071
2072 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Invalid);
2074
2075 free_content_model(cm);
2076 }
2077 }
2078
2079 #[test]
2080 fn test_valid_content_model_seq() {
2081 unsafe {
2082 let a_name = c_str(b"a");
2083 let b_name = c_str(b"b");
2084
2085 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2086 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2087 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
2088 (*seq).c1 = c1;
2089 (*seq).c2 = c2;
2090 (*c1).parent = seq;
2091 (*c2).parent = seq;
2092
2093 assert_eq!(
2095 valid_content_model(seq, &[a_name, b_name]),
2096 ContentModelResult::Valid
2097 );
2098
2099 assert_eq!(
2101 valid_content_model(seq, &[b_name, a_name]),
2102 ContentModelResult::Invalid
2103 );
2104
2105 assert_eq!(
2107 valid_content_model(seq, &[a_name]),
2108 ContentModelResult::Invalid
2109 );
2110
2111 free_content_model(seq);
2112 }
2113 }
2114
2115 #[test]
2116 fn test_valid_content_model_or() {
2117 unsafe {
2118 let a_name = c_str(b"a");
2119 let b_name = c_str(b"b");
2120
2121 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2122 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2123 let choice = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_OR as c_int);
2124 (*choice).c1 = c1;
2125 (*choice).c2 = c2;
2126 (*c1).parent = choice;
2127 (*c2).parent = choice;
2128
2129 assert_eq!(
2131 valid_content_model(choice, &[a_name]),
2132 ContentModelResult::Valid
2133 );
2134
2135 assert_eq!(
2137 valid_content_model(choice, &[b_name]),
2138 ContentModelResult::Valid
2139 );
2140
2141 let other = c_str(b"other");
2143 assert_eq!(
2144 valid_content_model(choice, &[other]),
2145 ContentModelResult::Invalid
2146 );
2147
2148 free_content_model(choice);
2149 }
2150 }
2151
2152 #[test]
2153 fn test_valid_content_model_optional() {
2154 unsafe {
2155 let a_name = c_str(b"a");
2156
2157 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2158 (*c1).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
2159
2160 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2162
2163 assert_eq!(
2165 valid_content_model(c1, &[a_name]),
2166 ContentModelResult::Valid
2167 );
2168
2169 free_content_model(c1);
2170 }
2171 }
2172
2173 #[test]
2174 fn test_valid_content_model_zero_or_more() {
2175 unsafe {
2176 let a_name = c_str(b"a");
2177
2178 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2179 (*c1).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2180
2181 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2183
2184 assert_eq!(
2186 valid_content_model(c1, &[a_name]),
2187 ContentModelResult::Valid
2188 );
2189
2190 assert_eq!(
2192 valid_content_model(c1, &[a_name, a_name, a_name]),
2193 ContentModelResult::Valid
2194 );
2195
2196 free_content_model(c1);
2197 }
2198 }
2199
2200 #[test]
2201 fn test_valid_content_model_one_or_more() {
2202 unsafe {
2203 let a_name = c_str(b"a");
2204
2205 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2206 (*c1).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2207
2208 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Invalid);
2210
2211 assert_eq!(
2213 valid_content_model(c1, &[a_name]),
2214 ContentModelResult::Valid
2215 );
2216
2217 assert_eq!(
2219 valid_content_model(c1, &[a_name, a_name]),
2220 ContentModelResult::Valid
2221 );
2222
2223 free_content_model(c1);
2224 }
2225 }
2226}