1use core::ffi::c_void;
70use core::ptr;
71use std::os::raw::c_int;
72
73use crate::abi::allocator;
74
75pub type xmlListDeallocator = unsafe extern "C" fn(*mut c_void);
81
82pub type xmlListDataCompare = unsafe extern "C" fn(*const c_void, *const c_void) -> c_int;
84
85pub type xmlListWalker = unsafe extern "C" fn(*mut c_void, *mut c_void) -> c_int;
87
88struct ListNode {
90 data: *mut c_void,
91 prev: *mut ListNode,
92 next: *mut ListNode,
93}
94
95#[derive(Debug)]
97pub struct List {
98 front: *mut ListNode,
99 back: *mut ListNode,
100 count: usize,
101 deallocator: Option<xmlListDeallocator>,
102 comparator: Option<xmlListDataCompare>,
103}
104
105pub fn list_create(
121 deallocator: Option<xmlListDeallocator>,
122 comparator: Option<xmlListDataCompare>,
123) -> *mut List {
124 let list = Box::new(List {
125 front: ptr::null_mut(),
126 back: ptr::null_mut(),
127 count: 0,
128 deallocator,
129 comparator,
130 });
131
132 Box::into_raw(list)
133}
134
135pub unsafe fn list_delete(l: *mut List) {
147 if l.is_null() {
148 return;
149 }
150
151 let list = unsafe { &mut *l };
152 let mut cur = list.front;
153
154 while !cur.is_null() {
155 let next = unsafe { (*cur).next };
156 if let Some(dealloc) = list.deallocator {
159 unsafe { dealloc(cur as *mut c_void) };
160 }
161 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
162 cur = next;
163 }
164
165 drop(Box::from_raw(l));
166}
167
168pub unsafe fn list_search(l: *mut List, data: *const c_void) -> *mut c_void {
182 if l.is_null() {
183 return ptr::null_mut();
184 }
185
186 let list = unsafe { &*l };
187 let comparator = match list.comparator {
188 Some(c) => c,
189 None => return ptr::null_mut(),
190 };
191
192 let mut cur = list.front;
193 while !cur.is_null() {
194 let node = unsafe { &*cur };
195 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
196 return node.data;
197 }
198 cur = node.next;
199 }
200
201 ptr::null_mut()
202}
203
204pub unsafe fn list_end(l: *mut List) -> *mut c_void {
211 if l.is_null() {
212 return ptr::null_mut();
213 }
214 let list = unsafe { &*l };
215 if list.back.is_null() {
216 return ptr::null_mut();
217 }
218 unsafe { (*list.back).data }
219}
220
221pub unsafe fn list_reverse_search(l: *mut List, data: *const c_void) -> *mut c_void {
230 if l.is_null() {
231 return ptr::null_mut();
232 }
233 let list = unsafe { &*l };
234 let comparator = match list.comparator {
235 Some(c) => c,
236 None => return ptr::null_mut(),
237 };
238 let mut cur = list.back;
239 while !cur.is_null() {
240 let node_data = unsafe { (*cur).data };
242 if unsafe { comparator(node_data as *const c_void, data) } == 0 {
243 return node_data;
244 }
245 cur = unsafe { (*cur).prev };
246 }
247 ptr::null_mut()
248}
249
250pub unsafe fn list_reverse_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
258 if l.is_null() {
259 return;
260 }
261 let walker = match walker {
262 Some(w) => w,
263 None => return,
264 };
265 let list = unsafe { &*l };
266 let mut cur = list.back;
267 while !cur.is_null() {
268 let node_data = unsafe { (*cur).data };
270 if unsafe { walker(node_data, data) == 0 } {
272 return;
273 }
274 cur = unsafe { (*cur).prev };
275 }
276}
277
278pub unsafe fn list_dup(l: *mut List) -> *mut List {
286 if l.is_null() {
287 return ptr::null_mut();
288 }
289 let list = unsafe { &*l };
290 let new_list = Box::new(List {
291 front: ptr::null_mut(),
292 back: ptr::null_mut(),
293 count: 0,
294 deallocator: list.deallocator,
295 comparator: list.comparator,
296 });
297 let new_ptr = Box::into_raw(new_list);
298 let mut cur = list.front;
299 while !cur.is_null() {
300 let data = unsafe { (*cur).data };
302 if unsafe { list_push_back(new_ptr, data) } != 0 {
303 unsafe { list_delete(new_ptr) };
304 return ptr::null_mut();
305 }
306 cur = unsafe { (*cur).next };
307 }
308 new_ptr
309}
310
311pub unsafe fn list_copy(cur: *mut List, old: *mut List) -> c_int {
320 if old.is_null() || cur.is_null() {
321 return 1;
322 }
323 let mut lk = unsafe { (*old).front };
324 while !lk.is_null() {
325 let data = unsafe { (*lk).data };
328 if unsafe { list_insert(cur, data) } != 0 {
329 unsafe { list_delete(cur) };
330 return 1;
331 }
332 lk = unsafe { (*lk).next };
333 }
334 0
335}
336
337pub unsafe fn link_get_data(link: *mut c_void) -> *mut c_void {
343 if link.is_null() {
344 return ptr::null_mut();
345 }
346 unsafe { (*(link as *mut ListNode)).data }
347}
348
349pub unsafe fn list_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
362 if l.is_null() || walker.is_none() {
363 return;
364 }
365 let walker = walker.unwrap();
366
367 let list = unsafe { &*l };
368 let mut cur = list.front;
369 while !cur.is_null() {
370 let node = unsafe { &*cur };
371 if unsafe { walker(node.data, data) == 0 } {
373 break;
374 }
375 cur = node.next;
376 }
377}
378
379pub unsafe fn list_push_back(l: *mut List, data: *mut c_void) -> c_int {
393 if l.is_null() {
394 return -1;
395 }
396
397 let list = unsafe { &mut *l };
398
399 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
400 if node.is_null() {
401 return -1;
402 }
403
404 unsafe {
405 (*node).data = data;
406 (*node).prev = list.back;
407 (*node).next = ptr::null_mut();
408 }
409
410 if list.back.is_null() {
411 list.front = node;
412 list.back = node;
413 } else {
414 unsafe { (*list.back).next = node };
415 list.back = node;
416 }
417
418 list.count += 1;
419 0
420}
421
422pub unsafe fn list_push_front(l: *mut List, data: *mut c_void) -> c_int {
436 if l.is_null() {
437 return -1;
438 }
439
440 let list = unsafe { &mut *l };
441
442 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
443 if node.is_null() {
444 return -1;
445 }
446
447 unsafe {
448 (*node).data = data;
449 (*node).prev = ptr::null_mut();
450 (*node).next = list.front;
451 }
452
453 if list.front.is_null() {
454 list.front = node;
455 list.back = node;
456 } else {
457 unsafe { (*list.front).prev = node };
458 list.front = node;
459 }
460
461 list.count += 1;
462 0
463}
464
465pub unsafe fn list_pop_back(l: *mut List) {
477 if l.is_null() {
478 return;
479 }
480
481 let list = unsafe { &mut *l };
482 if list.back.is_null() {
483 return;
484 }
485
486 let node = list.back;
487 let prev = unsafe { (*node).prev };
488
489 if let Some(dealloc) = list.deallocator {
490 unsafe { dealloc((*node).data) };
491 }
492 unsafe { allocator::xmlFreeImpl(node as *mut c_void) };
493
494 list.back = prev;
495 if prev.is_null() {
496 list.front = ptr::null_mut();
497 } else {
498 unsafe { (*prev).next = ptr::null_mut() };
499 }
500
501 list.count = list.count.saturating_sub(1);
502}
503
504pub unsafe fn list_pop_front(l: *mut List) {
516 if l.is_null() {
517 return;
518 }
519
520 let list = unsafe { &mut *l };
521 if list.front.is_null() {
522 return;
523 }
524
525 let node = list.front;
526 let next = unsafe { (*node).next };
527
528 if let Some(dealloc) = list.deallocator {
529 unsafe { dealloc((*node).data) };
530 }
531 unsafe { allocator::xmlFreeImpl(node as *mut c_void) };
532
533 list.front = next;
534 if next.is_null() {
535 list.back = ptr::null_mut();
536 } else {
537 unsafe { (*next).prev = ptr::null_mut() };
538 }
539
540 list.count = list.count.saturating_sub(1);
541}
542
543pub unsafe fn list_insert(l: *mut List, data: *mut c_void) -> c_int {
558 if l.is_null() {
559 return -1;
560 }
561
562 let list = unsafe { &mut *l };
563
564 let comparator = match list.comparator {
566 Some(c) => c,
567 None => return list_push_back(l, data),
568 };
569
570 let mut cur = list.front;
572 while !cur.is_null() {
573 let node = unsafe { &*cur };
574 if unsafe { comparator(data as *const c_void, node.data as *const c_void) <= 0 } {
575 let new_node =
577 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
578 if new_node.is_null() {
579 return -1;
580 }
581 unsafe {
582 (*new_node).data = data;
583 (*new_node).prev = node.prev;
584 (*new_node).next = cur;
585 if !node.prev.is_null() {
586 (*node.prev).next = new_node;
587 } else {
588 list.front = new_node;
589 }
590 (*cur).prev = new_node;
591 }
592 list.count += 1;
593 return 0;
594 }
595 cur = node.next;
596 }
597
598 list_push_back(l, data)
600}
601
602pub unsafe fn list_append(l: *mut List, data: *mut c_void) -> c_int {
625 if l.is_null() {
629 return -1;
630 }
631 let comparator = unsafe { (*l).comparator };
632 match comparator {
633 None => unsafe { list_push_back(l, data) },
634 Some(cmp) => {
635 unsafe {
636 let mut cur = (*l).front;
637 while !cur.is_null() {
638 if cmp((*cur).data as *const c_void, data as *const c_void) > 0 {
639 break;
640 }
641 cur = (*cur).next;
642 }
643 let node =
645 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
646 if node.is_null() {
647 return -1;
648 }
649 (*node).data = data;
650 (*node).next = cur;
651 if cur.is_null() {
652 (*node).prev = (*l).back;
653 if !(*l).back.is_null() {
654 (*(*l).back).next = node;
655 }
656 (*l).back = node;
657 if (*l).front.is_null() {
658 (*l).front = node;
659 }
660 } else {
661 (*node).prev = (*cur).prev;
662 if !(*cur).prev.is_null() {
663 (*(*cur).prev).next = node;
664 } else {
665 (*l).front = node;
666 }
667 (*cur).prev = node;
668 }
669 }
670 0
671 }
672 }
673}
674
675pub unsafe fn list_remove_first(l: *mut List, data: *const c_void) -> c_int {
689 if l.is_null() {
690 return -1;
691 }
692
693 let list = unsafe { &mut *l };
694 let comparator = match list.comparator {
695 Some(c) => c,
696 None => return -1,
697 };
698
699 let mut cur = list.front;
700 while !cur.is_null() {
701 let node = unsafe { &*cur };
702 let next = node.next;
703 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
704 if !node.prev.is_null() {
706 unsafe { (*node.prev).next = node.next };
707 } else {
708 list.front = node.next;
709 }
710 if !node.next.is_null() {
711 unsafe { (*node.next).prev = node.prev };
712 } else {
713 list.back = node.prev;
714 }
715
716 if let Some(dealloc) = list.deallocator {
717 unsafe { dealloc(node.data) };
718 }
719 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
720 list.count = list.count.saturating_sub(1);
721 return 0;
722 }
723 cur = next;
724 }
725
726 -1
727}
728
729pub unsafe fn list_remove_last(l: *mut List, data: *const c_void) -> c_int {
743 if l.is_null() {
744 return -1;
745 }
746
747 let list = unsafe { &mut *l };
748 let comparator = match list.comparator {
749 Some(c) => c,
750 None => return -1,
751 };
752
753 let mut cur = list.back;
754 while !cur.is_null() {
755 let node = unsafe { &*cur };
756 let prev = node.prev;
757 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
758 if !node.prev.is_null() {
760 unsafe { (*node.prev).next = node.next };
761 } else {
762 list.front = node.next;
763 }
764 if !node.next.is_null() {
765 unsafe { (*node.next).prev = node.prev };
766 } else {
767 list.back = node.prev;
768 }
769
770 if let Some(dealloc) = list.deallocator {
771 unsafe { dealloc(node.data) };
772 }
773 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
774 list.count = list.count.saturating_sub(1);
775 return 0;
776 }
777 cur = prev;
778 }
779
780 -1
781}
782
783pub unsafe fn list_remove_all(l: *mut List, data: *const c_void) -> c_int {
797 if l.is_null() {
798 return 0;
799 }
800
801 let list = unsafe { &mut *l };
802 let comparator = match list.comparator {
803 Some(c) => c,
804 None => return 0,
805 };
806
807 let mut removed = 0;
808 let mut cur = list.front;
809
810 while !cur.is_null() {
811 let node = unsafe { &*cur };
812 let next = node.next;
813
814 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
815 if !node.prev.is_null() {
817 unsafe { (*node.prev).next = node.next };
818 } else {
819 list.front = node.next;
820 }
821 if !node.next.is_null() {
822 unsafe { (*node.next).prev = node.prev };
823 } else {
824 list.back = node.prev;
825 }
826
827 if let Some(dealloc) = list.deallocator {
828 unsafe { dealloc(node.data) };
829 }
830 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
831 list.count = list.count.saturating_sub(1);
832 removed += 1;
833 }
834
835 cur = next;
836 }
837
838 removed
839}
840
841pub unsafe fn list_clear(l: *mut List) {
853 if l.is_null() {
854 return;
855 }
856
857 let list = unsafe { &mut *l };
858 let mut cur = list.front;
859
860 while !cur.is_null() {
861 let next = unsafe { (*cur).next };
862 if let Some(dealloc) = list.deallocator {
863 unsafe { dealloc((*cur).data) };
864 }
865 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
866 cur = next;
867 }
868
869 list.front = ptr::null_mut();
870 list.back = ptr::null_mut();
871 list.count = 0;
872}
873
874pub fn list_empty(l: *mut List) -> c_int {
884 if l.is_null() {
885 return 1;
886 }
887 let list = unsafe { &*l };
888 if list.front.is_null() {
889 1
890 } else {
891 0
892 }
893}
894
895pub fn list_front(l: *mut List) -> *mut c_void {
905 if l.is_null() {
906 return ptr::null_mut();
907 }
908 let list = unsafe { &*l };
909 if list.front.is_null() {
910 ptr::null_mut()
911 } else {
912 unsafe { (*list.front).data }
913 }
914}
915
916pub fn list_back(l: *mut List) -> *mut c_void {
926 if l.is_null() {
927 return ptr::null_mut();
928 }
929 let list = unsafe { &*l };
930 if list.back.is_null() {
931 ptr::null_mut()
932 } else {
933 unsafe { (*list.back).data }
934 }
935}
936
937pub fn list_size(l: *mut List) -> c_int {
947 if l.is_null() {
948 return -1;
949 }
950 let list = unsafe { &*l };
951 list.count as c_int
952}
953
954pub unsafe fn list_sort(l: *mut List) {
966 if l.is_null() {
967 return;
968 }
969
970 let list = unsafe { &mut *l };
971 if list.count <= 1 {
972 return;
973 }
974
975 let comparator = match list.comparator {
976 Some(c) => c,
977 None => return,
978 };
979
980 let mut nodes: Vec<*mut ListNode> = Vec::with_capacity(list.count);
982 let mut cur = list.front;
983 while !cur.is_null() {
984 nodes.push(cur);
985 cur = unsafe { (*cur).next };
986 }
987
988 for i in 0..nodes.len() {
990 for j in 0..nodes.len() - 1 - i {
991 let a = unsafe { &*nodes[j] };
992 let b = unsafe { &*nodes[j + 1] };
993 if unsafe { comparator(a.data as *const c_void, b.data as *const c_void) > 0 } {
994 nodes.swap(j, j + 1);
995 }
996 }
997 }
998
999 list.front = nodes[0];
1001 list.back = nodes[nodes.len() - 1];
1002
1003 for i in 0..nodes.len() {
1004 unsafe {
1005 (*nodes[i]).prev = if i > 0 { nodes[i - 1] } else { ptr::null_mut() };
1006 (*nodes[i]).next = if i + 1 < nodes.len() {
1007 nodes[i + 1]
1008 } else {
1009 ptr::null_mut()
1010 };
1011 }
1012 }
1013}
1014
1015pub unsafe fn list_reverse(l: *mut List) {
1027 if l.is_null() {
1028 return;
1029 }
1030
1031 let list = unsafe { &mut *l };
1032
1033 let mut cur = list.front;
1036 std::mem::swap(&mut list.front, &mut list.back);
1037
1038 while !cur.is_null() {
1039 let next = unsafe { (*cur).next };
1040 unsafe {
1041 (*cur).next = (*cur).prev;
1042 (*cur).prev = next;
1043 }
1044 cur = next;
1045 }
1046}
1047
1048pub unsafe fn list_reverse_splice(l1: *mut List, l2: *mut List) {
1060 if l1.is_null() || l2.is_null() {
1061 return;
1062 }
1063
1064 let list1 = unsafe { &mut *l1 };
1065 let list2 = unsafe { &mut *l2 };
1066
1067 if list2.front.is_null() {
1068 return;
1069 }
1070
1071 list_reverse(l2);
1073
1074 unsafe {
1076 (*list2.back).next = list1.front;
1077 if !list1.front.is_null() {
1078 (*list1.front).prev = list2.back;
1079 } else {
1080 list1.back = list2.back;
1081 }
1082 list1.front = list2.front;
1083 }
1084
1085 list1.count += list2.count;
1086
1087 list2.front = ptr::null_mut();
1089 list2.back = ptr::null_mut();
1090 list2.count = 0;
1091}
1092
1093pub unsafe fn list_merge(l1: *mut List, l2: *mut List) {
1107 if l1.is_null() || l2.is_null() {
1108 return;
1109 }
1110
1111 let list1 = unsafe { &mut *l1 };
1112 let list2 = unsafe { &mut *l2 };
1113
1114 if list2.front.is_null() {
1115 return;
1116 }
1117
1118 let comparator = match list1.comparator {
1119 Some(c) => c,
1120 None => {
1121 if !list1.back.is_null() {
1123 unsafe { (*list1.back).next = list2.front };
1124 unsafe { (*list2.front).prev = list1.back };
1125 } else {
1126 list1.front = list2.front;
1127 }
1128 list1.back = list2.back;
1129 list1.count += list2.count;
1130 list2.front = ptr::null_mut();
1131 list2.back = ptr::null_mut();
1132 list2.count = 0;
1133 return;
1134 }
1135 };
1136
1137 let mut cur2 = list2.front;
1139 let mut insert_before = list1.front;
1140
1141 while !cur2.is_null() {
1142 let next2 = unsafe { (*cur2).next };
1143
1144 while !insert_before.is_null() {
1146 if unsafe {
1147 comparator(
1148 (*cur2).data as *const c_void,
1149 (*insert_before).data as *const c_void,
1150 ) <= 0
1151 } {
1152 break;
1153 }
1154 insert_before = unsafe { (*insert_before).next };
1155 }
1156
1157 if insert_before.is_null() {
1159 if list1.back.is_null() {
1161 list1.front = cur2;
1162 list1.back = cur2;
1163 unsafe {
1164 (*cur2).prev = ptr::null_mut();
1165 (*cur2).next = ptr::null_mut();
1166 }
1167 } else {
1168 unsafe {
1169 (*cur2).prev = list1.back;
1170 (*cur2).next = ptr::null_mut();
1171 (*list1.back).next = cur2;
1172 }
1173 list1.back = cur2;
1174 }
1175 } else {
1176 unsafe {
1177 (*cur2).prev = (*insert_before).prev;
1178 (*cur2).next = insert_before;
1179 if !(*insert_before).prev.is_null() {
1180 (*(*insert_before).prev).next = cur2;
1181 } else {
1182 list1.front = cur2;
1183 }
1184 (*insert_before).prev = cur2;
1185 }
1186 }
1187
1188 list1.count += 1;
1189 cur2 = next2;
1190 }
1191
1192 list2.front = ptr::null_mut();
1194 list2.back = ptr::null_mut();
1195 list2.count = 0;
1196}
1197
1198#[cfg(test)]
1203mod tests {
1204 use super::*;
1205
1206 unsafe extern "C" fn int_compare(a: *const c_void, b: *const c_void) -> c_int {
1207 let ai = *(a as *const i32);
1208 let bi = *(b as *const i32);
1209 ai.cmp(&bi) as c_int
1210 }
1211
1212 #[test]
1213 fn test_list_create_delete() {
1214 unsafe {
1215 let list = list_create(None, None);
1216 assert!(!list.is_null());
1217 list_delete(list);
1218 }
1219 }
1220
1221 #[test]
1222 fn test_list_push_pop() {
1223 unsafe {
1224 let list = list_create(None, None);
1225 let v1 = &mut 1 as *mut c_int as *mut c_void;
1226 let v2 = &mut 2 as *mut c_int as *mut c_void;
1227
1228 list_push_back(list, v1);
1229 list_push_back(list, v2);
1230 assert_eq!(list_size(list), 2);
1231
1232 assert_eq!(*(list_front(list) as *const i32), 1);
1233 assert_eq!(*(list_back(list) as *const i32), 2);
1234
1235 list_pop_back(list);
1236 assert_eq!(list_size(list), 1);
1237 assert_eq!(*(list_back(list) as *const i32), 1);
1238
1239 list_pop_front(list);
1240 assert_eq!(list_size(list), 0);
1241 assert_eq!(list_empty(list), 1);
1242
1243 list_delete(list);
1244 }
1245 }
1246
1247 #[test]
1248 fn test_list_push_front() {
1249 unsafe {
1250 let list = list_create(None, None);
1251 let v1 = &mut 1 as *mut c_int as *mut c_void;
1252 let v2 = &mut 2 as *mut c_int as *mut c_void;
1253
1254 list_push_front(list, v1);
1255 list_push_front(list, v2);
1256 assert_eq!(*(list_front(list) as *const i32), 2);
1257 assert_eq!(*(list_back(list) as *const i32), 1);
1258
1259 list_delete(list);
1260 }
1261 }
1262
1263 #[test]
1264 fn test_list_insert_sorted() {
1265 unsafe {
1266 let list = list_create(None, Some(int_compare));
1267 let v2 = &mut 2 as *mut c_int as *mut c_void;
1268 let v1 = &mut 1 as *mut c_int as *mut c_void;
1269 let v3 = &mut 3 as *mut c_int as *mut c_void;
1270
1271 list_insert(list, v2);
1272 list_insert(list, v1);
1273 list_insert(list, v3);
1274
1275 assert_eq!(*(list_front(list) as *const i32), 1);
1277 assert_eq!(*(list_back(list) as *const i32), 3);
1278 assert_eq!(list_size(list), 3);
1279
1280 list_delete(list);
1281 }
1282 }
1283
1284 #[test]
1285 fn test_list_remove_first() {
1286 unsafe {
1287 let list = list_create(None, Some(int_compare));
1288 let v1 = &mut 1 as *mut c_int as *mut c_void;
1289 let v2 = &mut 2 as *mut c_int as *mut c_void;
1290
1291 list_push_back(list, v1);
1292 list_push_back(list, v2);
1293
1294 let one: i32 = 1;
1295 let result = list_remove_first(list, &one as *const i32 as *const c_void);
1296 assert_eq!(result, 0);
1297 assert_eq!(list_size(list), 1);
1298 assert_eq!(*(list_front(list) as *const i32), 2);
1299
1300 list_delete(list);
1301 }
1302 }
1303
1304 #[test]
1305 fn test_list_clear() {
1306 unsafe {
1307 let list = list_create(None, None);
1308 list_push_back(list, &mut 1 as *mut c_int as *mut c_void);
1309 list_push_back(list, &mut 2 as *mut c_int as *mut c_void);
1310 assert_eq!(list_size(list), 2);
1311
1312 list_clear(list);
1313 assert_eq!(list_empty(list), 1);
1314 assert_eq!(list_size(list), 0);
1315
1316 list_delete(list);
1317 }
1318 }
1319
1320 #[test]
1321 fn test_list_reverse() {
1322 unsafe {
1323 let list = list_create(None, None);
1324 let v1 = &mut 1 as *mut c_int as *mut c_void;
1325 let v2 = &mut 2 as *mut c_int as *mut c_void;
1326 let v3 = &mut 3 as *mut c_int as *mut c_void;
1327
1328 list_push_back(list, v1);
1329 list_push_back(list, v2);
1330 list_push_back(list, v3);
1331
1332 list_reverse(list);
1333
1334 assert_eq!(*(list_front(list) as *const i32), 3);
1335 assert_eq!(*(list_back(list) as *const i32), 1);
1336
1337 list_delete(list);
1338 }
1339 }
1340
1341 #[test]
1342 fn test_list_null_handling() {
1343 unsafe {
1344 assert_eq!(list_empty(ptr::null_mut()), 1);
1345 assert_eq!(list_size(ptr::null_mut()), -1);
1346 assert!(list_front(ptr::null_mut()).is_null());
1347 assert!(list_back(ptr::null_mut()).is_null());
1348 list_delete(ptr::null_mut()); list_clear(ptr::null_mut()); list_pop_front(ptr::null_mut()); list_pop_back(ptr::null_mut()); }
1353 }
1354}