1use core::ffi::c_void;
11use core::ptr;
12use std::os::raw::c_int;
13
14use crate::abi::allocator;
15use crate::abi::structs::*;
16use crate::abi::types::xmlElementContentOccur::*;
17use crate::abi::types::xmlElementContentType::*;
18use crate::abi::types::xmlElementType::*;
19use crate::abi::types::xmlElementTypeVal::*;
20use crate::abi::types::*;
21use crate::xml::hash;
22use crate::xml::string;
23
24#[cfg(test)]
25use crate::abi::types::xmlAttributeDefault::*;
26#[cfg(test)]
27use crate::abi::types::xmlAttributeType::*;
28
29pub const fn get_int_subset(doc: *const _xmlDoc) -> *mut _xmlDtd {
43 if doc.is_null() {
44 return ptr::null_mut();
45 }
46 unsafe { (*doc).intSubset }
47}
48
49pub unsafe fn create_int_subset(
66 doc: *mut _xmlDoc,
67 name: *const xmlChar,
68 ExternalID: *const xmlChar,
69 SystemID: *const xmlChar,
70) -> *mut _xmlDtd {
71 if doc.is_null() {
72 return ptr::null_mut();
73 }
74
75 if !(*doc).intSubset.is_null() {
78 return (*doc).intSubset;
79 }
80
81 let dtd = allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd;
83 if dtd.is_null() {
84 return ptr::null_mut();
85 }
86
87 unsafe {
88 (*dtd).type_ = XML_DTD_NODE as c_int;
89 (*dtd).name = string::xml_strdup(name);
90 (*dtd).ExternalID = string::xml_strdup(ExternalID);
91 (*dtd).SystemID = string::xml_strdup(SystemID);
92 (*dtd).parent = doc;
93 (*dtd).doc = doc;
94
95 (*doc).intSubset = dtd;
101
102 let doc_children = (*doc).children;
106 if doc_children.is_null() {
107 (*doc).children = dtd as *mut _xmlNode;
108 (*doc).last = dtd as *mut _xmlNode;
109 } else {
110 let mut next = doc_children;
111 while !next.is_null() && (*next).type_ != XML_ELEMENT_NODE as c_int {
112 next = (*next).next;
113 }
114 if next.is_null() {
115 (*dtd).prev = (*doc).last;
116 (*(*doc).last).next = dtd as *mut _xmlNode;
117 (*doc).last = dtd as *mut _xmlNode;
118 } else {
119 (*dtd).next = next;
120 (*dtd).prev = (*next).prev;
121 if (*dtd).prev.is_null() {
122 (*doc).children = dtd as *mut _xmlNode;
123 } else {
124 (*(*dtd).prev).next = dtd as *mut _xmlNode;
125 }
126 (*next).prev = dtd as *mut _xmlNode;
127 }
128 }
129 }
130
131 dtd
132}
133
134pub unsafe fn new_dtd(
151 doc: *mut _xmlDoc,
152 name: *const xmlChar,
153 ExternalID: *const xmlChar,
154 SystemID: *const xmlChar,
155) -> *mut _xmlDtd {
156 let dtd = allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd;
158 if dtd.is_null() {
159 return ptr::null_mut();
160 }
161
162 unsafe {
163 (*dtd).type_ = XML_DTD_NODE as c_int;
164 (*dtd).name = string::xml_strdup(name);
165 (*dtd).ExternalID = string::xml_strdup(ExternalID);
166 (*dtd).SystemID = string::xml_strdup(SystemID);
167 (*dtd).parent = doc;
168 (*dtd).doc = doc;
169
170 if !doc.is_null() && (*doc).intSubset.is_null() {
175 (*doc).intSubset = dtd;
176 }
177 }
178
179 dtd
180}
181
182unsafe extern "C" fn copy_elem_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
184 unsafe { copy_element(payload as *mut _xmlElement) as *mut c_void }
185}
186
187unsafe extern "C" fn copy_attr_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
188 unsafe { copy_attribute_decl(payload as *mut _xmlAttribute) as *mut c_void }
189}
190
191unsafe extern "C" fn copy_ent_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
192 unsafe { crate::xml::entities::copy_entity(payload as *mut _xmlEntity) as *mut c_void }
193}
194
195unsafe extern "C" fn copy_notation_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
196 unsafe { copy_notation(payload as *mut _xmlNotation) as *mut c_void }
197}
198
199pub unsafe fn copy_dtd(dtd: *const _xmlDtd) -> *mut _xmlDtd {
209 if dtd.is_null() {
210 return ptr::null_mut();
211 }
212 let d = unsafe { &*dtd };
213
214 let copy = unsafe { allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd };
215 if copy.is_null() {
216 return ptr::null_mut();
217 }
218
219 unsafe {
220 (*copy).type_ = d.type_;
221 (*copy).name = string::xml_strdup(d.name);
222 (*copy).ExternalID = string::xml_strdup(d.ExternalID);
223 (*copy).SystemID = string::xml_strdup(d.SystemID);
224 (*copy).notations =
225 hash::hash_copy(d.notations as *mut hash::HashTable, Some(copy_notation_cb))
226 as *mut c_void;
227 (*copy).elements =
228 hash::hash_copy(d.elements as *mut hash::HashTable, Some(copy_elem_cb)) as *mut c_void;
229 (*copy).attributes =
230 hash::hash_copy(d.attributes as *mut hash::HashTable, Some(copy_attr_cb))
231 as *mut c_void;
232 (*copy).entities =
233 hash::hash_copy(d.entities as *mut hash::HashTable, Some(copy_ent_cb)) as *mut c_void;
234 (*copy).pentities =
235 hash::hash_copy(d.pentities as *mut hash::HashTable, Some(copy_ent_cb)) as *mut c_void;
236 }
237
238 copy
239}
240
241pub unsafe fn free_dtd(dtd: *mut _xmlDtd) {
253 if dtd.is_null() {
254 return;
255 }
256
257 unsafe {
258 let d = &mut *dtd;
259
260 if !d.children.is_null() {
267 let mut c = d.children;
268 while !c.is_null() {
269 let next = (*c).next;
270 let t = (*c).type_;
271 if t != XML_ELEMENT_DECL as c_int
272 && t != XML_ATTRIBUTE_DECL as c_int
273 && t != XML_ENTITY_DECL as c_int
274 {
275 crate::xml::tree::free_node(c);
276 }
277 c = next;
278 }
279 }
280
281 if !d.notations.is_null() {
283 hash::hash_free(
284 d.notations as *mut hash::HashTable,
285 Some(notation_deallocator),
286 );
287 d.notations = ptr::null_mut();
288 }
289 if !d.elements.is_null() {
290 hash::hash_free(
291 d.elements as *mut hash::HashTable,
292 Some(element_deallocator),
293 );
294 d.elements = ptr::null_mut();
295 }
296 if !d.attributes.is_null() {
297 hash::hash_free(
298 d.attributes as *mut hash::HashTable,
299 Some(attribute_deallocator),
300 );
301 d.attributes = ptr::null_mut();
302 }
303 if !d.entities.is_null() {
304 hash::hash_free(d.entities as *mut hash::HashTable, Some(entity_deallocator));
305 d.entities = ptr::null_mut();
306 }
307 if !d.pentities.is_null() {
308 hash::hash_free(
309 d.pentities as *mut hash::HashTable,
310 Some(entity_deallocator),
311 );
312 d.pentities = ptr::null_mut();
313 }
314
315 if !d.name.is_null() {
317 allocator::xmlFreeImpl(d.name as *mut c_void);
318 }
319 if !d.ExternalID.is_null() {
320 allocator::xmlFreeImpl(d.ExternalID as *mut c_void);
321 }
322 if !d.SystemID.is_null() {
323 allocator::xmlFreeImpl(d.SystemID as *mut c_void);
324 }
325
326 allocator::xmlFreeImpl(dtd as *mut c_void);
327 }
328}
329
330unsafe extern "C" fn notation_deallocator(payload: *mut c_void, _name: *mut u8) {
335 if !payload.is_null() {
336 free_notation(payload as *mut _xmlNotation);
337 }
338}
339
340unsafe extern "C" fn element_deallocator(payload: *mut c_void, _name: *mut u8) {
341 if !payload.is_null() {
342 free_element(payload as *mut _xmlElement);
343 }
344}
345
346unsafe extern "C" fn attribute_deallocator(payload: *mut c_void, _name: *mut u8) {
347 if !payload.is_null() {
348 free_attribute(payload as *mut _xmlAttribute);
349 }
350}
351
352unsafe extern "C" fn entity_deallocator(payload: *mut c_void, _name: *mut u8) {
353 if !payload.is_null() {
354 crate::xml::entities::free_entity(payload as *mut _xmlEntity);
355 }
356}
357
358pub unsafe fn add_notation_decl(
378 dtd: *mut _xmlDtd,
379 name: *const xmlChar,
380 PublicID: *const xmlChar,
381 SystemID: *const xmlChar,
382) -> *mut _xmlNotation {
383 if dtd.is_null() || name.is_null() {
384 return ptr::null_mut();
385 }
386
387 unsafe {
388 if (*dtd).notations.is_null() {
391 (*dtd).notations = hash::hash_create(8) as *mut c_void;
392 }
393 let d = &*dtd;
394
395 let existing = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
397 if !existing.is_null() {
398 return existing as *mut _xmlNotation;
399 }
400
401 let not = allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
403 if not.is_null() {
404 return ptr::null_mut();
405 }
406
407 (*not).name = string::xml_strdup(name);
408 (*not).PublicID = string::xml_strdup(PublicID);
409 (*not).SystemID = string::xml_strdup(SystemID);
410
411 let ret = hash::hash_add_entry(
413 d.notations as *mut hash::HashTable,
414 name,
415 not as *mut c_void,
416 );
417 if ret != 0 {
418 free_notation(not);
420 return ptr::null_mut();
421 }
422
423 not
424 }
425}
426
427pub unsafe fn get_notation_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlNotation {
440 if dtd.is_null() || name.is_null() {
441 return ptr::null_mut();
442 }
443
444 unsafe {
445 let d = &*dtd;
446 let payload = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
447 payload as *mut _xmlNotation
448 }
449}
450
451pub unsafe fn copy_notation(notation: *mut _xmlNotation) -> *mut _xmlNotation {
463 if notation.is_null() {
464 return ptr::null_mut();
465 }
466
467 unsafe {
468 let n = &*notation;
469 let copy =
471 allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
472 if copy.is_null() {
473 return ptr::null_mut();
474 }
475
476 (*copy).name = string::xml_strdup(n.name);
477 (*copy).PublicID = string::xml_strdup(n.PublicID);
478 (*copy).SystemID = string::xml_strdup(n.SystemID);
479
480 copy
481 }
482}
483
484pub unsafe fn free_notation(notation: *mut _xmlNotation) {
496 if notation.is_null() {
497 return;
498 }
499
500 unsafe {
501 let n = &*notation;
502 if !n.name.is_null() {
503 allocator::xmlFreeImpl(n.name as *mut c_void);
504 }
505 if !n.PublicID.is_null() {
506 allocator::xmlFreeImpl(n.PublicID as *mut c_void);
507 }
508 if !n.SystemID.is_null() {
509 allocator::xmlFreeImpl(n.SystemID as *mut c_void);
510 }
511 allocator::xmlFreeImpl(notation as *mut c_void);
512 }
513}
514
515pub unsafe fn create_content_model(name: *const xmlChar, type_: c_int) -> *mut _xmlElementContent {
534 let content = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
536 as *mut _xmlElementContent;
537 if content.is_null() {
538 return ptr::null_mut();
539 }
540
541 unsafe {
542 (*content).type_ = type_;
543 (*content).ocur = XML_ELEMENT_CONTENT_ONCE as c_int;
544 (*content).name = string::xml_strdup(name);
545 (*content).c1 = ptr::null_mut();
546 (*content).c2 = ptr::null_mut();
547 (*content).parent = ptr::null_mut();
548 (*content).prefix = ptr::null_mut();
549 }
550
551 content
552}
553
554pub unsafe fn free_content_model(cur: *mut _xmlElementContent) {
568 if cur.is_null() {
569 return;
570 }
571
572 unsafe {
573 let c = &*cur;
574
575 if !c.c1.is_null() {
577 free_content_model(c.c1);
578 }
579 if !c.c2.is_null() {
580 free_content_model(c.c2);
581 }
582
583 if !c.name.is_null() {
585 allocator::xmlFreeImpl(c.name as *mut c_void);
586 }
587 if !c.prefix.is_null() {
588 allocator::xmlFreeImpl(c.prefix as *mut c_void);
589 }
590
591 allocator::xmlFreeImpl(cur as *mut c_void);
592 }
593}
594
595pub unsafe fn copy_content_model(content: *mut _xmlElementContent) -> *mut _xmlElementContent {
609 if content.is_null() {
610 return ptr::null_mut();
611 }
612
613 unsafe {
614 let c = &*content;
615
616 let copy = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
618 as *mut _xmlElementContent;
619 if copy.is_null() {
620 return ptr::null_mut();
621 }
622
623 (*copy).type_ = c.type_;
624 (*copy).ocur = c.ocur;
625 (*copy).name = string::xml_strdup(c.name);
626 (*copy).prefix = string::xml_strdup(c.prefix);
627
628 if !c.c1.is_null() {
630 (*copy).c1 = copy_content_model(c.c1);
631 if !(*copy).c1.is_null() {
632 (*(*copy).c1).parent = copy;
633 }
634 }
635 if !c.c2.is_null() {
636 (*copy).c2 = copy_content_model(c.c2);
637 if !(*copy).c2.is_null() {
638 (*(*copy).c2).parent = copy;
639 }
640 }
641
642 copy
643 }
644}
645
646pub unsafe fn add_element_decl(
667 dtd: *mut _xmlDtd,
668 name: *const xmlChar,
669 type_: c_int,
670 content: *mut _xmlElementContent,
671) -> *mut _xmlElement {
672 if dtd.is_null() || name.is_null() {
673 return ptr::null_mut();
674 }
675
676 unsafe {
677 if (*dtd).elements.is_null() {
680 (*dtd).elements = hash::hash_create(8) as *mut c_void;
681 }
682 let d = &*dtd;
683
684 let existing = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
686 if !existing.is_null() {
687 return existing as *mut _xmlElement;
688 }
689
690 let elem = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
692 if elem.is_null() {
693 return ptr::null_mut();
694 }
695
696 (*elem).name = string::xml_strdup(name);
701 (*elem).type_ = XML_ELEMENT_DECL as c_int;
702 (*elem).etype = type_; (*elem).content = content; (*elem).attributes = ptr::null_mut();
705 (*elem).prefix = ptr::null_mut();
706 (*elem).children = ptr::null_mut();
707 (*elem).last = ptr::null_mut();
708 (*elem).parent = dtd;
709 (*elem).next = ptr::null_mut();
710 (*elem).prev = ptr::null_mut();
711 (*elem).doc = (*dtd).doc;
712 (*elem).cont_model = ptr::null_mut();
713
714 let ret = hash::hash_add_entry(
716 d.elements as *mut hash::HashTable,
717 name,
718 elem as *mut c_void,
719 );
720 if ret != 0 {
721 free_element(elem);
723 return ptr::null_mut();
724 }
725
726 if (*dtd).last.is_null() {
729 (*dtd).children = elem as *mut _xmlNode;
730 (*dtd).last = elem as *mut _xmlNode;
731 } else {
732 (*(*dtd).last).next = elem as *mut _xmlNode;
733 (*elem).prev = (*dtd).last;
734 (*dtd).last = elem as *mut _xmlNode;
735 }
736
737 elem
738 }
739}
740
741pub unsafe fn get_element_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlElement {
754 if dtd.is_null() || name.is_null() {
755 return ptr::null_mut();
756 }
757
758 unsafe {
759 let d = &*dtd;
760 if d.elements.is_null() {
761 return ptr::null_mut();
762 }
763 let payload = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
764 payload as *mut _xmlElement
765 }
766}
767
768pub unsafe fn get_element_decl_created(
779 dtd: *mut _xmlDtd,
780 name: *const xmlChar,
781) -> *mut _xmlElement {
782 if dtd.is_null() || name.is_null() {
783 return ptr::null_mut();
784 }
785
786 unsafe {
787 if (*dtd).elements.is_null() {
788 (*dtd).elements = hash::hash_create(8) as *mut c_void;
789 }
790 let existing = hash::hash_lookup((*dtd).elements as *mut hash::HashTable, name);
791 if !existing.is_null() {
792 return existing as *mut _xmlElement;
793 }
794
795 let elem = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
796 if elem.is_null() {
797 return ptr::null_mut();
798 }
799 (*elem).type_ = XML_ELEMENT_DECL as c_int;
800 (*elem).name = string::xml_strdup(name);
801 (*elem).etype = XML_ELEMENT_TYPE_UNDEFINED as c_int;
802 (*elem).doc = (*dtd).doc;
803 (*elem).parent = dtd;
804 if hash::hash_add_entry(
805 (*dtd).elements as *mut hash::HashTable,
806 name,
807 elem as *mut c_void,
808 ) != 0
809 {
810 free_element(elem);
811 return ptr::null_mut();
812 }
813 elem
814 }
815}
816
817pub unsafe fn copy_element(elem: *mut _xmlElement) -> *mut _xmlElement {
829 if elem.is_null() {
830 return ptr::null_mut();
831 }
832
833 unsafe {
834 let e = &*elem;
835
836 let copy = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
838 if copy.is_null() {
839 return ptr::null_mut();
840 }
841
842 (*copy).name = string::xml_strdup(e.name);
843 (*copy).type_ = e.type_;
844 (*copy).etype = e.etype;
845 (*copy).content = copy_content_model(e.content);
846 (*copy).prefix = string::xml_strdup(e.prefix);
847 (*copy)._private = e._private;
848 (*copy).parent = e.parent;
849 (*copy).doc = e.doc;
850
851 if !e.attributes.is_null() {
853 let mut src_attr = e.attributes;
856 let mut prev_copy: *mut _xmlAttribute = ptr::null_mut();
857 let mut first_copy: *mut _xmlAttribute = ptr::null_mut();
858
859 while !src_attr.is_null() {
860 let attr_copy = copy_attribute_decl(src_attr);
861 if attr_copy.is_null() {
862 let mut to_free = first_copy;
864 while !to_free.is_null() {
865 let next = (*to_free).nexth;
866 free_attribute(to_free);
867 to_free = next;
868 }
869 allocator::xmlFreeImpl(copy as *mut c_void);
870 return ptr::null_mut();
871 }
872
873 if prev_copy.is_null() {
874 first_copy = attr_copy;
875 } else {
876 (*prev_copy).nexth = attr_copy;
877 }
878 prev_copy = attr_copy;
879 src_attr = (*src_attr).nexth;
880 }
881
882 (*copy).attributes = first_copy;
883 }
884
885 copy
886 }
887}
888
889pub unsafe fn free_element(elem: *mut _xmlElement) {
904 if elem.is_null() {
905 return;
906 }
907
908 unsafe {
909 if !(*elem).name.is_null() {
911 allocator::xmlFreeImpl((*elem).name as *mut c_void);
912 }
913
914 if !(*elem).prefix.is_null() {
916 allocator::xmlFreeImpl((*elem).prefix as *mut c_void);
917 }
918
919 if !(*elem).content.is_null() {
921 free_content_model((*elem).content);
922 }
923
924 if !(*elem).cont_model.is_null() {
927 crate::xml::validation::free_content_model_nfa(
928 (*elem).cont_model as *mut crate::xml::validation::ContentModelNfa,
929 );
930 }
931
932 (*elem).attributes = ptr::null_mut();
938
939 allocator::xmlFreeImpl(elem as *mut c_void);
940 }
941}
942
943unsafe fn free_enumeration(tree: *mut _xmlEnumeration) {
953 if tree.is_null() {
954 return;
955 }
956
957 unsafe {
958 let mut cur = tree;
959 while !cur.is_null() {
960 let next = (*cur).next;
961 if !(*cur).name.is_null() {
962 allocator::xmlFreeImpl((*cur).name as *mut c_void);
963 }
964 allocator::xmlFreeImpl(cur as *mut c_void);
965 cur = next;
966 }
967 }
968}
969
970unsafe fn copy_enumeration(tree: *mut _xmlEnumeration) -> *mut _xmlEnumeration {
976 if tree.is_null() {
977 return ptr::null_mut();
978 }
979
980 unsafe {
981 let mut src = tree;
982 let mut first_copy: *mut _xmlEnumeration = ptr::null_mut();
983 let mut prev_copy: *mut _xmlEnumeration = ptr::null_mut();
984
985 while !src.is_null() {
986 let copy = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
987 as *mut _xmlEnumeration;
988 if copy.is_null() {
989 let mut to_free = first_copy;
991 while !to_free.is_null() {
992 let next = (*to_free).next;
993 if !(*to_free).name.is_null() {
994 allocator::xmlFreeImpl((*to_free).name as *mut c_void);
995 }
996 allocator::xmlFreeImpl(to_free as *mut c_void);
997 to_free = next;
998 }
999 return ptr::null_mut();
1000 }
1001
1002 (*copy).name = string::xml_strdup((*src).name);
1003 (*copy).next = ptr::null_mut();
1004
1005 if prev_copy.is_null() {
1006 first_copy = copy;
1007 } else {
1008 (*prev_copy).next = copy;
1009 }
1010 prev_copy = copy;
1011 src = (*src).next;
1012 }
1013
1014 first_copy
1015 }
1016}
1017
1018pub unsafe fn add_attribute_decl(
1040 dtd: *mut _xmlDtd,
1041 elem: *mut _xmlElement,
1042 name: *const xmlChar,
1043 type_: c_int,
1044 def: c_int,
1045 defaultValue: *const xmlChar,
1046 tree: *mut _xmlEnumeration,
1047) -> *mut _xmlAttribute {
1048 if dtd.is_null() || name.is_null() {
1049 return ptr::null_mut();
1050 }
1051
1052 unsafe {
1053 if (*dtd).attributes.is_null() {
1056 (*dtd).attributes = hash::hash_create(8) as *mut c_void;
1057 }
1058 let d = &*dtd;
1059 let elem_name = if elem.is_null() {
1060 ptr::null()
1061 } else {
1062 (*elem).name
1063 };
1064
1065 let existing = hash::hash_lookup3(
1069 d.attributes as *mut hash::HashTable,
1070 name,
1071 ptr::null(),
1072 elem_name,
1073 );
1074 if !existing.is_null() {
1075 return existing as *mut _xmlAttribute;
1076 }
1077
1078 let attr =
1080 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
1081 if attr.is_null() {
1082 return ptr::null_mut();
1083 }
1084
1085 (*attr).type_ = XML_ATTRIBUTE_DECL as c_int;
1086 (*attr).name = string::xml_strdup(name);
1087 (*attr).parent = dtd;
1088 (*attr).doc = d.doc;
1089 (*attr).nexth = ptr::null_mut();
1090 (*attr).atype = type_;
1091 (*attr).def = def;
1092 (*attr).defaultValue = string::xml_strdup(defaultValue);
1093 (*attr).tree = tree; (*attr).prefix = ptr::null_mut();
1095 (*attr).elem = string::xml_strdup(elem_name);
1096
1097 let ret = hash::hash_add_entry3(
1100 d.attributes as *mut hash::HashTable,
1101 name,
1102 ptr::null(),
1103 elem_name,
1104 attr as *mut c_void,
1105 );
1106 if ret != 0 {
1107 if !(*attr).defaultValue.is_null() {
1109 allocator::xmlFreeImpl((*attr).defaultValue as *mut c_void);
1110 }
1111 if !(*attr).name.is_null() {
1112 allocator::xmlFreeImpl((*attr).name as *mut c_void);
1113 }
1114 if !(*attr).elem.is_null() {
1115 allocator::xmlFreeImpl((*attr).elem as *mut c_void);
1116 }
1117 allocator::xmlFreeImpl(attr as *mut c_void);
1118 return ptr::null_mut();
1120 }
1121
1122 if !elem.is_null() {
1124 (*attr).nexth = (*elem).attributes;
1125 (*elem).attributes = attr;
1126 }
1127
1128 if (*dtd).last.is_null() {
1131 (*dtd).children = attr as *mut _xmlNode;
1132 (*dtd).last = attr as *mut _xmlNode;
1133 } else {
1134 (*(*dtd).last).next = attr as *mut _xmlNode;
1135 (*attr).prev = (*dtd).last;
1136 (*dtd).last = attr as *mut _xmlNode;
1137 }
1138
1139 attr
1140 }
1141}
1142
1143pub unsafe fn get_attribute_decl(
1161 dtd: *mut _xmlDtd,
1162 elem: *mut _xmlElement,
1163 name: *const xmlChar,
1164 _namePrefix: c_int,
1165) -> *mut _xmlAttribute {
1166 if dtd.is_null() || name.is_null() {
1167 return ptr::null_mut();
1168 }
1169
1170 unsafe {
1171 let d = &*dtd;
1172 let elem_name = if elem.is_null() {
1173 ptr::null()
1174 } else {
1175 (*elem).name
1176 };
1177
1178 let payload = hash::hash_lookup3(
1181 d.attributes as *mut hash::HashTable,
1182 name,
1183 ptr::null(),
1184 elem_name,
1185 );
1186 payload as *mut _xmlAttribute
1187 }
1188}
1189
1190pub unsafe fn copy_attribute_decl(attr: *mut _xmlAttribute) -> *mut _xmlAttribute {
1202 if attr.is_null() {
1203 return ptr::null_mut();
1204 }
1205
1206 unsafe {
1207 let a = &*attr;
1208
1209 let copy =
1211 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
1212 if copy.is_null() {
1213 return ptr::null_mut();
1214 }
1215
1216 (*copy).type_ = a.type_;
1217 (*copy).name = string::xml_strdup(a.name);
1218 (*copy).parent = a.parent;
1219 (*copy).doc = a.doc;
1220 (*copy).nexth = ptr::null_mut();
1221 (*copy).atype = a.atype;
1222 (*copy).def = a.def;
1223 (*copy).defaultValue = string::xml_strdup(a.defaultValue);
1224 (*copy).tree = copy_enumeration(a.tree);
1225 (*copy).prefix = string::xml_strdup(a.prefix);
1226 (*copy).elem = string::xml_strdup(a.elem);
1227
1228 copy
1229 }
1230}
1231
1232pub unsafe fn free_attribute(attr: *mut _xmlAttribute) {
1244 if attr.is_null() {
1245 return;
1246 }
1247
1248 unsafe {
1249 let a = &*attr;
1250
1251 if !a.name.is_null() {
1252 allocator::xmlFreeImpl(a.name as *mut c_void);
1253 }
1254 if !a.defaultValue.is_null() {
1255 allocator::xmlFreeImpl(a.defaultValue as *mut c_void);
1256 }
1257 if !a.prefix.is_null() {
1258 allocator::xmlFreeImpl(a.prefix as *mut c_void);
1259 }
1260 if !a.elem.is_null() {
1261 allocator::xmlFreeImpl(a.elem as *mut c_void);
1262 }
1263 if !a.tree.is_null() {
1264 free_enumeration(a.tree);
1265 }
1266
1267 allocator::xmlFreeImpl(attr as *mut c_void);
1268 }
1269}
1270
1271#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1277pub enum ContentModelResult {
1278 Valid,
1280 Invalid,
1282 Indeterminate,
1284}
1285
1286pub unsafe fn valid_content_model(
1307 model: *mut _xmlElementContent,
1308 names: &[*const xmlChar],
1309) -> ContentModelResult {
1310 if model.is_null() {
1311 return ContentModelResult::Invalid;
1312 }
1313
1314 unsafe {
1315 let m = &*model;
1316
1317 match m.ocur as u32 {
1319 o if o == XML_ELEMENT_CONTENT_OPT as u32 => {
1320 if names.is_empty() {
1322 return ContentModelResult::Valid;
1323 }
1324 return valid_content_model_inner(model, names);
1325 }
1326 o if o == XML_ELEMENT_CONTENT_MULT as u32 => {
1327 if names.is_empty() {
1329 return ContentModelResult::Valid;
1330 }
1331 return valid_content_model_zero_or_more(model, names);
1332 }
1333 o if o == XML_ELEMENT_CONTENT_PLUS as u32 => {
1334 if names.is_empty() {
1336 return ContentModelResult::Invalid;
1337 }
1338 return valid_content_model_one_or_more(model, names);
1339 }
1340 _ => {}
1341 }
1342
1343 valid_content_model_inner(model, names)
1344 }
1345}
1346
1347unsafe fn valid_content_model_inner(
1349 model: *mut _xmlElementContent,
1350 names: &[*const xmlChar],
1351) -> ContentModelResult {
1352 unsafe {
1353 let m = &*model;
1354
1355 match m.type_ as u32 {
1356 t if t == XML_ELEMENT_CONTENT_PCDATA as u32 => {
1357 if names.is_empty() {
1359 ContentModelResult::Valid
1360 } else {
1361 ContentModelResult::Invalid
1362 }
1363 }
1364 t if t == XML_ELEMENT_CONTENT_ELEMENT as u32 => {
1365 if names.len() != 1 {
1367 return ContentModelResult::Invalid;
1368 }
1369 if names[0].is_null() {
1370 return ContentModelResult::Invalid;
1371 }
1372 if string::xml_strcmp(names[0], m.name) != 0 {
1374 return ContentModelResult::Invalid;
1375 }
1376 ContentModelResult::Valid
1377 }
1378 t if t == XML_ELEMENT_CONTENT_SEQ as u32 => {
1379 valid_content_model_seq(m, names)
1381 }
1382 t if t == XML_ELEMENT_CONTENT_OR as u32 => {
1383 valid_content_model_or(m, names)
1385 }
1386 _ => ContentModelResult::Invalid,
1387 }
1388 }
1389}
1390
1391unsafe fn valid_content_model_zero_or_more(
1393 model: *mut _xmlElementContent,
1394 names: &[*const xmlChar],
1395) -> ContentModelResult {
1396 let mut i = 0;
1398 while i <= names.len() {
1399 let consumed = &names[..i];
1400 let remaining = &names[i..];
1401
1402 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1403 if consumed_valid == ContentModelResult::Valid {
1404 if remaining.is_empty() {
1405 return ContentModelResult::Valid;
1406 }
1407 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1409 if remaining_valid == ContentModelResult::Valid {
1410 return ContentModelResult::Valid;
1411 }
1412 }
1413
1414 i += 1;
1415 }
1416 ContentModelResult::Invalid
1417}
1418
1419unsafe fn valid_content_model_one_or_more(
1421 model: *mut _xmlElementContent,
1422 names: &[*const xmlChar],
1423) -> ContentModelResult {
1424 let mut i = 1;
1426 while i <= names.len() {
1427 let consumed = &names[..i];
1428 let remaining = &names[i..];
1429
1430 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1431 if consumed_valid == ContentModelResult::Valid {
1432 if remaining.is_empty() {
1433 return ContentModelResult::Valid;
1434 }
1435 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1436 if remaining_valid == ContentModelResult::Valid {
1437 return ContentModelResult::Valid;
1438 }
1439 }
1440
1441 i += 1;
1442 }
1443 ContentModelResult::Invalid
1444}
1445
1446unsafe fn valid_content_model_seq(
1448 model: &_xmlElementContent,
1449 names: &[*const xmlChar],
1450) -> ContentModelResult {
1451 let c1 = model.c1;
1456 let c2 = model.c2;
1457
1458 if c1.is_null() && c2.is_null() {
1459 return ContentModelResult::Valid;
1460 }
1461
1462 if c1.is_null() {
1463 return unsafe { valid_content_model(c2, names) };
1464 }
1465
1466 if c2.is_null() {
1467 return unsafe { valid_content_model(c1, names) };
1468 }
1469
1470 for split in 0..=names.len() {
1473 let left = &names[..split];
1474 let right = &names[split..];
1475
1476 let left_valid = unsafe { valid_content_model(c1, left) };
1477 if left_valid != ContentModelResult::Valid {
1478 continue;
1479 }
1480
1481 let right_valid = unsafe { valid_content_model(c2, right) };
1482 if right_valid == ContentModelResult::Valid {
1483 return ContentModelResult::Valid;
1484 }
1485 }
1486
1487 ContentModelResult::Invalid
1488}
1489
1490unsafe fn valid_content_model_or(
1492 model: &_xmlElementContent,
1493 names: &[*const xmlChar],
1494) -> ContentModelResult {
1495 let c1 = model.c1;
1496 let c2 = model.c2;
1497
1498 if c1.is_null() && c2.is_null() {
1499 return ContentModelResult::Invalid;
1500 }
1501
1502 if !c1.is_null() {
1503 let result = unsafe { valid_content_model(c1, names) };
1504 if result == ContentModelResult::Valid {
1505 return ContentModelResult::Valid;
1506 }
1507 }
1508
1509 if !c2.is_null() {
1510 let result = unsafe { valid_content_model(c2, names) };
1511 if result == ContentModelResult::Valid {
1512 return ContentModelResult::Valid;
1513 }
1514 }
1515
1516 ContentModelResult::Invalid
1517}
1518
1519#[cfg(test)]
1524mod tests {
1525 use super::*;
1526
1527 use core::ffi::c_void;
1528 use core::ptr;
1529
1530 unsafe fn c_str(s: &[u8]) -> *const xmlChar {
1533 let len = s.len();
1535 let buf = allocator::xmlMallocImpl(len + 1) as *mut xmlChar;
1536 assert!(!buf.is_null());
1537 ptr::copy_nonoverlapping(s.as_ptr(), buf, len);
1538 *buf.add(len) = 0;
1539 buf as *const xmlChar
1540 }
1541
1542 unsafe fn make_doc_and_dtd() -> (*mut _xmlDoc, *mut _xmlDtd) {
1543 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1544 assert!(!doc.is_null());
1545 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1546 (*doc).doc = doc;
1547 let dtd = create_int_subset(doc, c_str(b"root"), ptr::null(), ptr::null());
1548 assert!(!dtd.is_null());
1549 (doc, dtd)
1550 }
1551
1552 #[test]
1555 fn test_get_int_subset_null() {
1556 {
1557 assert!(get_int_subset(ptr::null()).is_null());
1558 }
1559 }
1560
1561 #[test]
1562 fn test_create_int_subset() {
1563 unsafe {
1564 let (doc, dtd) = make_doc_and_dtd();
1565 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1566 assert!(!(*dtd).name.is_null());
1567 assert_eq!((*doc).intSubset, dtd);
1568
1569 free_dtd(dtd);
1571 allocator::xmlFreeImpl(doc as *mut c_void);
1572 }
1573 }
1574
1575 #[test]
1576 fn test_create_int_subset_null_doc() {
1577 unsafe {
1578 let dtd = create_int_subset(ptr::null_mut(), c_str(b"root"), ptr::null(), ptr::null());
1579 assert!(dtd.is_null());
1580 }
1581 }
1582
1583 #[test]
1584 fn test_new_dtd() {
1585 unsafe {
1586 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1587 assert!(!doc.is_null());
1588 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1589 (*doc).doc = doc;
1590
1591 let dtd = new_dtd(doc, c_str(b"test"), c_str(b"-//TEST//"), c_str(b"test.dtd"));
1592 assert!(!dtd.is_null());
1593 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1594 assert_eq!((*doc).intSubset, dtd);
1595
1596 free_dtd(dtd);
1597 allocator::xmlFreeImpl(doc as *mut c_void);
1598 }
1599 }
1600
1601 #[test]
1602 fn test_new_dtd_no_doc() {
1603 unsafe {
1604 let dtd = new_dtd(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1605 assert!(!dtd.is_null());
1606 free_dtd(dtd);
1607 }
1608 }
1609
1610 #[test]
1613 fn test_add_get_notation() {
1614 unsafe {
1615 let (doc, dtd) = make_doc_and_dtd();
1616 let name = c_str(b"note");
1617 let pubid = c_str(b"-//TEST//NOTATION");
1618 let sysid = c_str(b"note.ent");
1619
1620 let n = add_notation_decl(dtd, name, pubid, sysid);
1621 assert!(!n.is_null());
1622 assert_eq!(string::xml_strcmp((*n).name, name), 0);
1623
1624 let found = get_notation_decl(dtd, name);
1626 assert_eq!(found, n);
1627
1628 let not_found = get_notation_decl(dtd, c_str(b"nonexistent"));
1630 assert!(not_found.is_null());
1631
1632 free_dtd(dtd);
1633 allocator::xmlFreeImpl(doc as *mut c_void);
1634 }
1635 }
1636
1637 #[test]
1638 fn test_add_notation_null_dtd() {
1639 unsafe {
1640 let n = add_notation_decl(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1641 assert!(n.is_null());
1642 }
1643 }
1644
1645 #[test]
1646 fn test_copy_notation() {
1647 unsafe {
1648 let (doc, dtd) = make_doc_and_dtd();
1649 let name = c_str(b"note1");
1650 let pubid = c_str(b"public");
1651 let sysid = c_str(b"system");
1652
1653 let n = add_notation_decl(dtd, name, pubid, sysid);
1654 assert!(!n.is_null());
1655
1656 let copy = copy_notation(n);
1657 assert!(!copy.is_null());
1658 assert_ne!(copy, n);
1659 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1660 assert_eq!(string::xml_strcmp((*copy).PublicID, pubid), 0);
1661 assert_eq!(string::xml_strcmp((*copy).SystemID, sysid), 0);
1662
1663 free_notation(copy);
1664 free_dtd(dtd);
1665 allocator::xmlFreeImpl(doc as *mut c_void);
1666 }
1667 }
1668
1669 #[test]
1670 fn test_copy_notation_null() {
1671 unsafe {
1672 assert!(copy_notation(ptr::null_mut()).is_null());
1673 }
1674 }
1675
1676 #[test]
1677 fn test_free_notation_null() {
1678 unsafe {
1679 free_notation(ptr::null_mut()); }
1681 }
1682
1683 #[test]
1686 fn test_create_free_content_model() {
1687 unsafe {
1688 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1689 assert!(!cm.is_null());
1690 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1691 assert_eq!((*cm).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1692
1693 free_content_model(cm);
1694 }
1695 }
1696
1697 #[test]
1698 fn test_create_content_model_pcdata() {
1699 unsafe {
1700 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1701 assert!(!cm.is_null());
1702 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_PCDATA as c_int);
1703 free_content_model(cm);
1704 }
1705 }
1706
1707 #[test]
1708 fn test_copy_content_model() {
1709 unsafe {
1710 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1711 assert!(!cm.is_null());
1712
1713 let copy = copy_content_model(cm);
1714 assert!(!copy.is_null());
1715 assert_ne!(copy, cm);
1716 assert_eq!((*copy).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1717 assert_eq!((*copy).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1718 assert_eq!(string::xml_strcmp((*copy).name, (*cm).name), 0);
1719
1720 free_content_model(cm);
1721 free_content_model(copy);
1722 }
1723 }
1724
1725 #[test]
1726 fn test_copy_content_model_null() {
1727 unsafe {
1728 assert!(copy_content_model(ptr::null_mut()).is_null());
1729 }
1730 }
1731
1732 #[test]
1733 fn test_free_content_model_null() {
1734 unsafe {
1735 free_content_model(ptr::null_mut()); }
1737 }
1738
1739 #[test]
1740 fn test_create_sequence_content_model() {
1741 unsafe {
1742 let c1 = create_content_model(c_str(b"a"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1743 let c2 = create_content_model(c_str(b"b"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1744 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1745 assert!(!seq.is_null());
1746 (*seq).c1 = c1;
1747 (*seq).c2 = c2;
1748 (*c1).parent = seq;
1749 (*c2).parent = seq;
1750
1751 free_content_model(seq);
1752 }
1753 }
1754
1755 #[test]
1758 fn test_add_get_element() {
1759 unsafe {
1760 let (doc, dtd) = make_doc_and_dtd();
1761 let name = c_str(b"myElement");
1762
1763 let elem =
1764 add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1765 assert!(!elem.is_null());
1766 assert_eq!((*elem).etype, XML_ELEMENT_TYPE_EMPTY as c_int);
1767
1768 let found = get_element_decl(dtd, name);
1769 assert_eq!(found, elem);
1770
1771 let not_found = get_element_decl(dtd, c_str(b"nonexistent"));
1772 assert!(not_found.is_null());
1773
1774 free_dtd(dtd);
1775 allocator::xmlFreeImpl(doc as *mut c_void);
1776 }
1777 }
1778
1779 #[test]
1780 fn test_add_element_duplicate() {
1781 unsafe {
1782 let (doc, dtd) = make_doc_and_dtd();
1783 let name = c_str(b"dup");
1784
1785 let e1 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1786 assert!(!e1.is_null());
1787
1788 let e2 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ANY as c_int, ptr::null_mut());
1789 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);
1794 allocator::xmlFreeImpl(doc as *mut c_void);
1795 }
1796 }
1797
1798 #[test]
1799 fn test_add_element_null_dtd() {
1800 unsafe {
1801 let elem = add_element_decl(
1802 ptr::null_mut(),
1803 c_str(b"test"),
1804 XML_ELEMENT_TYPE_EMPTY as c_int,
1805 ptr::null_mut(),
1806 );
1807 assert!(elem.is_null());
1808 }
1809 }
1810
1811 #[test]
1812 fn test_copy_element() {
1813 unsafe {
1814 let (doc, dtd) = make_doc_and_dtd();
1815 let name = c_str(b"source");
1816 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1817
1818 let elem = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ELEMENT as c_int, cm);
1819 assert!(!elem.is_null());
1820
1821 let copy = copy_element(elem);
1822 assert!(!copy.is_null());
1823 assert_ne!(copy, elem);
1824 assert_eq!((*copy).type_, XML_ELEMENT_DECL as c_int);
1825 assert_eq!((*copy).etype, XML_ELEMENT_TYPE_ELEMENT as c_int);
1826 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1827 assert!(!(*copy).content.is_null());
1828 assert_ne!((*copy).content, cm);
1829
1830 free_element(copy);
1831 free_dtd(dtd);
1832 allocator::xmlFreeImpl(doc as *mut c_void);
1833 }
1834 }
1835
1836 #[test]
1837 fn test_free_element_null() {
1838 unsafe {
1839 free_element(ptr::null_mut()); }
1841 }
1842
1843 #[test]
1846 fn test_add_get_attribute() {
1847 unsafe {
1848 let (doc, dtd) = make_doc_and_dtd();
1849 let elem_name = c_str(b"elem");
1850 let attr_name = c_str(b"attr1");
1851
1852 let elem = add_element_decl(
1853 dtd,
1854 elem_name,
1855 XML_ELEMENT_TYPE_EMPTY as c_int,
1856 ptr::null_mut(),
1857 );
1858 assert!(!elem.is_null());
1859
1860 let attr = add_attribute_decl(
1861 dtd,
1862 elem,
1863 attr_name,
1864 XML_ATTRIBUTE_CDATA as c_int,
1865 XML_ATTRIBUTE_IMPLIED as c_int,
1866 ptr::null(),
1867 ptr::null_mut(),
1868 );
1869 assert!(!attr.is_null());
1870 assert_eq!((*attr).atype, XML_ATTRIBUTE_CDATA as c_int);
1871 assert_eq!((*attr).def, XML_ATTRIBUTE_IMPLIED as c_int);
1872
1873 let found = get_attribute_decl(dtd, elem, attr_name, 0);
1875 assert_eq!(found, attr);
1876
1877 let not_found = get_attribute_decl(dtd, elem, c_str(b"nonexistent"), 0);
1879 assert!(not_found.is_null());
1880
1881 free_dtd(dtd);
1882 allocator::xmlFreeImpl(doc as *mut c_void);
1883 }
1884 }
1885
1886 #[test]
1887 fn test_add_attribute_with_default() {
1888 unsafe {
1889 let (doc, dtd) = make_doc_and_dtd();
1890 let elem_name = c_str(b"elem");
1891 let attr_name = c_str(b"color");
1892 let default_val = c_str(b"red");
1893
1894 let elem = add_element_decl(
1895 dtd,
1896 elem_name,
1897 XML_ELEMENT_TYPE_EMPTY as c_int,
1898 ptr::null_mut(),
1899 );
1900
1901 let attr = add_attribute_decl(
1902 dtd,
1903 elem,
1904 attr_name,
1905 XML_ATTRIBUTE_CDATA as c_int,
1906 XML_ATTRIBUTE_FIXED as c_int,
1907 default_val,
1908 ptr::null_mut(),
1909 );
1910 assert!(!attr.is_null());
1911 assert_eq!((*attr).def, XML_ATTRIBUTE_FIXED as c_int);
1912 assert_eq!(string::xml_strcmp((*attr).defaultValue, default_val), 0);
1913
1914 free_dtd(dtd);
1915 allocator::xmlFreeImpl(doc as *mut c_void);
1916 }
1917 }
1918
1919 #[test]
1920 fn test_add_attribute_enumeration() {
1921 unsafe {
1922 let (doc, dtd) = make_doc_and_dtd();
1923 let elem_name = c_str(b"elem");
1924 let attr_name = c_str(b"size");
1925
1926 let v3 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1928 as *mut _xmlEnumeration;
1929 (*v3).name = string::xml_strdup(c_str(b"large"));
1930 let v2 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1931 as *mut _xmlEnumeration;
1932 (*v2).name = string::xml_strdup(c_str(b"medium"));
1933 (*v2).next = v3;
1934 let v1 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1935 as *mut _xmlEnumeration;
1936 (*v1).name = string::xml_strdup(c_str(b"small"));
1937 (*v1).next = v2;
1938
1939 let elem = add_element_decl(
1940 dtd,
1941 elem_name,
1942 XML_ELEMENT_TYPE_EMPTY as c_int,
1943 ptr::null_mut(),
1944 );
1945 let attr = add_attribute_decl(
1946 dtd,
1947 elem,
1948 attr_name,
1949 XML_ATTRIBUTE_ENUMERATION as c_int,
1950 XML_ATTRIBUTE_REQUIRED as c_int,
1951 ptr::null(),
1952 v1,
1953 );
1954 assert!(!attr.is_null());
1955 assert_eq!((*attr).atype, XML_ATTRIBUTE_ENUMERATION as c_int);
1956
1957 free_dtd(dtd);
1958 allocator::xmlFreeImpl(doc as *mut c_void);
1959 }
1960 }
1961
1962 #[test]
1963 fn test_add_attribute_null_dtd() {
1964 unsafe {
1965 let attr = add_attribute_decl(
1966 ptr::null_mut(),
1967 ptr::null_mut(),
1968 c_str(b"test"),
1969 XML_ATTRIBUTE_CDATA as c_int,
1970 XML_ATTRIBUTE_IMPLIED as c_int,
1971 ptr::null(),
1972 ptr::null_mut(),
1973 );
1974 assert!(attr.is_null());
1975 }
1976 }
1977
1978 #[test]
1979 fn test_copy_attribute() {
1980 unsafe {
1981 let (doc, dtd) = make_doc_and_dtd();
1982 let elem_name = c_str(b"elem");
1983 let attr_name = c_str(b"id");
1984 let default_val = c_str(b"default");
1985
1986 let elem = add_element_decl(
1987 dtd,
1988 elem_name,
1989 XML_ELEMENT_TYPE_EMPTY as c_int,
1990 ptr::null_mut(),
1991 );
1992 let attr = add_attribute_decl(
1993 dtd,
1994 elem,
1995 attr_name,
1996 XML_ATTRIBUTE_ID as c_int,
1997 XML_ATTRIBUTE_IMPLIED as c_int,
1998 default_val,
1999 ptr::null_mut(),
2000 );
2001 assert!(!attr.is_null());
2002
2003 let copy = copy_attribute_decl(attr);
2004 assert!(!copy.is_null());
2005 assert_ne!(copy, attr);
2006 assert_eq!((*copy).atype, XML_ATTRIBUTE_ID as c_int);
2007 assert_eq!(string::xml_strcmp((*copy).name, attr_name), 0);
2008
2009 free_attribute(copy);
2010 free_dtd(dtd);
2011 allocator::xmlFreeImpl(doc as *mut c_void);
2012 }
2013 }
2014
2015 #[test]
2016 fn test_free_attribute_null() {
2017 unsafe {
2018 free_attribute(ptr::null_mut()); }
2020 }
2021
2022 #[test]
2025 fn test_valid_content_model_null() {
2026 unsafe {
2027 assert_eq!(
2028 valid_content_model(ptr::null_mut(), &[]),
2029 ContentModelResult::Invalid
2030 );
2031 }
2032 }
2033
2034 #[test]
2035 fn test_valid_content_model_pcdata() {
2036 unsafe {
2037 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
2038 assert!(!cm.is_null());
2039
2040 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Valid);
2042
2043 let name = c_str(b"child");
2045 assert_eq!(
2046 valid_content_model(cm, &[name]),
2047 ContentModelResult::Invalid
2048 );
2049
2050 free_content_model(cm);
2051 }
2052 }
2053
2054 #[test]
2055 fn test_valid_content_model_element() {
2056 unsafe {
2057 let child_name = c_str(b"child");
2058 let cm = create_content_model(child_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2059 assert!(!cm.is_null());
2060
2061 assert_eq!(
2063 valid_content_model(cm, &[child_name]),
2064 ContentModelResult::Valid
2065 );
2066
2067 let other = c_str(b"other");
2069 assert_eq!(
2070 valid_content_model(cm, &[other]),
2071 ContentModelResult::Invalid
2072 );
2073
2074 assert_eq!(
2076 valid_content_model(cm, &[child_name, child_name]),
2077 ContentModelResult::Invalid
2078 );
2079
2080 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Invalid);
2082
2083 free_content_model(cm);
2084 }
2085 }
2086
2087 #[test]
2088 fn test_valid_content_model_seq() {
2089 unsafe {
2090 let a_name = c_str(b"a");
2091 let b_name = c_str(b"b");
2092
2093 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2094 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2095 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
2096 (*seq).c1 = c1;
2097 (*seq).c2 = c2;
2098 (*c1).parent = seq;
2099 (*c2).parent = seq;
2100
2101 assert_eq!(
2103 valid_content_model(seq, &[a_name, b_name]),
2104 ContentModelResult::Valid
2105 );
2106
2107 assert_eq!(
2109 valid_content_model(seq, &[b_name, a_name]),
2110 ContentModelResult::Invalid
2111 );
2112
2113 assert_eq!(
2115 valid_content_model(seq, &[a_name]),
2116 ContentModelResult::Invalid
2117 );
2118
2119 free_content_model(seq);
2120 }
2121 }
2122
2123 #[test]
2124 fn test_valid_content_model_or() {
2125 unsafe {
2126 let a_name = c_str(b"a");
2127 let b_name = c_str(b"b");
2128
2129 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2130 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2131 let choice = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_OR as c_int);
2132 (*choice).c1 = c1;
2133 (*choice).c2 = c2;
2134 (*c1).parent = choice;
2135 (*c2).parent = choice;
2136
2137 assert_eq!(
2139 valid_content_model(choice, &[a_name]),
2140 ContentModelResult::Valid
2141 );
2142
2143 assert_eq!(
2145 valid_content_model(choice, &[b_name]),
2146 ContentModelResult::Valid
2147 );
2148
2149 let other = c_str(b"other");
2151 assert_eq!(
2152 valid_content_model(choice, &[other]),
2153 ContentModelResult::Invalid
2154 );
2155
2156 free_content_model(choice);
2157 }
2158 }
2159
2160 #[test]
2161 fn test_valid_content_model_optional() {
2162 unsafe {
2163 let a_name = c_str(b"a");
2164
2165 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2166 (*c1).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
2167
2168 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2170
2171 assert_eq!(
2173 valid_content_model(c1, &[a_name]),
2174 ContentModelResult::Valid
2175 );
2176
2177 free_content_model(c1);
2178 }
2179 }
2180
2181 #[test]
2182 fn test_valid_content_model_zero_or_more() {
2183 unsafe {
2184 let a_name = c_str(b"a");
2185
2186 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2187 (*c1).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2188
2189 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2191
2192 assert_eq!(
2194 valid_content_model(c1, &[a_name]),
2195 ContentModelResult::Valid
2196 );
2197
2198 assert_eq!(
2200 valid_content_model(c1, &[a_name, a_name, a_name]),
2201 ContentModelResult::Valid
2202 );
2203
2204 free_content_model(c1);
2205 }
2206 }
2207
2208 #[test]
2209 fn test_valid_content_model_one_or_more() {
2210 unsafe {
2211 let a_name = c_str(b"a");
2212
2213 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2214 (*c1).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2215
2216 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Invalid);
2218
2219 assert_eq!(
2221 valid_content_model(c1, &[a_name]),
2222 ContentModelResult::Valid
2223 );
2224
2225 assert_eq!(
2227 valid_content_model(c1, &[a_name, a_name]),
2228 ContentModelResult::Valid
2229 );
2230
2231 free_content_model(c1);
2232 }
2233 }
2234}