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