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
1072#[allow(clippy::too_many_arguments)]
1094pub unsafe fn add_attribute_decl(
1095 dtd: *mut _xmlDtd,
1096 elem: *mut _xmlElement,
1097 name: *const xmlChar,
1098 ns: *const xmlChar,
1099 type_: c_int,
1100 def: c_int,
1101 defaultValue: *const xmlChar,
1102 tree: *mut _xmlEnumeration,
1103) -> *mut _xmlAttribute {
1104 if dtd.is_null() || name.is_null() {
1105 return ptr::null_mut();
1106 }
1107
1108 unsafe {
1109 if (*dtd).attributes.is_null() {
1112 (*dtd).attributes = hash::hash_create(8) as *mut c_void;
1113 }
1114 let d = &*dtd;
1115 let elem_name = if elem.is_null() {
1116 ptr::null()
1117 } else {
1118 (*elem).name
1119 };
1120
1121 let existing =
1127 hash::hash_lookup3(d.attributes as *mut hash::HashTable, name, ns, elem_name);
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 = if ns.is_null() {
1151 ptr::null_mut()
1152 } else {
1153 string::xml_strdup(ns)
1154 };
1155 (*attr).elem = string::xml_strdup(elem_name);
1156
1157 let ret = hash::hash_add_entry3(
1160 d.attributes as *mut hash::HashTable,
1161 name,
1162 ns,
1163 elem_name,
1164 attr as *mut c_void,
1165 );
1166 if ret != 0 {
1167 if !(*attr).defaultValue.is_null() {
1169 allocator::xmlFreeImpl((*attr).defaultValue as *mut c_void);
1170 }
1171 if !(*attr).name.is_null() {
1172 allocator::xmlFreeImpl((*attr).name as *mut c_void);
1173 }
1174 if !(*attr).elem.is_null() {
1175 allocator::xmlFreeImpl((*attr).elem as *mut c_void);
1176 }
1177 if !(*attr).prefix.is_null() {
1178 allocator::xmlFreeImpl((*attr).prefix as *mut c_void);
1179 }
1180 allocator::xmlFreeImpl(attr as *mut c_void);
1181 return ptr::null_mut();
1183 }
1184
1185 if !elem.is_null() {
1187 (*attr).nexth = (*elem).attributes;
1188 (*elem).attributes = attr;
1189 }
1190
1191 if (*dtd).last.is_null() {
1194 (*dtd).children = attr as *mut _xmlNode;
1195 (*dtd).last = attr as *mut _xmlNode;
1196 } else {
1197 (*(*dtd).last).next = attr as *mut _xmlNode;
1198 (*attr).prev = (*dtd).last;
1199 (*dtd).last = attr as *mut _xmlNode;
1200 }
1201
1202 attr
1203 }
1204}
1205
1206pub unsafe fn get_attribute_decl(
1224 dtd: *mut _xmlDtd,
1225 elem: *mut _xmlElement,
1226 name: *const xmlChar,
1227 _namePrefix: c_int,
1228) -> *mut _xmlAttribute {
1229 if dtd.is_null() || name.is_null() {
1230 return ptr::null_mut();
1231 }
1232
1233 unsafe {
1234 let d = &*dtd;
1235 let elem_name = if elem.is_null() {
1236 ptr::null()
1237 } else {
1238 (*elem).name
1239 };
1240
1241 let payload = hash::hash_lookup3(
1244 d.attributes as *mut hash::HashTable,
1245 name,
1246 ptr::null(),
1247 elem_name,
1248 );
1249 payload as *mut _xmlAttribute
1250 }
1251}
1252
1253pub unsafe fn copy_attribute_decl(attr: *mut _xmlAttribute) -> *mut _xmlAttribute {
1265 if attr.is_null() {
1266 return ptr::null_mut();
1267 }
1268
1269 unsafe {
1270 let a = &*attr;
1271
1272 let copy =
1274 allocator::xmlMallocZero(size_of::<_xmlAttribute>() as usize) as *mut _xmlAttribute;
1275 if copy.is_null() {
1276 return ptr::null_mut();
1277 }
1278
1279 (*copy).type_ = a.type_;
1280 (*copy).name = string::xml_strdup(a.name);
1281 (*copy).parent = a.parent;
1282 (*copy).doc = a.doc;
1283 (*copy).nexth = ptr::null_mut();
1284 (*copy).atype = a.atype;
1285 (*copy).def = a.def;
1286 (*copy).defaultValue = string::xml_strdup(a.defaultValue);
1287 (*copy).tree = copy_enumeration(a.tree);
1288 (*copy).prefix = string::xml_strdup(a.prefix);
1289 (*copy).elem = string::xml_strdup(a.elem);
1290
1291 copy
1292 }
1293}
1294
1295pub unsafe fn free_attribute(attr: *mut _xmlAttribute) {
1307 if attr.is_null() {
1308 return;
1309 }
1310
1311 unsafe {
1312 let a = &*attr;
1313
1314 if !a.name.is_null() {
1315 allocator::xmlFreeImpl(a.name as *mut c_void);
1316 }
1317 if !a.defaultValue.is_null() {
1318 allocator::xmlFreeImpl(a.defaultValue as *mut c_void);
1319 }
1320 if !a.prefix.is_null() {
1321 allocator::xmlFreeImpl(a.prefix as *mut c_void);
1322 }
1323 if !a.elem.is_null() {
1324 allocator::xmlFreeImpl(a.elem as *mut c_void);
1325 }
1326 if !a.tree.is_null() {
1327 free_enumeration(a.tree);
1328 }
1329
1330 allocator::xmlFreeImpl(attr as *mut c_void);
1331 }
1332}
1333
1334#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1340pub enum ContentModelResult {
1341 Valid,
1343 Invalid,
1345 Indeterminate,
1347}
1348
1349pub unsafe fn valid_content_model(
1370 model: *mut _xmlElementContent,
1371 names: &[*const xmlChar],
1372) -> ContentModelResult {
1373 if model.is_null() {
1374 return ContentModelResult::Invalid;
1375 }
1376
1377 unsafe {
1378 let m = &*model;
1379
1380 match m.ocur as u32 {
1382 o if o == XML_ELEMENT_CONTENT_OPT as u32 => {
1383 if names.is_empty() {
1385 return ContentModelResult::Valid;
1386 }
1387 return valid_content_model_inner(model, names);
1388 }
1389 o if o == XML_ELEMENT_CONTENT_MULT as u32 => {
1390 if names.is_empty() {
1392 return ContentModelResult::Valid;
1393 }
1394 return valid_content_model_zero_or_more(model, names);
1395 }
1396 o if o == XML_ELEMENT_CONTENT_PLUS as u32 => {
1397 if names.is_empty() {
1399 return ContentModelResult::Invalid;
1400 }
1401 return valid_content_model_one_or_more(model, names);
1402 }
1403 _ => {}
1404 }
1405
1406 valid_content_model_inner(model, names)
1407 }
1408}
1409
1410unsafe fn valid_content_model_inner(
1412 model: *mut _xmlElementContent,
1413 names: &[*const xmlChar],
1414) -> ContentModelResult {
1415 unsafe {
1416 let m = &*model;
1417
1418 match m.type_ as u32 {
1419 t if t == XML_ELEMENT_CONTENT_PCDATA as u32 => {
1420 if names.is_empty() {
1422 ContentModelResult::Valid
1423 } else {
1424 ContentModelResult::Invalid
1425 }
1426 }
1427 t if t == XML_ELEMENT_CONTENT_ELEMENT as u32 => {
1428 if names.len() != 1 {
1430 return ContentModelResult::Invalid;
1431 }
1432 if names[0].is_null() {
1433 return ContentModelResult::Invalid;
1434 }
1435 if string::xml_strcmp(names[0], m.name) != 0 {
1437 return ContentModelResult::Invalid;
1438 }
1439 ContentModelResult::Valid
1440 }
1441 t if t == XML_ELEMENT_CONTENT_SEQ as u32 => {
1442 valid_content_model_seq(m, names)
1444 }
1445 t if t == XML_ELEMENT_CONTENT_OR as u32 => {
1446 valid_content_model_or(m, names)
1448 }
1449 _ => ContentModelResult::Invalid,
1450 }
1451 }
1452}
1453
1454unsafe fn valid_content_model_zero_or_more(
1456 model: *mut _xmlElementContent,
1457 names: &[*const xmlChar],
1458) -> ContentModelResult {
1459 let mut i = 0;
1461 while i <= names.len() {
1462 let consumed = &names[..i];
1463 let remaining = &names[i..];
1464
1465 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1466 if consumed_valid == ContentModelResult::Valid {
1467 if remaining.is_empty() {
1468 return ContentModelResult::Valid;
1469 }
1470 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1472 if remaining_valid == ContentModelResult::Valid {
1473 return ContentModelResult::Valid;
1474 }
1475 }
1476
1477 i += 1;
1478 }
1479 ContentModelResult::Invalid
1480}
1481
1482unsafe fn valid_content_model_one_or_more(
1484 model: *mut _xmlElementContent,
1485 names: &[*const xmlChar],
1486) -> ContentModelResult {
1487 let mut i = 1;
1489 while i <= names.len() {
1490 let consumed = &names[..i];
1491 let remaining = &names[i..];
1492
1493 let consumed_valid = unsafe { valid_content_model_inner(model, consumed) };
1494 if consumed_valid == ContentModelResult::Valid {
1495 if remaining.is_empty() {
1496 return ContentModelResult::Valid;
1497 }
1498 let remaining_valid = unsafe { valid_content_model_zero_or_more(model, remaining) };
1499 if remaining_valid == ContentModelResult::Valid {
1500 return ContentModelResult::Valid;
1501 }
1502 }
1503
1504 i += 1;
1505 }
1506 ContentModelResult::Invalid
1507}
1508
1509unsafe fn valid_content_model_seq(
1511 model: &_xmlElementContent,
1512 names: &[*const xmlChar],
1513) -> ContentModelResult {
1514 let c1 = model.c1;
1519 let c2 = model.c2;
1520
1521 if c1.is_null() && c2.is_null() {
1522 return ContentModelResult::Valid;
1523 }
1524
1525 if c1.is_null() {
1526 return unsafe { valid_content_model(c2, names) };
1527 }
1528
1529 if c2.is_null() {
1530 return unsafe { valid_content_model(c1, names) };
1531 }
1532
1533 for split in 0..=names.len() {
1536 let left = &names[..split];
1537 let right = &names[split..];
1538
1539 let left_valid = unsafe { valid_content_model(c1, left) };
1540 if left_valid != ContentModelResult::Valid {
1541 continue;
1542 }
1543
1544 let right_valid = unsafe { valid_content_model(c2, right) };
1545 if right_valid == ContentModelResult::Valid {
1546 return ContentModelResult::Valid;
1547 }
1548 }
1549
1550 ContentModelResult::Invalid
1551}
1552
1553unsafe fn valid_content_model_or(
1555 model: &_xmlElementContent,
1556 names: &[*const xmlChar],
1557) -> ContentModelResult {
1558 let c1 = model.c1;
1559 let c2 = model.c2;
1560
1561 if c1.is_null() && c2.is_null() {
1562 return ContentModelResult::Invalid;
1563 }
1564
1565 if !c1.is_null() {
1566 let result = unsafe { valid_content_model(c1, names) };
1567 if result == ContentModelResult::Valid {
1568 return ContentModelResult::Valid;
1569 }
1570 }
1571
1572 if !c2.is_null() {
1573 let result = unsafe { valid_content_model(c2, names) };
1574 if result == ContentModelResult::Valid {
1575 return ContentModelResult::Valid;
1576 }
1577 }
1578
1579 ContentModelResult::Invalid
1580}
1581
1582#[cfg(test)]
1587mod tests {
1588 use super::*;
1589
1590 use core::ffi::c_void;
1591 use core::ptr;
1592
1593 unsafe fn c_str(s: &[u8]) -> *const xmlChar {
1596 let len = s.len();
1598 let buf = allocator::xmlMallocImpl(len + 1) as *mut xmlChar;
1599 assert!(!buf.is_null());
1600 ptr::copy_nonoverlapping(s.as_ptr(), buf, len);
1601 *buf.add(len) = 0;
1602 buf as *const xmlChar
1603 }
1604
1605 unsafe fn make_doc_and_dtd() -> (*mut _xmlDoc, *mut _xmlDtd) {
1606 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1607 assert!(!doc.is_null());
1608 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1609 (*doc).doc = doc;
1610 let dtd = create_int_subset(doc, c_str(b"root"), ptr::null(), ptr::null());
1611 assert!(!dtd.is_null());
1612 (doc, dtd)
1613 }
1614
1615 #[test]
1618 fn test_get_int_subset_null() {
1619 {
1620 assert!(get_int_subset(ptr::null()).is_null());
1621 }
1622 }
1623
1624 #[test]
1625 fn test_create_int_subset() {
1626 unsafe {
1627 let (doc, dtd) = make_doc_and_dtd();
1628 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1629 assert!(!(*dtd).name.is_null());
1630 assert_eq!((*doc).intSubset, dtd);
1631
1632 free_dtd(dtd);
1634 allocator::xmlFreeImpl(doc as *mut c_void);
1635 }
1636 }
1637
1638 #[test]
1639 fn test_create_int_subset_null_doc() {
1640 unsafe {
1641 let dtd = create_int_subset(ptr::null_mut(), c_str(b"root"), ptr::null(), ptr::null());
1642 assert!(dtd.is_null());
1643 }
1644 }
1645
1646 #[test]
1647 fn test_new_dtd() {
1648 unsafe {
1649 let doc = allocator::xmlMallocZero(size_of::<_xmlDoc>() as usize) as *mut _xmlDoc;
1650 assert!(!doc.is_null());
1651 (*doc).type_ = XML_DOCUMENT_NODE as c_int;
1652 (*doc).doc = doc;
1653
1654 let dtd = new_dtd(doc, c_str(b"test"), c_str(b"-//TEST//"), c_str(b"test.dtd"));
1655 assert!(!dtd.is_null());
1656 assert_eq!((*dtd).type_, XML_DTD_NODE as c_int);
1657 assert_eq!((*doc).intSubset, dtd);
1658
1659 free_dtd(dtd);
1660 allocator::xmlFreeImpl(doc as *mut c_void);
1661 }
1662 }
1663
1664 #[test]
1665 fn test_new_dtd_no_doc() {
1666 unsafe {
1667 let dtd = new_dtd(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1668 assert!(!dtd.is_null());
1669 free_dtd(dtd);
1670 }
1671 }
1672
1673 #[test]
1676 fn test_add_get_notation() {
1677 unsafe {
1678 let (doc, dtd) = make_doc_and_dtd();
1679 let name = c_str(b"note");
1680 let pubid = c_str(b"-//TEST//NOTATION");
1681 let sysid = c_str(b"note.ent");
1682
1683 let n = add_notation_decl(dtd, name, pubid, sysid);
1684 assert!(!n.is_null());
1685 assert_eq!(string::xml_strcmp((*n).name, name), 0);
1686
1687 let found = get_notation_decl(dtd, name);
1689 assert_eq!(found, n);
1690
1691 let not_found = get_notation_decl(dtd, c_str(b"nonexistent"));
1693 assert!(not_found.is_null());
1694
1695 free_dtd(dtd);
1696 allocator::xmlFreeImpl(doc as *mut c_void);
1697 }
1698 }
1699
1700 #[test]
1701 fn test_add_notation_null_dtd() {
1702 unsafe {
1703 let n = add_notation_decl(ptr::null_mut(), c_str(b"test"), ptr::null(), ptr::null());
1704 assert!(n.is_null());
1705 }
1706 }
1707
1708 #[test]
1709 fn test_copy_notation() {
1710 unsafe {
1711 let (doc, dtd) = make_doc_and_dtd();
1712 let name = c_str(b"note1");
1713 let pubid = c_str(b"public");
1714 let sysid = c_str(b"system");
1715
1716 let n = add_notation_decl(dtd, name, pubid, sysid);
1717 assert!(!n.is_null());
1718
1719 let copy = copy_notation(n);
1720 assert!(!copy.is_null());
1721 assert_ne!(copy, n);
1722 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1723 assert_eq!(string::xml_strcmp((*copy).PublicID, pubid), 0);
1724 assert_eq!(string::xml_strcmp((*copy).SystemID, sysid), 0);
1725
1726 free_notation(copy);
1727 free_dtd(dtd);
1728 allocator::xmlFreeImpl(doc as *mut c_void);
1729 }
1730 }
1731
1732 #[test]
1733 fn test_copy_notation_null() {
1734 unsafe {
1735 assert!(copy_notation(ptr::null_mut()).is_null());
1736 }
1737 }
1738
1739 #[test]
1740 fn test_free_notation_null() {
1741 unsafe {
1742 free_notation(ptr::null_mut()); }
1744 }
1745
1746 #[test]
1749 fn test_create_free_content_model() {
1750 unsafe {
1751 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1752 assert!(!cm.is_null());
1753 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1754 assert_eq!((*cm).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1755
1756 free_content_model(cm);
1757 }
1758 }
1759
1760 #[test]
1761 fn test_create_content_model_pcdata() {
1762 unsafe {
1763 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
1764 assert!(!cm.is_null());
1765 assert_eq!((*cm).type_, XML_ELEMENT_CONTENT_PCDATA as c_int);
1766 free_content_model(cm);
1767 }
1768 }
1769
1770 #[test]
1771 fn test_copy_content_model() {
1772 unsafe {
1773 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1774 assert!(!cm.is_null());
1775
1776 let copy = copy_content_model(cm);
1777 assert!(!copy.is_null());
1778 assert_ne!(copy, cm);
1779 assert_eq!((*copy).type_, XML_ELEMENT_CONTENT_ELEMENT as c_int);
1780 assert_eq!((*copy).ocur, XML_ELEMENT_CONTENT_ONCE as c_int);
1781 assert_eq!(string::xml_strcmp((*copy).name, (*cm).name), 0);
1782
1783 free_content_model(cm);
1784 free_content_model(copy);
1785 }
1786 }
1787
1788 #[test]
1789 fn test_copy_content_model_null() {
1790 unsafe {
1791 assert!(copy_content_model(ptr::null_mut()).is_null());
1792 }
1793 }
1794
1795 #[test]
1796 fn test_free_content_model_null() {
1797 unsafe {
1798 free_content_model(ptr::null_mut()); }
1800 }
1801
1802 #[test]
1803 fn test_create_sequence_content_model() {
1804 unsafe {
1805 let c1 = create_content_model(c_str(b"a"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1806 let c2 = create_content_model(c_str(b"b"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1807 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
1808 assert!(!seq.is_null());
1809 (*seq).c1 = c1;
1810 (*seq).c2 = c2;
1811 (*c1).parent = seq;
1812 (*c2).parent = seq;
1813
1814 free_content_model(seq);
1815 }
1816 }
1817
1818 #[test]
1821 fn test_add_get_element() {
1822 unsafe {
1823 let (doc, dtd) = make_doc_and_dtd();
1824 let name = c_str(b"myElement");
1825
1826 let elem =
1827 add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1828 assert!(!elem.is_null());
1829 assert_eq!((*elem).etype, XML_ELEMENT_TYPE_EMPTY as c_int);
1830
1831 let found = get_element_decl(dtd, name);
1832 assert_eq!(found, elem);
1833
1834 let not_found = get_element_decl(dtd, c_str(b"nonexistent"));
1835 assert!(not_found.is_null());
1836
1837 free_dtd(dtd);
1838 allocator::xmlFreeImpl(doc as *mut c_void);
1839 }
1840 }
1841
1842 #[test]
1843 fn test_add_element_duplicate() {
1844 unsafe {
1845 let (doc, dtd) = make_doc_and_dtd();
1846 let name = c_str(b"dup");
1847
1848 let e1 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_EMPTY as c_int, ptr::null_mut());
1849 assert!(!e1.is_null());
1850
1851 let e2 = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ANY as c_int, ptr::null_mut());
1852 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);
1857 allocator::xmlFreeImpl(doc as *mut c_void);
1858 }
1859 }
1860
1861 #[test]
1862 fn test_add_element_null_dtd() {
1863 unsafe {
1864 let elem = add_element_decl(
1865 ptr::null_mut(),
1866 c_str(b"test"),
1867 XML_ELEMENT_TYPE_EMPTY as c_int,
1868 ptr::null_mut(),
1869 );
1870 assert!(elem.is_null());
1871 }
1872 }
1873
1874 #[test]
1875 fn test_copy_element() {
1876 unsafe {
1877 let (doc, dtd) = make_doc_and_dtd();
1878 let name = c_str(b"source");
1879 let cm = create_content_model(c_str(b"child"), XML_ELEMENT_CONTENT_ELEMENT as c_int);
1880
1881 let elem = add_element_decl(dtd, name, XML_ELEMENT_TYPE_ELEMENT as c_int, cm);
1882 assert!(!elem.is_null());
1883
1884 let copy = copy_element(elem);
1885 assert!(!copy.is_null());
1886 assert_ne!(copy, elem);
1887 assert_eq!((*copy).type_, XML_ELEMENT_DECL as c_int);
1888 assert_eq!((*copy).etype, XML_ELEMENT_TYPE_ELEMENT as c_int);
1889 assert_eq!(string::xml_strcmp((*copy).name, name), 0);
1890 assert!(!(*copy).content.is_null());
1891 assert_ne!((*copy).content, cm);
1892
1893 free_element(copy);
1894 free_dtd(dtd);
1895 allocator::xmlFreeImpl(doc as *mut c_void);
1896 }
1897 }
1898
1899 #[test]
1900 fn test_free_element_null() {
1901 unsafe {
1902 free_element(ptr::null_mut()); }
1904 }
1905
1906 #[test]
1909 fn test_add_get_attribute() {
1910 unsafe {
1911 let (doc, dtd) = make_doc_and_dtd();
1912 let elem_name = c_str(b"elem");
1913 let attr_name = c_str(b"attr1");
1914
1915 let elem = add_element_decl(
1916 dtd,
1917 elem_name,
1918 XML_ELEMENT_TYPE_EMPTY as c_int,
1919 ptr::null_mut(),
1920 );
1921 assert!(!elem.is_null());
1922
1923 let attr = add_attribute_decl(
1924 dtd,
1925 elem,
1926 attr_name,
1927 ptr::null(),
1928 XML_ATTRIBUTE_CDATA as c_int,
1929 XML_ATTRIBUTE_IMPLIED as c_int,
1930 ptr::null(),
1931 ptr::null_mut(),
1932 );
1933 assert!(!attr.is_null());
1934 assert_eq!((*attr).atype, XML_ATTRIBUTE_CDATA as c_int);
1935 assert_eq!((*attr).def, XML_ATTRIBUTE_IMPLIED as c_int);
1936
1937 let found = get_attribute_decl(dtd, elem, attr_name, 0);
1939 assert_eq!(found, attr);
1940
1941 let not_found = get_attribute_decl(dtd, elem, c_str(b"nonexistent"), 0);
1943 assert!(not_found.is_null());
1944
1945 free_dtd(dtd);
1946 allocator::xmlFreeImpl(doc as *mut c_void);
1947 }
1948 }
1949
1950 #[test]
1951 fn test_add_attribute_with_default() {
1952 unsafe {
1953 let (doc, dtd) = make_doc_and_dtd();
1954 let elem_name = c_str(b"elem");
1955 let attr_name = c_str(b"color");
1956 let default_val = c_str(b"red");
1957
1958 let elem = add_element_decl(
1959 dtd,
1960 elem_name,
1961 XML_ELEMENT_TYPE_EMPTY as c_int,
1962 ptr::null_mut(),
1963 );
1964
1965 let attr = add_attribute_decl(
1966 dtd,
1967 elem,
1968 attr_name,
1969 ptr::null(),
1970 XML_ATTRIBUTE_CDATA as c_int,
1971 XML_ATTRIBUTE_FIXED as c_int,
1972 default_val,
1973 ptr::null_mut(),
1974 );
1975 assert!(!attr.is_null());
1976 assert_eq!((*attr).def, XML_ATTRIBUTE_FIXED as c_int);
1977 assert_eq!(string::xml_strcmp((*attr).defaultValue, default_val), 0);
1978
1979 free_dtd(dtd);
1980 allocator::xmlFreeImpl(doc as *mut c_void);
1981 }
1982 }
1983
1984 #[test]
1985 fn test_add_attribute_enumeration() {
1986 unsafe {
1987 let (doc, dtd) = make_doc_and_dtd();
1988 let elem_name = c_str(b"elem");
1989 let attr_name = c_str(b"size");
1990
1991 let v3 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1993 as *mut _xmlEnumeration;
1994 (*v3).name = string::xml_strdup(c_str(b"large"));
1995 let v2 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
1996 as *mut _xmlEnumeration;
1997 (*v2).name = string::xml_strdup(c_str(b"medium"));
1998 (*v2).next = v3;
1999 let v1 = allocator::xmlMallocZero(size_of::<_xmlEnumeration>() as usize)
2000 as *mut _xmlEnumeration;
2001 (*v1).name = string::xml_strdup(c_str(b"small"));
2002 (*v1).next = v2;
2003
2004 let elem = add_element_decl(
2005 dtd,
2006 elem_name,
2007 XML_ELEMENT_TYPE_EMPTY as c_int,
2008 ptr::null_mut(),
2009 );
2010 let attr = add_attribute_decl(
2011 dtd,
2012 elem,
2013 attr_name,
2014 ptr::null(),
2015 XML_ATTRIBUTE_ENUMERATION as c_int,
2016 XML_ATTRIBUTE_REQUIRED as c_int,
2017 ptr::null(),
2018 v1,
2019 );
2020 assert!(!attr.is_null());
2021 assert_eq!((*attr).atype, XML_ATTRIBUTE_ENUMERATION as c_int);
2022
2023 free_dtd(dtd);
2024 allocator::xmlFreeImpl(doc as *mut c_void);
2025 }
2026 }
2027
2028 #[test]
2029 fn test_add_attribute_null_dtd() {
2030 unsafe {
2031 let attr = add_attribute_decl(
2032 ptr::null_mut(),
2033 ptr::null_mut(),
2034 c_str(b"test"),
2035 ptr::null(),
2036 XML_ATTRIBUTE_CDATA as c_int,
2037 XML_ATTRIBUTE_IMPLIED as c_int,
2038 ptr::null(),
2039 ptr::null_mut(),
2040 );
2041 assert!(attr.is_null());
2042 }
2043 }
2044
2045 #[test]
2046 fn test_copy_attribute() {
2047 unsafe {
2048 let (doc, dtd) = make_doc_and_dtd();
2049 let elem_name = c_str(b"elem");
2050 let attr_name = c_str(b"id");
2051 let default_val = c_str(b"default");
2052
2053 let elem = add_element_decl(
2054 dtd,
2055 elem_name,
2056 XML_ELEMENT_TYPE_EMPTY as c_int,
2057 ptr::null_mut(),
2058 );
2059 let attr = add_attribute_decl(
2060 dtd,
2061 elem,
2062 attr_name,
2063 ptr::null(),
2064 XML_ATTRIBUTE_ID as c_int,
2065 XML_ATTRIBUTE_IMPLIED as c_int,
2066 default_val,
2067 ptr::null_mut(),
2068 );
2069 assert!(!attr.is_null());
2070
2071 let copy = copy_attribute_decl(attr);
2072 assert!(!copy.is_null());
2073 assert_ne!(copy, attr);
2074 assert_eq!((*copy).atype, XML_ATTRIBUTE_ID as c_int);
2075 assert_eq!(string::xml_strcmp((*copy).name, attr_name), 0);
2076
2077 free_attribute(copy);
2078 free_dtd(dtd);
2079 allocator::xmlFreeImpl(doc as *mut c_void);
2080 }
2081 }
2082
2083 #[test]
2084 fn test_free_attribute_null() {
2085 unsafe {
2086 free_attribute(ptr::null_mut()); }
2088 }
2089
2090 #[test]
2093 fn test_valid_content_model_null() {
2094 unsafe {
2095 assert_eq!(
2096 valid_content_model(ptr::null_mut(), &[]),
2097 ContentModelResult::Invalid
2098 );
2099 }
2100 }
2101
2102 #[test]
2103 fn test_valid_content_model_pcdata() {
2104 unsafe {
2105 let cm = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_PCDATA as c_int);
2106 assert!(!cm.is_null());
2107
2108 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Valid);
2110
2111 let name = c_str(b"child");
2113 assert_eq!(
2114 valid_content_model(cm, &[name]),
2115 ContentModelResult::Invalid
2116 );
2117
2118 free_content_model(cm);
2119 }
2120 }
2121
2122 #[test]
2123 fn test_valid_content_model_element() {
2124 unsafe {
2125 let child_name = c_str(b"child");
2126 let cm = create_content_model(child_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2127 assert!(!cm.is_null());
2128
2129 assert_eq!(
2131 valid_content_model(cm, &[child_name]),
2132 ContentModelResult::Valid
2133 );
2134
2135 let other = c_str(b"other");
2137 assert_eq!(
2138 valid_content_model(cm, &[other]),
2139 ContentModelResult::Invalid
2140 );
2141
2142 assert_eq!(
2144 valid_content_model(cm, &[child_name, child_name]),
2145 ContentModelResult::Invalid
2146 );
2147
2148 assert_eq!(valid_content_model(cm, &[]), ContentModelResult::Invalid);
2150
2151 free_content_model(cm);
2152 }
2153 }
2154
2155 #[test]
2156 fn test_valid_content_model_seq() {
2157 unsafe {
2158 let a_name = c_str(b"a");
2159 let b_name = c_str(b"b");
2160
2161 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2162 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2163 let seq = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_SEQ as c_int);
2164 (*seq).c1 = c1;
2165 (*seq).c2 = c2;
2166 (*c1).parent = seq;
2167 (*c2).parent = seq;
2168
2169 assert_eq!(
2171 valid_content_model(seq, &[a_name, b_name]),
2172 ContentModelResult::Valid
2173 );
2174
2175 assert_eq!(
2177 valid_content_model(seq, &[b_name, a_name]),
2178 ContentModelResult::Invalid
2179 );
2180
2181 assert_eq!(
2183 valid_content_model(seq, &[a_name]),
2184 ContentModelResult::Invalid
2185 );
2186
2187 free_content_model(seq);
2188 }
2189 }
2190
2191 #[test]
2192 fn test_valid_content_model_or() {
2193 unsafe {
2194 let a_name = c_str(b"a");
2195 let b_name = c_str(b"b");
2196
2197 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2198 let c2 = create_content_model(b_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2199 let choice = create_content_model(ptr::null(), XML_ELEMENT_CONTENT_OR as c_int);
2200 (*choice).c1 = c1;
2201 (*choice).c2 = c2;
2202 (*c1).parent = choice;
2203 (*c2).parent = choice;
2204
2205 assert_eq!(
2207 valid_content_model(choice, &[a_name]),
2208 ContentModelResult::Valid
2209 );
2210
2211 assert_eq!(
2213 valid_content_model(choice, &[b_name]),
2214 ContentModelResult::Valid
2215 );
2216
2217 let other = c_str(b"other");
2219 assert_eq!(
2220 valid_content_model(choice, &[other]),
2221 ContentModelResult::Invalid
2222 );
2223
2224 free_content_model(choice);
2225 }
2226 }
2227
2228 #[test]
2229 fn test_valid_content_model_optional() {
2230 unsafe {
2231 let a_name = c_str(b"a");
2232
2233 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2234 (*c1).ocur = XML_ELEMENT_CONTENT_OPT as c_int;
2235
2236 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2238
2239 assert_eq!(
2241 valid_content_model(c1, &[a_name]),
2242 ContentModelResult::Valid
2243 );
2244
2245 free_content_model(c1);
2246 }
2247 }
2248
2249 #[test]
2250 fn test_valid_content_model_zero_or_more() {
2251 unsafe {
2252 let a_name = c_str(b"a");
2253
2254 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2255 (*c1).ocur = XML_ELEMENT_CONTENT_MULT as c_int;
2256
2257 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Valid);
2259
2260 assert_eq!(
2262 valid_content_model(c1, &[a_name]),
2263 ContentModelResult::Valid
2264 );
2265
2266 assert_eq!(
2268 valid_content_model(c1, &[a_name, a_name, a_name]),
2269 ContentModelResult::Valid
2270 );
2271
2272 free_content_model(c1);
2273 }
2274 }
2275
2276 #[test]
2277 fn test_valid_content_model_one_or_more() {
2278 unsafe {
2279 let a_name = c_str(b"a");
2280
2281 let c1 = create_content_model(a_name, XML_ELEMENT_CONTENT_ELEMENT as c_int);
2282 (*c1).ocur = XML_ELEMENT_CONTENT_PLUS as c_int;
2283
2284 assert_eq!(valid_content_model(c1, &[]), ContentModelResult::Invalid);
2286
2287 assert_eq!(
2289 valid_content_model(c1, &[a_name]),
2290 ContentModelResult::Valid
2291 );
2292
2293 assert_eq!(
2295 valid_content_model(c1, &[a_name, a_name]),
2296 ContentModelResult::Valid
2297 );
2298
2299 free_content_model(c1);
2300 }
2301 }
2302}