1use core::ffi::c_void;
23use core::ptr;
24use std::os::raw::c_int;
25
26use crate::abi::allocator;
27
28pub type xmlListDeallocator = unsafe extern "C" fn(*mut c_void);
34
35pub type xmlListDataCompare = unsafe extern "C" fn(*const c_void, *const c_void) -> c_int;
37
38pub type xmlListWalker = unsafe extern "C" fn(*mut c_void, *mut c_void) -> c_int;
40
41struct ListNode {
43 data: *mut c_void,
44 prev: *mut ListNode,
45 next: *mut ListNode,
46}
47
48#[derive(Debug)]
50pub struct List {
51 front: *mut ListNode,
52 back: *mut ListNode,
53 count: usize,
54 deallocator: Option<xmlListDeallocator>,
55 comparator: Option<xmlListDataCompare>,
56}
57
58pub fn list_create(
74 deallocator: Option<xmlListDeallocator>,
75 comparator: Option<xmlListDataCompare>,
76) -> *mut List {
77 let list = Box::new(List {
78 front: ptr::null_mut(),
79 back: ptr::null_mut(),
80 count: 0,
81 deallocator,
82 comparator,
83 });
84
85 Box::into_raw(list)
86}
87
88pub unsafe fn list_delete(l: *mut List) {
100 if l.is_null() {
101 return;
102 }
103
104 let list = unsafe { &mut *l };
105 let mut cur = list.front;
106
107 while !cur.is_null() {
108 let next = unsafe { (*cur).next };
109 if let Some(dealloc) = list.deallocator {
112 unsafe { dealloc(cur as *mut c_void) };
113 }
114 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
115 cur = next;
116 }
117
118 drop(Box::from_raw(l));
119}
120
121pub unsafe fn list_search(l: *mut List, data: *const c_void) -> *mut c_void {
135 if l.is_null() {
136 return ptr::null_mut();
137 }
138
139 let list = unsafe { &*l };
140 let comparator = match list.comparator {
141 Some(c) => c,
142 None => return ptr::null_mut(),
143 };
144
145 let mut cur = list.front;
146 while !cur.is_null() {
147 let node = unsafe { &*cur };
148 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
149 return node.data;
150 }
151 cur = node.next;
152 }
153
154 ptr::null_mut()
155}
156
157pub unsafe fn list_end(l: *mut List) -> *mut c_void {
164 if l.is_null() {
165 return ptr::null_mut();
166 }
167 let list = unsafe { &*l };
168 if list.back.is_null() {
169 return ptr::null_mut();
170 }
171 unsafe { (*list.back).data }
172}
173
174pub unsafe fn list_reverse_search(l: *mut List, data: *const c_void) -> *mut c_void {
183 if l.is_null() {
184 return ptr::null_mut();
185 }
186 let list = unsafe { &*l };
187 let comparator = match list.comparator {
188 Some(c) => c,
189 None => return ptr::null_mut(),
190 };
191 let mut cur = list.back;
192 while !cur.is_null() {
193 let node_data = unsafe { (*cur).data };
195 if unsafe { comparator(node_data as *const c_void, data) } == 0 {
196 return node_data;
197 }
198 cur = unsafe { (*cur).prev };
199 }
200 ptr::null_mut()
201}
202
203pub unsafe fn list_reverse_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
211 if l.is_null() {
212 return;
213 }
214 let walker = match walker {
215 Some(w) => w,
216 None => return,
217 };
218 let list = unsafe { &*l };
219 let mut cur = list.back;
220 while !cur.is_null() {
221 let node_data = unsafe { (*cur).data };
223 if unsafe { walker(node_data, data) == 0 } {
225 return;
226 }
227 cur = unsafe { (*cur).prev };
228 }
229}
230
231pub unsafe fn list_dup(l: *mut List) -> *mut List {
239 if l.is_null() {
240 return ptr::null_mut();
241 }
242 let list = unsafe { &*l };
243 let new_list = Box::new(List {
244 front: ptr::null_mut(),
245 back: ptr::null_mut(),
246 count: 0,
247 deallocator: list.deallocator,
248 comparator: list.comparator,
249 });
250 let new_ptr = Box::into_raw(new_list);
251 let mut cur = list.front;
252 while !cur.is_null() {
253 let data = unsafe { (*cur).data };
255 if unsafe { list_push_back(new_ptr, data) } != 0 {
256 unsafe { list_delete(new_ptr) };
257 return ptr::null_mut();
258 }
259 cur = unsafe { (*cur).next };
260 }
261 new_ptr
262}
263
264pub unsafe fn list_copy(
274 l: *mut List,
275 copier: Option<unsafe extern "C" fn(*mut c_void) -> *mut c_void>,
276) -> c_int {
277 if l.is_null() {
278 return -1;
279 }
280 let copier = match copier {
281 Some(c) => c,
282 None => return -1,
283 };
284 let list = unsafe { &*l };
285 let new_list = Box::new(List {
286 front: ptr::null_mut(),
287 back: ptr::null_mut(),
288 count: 0,
289 deallocator: list.deallocator,
290 comparator: list.comparator,
291 });
292 let new_ptr = Box::into_raw(new_list);
293 let mut cur = list.front;
294 while !cur.is_null() {
295 let copied = unsafe { copier((*cur).data) };
297 if copied.is_null() {
298 unsafe { list_delete(new_ptr) };
299 return -1;
300 }
301 if unsafe { list_push_back(new_ptr, copied) } != 0 {
302 unsafe { list_delete(new_ptr) };
303 return -1;
304 }
305 cur = unsafe { (*cur).next };
306 }
307 unsafe {
309 list_clear(l);
310 let dst = &mut *l;
311 let src = &mut *new_ptr;
312 core::mem::swap(dst, src);
313 list_delete(new_ptr);
314 }
315 0
316}
317
318pub unsafe fn link_get_data(link: *mut c_void) -> *mut c_void {
324 if link.is_null() {
325 return ptr::null_mut();
326 }
327 unsafe { (*(link as *mut ListNode)).data }
328}
329
330pub unsafe fn list_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
343 if l.is_null() || walker.is_none() {
344 return;
345 }
346 let walker = walker.unwrap();
347
348 let list = unsafe { &*l };
349 let mut cur = list.front;
350 while !cur.is_null() {
351 let node = unsafe { &*cur };
352 if unsafe { walker(node.data, data) == 0 } {
354 break;
355 }
356 cur = node.next;
357 }
358}
359
360pub unsafe fn list_push_back(l: *mut List, data: *mut c_void) -> c_int {
374 if l.is_null() {
375 return -1;
376 }
377
378 let list = unsafe { &mut *l };
379
380 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
381 if node.is_null() {
382 return -1;
383 }
384
385 unsafe {
386 (*node).data = data;
387 (*node).prev = list.back;
388 (*node).next = ptr::null_mut();
389 }
390
391 if list.back.is_null() {
392 list.front = node;
393 list.back = node;
394 } else {
395 unsafe { (*list.back).next = node };
396 list.back = node;
397 }
398
399 list.count += 1;
400 0
401}
402
403pub unsafe fn list_push_front(l: *mut List, data: *mut c_void) -> c_int {
417 if l.is_null() {
418 return -1;
419 }
420
421 let list = unsafe { &mut *l };
422
423 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
424 if node.is_null() {
425 return -1;
426 }
427
428 unsafe {
429 (*node).data = data;
430 (*node).prev = ptr::null_mut();
431 (*node).next = list.front;
432 }
433
434 if list.front.is_null() {
435 list.front = node;
436 list.back = node;
437 } else {
438 unsafe { (*list.front).prev = node };
439 list.front = node;
440 }
441
442 list.count += 1;
443 0
444}
445
446pub unsafe fn list_pop_back(l: *mut List) {
458 if l.is_null() {
459 return;
460 }
461
462 let list = unsafe { &mut *l };
463 if list.back.is_null() {
464 return;
465 }
466
467 let node = list.back;
468 let prev = unsafe { (*node).prev };
469
470 if let Some(dealloc) = list.deallocator {
471 unsafe { dealloc((*node).data) };
472 }
473 unsafe { allocator::xmlFreeImpl(node as *mut c_void) };
474
475 list.back = prev;
476 if prev.is_null() {
477 list.front = ptr::null_mut();
478 } else {
479 unsafe { (*prev).next = ptr::null_mut() };
480 }
481
482 list.count = list.count.saturating_sub(1);
483}
484
485pub unsafe fn list_pop_front(l: *mut List) {
497 if l.is_null() {
498 return;
499 }
500
501 let list = unsafe { &mut *l };
502 if list.front.is_null() {
503 return;
504 }
505
506 let node = list.front;
507 let next = unsafe { (*node).next };
508
509 if let Some(dealloc) = list.deallocator {
510 unsafe { dealloc((*node).data) };
511 }
512 unsafe { allocator::xmlFreeImpl(node as *mut c_void) };
513
514 list.front = next;
515 if next.is_null() {
516 list.back = ptr::null_mut();
517 } else {
518 unsafe { (*next).prev = ptr::null_mut() };
519 }
520
521 list.count = list.count.saturating_sub(1);
522}
523
524pub unsafe fn list_insert(l: *mut List, data: *mut c_void) -> c_int {
539 if l.is_null() {
540 return -1;
541 }
542
543 let list = unsafe { &mut *l };
544
545 let comparator = match list.comparator {
547 Some(c) => c,
548 None => return list_push_back(l, data),
549 };
550
551 let mut cur = list.front;
553 while !cur.is_null() {
554 let node = unsafe { &*cur };
555 if unsafe { comparator(data as *const c_void, node.data as *const c_void) <= 0 } {
556 let new_node =
558 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
559 if new_node.is_null() {
560 return -1;
561 }
562 unsafe {
563 (*new_node).data = data;
564 (*new_node).prev = node.prev;
565 (*new_node).next = cur;
566 if !node.prev.is_null() {
567 (*node.prev).next = new_node;
568 } else {
569 list.front = new_node;
570 }
571 (*cur).prev = new_node;
572 }
573 list.count += 1;
574 return 0;
575 }
576 cur = node.next;
577 }
578
579 list_push_back(l, data)
581}
582
583pub unsafe fn list_append(l: *mut List, data: *mut c_void) -> c_int {
606 if l.is_null() {
610 return -1;
611 }
612 let comparator = unsafe { (*l).comparator };
613 match comparator {
614 None => unsafe { list_push_back(l, data) },
615 Some(cmp) => {
616 unsafe {
617 let mut cur = (*l).front;
618 while !cur.is_null() {
619 if cmp((*cur).data as *const c_void, data as *const c_void) > 0 {
620 break;
621 }
622 cur = (*cur).next;
623 }
624 let node =
626 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
627 if node.is_null() {
628 return -1;
629 }
630 (*node).data = data;
631 (*node).next = cur;
632 if cur.is_null() {
633 (*node).prev = (*l).back;
634 if !(*l).back.is_null() {
635 (*(*l).back).next = node;
636 }
637 (*l).back = node;
638 if (*l).front.is_null() {
639 (*l).front = node;
640 }
641 } else {
642 (*node).prev = (*cur).prev;
643 if !(*cur).prev.is_null() {
644 (*(*cur).prev).next = node;
645 } else {
646 (*l).front = node;
647 }
648 (*cur).prev = node;
649 }
650 }
651 0
652 }
653 }
654}
655
656pub unsafe fn list_remove_first(l: *mut List, data: *const c_void) -> c_int {
670 if l.is_null() {
671 return -1;
672 }
673
674 let list = unsafe { &mut *l };
675 let comparator = match list.comparator {
676 Some(c) => c,
677 None => return -1,
678 };
679
680 let mut cur = list.front;
681 while !cur.is_null() {
682 let node = unsafe { &*cur };
683 let next = node.next;
684 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
685 if !node.prev.is_null() {
687 unsafe { (*node.prev).next = node.next };
688 } else {
689 list.front = node.next;
690 }
691 if !node.next.is_null() {
692 unsafe { (*node.next).prev = node.prev };
693 } else {
694 list.back = node.prev;
695 }
696
697 if let Some(dealloc) = list.deallocator {
698 unsafe { dealloc(node.data) };
699 }
700 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
701 list.count = list.count.saturating_sub(1);
702 return 0;
703 }
704 cur = next;
705 }
706
707 -1
708}
709
710pub unsafe fn list_remove_last(l: *mut List, data: *const c_void) -> c_int {
724 if l.is_null() {
725 return -1;
726 }
727
728 let list = unsafe { &mut *l };
729 let comparator = match list.comparator {
730 Some(c) => c,
731 None => return -1,
732 };
733
734 let mut cur = list.back;
735 while !cur.is_null() {
736 let node = unsafe { &*cur };
737 let prev = node.prev;
738 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
739 if !node.prev.is_null() {
741 unsafe { (*node.prev).next = node.next };
742 } else {
743 list.front = node.next;
744 }
745 if !node.next.is_null() {
746 unsafe { (*node.next).prev = node.prev };
747 } else {
748 list.back = node.prev;
749 }
750
751 if let Some(dealloc) = list.deallocator {
752 unsafe { dealloc(node.data) };
753 }
754 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
755 list.count = list.count.saturating_sub(1);
756 return 0;
757 }
758 cur = prev;
759 }
760
761 -1
762}
763
764pub unsafe fn list_remove_all(l: *mut List, data: *const c_void) -> c_int {
778 if l.is_null() {
779 return 0;
780 }
781
782 let list = unsafe { &mut *l };
783 let comparator = match list.comparator {
784 Some(c) => c,
785 None => return 0,
786 };
787
788 let mut removed = 0;
789 let mut cur = list.front;
790
791 while !cur.is_null() {
792 let node = unsafe { &*cur };
793 let next = node.next;
794
795 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
796 if !node.prev.is_null() {
798 unsafe { (*node.prev).next = node.next };
799 } else {
800 list.front = node.next;
801 }
802 if !node.next.is_null() {
803 unsafe { (*node.next).prev = node.prev };
804 } else {
805 list.back = node.prev;
806 }
807
808 if let Some(dealloc) = list.deallocator {
809 unsafe { dealloc(node.data) };
810 }
811 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
812 list.count = list.count.saturating_sub(1);
813 removed += 1;
814 }
815
816 cur = next;
817 }
818
819 removed
820}
821
822pub unsafe fn list_clear(l: *mut List) {
834 if l.is_null() {
835 return;
836 }
837
838 let list = unsafe { &mut *l };
839 let mut cur = list.front;
840
841 while !cur.is_null() {
842 let next = unsafe { (*cur).next };
843 if let Some(dealloc) = list.deallocator {
844 unsafe { dealloc((*cur).data) };
845 }
846 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
847 cur = next;
848 }
849
850 list.front = ptr::null_mut();
851 list.back = ptr::null_mut();
852 list.count = 0;
853}
854
855pub fn list_empty(l: *mut List) -> c_int {
865 if l.is_null() {
866 return 1;
867 }
868 let list = unsafe { &*l };
869 if list.front.is_null() {
870 1
871 } else {
872 0
873 }
874}
875
876pub fn list_front(l: *mut List) -> *mut c_void {
886 if l.is_null() {
887 return ptr::null_mut();
888 }
889 let list = unsafe { &*l };
890 if list.front.is_null() {
891 ptr::null_mut()
892 } else {
893 unsafe { (*list.front).data }
894 }
895}
896
897pub fn list_back(l: *mut List) -> *mut c_void {
907 if l.is_null() {
908 return ptr::null_mut();
909 }
910 let list = unsafe { &*l };
911 if list.back.is_null() {
912 ptr::null_mut()
913 } else {
914 unsafe { (*list.back).data }
915 }
916}
917
918pub fn list_size(l: *mut List) -> c_int {
928 if l.is_null() {
929 return -1;
930 }
931 let list = unsafe { &*l };
932 list.count as c_int
933}
934
935pub unsafe fn list_sort(l: *mut List) {
947 if l.is_null() {
948 return;
949 }
950
951 let list = unsafe { &mut *l };
952 if list.count <= 1 {
953 return;
954 }
955
956 let comparator = match list.comparator {
957 Some(c) => c,
958 None => return,
959 };
960
961 let mut nodes: Vec<*mut ListNode> = Vec::with_capacity(list.count);
963 let mut cur = list.front;
964 while !cur.is_null() {
965 nodes.push(cur);
966 cur = unsafe { (*cur).next };
967 }
968
969 for i in 0..nodes.len() {
971 for j in 0..nodes.len() - 1 - i {
972 let a = unsafe { &*nodes[j] };
973 let b = unsafe { &*nodes[j + 1] };
974 if unsafe { comparator(a.data as *const c_void, b.data as *const c_void) > 0 } {
975 nodes.swap(j, j + 1);
976 }
977 }
978 }
979
980 list.front = nodes[0];
982 list.back = nodes[nodes.len() - 1];
983
984 for i in 0..nodes.len() {
985 unsafe {
986 (*nodes[i]).prev = if i > 0 { nodes[i - 1] } else { ptr::null_mut() };
987 (*nodes[i]).next = if i + 1 < nodes.len() {
988 nodes[i + 1]
989 } else {
990 ptr::null_mut()
991 };
992 }
993 }
994}
995
996pub unsafe fn list_reverse(l: *mut List) {
1008 if l.is_null() {
1009 return;
1010 }
1011
1012 let list = unsafe { &mut *l };
1013
1014 let mut cur = list.front;
1017 std::mem::swap(&mut list.front, &mut list.back);
1018
1019 while !cur.is_null() {
1020 let next = unsafe { (*cur).next };
1021 unsafe {
1022 (*cur).next = (*cur).prev;
1023 (*cur).prev = next;
1024 }
1025 cur = next;
1026 }
1027}
1028
1029pub unsafe fn list_reverse_splice(l1: *mut List, l2: *mut List) {
1041 if l1.is_null() || l2.is_null() {
1042 return;
1043 }
1044
1045 let list1 = unsafe { &mut *l1 };
1046 let list2 = unsafe { &mut *l2 };
1047
1048 if list2.front.is_null() {
1049 return;
1050 }
1051
1052 list_reverse(l2);
1054
1055 unsafe {
1057 (*list2.back).next = list1.front;
1058 if !list1.front.is_null() {
1059 (*list1.front).prev = list2.back;
1060 } else {
1061 list1.back = list2.back;
1062 }
1063 list1.front = list2.front;
1064 }
1065
1066 list1.count += list2.count;
1067
1068 list2.front = ptr::null_mut();
1070 list2.back = ptr::null_mut();
1071 list2.count = 0;
1072}
1073
1074pub unsafe fn list_merge(l1: *mut List, l2: *mut List) {
1088 if l1.is_null() || l2.is_null() {
1089 return;
1090 }
1091
1092 let list1 = unsafe { &mut *l1 };
1093 let list2 = unsafe { &mut *l2 };
1094
1095 if list2.front.is_null() {
1096 return;
1097 }
1098
1099 let comparator = match list1.comparator {
1100 Some(c) => c,
1101 None => {
1102 if !list1.back.is_null() {
1104 unsafe { (*list1.back).next = list2.front };
1105 unsafe { (*list2.front).prev = list1.back };
1106 } else {
1107 list1.front = list2.front;
1108 }
1109 list1.back = list2.back;
1110 list1.count += list2.count;
1111 list2.front = ptr::null_mut();
1112 list2.back = ptr::null_mut();
1113 list2.count = 0;
1114 return;
1115 }
1116 };
1117
1118 let mut cur2 = list2.front;
1120 let mut insert_before = list1.front;
1121
1122 while !cur2.is_null() {
1123 let next2 = unsafe { (*cur2).next };
1124
1125 while !insert_before.is_null() {
1127 if unsafe {
1128 comparator(
1129 (*cur2).data as *const c_void,
1130 (*insert_before).data as *const c_void,
1131 ) <= 0
1132 } {
1133 break;
1134 }
1135 insert_before = unsafe { (*insert_before).next };
1136 }
1137
1138 if insert_before.is_null() {
1140 if list1.back.is_null() {
1142 list1.front = cur2;
1143 list1.back = cur2;
1144 unsafe {
1145 (*cur2).prev = ptr::null_mut();
1146 (*cur2).next = ptr::null_mut();
1147 }
1148 } else {
1149 unsafe {
1150 (*cur2).prev = list1.back;
1151 (*cur2).next = ptr::null_mut();
1152 (*list1.back).next = cur2;
1153 }
1154 list1.back = cur2;
1155 }
1156 } else {
1157 unsafe {
1158 (*cur2).prev = (*insert_before).prev;
1159 (*cur2).next = insert_before;
1160 if !(*insert_before).prev.is_null() {
1161 (*(*insert_before).prev).next = cur2;
1162 } else {
1163 list1.front = cur2;
1164 }
1165 (*insert_before).prev = cur2;
1166 }
1167 }
1168
1169 list1.count += 1;
1170 cur2 = next2;
1171 }
1172
1173 list2.front = ptr::null_mut();
1175 list2.back = ptr::null_mut();
1176 list2.count = 0;
1177}
1178
1179#[cfg(test)]
1184mod tests {
1185 use super::*;
1186
1187 unsafe extern "C" fn int_compare(a: *const c_void, b: *const c_void) -> c_int {
1188 let ai = *(a as *const i32);
1189 let bi = *(b as *const i32);
1190 ai.cmp(&bi) as c_int
1191 }
1192
1193 #[test]
1194 fn test_list_create_delete() {
1195 unsafe {
1196 let list = list_create(None, None);
1197 assert!(!list.is_null());
1198 list_delete(list);
1199 }
1200 }
1201
1202 #[test]
1203 fn test_list_push_pop() {
1204 unsafe {
1205 let list = list_create(None, None);
1206 let v1 = &mut 1 as *mut c_int as *mut c_void;
1207 let v2 = &mut 2 as *mut c_int as *mut c_void;
1208
1209 list_push_back(list, v1);
1210 list_push_back(list, v2);
1211 assert_eq!(list_size(list), 2);
1212
1213 assert_eq!(*(list_front(list) as *const i32), 1);
1214 assert_eq!(*(list_back(list) as *const i32), 2);
1215
1216 list_pop_back(list);
1217 assert_eq!(list_size(list), 1);
1218 assert_eq!(*(list_back(list) as *const i32), 1);
1219
1220 list_pop_front(list);
1221 assert_eq!(list_size(list), 0);
1222 assert_eq!(list_empty(list), 1);
1223
1224 list_delete(list);
1225 }
1226 }
1227
1228 #[test]
1229 fn test_list_push_front() {
1230 unsafe {
1231 let list = list_create(None, None);
1232 let v1 = &mut 1 as *mut c_int as *mut c_void;
1233 let v2 = &mut 2 as *mut c_int as *mut c_void;
1234
1235 list_push_front(list, v1);
1236 list_push_front(list, v2);
1237 assert_eq!(*(list_front(list) as *const i32), 2);
1238 assert_eq!(*(list_back(list) as *const i32), 1);
1239
1240 list_delete(list);
1241 }
1242 }
1243
1244 #[test]
1245 fn test_list_insert_sorted() {
1246 unsafe {
1247 let list = list_create(None, Some(int_compare));
1248 let v2 = &mut 2 as *mut c_int as *mut c_void;
1249 let v1 = &mut 1 as *mut c_int as *mut c_void;
1250 let v3 = &mut 3 as *mut c_int as *mut c_void;
1251
1252 list_insert(list, v2);
1253 list_insert(list, v1);
1254 list_insert(list, v3);
1255
1256 assert_eq!(*(list_front(list) as *const i32), 1);
1258 assert_eq!(*(list_back(list) as *const i32), 3);
1259 assert_eq!(list_size(list), 3);
1260
1261 list_delete(list);
1262 }
1263 }
1264
1265 #[test]
1266 fn test_list_remove_first() {
1267 unsafe {
1268 let list = list_create(None, Some(int_compare));
1269 let v1 = &mut 1 as *mut c_int as *mut c_void;
1270 let v2 = &mut 2 as *mut c_int as *mut c_void;
1271
1272 list_push_back(list, v1);
1273 list_push_back(list, v2);
1274
1275 let one: i32 = 1;
1276 let result = list_remove_first(list, &one as *const i32 as *const c_void);
1277 assert_eq!(result, 0);
1278 assert_eq!(list_size(list), 1);
1279 assert_eq!(*(list_front(list) as *const i32), 2);
1280
1281 list_delete(list);
1282 }
1283 }
1284
1285 #[test]
1286 fn test_list_clear() {
1287 unsafe {
1288 let list = list_create(None, None);
1289 list_push_back(list, &mut 1 as *mut c_int as *mut c_void);
1290 list_push_back(list, &mut 2 as *mut c_int as *mut c_void);
1291 assert_eq!(list_size(list), 2);
1292
1293 list_clear(list);
1294 assert_eq!(list_empty(list), 1);
1295 assert_eq!(list_size(list), 0);
1296
1297 list_delete(list);
1298 }
1299 }
1300
1301 #[test]
1302 fn test_list_reverse() {
1303 unsafe {
1304 let list = list_create(None, None);
1305 let v1 = &mut 1 as *mut c_int as *mut c_void;
1306 let v2 = &mut 2 as *mut c_int as *mut c_void;
1307 let v3 = &mut 3 as *mut c_int as *mut c_void;
1308
1309 list_push_back(list, v1);
1310 list_push_back(list, v2);
1311 list_push_back(list, v3);
1312
1313 list_reverse(list);
1314
1315 assert_eq!(*(list_front(list) as *const i32), 3);
1316 assert_eq!(*(list_back(list) as *const i32), 1);
1317
1318 list_delete(list);
1319 }
1320 }
1321
1322 #[test]
1323 fn test_list_null_handling() {
1324 unsafe {
1325 assert_eq!(list_empty(ptr::null_mut()), 1);
1326 assert_eq!(list_size(ptr::null_mut()), -1);
1327 assert!(list_front(ptr::null_mut()).is_null());
1328 assert!(list_back(ptr::null_mut()).is_null());
1329 list_delete(ptr::null_mut()); list_clear(ptr::null_mut()); list_pop_front(ptr::null_mut()); list_pop_back(ptr::null_mut()); }
1334 }
1335}