1use core::ffi::c_void;
65use core::ptr;
66use std::os::raw::c_int;
67
68use crate::abi::allocator;
69use crate::abi::structs::*;
70use crate::abi::types::xmlElementContentOccur::*;
71use crate::abi::types::xmlElementContentType::*;
72use crate::abi::types::xmlElementType::*;
73use crate::abi::types::xmlElementTypeVal::*;
74use crate::abi::types::*;
75use crate::xml::hash;
76use crate::xml::string;
77
78#[cfg(test)]
79use crate::abi::types::xmlAttributeDefault::*;
80#[cfg(test)]
81use crate::abi::types::xmlAttributeType::*;
82
83pub const fn get_int_subset(doc: *const _xmlDoc) -> *mut _xmlDtd {
97 if doc.is_null() {
98 return ptr::null_mut();
99 }
100 unsafe { (*doc).intSubset }
101}
102
103pub unsafe fn create_int_subset(
120 doc: *mut _xmlDoc,
121 name: *const xmlChar,
122 ExternalID: *const xmlChar,
123 SystemID: *const xmlChar,
124) -> *mut _xmlDtd {
125 if doc.is_null() {
126 return ptr::null_mut();
127 }
128
129 if !(*doc).intSubset.is_null() {
132 return (*doc).intSubset;
133 }
134
135 let dtd = allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd;
137 if dtd.is_null() {
138 return ptr::null_mut();
139 }
140
141 unsafe {
142 (*dtd).type_ = XML_DTD_NODE as c_int;
143 (*dtd).name = string::xml_strdup(name);
144 (*dtd).ExternalID = string::xml_strdup(ExternalID);
145 (*dtd).SystemID = string::xml_strdup(SystemID);
146 (*dtd).parent = doc;
147 (*dtd).doc = doc;
148
149 (*doc).intSubset = dtd;
155
156 let doc_children = (*doc).children;
160 if doc_children.is_null() {
161 (*doc).children = dtd as *mut _xmlNode;
162 (*doc).last = dtd as *mut _xmlNode;
163 } else {
164 let mut next = doc_children;
165 while !next.is_null() && (*next).type_ != XML_ELEMENT_NODE as c_int {
166 next = (*next).next;
167 }
168 if next.is_null() {
169 (*dtd).prev = (*doc).last;
170 (*(*doc).last).next = dtd as *mut _xmlNode;
171 (*doc).last = dtd as *mut _xmlNode;
172 } else {
173 (*dtd).next = next;
174 (*dtd).prev = (*next).prev;
175 if (*dtd).prev.is_null() {
176 (*doc).children = dtd as *mut _xmlNode;
177 } else {
178 (*(*dtd).prev).next = dtd as *mut _xmlNode;
179 }
180 (*next).prev = dtd as *mut _xmlNode;
181 }
182 }
183 }
184
185 dtd
186}
187
188pub unsafe fn new_dtd(
205 doc: *mut _xmlDoc,
206 name: *const xmlChar,
207 ExternalID: *const xmlChar,
208 SystemID: *const xmlChar,
209) -> *mut _xmlDtd {
210 let dtd = allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd;
212 if dtd.is_null() {
213 return ptr::null_mut();
214 }
215
216 unsafe {
217 (*dtd).type_ = XML_DTD_NODE as c_int;
218 (*dtd).name = string::xml_strdup(name);
219 (*dtd).ExternalID = string::xml_strdup(ExternalID);
220 (*dtd).SystemID = string::xml_strdup(SystemID);
221 (*dtd).parent = doc;
222 (*dtd).doc = doc;
223
224 if !doc.is_null() && (*doc).intSubset.is_null() {
229 (*doc).intSubset = dtd;
230 }
231 }
232
233 dtd
234}
235
236unsafe extern "C" fn copy_elem_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
238 unsafe { copy_element(payload as *mut _xmlElement) as *mut c_void }
239}
240
241unsafe extern "C" fn copy_attr_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
242 unsafe { copy_attribute_decl(payload as *mut _xmlAttribute) as *mut c_void }
243}
244
245unsafe extern "C" fn copy_ent_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
246 unsafe { crate::xml::entities::copy_entity(payload as *mut _xmlEntity) as *mut c_void }
247}
248
249unsafe extern "C" fn copy_notation_cb(payload: *mut c_void, _name: *const xmlChar) -> *mut c_void {
250 unsafe { copy_notation(payload as *mut _xmlNotation) as *mut c_void }
251}
252
253pub unsafe fn copy_dtd(dtd: *const _xmlDtd) -> *mut _xmlDtd {
263 if dtd.is_null() {
264 return ptr::null_mut();
265 }
266 let d = unsafe { &*dtd };
267
268 let copy = unsafe { allocator::xmlMallocZero(size_of::<_xmlDtd>() as usize) as *mut _xmlDtd };
269 if copy.is_null() {
270 return ptr::null_mut();
271 }
272
273 unsafe {
274 (*copy).type_ = d.type_;
275 (*copy).name = string::xml_strdup(d.name);
276 (*copy).ExternalID = string::xml_strdup(d.ExternalID);
277 (*copy).SystemID = string::xml_strdup(d.SystemID);
278 (*copy).notations =
279 hash::hash_copy(d.notations as *mut hash::HashTable, Some(copy_notation_cb))
280 as *mut c_void;
281 (*copy).elements =
282 hash::hash_copy(d.elements as *mut hash::HashTable, Some(copy_elem_cb)) as *mut c_void;
283 (*copy).attributes =
284 hash::hash_copy(d.attributes as *mut hash::HashTable, Some(copy_attr_cb))
285 as *mut c_void;
286 (*copy).entities =
287 hash::hash_copy(d.entities as *mut hash::HashTable, Some(copy_ent_cb)) as *mut c_void;
288 (*copy).pentities =
289 hash::hash_copy(d.pentities as *mut hash::HashTable, Some(copy_ent_cb)) as *mut c_void;
290 }
291
292 copy
293}
294
295pub unsafe fn free_dtd(dtd: *mut _xmlDtd) {
307 if dtd.is_null() {
308 return;
309 }
310
311 unsafe {
312 let d = &mut *dtd;
313
314 if !d.children.is_null() {
321 let mut c = d.children;
322 while !c.is_null() {
323 let next = (*c).next;
324 let t = (*c).type_;
325 if t != XML_ELEMENT_DECL as c_int
326 && t != XML_ATTRIBUTE_DECL as c_int
327 && t != XML_ENTITY_DECL as c_int
328 {
329 crate::xml::tree::free_node(c);
330 }
331 c = next;
332 }
333 }
334
335 if !d.notations.is_null() {
337 hash::hash_free(
338 d.notations as *mut hash::HashTable,
339 Some(notation_deallocator),
340 );
341 d.notations = ptr::null_mut();
342 }
343 if !d.elements.is_null() {
344 hash::hash_free(
345 d.elements as *mut hash::HashTable,
346 Some(element_deallocator),
347 );
348 d.elements = ptr::null_mut();
349 }
350 if !d.attributes.is_null() {
351 hash::hash_free(
352 d.attributes as *mut hash::HashTable,
353 Some(attribute_deallocator),
354 );
355 d.attributes = ptr::null_mut();
356 }
357 if !d.entities.is_null() {
358 hash::hash_free(d.entities as *mut hash::HashTable, Some(entity_deallocator));
359 d.entities = ptr::null_mut();
360 }
361 if !d.pentities.is_null() {
362 hash::hash_free(
363 d.pentities as *mut hash::HashTable,
364 Some(entity_deallocator),
365 );
366 d.pentities = ptr::null_mut();
367 }
368
369 if !d.name.is_null() {
371 allocator::xmlFreeImpl(d.name as *mut c_void);
372 }
373 if !d.ExternalID.is_null() {
374 allocator::xmlFreeImpl(d.ExternalID as *mut c_void);
375 }
376 if !d.SystemID.is_null() {
377 allocator::xmlFreeImpl(d.SystemID as *mut c_void);
378 }
379
380 allocator::xmlFreeImpl(dtd as *mut c_void);
381 }
382}
383
384unsafe extern "C" fn notation_deallocator(payload: *mut c_void, _name: *mut u8) {
389 if !payload.is_null() {
390 free_notation(payload as *mut _xmlNotation);
391 }
392}
393
394unsafe extern "C" fn element_deallocator(payload: *mut c_void, _name: *mut u8) {
395 if !payload.is_null() {
396 free_element(payload as *mut _xmlElement);
397 }
398}
399
400unsafe extern "C" fn attribute_deallocator(payload: *mut c_void, _name: *mut u8) {
401 if !payload.is_null() {
402 free_attribute(payload as *mut _xmlAttribute);
403 }
404}
405
406unsafe extern "C" fn entity_deallocator(payload: *mut c_void, _name: *mut u8) {
407 if !payload.is_null() {
408 crate::xml::entities::free_entity(payload as *mut _xmlEntity);
409 }
410}
411
412pub unsafe fn add_notation_decl(
432 dtd: *mut _xmlDtd,
433 name: *const xmlChar,
434 PublicID: *const xmlChar,
435 SystemID: *const xmlChar,
436) -> *mut _xmlNotation {
437 if dtd.is_null() || name.is_null() {
438 return ptr::null_mut();
439 }
440
441 unsafe {
442 if (*dtd).notations.is_null() {
445 (*dtd).notations = hash::hash_create(8) as *mut c_void;
446 }
447 let d = &*dtd;
448
449 let existing = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
451 if !existing.is_null() {
452 return existing as *mut _xmlNotation;
453 }
454
455 let not = allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
457 if not.is_null() {
458 return ptr::null_mut();
459 }
460
461 (*not).name = string::xml_strdup(name);
462 (*not).PublicID = string::xml_strdup(PublicID);
463 (*not).SystemID = string::xml_strdup(SystemID);
464
465 let ret = hash::hash_add_entry(
467 d.notations as *mut hash::HashTable,
468 name,
469 not as *mut c_void,
470 );
471 if ret != 0 {
472 free_notation(not);
474 return ptr::null_mut();
475 }
476
477 not
478 }
479}
480
481pub unsafe fn get_notation_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlNotation {
494 if dtd.is_null() || name.is_null() {
495 return ptr::null_mut();
496 }
497
498 unsafe {
499 let d = &*dtd;
500 let payload = hash::hash_lookup(d.notations as *mut hash::HashTable, name);
501 payload as *mut _xmlNotation
502 }
503}
504
505pub unsafe fn copy_notation(notation: *mut _xmlNotation) -> *mut _xmlNotation {
517 if notation.is_null() {
518 return ptr::null_mut();
519 }
520
521 unsafe {
522 let n = &*notation;
523 let copy =
525 allocator::xmlMallocZero(size_of::<_xmlNotation>() as usize) as *mut _xmlNotation;
526 if copy.is_null() {
527 return ptr::null_mut();
528 }
529
530 (*copy).name = string::xml_strdup(n.name);
531 (*copy).PublicID = string::xml_strdup(n.PublicID);
532 (*copy).SystemID = string::xml_strdup(n.SystemID);
533
534 copy
535 }
536}
537
538pub unsafe fn free_notation(notation: *mut _xmlNotation) {
550 if notation.is_null() {
551 return;
552 }
553
554 unsafe {
555 let n = &*notation;
556 if !n.name.is_null() {
557 allocator::xmlFreeImpl(n.name as *mut c_void);
558 }
559 if !n.PublicID.is_null() {
560 allocator::xmlFreeImpl(n.PublicID as *mut c_void);
561 }
562 if !n.SystemID.is_null() {
563 allocator::xmlFreeImpl(n.SystemID as *mut c_void);
564 }
565 allocator::xmlFreeImpl(notation as *mut c_void);
566 }
567}
568
569pub unsafe fn create_content_model(name: *const xmlChar, type_: c_int) -> *mut _xmlElementContent {
588 let content = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
590 as *mut _xmlElementContent;
591 if content.is_null() {
592 return ptr::null_mut();
593 }
594
595 unsafe {
596 (*content).type_ = type_;
597 (*content).ocur = XML_ELEMENT_CONTENT_ONCE as c_int;
598 (*content).name = string::xml_strdup(name);
599 (*content).c1 = ptr::null_mut();
600 (*content).c2 = ptr::null_mut();
601 (*content).parent = ptr::null_mut();
602 (*content).prefix = ptr::null_mut();
603 }
604
605 content
606}
607
608pub unsafe fn free_content_model(cur: *mut _xmlElementContent) {
622 if cur.is_null() {
623 return;
624 }
625
626 unsafe {
627 let c = &*cur;
628
629 if !c.c1.is_null() {
631 free_content_model(c.c1);
632 }
633 if !c.c2.is_null() {
634 free_content_model(c.c2);
635 }
636
637 if !c.name.is_null() {
639 allocator::xmlFreeImpl(c.name as *mut c_void);
640 }
641 if !c.prefix.is_null() {
642 allocator::xmlFreeImpl(c.prefix as *mut c_void);
643 }
644
645 allocator::xmlFreeImpl(cur as *mut c_void);
646 }
647}
648
649pub unsafe fn copy_content_model(content: *mut _xmlElementContent) -> *mut _xmlElementContent {
663 if content.is_null() {
664 return ptr::null_mut();
665 }
666
667 unsafe {
668 let c = &*content;
669
670 let copy = allocator::xmlMallocZero(size_of::<_xmlElementContent>() as usize)
672 as *mut _xmlElementContent;
673 if copy.is_null() {
674 return ptr::null_mut();
675 }
676
677 (*copy).type_ = c.type_;
678 (*copy).ocur = c.ocur;
679 (*copy).name = string::xml_strdup(c.name);
680 (*copy).prefix = string::xml_strdup(c.prefix);
681
682 if !c.c1.is_null() {
684 (*copy).c1 = copy_content_model(c.c1);
685 if !(*copy).c1.is_null() {
686 (*(*copy).c1).parent = copy;
687 }
688 }
689 if !c.c2.is_null() {
690 (*copy).c2 = copy_content_model(c.c2);
691 if !(*copy).c2.is_null() {
692 (*(*copy).c2).parent = copy;
693 }
694 }
695
696 copy
697 }
698}
699
700pub unsafe fn add_element_decl(
721 dtd: *mut _xmlDtd,
722 name: *const xmlChar,
723 type_: c_int,
724 content: *mut _xmlElementContent,
725) -> *mut _xmlElement {
726 if dtd.is_null() || name.is_null() {
727 return ptr::null_mut();
728 }
729
730 unsafe {
731 if (*dtd).elements.is_null() {
734 (*dtd).elements = hash::hash_create(8) as *mut c_void;
735 }
736 let d = &*dtd;
737
738 let existing = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
740 if !existing.is_null() {
741 return existing as *mut _xmlElement;
742 }
743
744 let elem = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
746 if elem.is_null() {
747 return ptr::null_mut();
748 }
749
750 (*elem).name = string::xml_strdup(name);
755 (*elem).type_ = XML_ELEMENT_DECL as c_int;
756 (*elem).etype = type_; (*elem).content = content; (*elem).attributes = ptr::null_mut();
759 (*elem).prefix = ptr::null_mut();
760 (*elem).children = ptr::null_mut();
761 (*elem).last = ptr::null_mut();
762 (*elem).parent = dtd;
763 (*elem).next = ptr::null_mut();
764 (*elem).prev = ptr::null_mut();
765 (*elem).doc = (*dtd).doc;
766 (*elem).cont_model = ptr::null_mut();
767
768 let ret = hash::hash_add_entry(
770 d.elements as *mut hash::HashTable,
771 name,
772 elem as *mut c_void,
773 );
774 if ret != 0 {
775 free_element(elem);
777 return ptr::null_mut();
778 }
779
780 if (*dtd).last.is_null() {
783 (*dtd).children = elem as *mut _xmlNode;
784 (*dtd).last = elem as *mut _xmlNode;
785 } else {
786 (*(*dtd).last).next = elem as *mut _xmlNode;
787 (*elem).prev = (*dtd).last;
788 (*dtd).last = elem as *mut _xmlNode;
789 }
790
791 elem
792 }
793}
794
795pub unsafe fn get_element_decl(dtd: *mut _xmlDtd, name: *const xmlChar) -> *mut _xmlElement {
808 if dtd.is_null() || name.is_null() {
809 return ptr::null_mut();
810 }
811
812 unsafe {
813 let d = &*dtd;
814 if d.elements.is_null() {
815 return ptr::null_mut();
816 }
817 let payload = hash::hash_lookup(d.elements as *mut hash::HashTable, name);
818 payload as *mut _xmlElement
819 }
820}
821
822pub unsafe fn get_element_decl_created(
833 dtd: *mut _xmlDtd,
834 name: *const xmlChar,
835) -> *mut _xmlElement {
836 if dtd.is_null() || name.is_null() {
837 return ptr::null_mut();
838 }
839
840 unsafe {
841 if (*dtd).elements.is_null() {
842 (*dtd).elements = hash::hash_create(8) as *mut c_void;
843 }
844 let existing = hash::hash_lookup((*dtd).elements as *mut hash::HashTable, name);
845 if !existing.is_null() {
846 return existing as *mut _xmlElement;
847 }
848
849 let elem = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
850 if elem.is_null() {
851 return ptr::null_mut();
852 }
853 (*elem).type_ = XML_ELEMENT_DECL as c_int;
854 (*elem).name = string::xml_strdup(name);
855 (*elem).etype = XML_ELEMENT_TYPE_UNDEFINED as c_int;
856 (*elem).doc = (*dtd).doc;
857 (*elem).parent = dtd;
858 if hash::hash_add_entry(
859 (*dtd).elements as *mut hash::HashTable,
860 name,
861 elem as *mut c_void,
862 ) != 0
863 {
864 free_element(elem);
865 return ptr::null_mut();
866 }
867 elem
868 }
869}
870
871pub unsafe fn copy_element(elem: *mut _xmlElement) -> *mut _xmlElement {
883 if elem.is_null() {
884 return ptr::null_mut();
885 }
886
887 unsafe {
888 let e = &*elem;
889
890 let copy = allocator::xmlMallocZero(size_of::<_xmlElement>() as usize) as *mut _xmlElement;
892 if copy.is_null() {
893 return ptr::null_mut();
894 }
895
896 (*copy).name = string::xml_strdup(e.name);
897 (*copy).type_ = e.type_;
898 (*copy).etype = e.etype;
899 (*copy).content = copy_content_model(e.content);
900 (*copy).prefix = string::xml_strdup(e.prefix);
901 (*copy)._private = e._private;
902 (*copy).parent = e.parent;
903 (*copy).doc = e.doc;
904
905 if !e.attributes.is_null() {
907 let mut src_attr = e.attributes;
910 let mut prev_copy: *mut _xmlAttribute = ptr::null_mut();
911 let mut first_copy: *mut _xmlAttribute = ptr::null_mut();
912
913 while !src_attr.is_null() {
914 let attr_copy = copy_attribute_decl(src_attr);
915 if attr_copy.is_null() {
916 let mut to_free = first_copy;
918 while !to_free.is_null() {
919 let next = (*to_free).nexth;
920 free_attribute(to_free);
921 to_free = next;
922 }
923 allocator::xmlFreeImpl(copy as *mut c_void);
924 return ptr::null_mut();
925 }
926
927 if prev_copy.is_null() {
928 first_copy = attr_copy;
929 } else {
930 (*prev_copy).nexth = attr_copy;
931 }
932 prev_copy = attr_copy;
933 src_attr = (*src_attr).nexth;
934 }
935
936 (*copy).attributes = first_copy;
937 }
938
939 copy
940 }
941}
942
943pub unsafe fn free_element(elem: *mut _xmlElement) {
958 if elem.is_null() {
959 return;
960 }
961
962 unsafe {
963 if !(*elem).name.is_null() {
965 allocator::xmlFreeImpl((*elem).name as *mut c_void);
966 }
967
968 if !(*elem).prefix.is_null() {
970 allocator::xmlFreeImpl((*elem).prefix as *mut c_void);
971 }
972
973 if !(*elem).content.is_null() {
975 free_content_model((*elem).content);
976 }
977
978 if !(*elem).cont_model.is_null() {
981 crate::xml::validation::free_content_model_nfa(
982 (*elem).cont_model as *mut crate::xml::validation::ContentModelNfa,
983 );
984 }
985
986 (*elem).attributes = ptr::null_mut();
992
993 allocator::xmlFreeImpl(elem as *mut c_void);
994 }
995}
996
997unsafe fn free_enumeration(tree: *mut _xmlEnumeration) {
1007 if tree.is_null() {
1008 return;
1009 }
1010
1011 unsafe {
1012 let mut cur = tree;
1013 while !cur.is_null() {
1014 let next = (*cur).next;
1015 if !(*cur).name.is_null() {
1016 allocator::xmlFreeImpl((*cur).name as *mut c_void);
1017 }
1018 allocator::xmlFreeImpl(cur as *mut c_void);
1019 cur = next;
1020 }
1021 }
1022}
1023
1024unsafe fn copy_enumeration(tree: *mut _xmlEnumeration) -> *mut _xmlEnumeration {
1030 if tree.is_null() {
1031 return ptr::null_mut();
1032 }
1033
1034 unsafe {
1035 let mut src = tree;
1036 let mut first_copy: *mut _xmlEnumeration = ptr::null_mut();
1037 let mut prev_copy: *mut _xmlEnumeration = ptr::null_mut();
1038
1039 while !src.is_null() {
1040 let copy = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1041 as *mut _xmlEnumeration;
1042 if copy.is_null() {
1043 let mut to_free = first_copy;
1045 while !to_free.is_null() {
1046 let next = (*to_free).next;
1047 if !(*to_free).name.is_null() {
1048 allocator::xmlFreeImpl((*to_free).name as *mut c_void);
1049 }
1050 allocator::xmlFreeImpl(to_free as *mut c_void);
1051 to_free = next;
1052 }
1053 return ptr::null_mut();
1054 }
1055
1056 (*copy).name = string::xml_strdup((*src).name);
1057 (*copy).next = ptr::null_mut();
1058
1059 if prev_copy.is_null() {
1060 first_copy = copy;
1061 } else {
1062 (*prev_copy).next = copy;
1063 }
1064 prev_copy = copy;
1065 src = (*src).next;
1066 }
1067
1068 first_copy
1069 }
1070}
1071
1072pub unsafe fn add_attribute_decl(
1094 dtd: *mut _xmlDtd,
1095 elem: *mut _xmlElement,
1096 name: *const xmlChar,
1097 type_: c_int,
1098 def: c_int,
1099 defaultValue: *const xmlChar,
1100 tree: *mut _xmlEnumeration,
1101) -> *mut _xmlAttribute {
1102 if dtd.is_null() || name.is_null() {
1103 return ptr::null_mut();
1104 }
1105
1106 unsafe {
1107 if (*dtd).attributes.is_null() {
1110 (*dtd).attributes = hash::hash_create(8) as *mut c_void;
1111 }
1112 let d = &*dtd;
1113 let elem_name = if elem.is_null() {
1114 ptr::null()
1115 } else {
1116 (*elem).name
1117 };
1118
1119 let existing = hash::hash_lookup3(
1123 d.attributes as *mut hash::HashTable,
1124 name,
1125 ptr::null(),
1126 elem_name,
1127 );
1128 if !existing.is_null() {
1129 return existing as *mut _xmlAttribute;
1130 }
1131
1132 let attr =
1134 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
1135 if attr.is_null() {
1136 return ptr::null_mut();
1137 }
1138
1139 (*attr).type_ = XML_ATTRIBUTE_DECL as c_int;
1140 (*attr).name = string::xml_strdup(name);
1141 (*attr).parent = dtd;
1142 (*attr).doc = d.doc;
1143 (*attr).nexth = ptr::null_mut();
1144 (*attr).atype = type_;
1145 (*attr).def = def;
1146 (*attr).defaultValue = string::xml_strdup(defaultValue);
1147 (*attr).tree = tree; (*attr).prefix = ptr::null_mut();
1149 (*attr).elem = string::xml_strdup(elem_name);
1150
1151 let ret = hash::hash_add_entry3(
1154 d.attributes as *mut hash::HashTable,
1155 name,
1156 ptr::null(),
1157 elem_name,
1158 attr as *mut c_void,
1159 );
1160 if ret != 0 {
1161 if !(*attr).defaultValue.is_null() {
1163 allocator::xmlFreeImpl((*attr).defaultValue as *mut c_void);
1164 }
1165 if !(*attr).name.is_null() {
1166 allocator::xmlFreeImpl((*attr).name as *mut c_void);
1167 }
1168 if !(*attr).elem.is_null() {
1169 allocator::xmlFreeImpl((*attr).elem as *mut c_void);
1170 }
1171 allocator::xmlFreeImpl(attr as *mut c_void);
1172 return ptr::null_mut();
1174 }
1175
1176 if !elem.is_null() {
1178 (*attr).nexth = (*elem).attributes;
1179 (*elem).attributes = attr;
1180 }
1181
1182 if (*dtd).last.is_null() {
1185 (*dtd).children = attr as *mut _xmlNode;
1186 (*dtd).last = attr as *mut _xmlNode;
1187 } else {
1188 (*(*dtd).last).next = attr as *mut _xmlNode;
1189 (*attr).prev = (*dtd).last;
1190 (*dtd).last = attr as *mut _xmlNode;
1191 }
1192
1193 attr
1194 }
1195}
1196
1197pub unsafe fn get_attribute_decl(
1215 dtd: *mut _xmlDtd,
1216 elem: *mut _xmlElement,
1217 name: *const xmlChar,
1218 _namePrefix: c_int,
1219) -> *mut _xmlAttribute {
1220 if dtd.is_null() || name.is_null() {
1221 return ptr::null_mut();
1222 }
1223
1224 unsafe {
1225 let d = &*dtd;
1226 let elem_name = if elem.is_null() {
1227 ptr::null()
1228 } else {
1229 (*elem).name
1230 };
1231
1232 let payload = hash::hash_lookup3(
1235 d.attributes as *mut hash::HashTable,
1236 name,
1237 ptr::null(),
1238 elem_name,
1239 );
1240 payload as *mut _xmlAttribute
1241 }
1242}
1243
1244pub unsafe fn copy_attribute_decl(attr: *mut _xmlAttribute) -> *mut _xmlAttribute {
1256 if attr.is_null() {
1257 return ptr::null_mut();
1258 }
1259
1260 unsafe {
1261 let a = &*attr;
1262
1263 let copy =
1265 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
1266 if copy.is_null() {
1267 return ptr::null_mut();
1268 }
1269
1270 (*copy).type_ = a.type_;
1271 (*copy).name = string::xml_strdup(a.name);
1272 (*copy).parent = a.parent;
1273 (*copy).doc = a.doc;
1274 (*copy).nexth = ptr::null_mut();
1275 (*copy).atype = a.atype;
1276 (*copy).def = a.def;
1277 (*copy).defaultValue = string::xml_strdup(a.defaultValue);
1278 (*copy).tree = copy_enumeration(a.tree);
1279 (*copy).prefix = string::xml_strdup(a.prefix);
1280 (*copy).elem = string::xml_strdup(a.elem);
1281
1282 copy
1283 }
1284}
1285
1286pub unsafe fn free_attribute(attr: *mut _xmlAttribute) {
1298 if attr.is_null() {
1299 return;
1300 }
1301
1302 unsafe {
1303 let a = &*attr;
1304
1305 if !a.name.is_null() {
1306 allocator::xmlFreeImpl(a.name as *mut c_void);
1307 }
1308 if !a.defaultValue.is_null() {
1309 allocator::xmlFreeImpl(a.defaultValue as *mut c_void);
1310 }
1311 if !a.prefix.is_null() {
1312 allocator::xmlFreeImpl(a.prefix as *mut c_void);
1313 }
1314 if !a.elem.is_null() {
1315 allocator::xmlFreeImpl(a.elem as *mut c_void);
1316 }
1317 if !a.tree.is_null() {
1318 free_enumeration(a.tree);
1319 }
1320
1321 allocator::xmlFreeImpl(attr as *mut c_void);
1322 }
1323}
1324
1325#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1331pub enum ContentModelResult {
1332 Valid,
1334 Invalid,
1336 Indeterminate,
1338}
1339
1340pub unsafe fn valid_content_model(
1361 model: *mut _xmlElementContent,
1362 names: &[*const xmlChar],
1363) -> ContentModelResult {
1364 if model.is_null() {
1365 return ContentModelResult::Invalid;
1366 }
1367
1368 unsafe {
1369 let m = &*model;
1370
1371 match m.ocur as u32 {
1373 o if o == XML_ELEMENT_CONTENT_OPT as u32 => {
1374 if names.is_empty() {
1376 return ContentModelResult::Valid;
1377 }
1378 return valid_content_model_inner(model, names);
1379 }
1380 o if o == XML_ELEMENT_CONTENT_MULT as u32 => {
1381 if names.is_empty() {
1383 return ContentModelResult::Valid;
1384 }
1385 return valid_content_model_zero_or_more(model, names);
1386 }
1387 o if o == XML_ELEMENT_CONTENT_PLUS as u32 => {
1388 if names.is_empty() {
1390 return ContentModelResult::Invalid;
1391 }
1392 return valid_content_model_one_or_more(model, names);
1393 }
1394 _ => {}
1395 }
1396
1397 valid_content_model_inner(model, names)
1398 }
1399}
1400
1401unsafe fn valid_content_model_inner(
1403 model: *mut _xmlElementContent,
1404 names: &[*const xmlChar],
1405) -> ContentModelResult {
1406 unsafe {
1407 let m = &*model;
1408
1409 match m.type_ as u32 {
1410 t if t == XML_ELEMENT_CONTENT_PCDATA as u32 => {
1411 if names.is_empty() {
1413 ContentModelResult::Valid
1414 } else {
1415 ContentModelResult::Invalid
1416 }
1417 }
1418 t if t == XML_ELEMENT_CONTENT_ELEMENT as u32 => {
1419 if names.len() != 1 {
1421 return ContentModelResult::Invalid;
1422 }
1423 if names[0].is_null() {
1424 return ContentModelResult::Invalid;
1425 }
1426 if string::xml_strcmp(names[0], m.name) != 0 {
1428 return ContentModelResult::Invalid;
1429 }
1430 ContentModelResult::Valid
1431 }
1432 t if t == XML_ELEMENT_CONTENT_SEQ as u32 => {
1433 valid_content_model_seq(m, names)
1435 }
1436 t if t == XML_ELEMENT_CONTENT_OR as u32 => {
1437 valid_content_model_or(m, names)
1439 }
1440 _ => ContentModelResult::Invalid,
1441 }
1442 }
1443}
1444
1445unsafe fn valid_content_model_zero_or_more(
1447 model: *mut _xmlElementContent,
1448 names: &[*const xmlChar],
1449) -> ContentModelResult {
1450 let mut i = 0;
1452 while i <= names.len() {
1453 let consumed = &names[..i];
1454 let remaining = &names[i..];
1455
1456 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1457 if consumed_valid == ContentModelResult::Valid {
1458 if remaining.is_empty() {
1459 return ContentModelResult::Valid;
1460 }
1461 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1463 if remaining_valid == ContentModelResult::Valid {
1464 return ContentModelResult::Valid;
1465 }
1466 }
1467
1468 i += 1;
1469 }
1470 ContentModelResult::Invalid
1471}
1472
1473unsafe fn valid_content_model_one_or_more(
1475 model: *mut _xmlElementContent,
1476 names: &[*const xmlChar],
1477) -> ContentModelResult {
1478 let mut i = 1;
1480 while i <= names.len() {
1481 let consumed = &names[..i];
1482 let remaining = &names[i..];
1483
1484 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1485 if consumed_valid == ContentModelResult::Valid {
1486 if remaining.is_empty() {
1487 return ContentModelResult::Valid;
1488 }
1489 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1490 if remaining_valid == ContentModelResult::Valid {
1491 return ContentModelResult::Valid;
1492 }
1493 }
1494
1495 i += 1;
1496 }
1497 ContentModelResult::Invalid
1498}
1499
1500unsafe fn valid_content_model_seq(
1502 model: &_xmlElementContent,
1503 names: &[*const xmlChar],
1504) -> ContentModelResult {
1505 let c1 = model.c1;
1510 let c2 = model.c2;
1511
1512 if c1.is_null() && c2.is_null() {
1513 return ContentModelResult::Valid;
1514 }
1515
1516 if c1.is_null() {
1517 return unsafe { valid_content_model(c2, names) };
1518 }
1519
1520 if c2.is_null() {
1521 return unsafe { valid_content_model(c1, names) };
1522 }
1523
1524 for split in 0..=names.len() {
1527 let left = &names[..split];
1528 let right = &names[split..];
1529
1530 let left_valid = unsafe { valid_content_model(c1, left) };
1531 if left_valid != ContentModelResult::Valid {
1532 continue;
1533 }
1534
1535 let right_valid = unsafe { valid_content_model(c2, right) };
1536 if right_valid == ContentModelResult::Valid {
1537 return ContentModelResult::Valid;
1538 }
1539 }
1540
1541 ContentModelResult::Invalid
1542}
1543
1544unsafe fn valid_content_model_or(
1546 model: &_xmlElementContent,
1547 names: &[*const xmlChar],
1548) -> ContentModelResult {
1549 let c1 = model.c1;
1550 let c2 = model.c2;
1551
1552 if c1.is_null() && c2.is_null() {
1553 return ContentModelResult::Invalid;
1554 }
1555
1556 if !c1.is_null() {
1557 let result = unsafe { valid_content_model(c1, names) };
1558 if result == ContentModelResult::Valid {
1559 return ContentModelResult::Valid;
1560 }
1561 }
1562
1563 if !c2.is_null() {
1564 let result = unsafe { valid_content_model(c2, names) };
1565 if result == ContentModelResult::Valid {
1566 return ContentModelResult::Valid;
1567 }
1568 }
1569
1570 ContentModelResult::Invalid
1571}
1572
1573#[cfg(test)]
1578mod tests {
1579 use super::*;
1580
1581 use core::ffi::c_void;
1582 use core::ptr;
1583
1584 unsafe fn c_str(s: &[u8]) -> *const xmlChar {
1587 let len = s.len();
1589 let buf = allocator::xmlMallocImpl(len + 1) as *mut xmlChar;
1590 assert!(!buf.is_null());
1591 ptr::copy_nonoverlapping(s.as_ptr(), buf, len);
1592 *buf.add(len) = 0;
1593 buf as *const xmlChar
1594 }
1595
1596 unsafe fn make_doc_and_dtd() -> (*mut _xmlDoc, *mut _xmlDtd) {
1597 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1598 assert!(!doc.is_null());
1599 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1600 (*doc).doc = doc;
1601 let dtd = create_int_subset(doc, c_str(b"root"), ptr::null(), ptr::null());
1602 assert!(!dtd.is_null());
1603 (doc, dtd)
1604 }
1605
1606 #[test]
1609 fn test_get_int_subset_null() {
1610 {
1611 assert!(get_int_subset(ptr::null()).is_null());
1612 }
1613 }
1614
1615 #[test]
1616 fn test_create_int_subset() {
1617 unsafe {
1618 let (doc, dtd) = make_doc_and_dtd();
1619 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1620 assert!(!(*dtd).name.is_null());
1621 assert_eq!((*doc).intSubset, dtd);
1622
1623 free_dtd(dtd);
1625 allocator::xmlFreeImpl(doc as *mut c_void);
1626 }
1627 }
1628
1629 #[test]
1630 fn test_create_int_subset_null_doc() {
1631 unsafe {
1632 let dtd = create_int_subset(ptr::null_mut(), c_str(b"root"), ptr::null(), ptr::null());
1633 assert!(dtd.is_null());
1634 }
1635 }
1636
1637 #[test]
1638 fn test_new_dtd() {
1639 unsafe {
1640 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1641 assert!(!doc.is_null());
1642 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1643 (*doc).doc = doc;
1644
1645 let dtd = new_dtd(doc, c_str(b"test"), c_str(b"-//TEST//"), c_str(b"test.dtd"));
1646 assert!(!dtd.is_null());
1647 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1648 assert_eq!((*doc).intSubset, dtd);
1649
1650 free_dtd(dtd);
1651 allocator::xmlFreeImpl(doc as *mut c_void);
1652 }
1653 }
1654
1655 #[test]
1656 fn test_new_dtd_no_doc() {
1657 unsafe {
1658 let dtd = new_dtd(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1659 assert!(!dtd.is_null());
1660 free_dtd(dtd);
1661 }
1662 }
1663
1664 #[test]
1667 fn test_add_get_notation() {
1668 unsafe {
1669 let (doc, dtd) = make_doc_and_dtd();
1670 let name = c_str(b"note");
1671 let pubid = c_str(b"-//TEST//NOTATION");
1672 let sysid = c_str(b"note.ent");
1673
1674 let n = add_notation_decl(dtd, name, pubid, sysid);
1675 assert!(!n.is_null());
1676 assert_eq!(string::xml_strcmp((*n).name, name), 0);
1677
1678 let found = get_notation_decl(dtd, name);
1680 assert_eq!(found, n);
1681
1682 let not_found = get_notation_decl(dtd, c_str(b"nonexistent"));
1684 assert!(not_found.is_null());
1685
1686 free_dtd(dtd);
1687 allocator::xmlFreeImpl(doc as *mut c_void);
1688 }
1689 }
1690
1691 #[test]
1692 fn test_add_notation_null_dtd() {
1693 unsafe {
1694 let n = add_notation_decl(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1695 assert!(n.is_null());
1696 }
1697 }
1698
1699 #[test]
1700 fn test_copy_notation() {
1701 unsafe {
1702 let (doc, dtd) = make_doc_and_dtd();
1703 let name = c_str(b"note1");
1704 let pubid = c_str(b"public");
1705 let sysid = c_str(b"system");
1706
1707 let n = add_notation_decl(dtd, name, pubid, sysid);
1708 assert!(!n.is_null());
1709
1710 let copy = copy_notation(n);
1711 assert!(!copy.is_null());
1712 assert_ne!(copy, n);
1713 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1714 assert_eq!(string::xml_strcmp((*copy).PublicID, pubid), 0);
1715 assert_eq!(string::xml_strcmp((*copy).SystemID, sysid), 0);
1716
1717 free_notation(copy);
1718 free_dtd(dtd);
1719 allocator::xmlFreeImpl(doc as *mut c_void);
1720 }
1721 }
1722
1723 #[test]
1724 fn test_copy_notation_null() {
1725 unsafe {
1726 assert!(copy_notation(ptr::null_mut()).is_null());
1727 }
1728 }
1729
1730 #[test]
1731 fn test_free_notation_null() {
1732 unsafe {
1733 free_notation(ptr::null_mut()); }
1735 }
1736
1737 #[test]
1740 fn test_create_free_content_model() {
1741 unsafe {
1742 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1743 assert!(!cm.is_null());
1744 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1745 assert_eq!((*cm).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1746
1747 free_content_model(cm);
1748 }
1749 }
1750
1751 #[test]
1752 fn test_create_content_model_pcdata() {
1753 unsafe {
1754 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1755 assert!(!cm.is_null());
1756 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_PCDATA as c_int);
1757 free_content_model(cm);
1758 }
1759 }
1760
1761 #[test]
1762 fn test_copy_content_model() {
1763 unsafe {
1764 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1765 assert!(!cm.is_null());
1766
1767 let copy = copy_content_model(cm);
1768 assert!(!copy.is_null());
1769 assert_ne!(copy, cm);
1770 assert_eq!((*copy).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1771 assert_eq!((*copy).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1772 assert_eq!(string::xml_strcmp((*copy).name, (*cm).name), 0);
1773
1774 free_content_model(cm);
1775 free_content_model(copy);
1776 }
1777 }
1778
1779 #[test]
1780 fn test_copy_content_model_null() {
1781 unsafe {
1782 assert!(copy_content_model(ptr::null_mut()).is_null());
1783 }
1784 }
1785
1786 #[test]
1787 fn test_free_content_model_null() {
1788 unsafe {
1789 free_content_model(ptr::null_mut()); }
1791 }
1792
1793 #[test]
1794 fn test_create_sequence_content_model() {
1795 unsafe {
1796 let c1 = create_content_model(c_str(b"a"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1797 let c2 = create_content_model(c_str(b"b"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1798 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1799 assert!(!seq.is_null());
1800 (*seq).c1 = c1;
1801 (*seq).c2 = c2;
1802 (*c1).parent = seq;
1803 (*c2).parent = seq;
1804
1805 free_content_model(seq);
1806 }
1807 }
1808
1809 #[test]
1812 fn test_add_get_element() {
1813 unsafe {
1814 let (doc, dtd) = make_doc_and_dtd();
1815 let name = c_str(b"myElement");
1816
1817 let elem =
1818 add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1819 assert!(!elem.is_null());
1820 assert_eq!((*elem).etype, XML_ELEMENT_TYPE_EMPTY as c_int);
1821
1822 let found = get_element_decl(dtd, name);
1823 assert_eq!(found, elem);
1824
1825 let not_found = get_element_decl(dtd, c_str(b"nonexistent"));
1826 assert!(not_found.is_null());
1827
1828 free_dtd(dtd);
1829 allocator::xmlFreeImpl(doc as *mut c_void);
1830 }
1831 }
1832
1833 #[test]
1834 fn test_add_element_duplicate() {
1835 unsafe {
1836 let (doc, dtd) = make_doc_and_dtd();
1837 let name = c_str(b"dup");
1838
1839 let e1 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1840 assert!(!e1.is_null());
1841
1842 let e2 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ANY as c_int, ptr::null_mut());
1843 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);
1848 allocator::xmlFreeImpl(doc as *mut c_void);
1849 }
1850 }
1851
1852 #[test]
1853 fn test_add_element_null_dtd() {
1854 unsafe {
1855 let elem = add_element_decl(
1856 ptr::null_mut(),
1857 c_str(b"test"),
1858 XML_ELEMENT_TYPE_EMPTY as c_int,
1859 ptr::null_mut(),
1860 );
1861 assert!(elem.is_null());
1862 }
1863 }
1864
1865 #[test]
1866 fn test_copy_element() {
1867 unsafe {
1868 let (doc, dtd) = make_doc_and_dtd();
1869 let name = c_str(b"source");
1870 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1871
1872 let elem = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ELEMENT as c_int, cm);
1873 assert!(!elem.is_null());
1874
1875 let copy = copy_element(elem);
1876 assert!(!copy.is_null());
1877 assert_ne!(copy, elem);
1878 assert_eq!((*copy).type_, XML_ELEMENT_DECL as c_int);
1879 assert_eq!((*copy).etype, XML_ELEMENT_TYPE_ELEMENT as c_int);
1880 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1881 assert!(!(*copy).content.is_null());
1882 assert_ne!((*copy).content, cm);
1883
1884 free_element(copy);
1885 free_dtd(dtd);
1886 allocator::xmlFreeImpl(doc as *mut c_void);
1887 }
1888 }
1889
1890 #[test]
1891 fn test_free_element_null() {
1892 unsafe {
1893 free_element(ptr::null_mut()); }
1895 }
1896
1897 #[test]
1900 fn test_add_get_attribute() {
1901 unsafe {
1902 let (doc, dtd) = make_doc_and_dtd();
1903 let elem_name = c_str(b"elem");
1904 let attr_name = c_str(b"attr1");
1905
1906 let elem = add_element_decl(
1907 dtd,
1908 elem_name,
1909 XML_ELEMENT_TYPE_EMPTY as c_int,
1910 ptr::null_mut(),
1911 );
1912 assert!(!elem.is_null());
1913
1914 let attr = add_attribute_decl(
1915 dtd,
1916 elem,
1917 attr_name,
1918 XML_ATTRIBUTE_CDATA as c_int,
1919 XML_ATTRIBUTE_IMPLIED as c_int,
1920 ptr::null(),
1921 ptr::null_mut(),
1922 );
1923 assert!(!attr.is_null());
1924 assert_eq!((*attr).atype, XML_ATTRIBUTE_CDATA as c_int);
1925 assert_eq!((*attr).def, XML_ATTRIBUTE_IMPLIED as c_int);
1926
1927 let found = get_attribute_decl(dtd, elem, attr_name, 0);
1929 assert_eq!(found, attr);
1930
1931 let not_found = get_attribute_decl(dtd, elem, c_str(b"nonexistent"), 0);
1933 assert!(not_found.is_null());
1934
1935 free_dtd(dtd);
1936 allocator::xmlFreeImpl(doc as *mut c_void);
1937 }
1938 }
1939
1940 #[test]
1941 fn test_add_attribute_with_default() {
1942 unsafe {
1943 let (doc, dtd) = make_doc_and_dtd();
1944 let elem_name = c_str(b"elem");
1945 let attr_name = c_str(b"color");
1946 let default_val = c_str(b"red");
1947
1948 let elem = add_element_decl(
1949 dtd,
1950 elem_name,
1951 XML_ELEMENT_TYPE_EMPTY as c_int,
1952 ptr::null_mut(),
1953 );
1954
1955 let attr = add_attribute_decl(
1956 dtd,
1957 elem,
1958 attr_name,
1959 XML_ATTRIBUTE_CDATA as c_int,
1960 XML_ATTRIBUTE_FIXED as c_int,
1961 default_val,
1962 ptr::null_mut(),
1963 );
1964 assert!(!attr.is_null());
1965 assert_eq!((*attr).def, XML_ATTRIBUTE_FIXED as c_int);
1966 assert_eq!(string::xml_strcmp((*attr).defaultValue, default_val), 0);
1967
1968 free_dtd(dtd);
1969 allocator::xmlFreeImpl(doc as *mut c_void);
1970 }
1971 }
1972
1973 #[test]
1974 fn test_add_attribute_enumeration() {
1975 unsafe {
1976 let (doc, dtd) = make_doc_and_dtd();
1977 let elem_name = c_str(b"elem");
1978 let attr_name = c_str(b"size");
1979
1980 let v3 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1982 as *mut _xmlEnumeration;
1983 (*v3).name = string::xml_strdup(c_str(b"large"));
1984 let v2 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1985 as *mut _xmlEnumeration;
1986 (*v2).name = string::xml_strdup(c_str(b"medium"));
1987 (*v2).next = v3;
1988 let v1 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1989 as *mut _xmlEnumeration;
1990 (*v1).name = string::xml_strdup(c_str(b"small"));
1991 (*v1).next = v2;
1992
1993 let elem = add_element_decl(
1994 dtd,
1995 elem_name,
1996 XML_ELEMENT_TYPE_EMPTY as c_int,
1997 ptr::null_mut(),
1998 );
1999 let attr = add_attribute_decl(
2000 dtd,
2001 elem,
2002 attr_name,
2003 XML_ATTRIBUTE_ENUMERATION as c_int,
2004 XML_ATTRIBUTE_REQUIRED as c_int,
2005 ptr::null(),
2006 v1,
2007 );
2008 assert!(!attr.is_null());
2009 assert_eq!((*attr).atype, XML_ATTRIBUTE_ENUMERATION as c_int);
2010
2011 free_dtd(dtd);
2012 allocator::xmlFreeImpl(doc as *mut c_void);
2013 }
2014 }
2015
2016 #[test]
2017 fn test_add_attribute_null_dtd() {
2018 unsafe {
2019 let attr = add_attribute_decl(
2020 ptr::null_mut(),
2021 ptr::null_mut(),
2022 c_str(b"test"),
2023 XML_ATTRIBUTE_CDATA as c_int,
2024 XML_ATTRIBUTE_IMPLIED as c_int,
2025 ptr::null(),
2026 ptr::null_mut(),
2027 );
2028 assert!(attr.is_null());
2029 }
2030 }
2031
2032 #[test]
2033 fn test_copy_attribute() {
2034 unsafe {
2035 let (doc, dtd) = make_doc_and_dtd();
2036 let elem_name = c_str(b"elem");
2037 let attr_name = c_str(b"id");
2038 let default_val = c_str(b"default");
2039
2040 let elem = add_element_decl(
2041 dtd,
2042 elem_name,
2043 XML_ELEMENT_TYPE_EMPTY as c_int,
2044 ptr::null_mut(),
2045 );
2046 let attr = add_attribute_decl(
2047 dtd,
2048 elem,
2049 attr_name,
2050 XML_ATTRIBUTE_ID as c_int,
2051 XML_ATTRIBUTE_IMPLIED as c_int,
2052 default_val,
2053 ptr::null_mut(),
2054 );
2055 assert!(!attr.is_null());
2056
2057 let copy = copy_attribute_decl(attr);
2058 assert!(!copy.is_null());
2059 assert_ne!(copy, attr);
2060 assert_eq!((*copy).atype, XML_ATTRIBUTE_ID as c_int);
2061 assert_eq!(string::xml_strcmp((*copy).name, attr_name), 0);
2062
2063 free_attribute(copy);
2064 free_dtd(dtd);
2065 allocator::xmlFreeImpl(doc as *mut c_void);
2066 }
2067 }
2068
2069 #[test]
2070 fn test_free_attribute_null() {
2071 unsafe {
2072 free_attribute(ptr::null_mut()); }
2074 }
2075
2076 #[test]
2079 fn test_valid_content_model_null() {
2080 unsafe {
2081 assert_eq!(
2082 valid_content_model(ptr::null_mut(), &[]),
2083 ContentModelResult::Invalid
2084 );
2085 }
2086 }
2087
2088 #[test]
2089 fn test_valid_content_model_pcdata() {
2090 unsafe {
2091 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
2092 assert!(!cm.is_null());
2093
2094 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Valid);
2096
2097 let name = c_str(b"child");
2099 assert_eq!(
2100 valid_content_model(cm, &[name]),
2101 ContentModelResult::Invalid
2102 );
2103
2104 free_content_model(cm);
2105 }
2106 }
2107
2108 #[test]
2109 fn test_valid_content_model_element() {
2110 unsafe {
2111 let child_name = c_str(b"child");
2112 let cm = create_content_model(child_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2113 assert!(!cm.is_null());
2114
2115 assert_eq!(
2117 valid_content_model(cm, &[child_name]),
2118 ContentModelResult::Valid
2119 );
2120
2121 let other = c_str(b"other");
2123 assert_eq!(
2124 valid_content_model(cm, &[other]),
2125 ContentModelResult::Invalid
2126 );
2127
2128 assert_eq!(
2130 valid_content_model(cm, &[child_name, child_name]),
2131 ContentModelResult::Invalid
2132 );
2133
2134 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Invalid);
2136
2137 free_content_model(cm);
2138 }
2139 }
2140
2141 #[test]
2142 fn test_valid_content_model_seq() {
2143 unsafe {
2144 let a_name = c_str(b"a");
2145 let b_name = c_str(b"b");
2146
2147 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2148 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2149 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
2150 (*seq).c1 = c1;
2151 (*seq).c2 = c2;
2152 (*c1).parent = seq;
2153 (*c2).parent = seq;
2154
2155 assert_eq!(
2157 valid_content_model(seq, &[a_name, b_name]),
2158 ContentModelResult::Valid
2159 );
2160
2161 assert_eq!(
2163 valid_content_model(seq, &[b_name, a_name]),
2164 ContentModelResult::Invalid
2165 );
2166
2167 assert_eq!(
2169 valid_content_model(seq, &[a_name]),
2170 ContentModelResult::Invalid
2171 );
2172
2173 free_content_model(seq);
2174 }
2175 }
2176
2177 #[test]
2178 fn test_valid_content_model_or() {
2179 unsafe {
2180 let a_name = c_str(b"a");
2181 let b_name = c_str(b"b");
2182
2183 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2184 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2185 let choice = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_OR as c_int);
2186 (*choice).c1 = c1;
2187 (*choice).c2 = c2;
2188 (*c1).parent = choice;
2189 (*c2).parent = choice;
2190
2191 assert_eq!(
2193 valid_content_model(choice, &[a_name]),
2194 ContentModelResult::Valid
2195 );
2196
2197 assert_eq!(
2199 valid_content_model(choice, &[b_name]),
2200 ContentModelResult::Valid
2201 );
2202
2203 let other = c_str(b"other");
2205 assert_eq!(
2206 valid_content_model(choice, &[other]),
2207 ContentModelResult::Invalid
2208 );
2209
2210 free_content_model(choice);
2211 }
2212 }
2213
2214 #[test]
2215 fn test_valid_content_model_optional() {
2216 unsafe {
2217 let a_name = c_str(b"a");
2218
2219 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2220 (*c1).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
2221
2222 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2224
2225 assert_eq!(
2227 valid_content_model(c1, &[a_name]),
2228 ContentModelResult::Valid
2229 );
2230
2231 free_content_model(c1);
2232 }
2233 }
2234
2235 #[test]
2236 fn test_valid_content_model_zero_or_more() {
2237 unsafe {
2238 let a_name = c_str(b"a");
2239
2240 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2241 (*c1).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2242
2243 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2245
2246 assert_eq!(
2248 valid_content_model(c1, &[a_name]),
2249 ContentModelResult::Valid
2250 );
2251
2252 assert_eq!(
2254 valid_content_model(c1, &[a_name, a_name, a_name]),
2255 ContentModelResult::Valid
2256 );
2257
2258 free_content_model(c1);
2259 }
2260 }
2261
2262 #[test]
2263 fn test_valid_content_model_one_or_more() {
2264 unsafe {
2265 let a_name = c_str(b"a");
2266
2267 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2268 (*c1).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2269
2270 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Invalid);
2272
2273 assert_eq!(
2275 valid_content_model(c1, &[a_name]),
2276 ContentModelResult::Valid
2277 );
2278
2279 assert_eq!(
2281 valid_content_model(c1, &[a_name, a_name]),
2282 ContentModelResult::Valid
2283 );
2284
2285 free_content_model(c1);
2286 }
2287 }
2288}