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
48pub struct List {
50 front: *mut ListNode,
51 back: *mut ListNode,
52 count: usize,
53 deallocator: Option<xmlListDeallocator>,
54 comparator: Option<xmlListDataCompare>,
55}
56
57pub fn list_create(
73 deallocator: Option<xmlListDeallocator>,
74 comparator: Option<xmlListDataCompare>,
75) -> *mut List {
76 let list = Box::new(List {
77 front: ptr::null_mut(),
78 back: ptr::null_mut(),
79 count: 0,
80 deallocator,
81 comparator,
82 });
83
84 Box::into_raw(list)
85}
86
87pub unsafe fn list_delete(l: *mut List) {
99 if l.is_null() {
100 return;
101 }
102
103 let list = unsafe { &mut *l };
104 let mut cur = list.front;
105
106 while !cur.is_null() {
107 let next = unsafe { (*cur).next };
108 if let Some(dealloc) = list.deallocator {
111 unsafe { dealloc(cur as *mut c_void) };
112 }
113 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
114 cur = next;
115 }
116
117 drop(Box::from_raw(l));
118}
119
120pub unsafe fn list_search(l: *mut List, data: *const c_void) -> *mut c_void {
134 if l.is_null() {
135 return ptr::null_mut();
136 }
137
138 let list = unsafe { &*l };
139 let comparator = match list.comparator {
140 Some(c) => c,
141 None => return ptr::null_mut(),
142 };
143
144 let mut cur = list.front;
145 while !cur.is_null() {
146 let node = unsafe { &*cur };
147 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
148 return node.data;
149 }
150 cur = node.next;
151 }
152
153 ptr::null_mut()
154}
155
156pub unsafe fn list_end(l: *mut List) -> *mut c_void {
163 if l.is_null() {
164 return ptr::null_mut();
165 }
166 let list = unsafe { &*l };
167 if list.back.is_null() {
168 return ptr::null_mut();
169 }
170 unsafe { (*list.back).data }
171}
172
173pub unsafe fn list_reverse_search(l: *mut List, data: *const c_void) -> *mut c_void {
182 if l.is_null() {
183 return ptr::null_mut();
184 }
185 let list = unsafe { &*l };
186 let comparator = match list.comparator {
187 Some(c) => c,
188 None => return ptr::null_mut(),
189 };
190 let mut cur = list.back;
191 while !cur.is_null() {
192 let node_data = unsafe { (*cur).data };
194 if unsafe { comparator(node_data as *const c_void, data) } == 0 {
195 return node_data;
196 }
197 cur = unsafe { (*cur).prev };
198 }
199 ptr::null_mut()
200}
201
202pub unsafe fn list_reverse_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
210 if l.is_null() {
211 return;
212 }
213 let walker = match walker {
214 Some(w) => w,
215 None => return,
216 };
217 let list = unsafe { &*l };
218 let mut cur = list.back;
219 while !cur.is_null() {
220 let node_data = unsafe { (*cur).data };
222 if unsafe { walker(node_data, data) == 0 } {
224 return;
225 }
226 cur = unsafe { (*cur).prev };
227 }
228}
229
230pub unsafe fn list_dup(l: *mut List) -> *mut List {
238 if l.is_null() {
239 return ptr::null_mut();
240 }
241 let list = unsafe { &*l };
242 let new_list = Box::new(List {
243 front: ptr::null_mut(),
244 back: ptr::null_mut(),
245 count: 0,
246 deallocator: list.deallocator,
247 comparator: list.comparator,
248 });
249 let new_ptr = Box::into_raw(new_list);
250 let mut cur = list.front;
251 while !cur.is_null() {
252 let data = unsafe { (*cur).data };
254 if unsafe { list_push_back(new_ptr, data) } != 0 {
255 unsafe { list_delete(new_ptr) };
256 return ptr::null_mut();
257 }
258 cur = unsafe { (*cur).next };
259 }
260 new_ptr
261}
262
263pub unsafe fn list_copy(
273 l: *mut List,
274 copier: Option<unsafe extern "C" fn(*mut c_void) -> *mut c_void>,
275) -> c_int {
276 if l.is_null() {
277 return -1;
278 }
279 let copier = match copier {
280 Some(c) => c,
281 None => return -1,
282 };
283 let list = unsafe { &*l };
284 let new_list = Box::new(List {
285 front: ptr::null_mut(),
286 back: ptr::null_mut(),
287 count: 0,
288 deallocator: list.deallocator,
289 comparator: list.comparator,
290 });
291 let new_ptr = Box::into_raw(new_list);
292 let mut cur = list.front;
293 while !cur.is_null() {
294 let copied = unsafe { copier((*cur).data) };
296 if copied.is_null() {
297 unsafe { list_delete(new_ptr) };
298 return -1;
299 }
300 if unsafe { list_push_back(new_ptr, copied) } != 0 {
301 unsafe { list_delete(new_ptr) };
302 return -1;
303 }
304 cur = unsafe { (*cur).next };
305 }
306 unsafe {
308 list_clear(l);
309 let dst = &mut *l;
310 let src = &mut *new_ptr;
311 core::mem::swap(dst, src);
312 list_delete(new_ptr);
313 }
314 0
315}
316
317pub unsafe fn link_get_data(link: *mut c_void) -> *mut c_void {
323 if link.is_null() {
324 return ptr::null_mut();
325 }
326 unsafe { (*(link as *mut ListNode)).data }
327}
328
329pub unsafe fn list_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
342 if l.is_null() || walker.is_none() {
343 return;
344 }
345 let walker = walker.unwrap();
346
347 let list = unsafe { &*l };
348 let mut cur = list.front;
349 while !cur.is_null() {
350 let node = unsafe { &*cur };
351 if unsafe { walker(node.data, data) == 0 } {
353 break;
354 }
355 cur = node.next;
356 }
357}
358
359pub unsafe fn list_push_back(l: *mut List, data: *mut c_void) -> c_int {
373 if l.is_null() {
374 return -1;
375 }
376
377 let list = unsafe { &mut *l };
378
379 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
380 if node.is_null() {
381 return -1;
382 }
383
384 unsafe {
385 (*node).data = data;
386 (*node).prev = list.back;
387 (*node).next = ptr::null_mut();
388 }
389
390 if list.back.is_null() {
391 list.front = node;
392 list.back = node;
393 } else {
394 unsafe { (*list.back).next = node };
395 list.back = node;
396 }
397
398 list.count += 1;
399 0
400}
401
402pub unsafe fn list_push_front(l: *mut List, data: *mut c_void) -> c_int {
416 if l.is_null() {
417 return -1;
418 }
419
420 let list = unsafe { &mut *l };
421
422 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
423 if node.is_null() {
424 return -1;
425 }
426
427 unsafe {
428 (*node).data = data;
429 (*node).prev = ptr::null_mut();
430 (*node).next = list.front;
431 }
432
433 if list.front.is_null() {
434 list.front = node;
435 list.back = node;
436 } else {
437 unsafe { (*list.front).prev = node };
438 list.front = node;
439 }
440
441 list.count += 1;
442 0
443}
444
445pub unsafe fn list_pop_back(l: *mut List) {
457 if l.is_null() {
458 return;
459 }
460
461 let list = unsafe { &mut *l };
462 if list.back.is_null() {
463 return;
464 }
465
466 let node = list.back;
467 let prev = unsafe { (*node).prev };
468
469 if let Some(dealloc) = list.deallocator {
470 unsafe { dealloc((*node).data) };
471 }
472 unsafe { allocator::xmlFreeImpl(node as *mut c_void) };
473
474 list.back = prev;
475 if prev.is_null() {
476 list.front = ptr::null_mut();
477 } else {
478 unsafe { (*prev).next = ptr::null_mut() };
479 }
480
481 list.count = list.count.saturating_sub(1);
482}
483
484pub unsafe fn list_pop_front(l: *mut List) {
496 if l.is_null() {
497 return;
498 }
499
500 let list = unsafe { &mut *l };
501 if list.front.is_null() {
502 return;
503 }
504
505 let node = list.front;
506 let next = unsafe { (*node).next };
507
508 if let Some(dealloc) = list.deallocator {
509 unsafe { dealloc((*node).data) };
510 }
511 unsafe { allocator::xmlFreeImpl(node as *mut c_void) };
512
513 list.front = next;
514 if next.is_null() {
515 list.back = ptr::null_mut();
516 } else {
517 unsafe { (*next).prev = ptr::null_mut() };
518 }
519
520 list.count = list.count.saturating_sub(1);
521}
522
523pub unsafe fn list_insert(l: *mut List, data: *mut c_void) -> c_int {
538 if l.is_null() {
539 return -1;
540 }
541
542 let list = unsafe { &mut *l };
543
544 let comparator = match list.comparator {
546 Some(c) => c,
547 None => return list_push_back(l, data),
548 };
549
550 let mut cur = list.front;
552 while !cur.is_null() {
553 let node = unsafe { &*cur };
554 if unsafe { comparator(data as *const c_void, node.data as *const c_void) <= 0 } {
555 let new_node =
557 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
558 if new_node.is_null() {
559 return -1;
560 }
561 unsafe {
562 (*new_node).data = data;
563 (*new_node).prev = node.prev;
564 (*new_node).next = cur;
565 if !node.prev.is_null() {
566 (*node.prev).next = new_node;
567 } else {
568 list.front = new_node;
569 }
570 (*cur).prev = new_node;
571 }
572 list.count += 1;
573 return 0;
574 }
575 cur = node.next;
576 }
577
578 list_push_back(l, data)
580}
581
582pub unsafe fn list_append(l: *mut List, data: *mut c_void) -> c_int {
590 if l.is_null() {
594 return -1;
595 }
596 let comparator = unsafe { (*l).comparator };
597 match comparator {
598 None => unsafe { list_push_back(l, data) },
599 Some(cmp) => {
600 unsafe {
601 let mut cur = (*l).front;
602 while !cur.is_null() {
603 if cmp((*cur).data as *const c_void, data as *const c_void) > 0 {
604 break;
605 }
606 cur = (*cur).next;
607 }
608 let node =
610 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
611 if node.is_null() {
612 return -1;
613 }
614 (*node).data = data;
615 (*node).next = cur;
616 if cur.is_null() {
617 (*node).prev = (*l).back;
618 if !(*l).back.is_null() {
619 (*(*l).back).next = node;
620 }
621 (*l).back = node;
622 if (*l).front.is_null() {
623 (*l).front = node;
624 }
625 } else {
626 (*node).prev = (*cur).prev;
627 if !(*cur).prev.is_null() {
628 (*(*cur).prev).next = node;
629 } else {
630 (*l).front = node;
631 }
632 (*cur).prev = node;
633 }
634 }
635 0
636 }
637 }
638}
639
640pub unsafe fn list_remove_first(l: *mut List, data: *const c_void) -> c_int {
654 if l.is_null() {
655 return -1;
656 }
657
658 let list = unsafe { &mut *l };
659 let comparator = match list.comparator {
660 Some(c) => c,
661 None => return -1,
662 };
663
664 let mut cur = list.front;
665 while !cur.is_null() {
666 let node = unsafe { &*cur };
667 let next = node.next;
668 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
669 if !node.prev.is_null() {
671 unsafe { (*node.prev).next = node.next };
672 } else {
673 list.front = node.next;
674 }
675 if !node.next.is_null() {
676 unsafe { (*node.next).prev = node.prev };
677 } else {
678 list.back = node.prev;
679 }
680
681 if let Some(dealloc) = list.deallocator {
682 unsafe { dealloc(node.data) };
683 }
684 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
685 list.count = list.count.saturating_sub(1);
686 return 0;
687 }
688 cur = next;
689 }
690
691 -1
692}
693
694pub unsafe fn list_remove_last(l: *mut List, data: *const c_void) -> c_int {
708 if l.is_null() {
709 return -1;
710 }
711
712 let list = unsafe { &mut *l };
713 let comparator = match list.comparator {
714 Some(c) => c,
715 None => return -1,
716 };
717
718 let mut cur = list.back;
719 while !cur.is_null() {
720 let node = unsafe { &*cur };
721 let prev = node.prev;
722 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
723 if !node.prev.is_null() {
725 unsafe { (*node.prev).next = node.next };
726 } else {
727 list.front = node.next;
728 }
729 if !node.next.is_null() {
730 unsafe { (*node.next).prev = node.prev };
731 } else {
732 list.back = node.prev;
733 }
734
735 if let Some(dealloc) = list.deallocator {
736 unsafe { dealloc(node.data) };
737 }
738 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
739 list.count = list.count.saturating_sub(1);
740 return 0;
741 }
742 cur = prev;
743 }
744
745 -1
746}
747
748pub unsafe fn list_remove_all(l: *mut List, data: *const c_void) -> c_int {
762 if l.is_null() {
763 return 0;
764 }
765
766 let list = unsafe { &mut *l };
767 let comparator = match list.comparator {
768 Some(c) => c,
769 None => return 0,
770 };
771
772 let mut removed = 0;
773 let mut cur = list.front;
774
775 while !cur.is_null() {
776 let node = unsafe { &*cur };
777 let next = node.next;
778
779 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
780 if !node.prev.is_null() {
782 unsafe { (*node.prev).next = node.next };
783 } else {
784 list.front = node.next;
785 }
786 if !node.next.is_null() {
787 unsafe { (*node.next).prev = node.prev };
788 } else {
789 list.back = node.prev;
790 }
791
792 if let Some(dealloc) = list.deallocator {
793 unsafe { dealloc(node.data) };
794 }
795 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
796 list.count = list.count.saturating_sub(1);
797 removed += 1;
798 }
799
800 cur = next;
801 }
802
803 removed
804}
805
806pub unsafe fn list_clear(l: *mut List) {
818 if l.is_null() {
819 return;
820 }
821
822 let list = unsafe { &mut *l };
823 let mut cur = list.front;
824
825 while !cur.is_null() {
826 let next = unsafe { (*cur).next };
827 if let Some(dealloc) = list.deallocator {
828 unsafe { dealloc((*cur).data) };
829 }
830 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
831 cur = next;
832 }
833
834 list.front = ptr::null_mut();
835 list.back = ptr::null_mut();
836 list.count = 0;
837}
838
839pub fn list_empty(l: *mut List) -> c_int {
849 if l.is_null() {
850 return 1;
851 }
852 let list = unsafe { &*l };
853 if list.front.is_null() {
854 1
855 } else {
856 0
857 }
858}
859
860pub fn list_front(l: *mut List) -> *mut c_void {
870 if l.is_null() {
871 return ptr::null_mut();
872 }
873 let list = unsafe { &*l };
874 if list.front.is_null() {
875 ptr::null_mut()
876 } else {
877 unsafe { (*list.front).data }
878 }
879}
880
881pub fn list_back(l: *mut List) -> *mut c_void {
891 if l.is_null() {
892 return ptr::null_mut();
893 }
894 let list = unsafe { &*l };
895 if list.back.is_null() {
896 ptr::null_mut()
897 } else {
898 unsafe { (*list.back).data }
899 }
900}
901
902pub fn list_size(l: *mut List) -> c_int {
912 if l.is_null() {
913 return -1;
914 }
915 let list = unsafe { &*l };
916 list.count as c_int
917}
918
919pub unsafe fn list_sort(l: *mut List) {
931 if l.is_null() {
932 return;
933 }
934
935 let list = unsafe { &mut *l };
936 if list.count <= 1 {
937 return;
938 }
939
940 let comparator = match list.comparator {
941 Some(c) => c,
942 None => return,
943 };
944
945 let mut nodes: Vec<*mut ListNode> = Vec::with_capacity(list.count);
947 let mut cur = list.front;
948 while !cur.is_null() {
949 nodes.push(cur);
950 cur = unsafe { (*cur).next };
951 }
952
953 for i in 0..nodes.len() {
955 for j in 0..nodes.len() - 1 - i {
956 let a = unsafe { &*nodes[j] };
957 let b = unsafe { &*nodes[j + 1] };
958 if unsafe { comparator(a.data as *const c_void, b.data as *const c_void) > 0 } {
959 nodes.swap(j, j + 1);
960 }
961 }
962 }
963
964 list.front = nodes[0];
966 list.back = nodes[nodes.len() - 1];
967
968 for i in 0..nodes.len() {
969 unsafe {
970 (*nodes[i]).prev = if i > 0 { nodes[i - 1] } else { ptr::null_mut() };
971 (*nodes[i]).next = if i + 1 < nodes.len() {
972 nodes[i + 1]
973 } else {
974 ptr::null_mut()
975 };
976 }
977 }
978}
979
980pub unsafe fn list_reverse(l: *mut List) {
992 if l.is_null() {
993 return;
994 }
995
996 let list = unsafe { &mut *l };
997
998 let mut cur = list.front;
999 list.front = list.back;
1000 list.back = cur;
1001
1002 while !cur.is_null() {
1003 let next = unsafe { (*cur).next };
1004 unsafe {
1005 (*cur).next = (*cur).prev;
1006 (*cur).prev = next;
1007 }
1008 cur = next;
1009 }
1010}
1011
1012pub unsafe fn list_reverse_splice(l1: *mut List, l2: *mut List) {
1024 if l1.is_null() || l2.is_null() {
1025 return;
1026 }
1027
1028 let list1 = unsafe { &mut *l1 };
1029 let list2 = unsafe { &mut *l2 };
1030
1031 if list2.front.is_null() {
1032 return;
1033 }
1034
1035 list_reverse(l2);
1037
1038 unsafe {
1040 (*list2.back).next = list1.front;
1041 if !list1.front.is_null() {
1042 (*list1.front).prev = list2.back;
1043 } else {
1044 list1.back = list2.back;
1045 }
1046 list1.front = list2.front;
1047 }
1048
1049 list1.count += list2.count;
1050
1051 list2.front = ptr::null_mut();
1053 list2.back = ptr::null_mut();
1054 list2.count = 0;
1055}
1056
1057pub unsafe fn list_merge(l1: *mut List, l2: *mut List) {
1071 if l1.is_null() || l2.is_null() {
1072 return;
1073 }
1074
1075 let list1 = unsafe { &mut *l1 };
1076 let list2 = unsafe { &mut *l2 };
1077
1078 if list2.front.is_null() {
1079 return;
1080 }
1081
1082 let comparator = match list1.comparator {
1083 Some(c) => c,
1084 None => {
1085 if !list1.back.is_null() {
1087 unsafe { (*list1.back).next = list2.front };
1088 unsafe { (*list2.front).prev = list1.back };
1089 } else {
1090 list1.front = list2.front;
1091 }
1092 list1.back = list2.back;
1093 list1.count += list2.count;
1094 list2.front = ptr::null_mut();
1095 list2.back = ptr::null_mut();
1096 list2.count = 0;
1097 return;
1098 }
1099 };
1100
1101 let mut cur2 = list2.front;
1103 let mut insert_before = list1.front;
1104
1105 while !cur2.is_null() {
1106 let next2 = unsafe { (*cur2).next };
1107
1108 while !insert_before.is_null() {
1110 if unsafe {
1111 comparator(
1112 (*cur2).data as *const c_void,
1113 (*insert_before).data as *const c_void,
1114 ) <= 0
1115 } {
1116 break;
1117 }
1118 insert_before = unsafe { (*insert_before).next };
1119 }
1120
1121 if insert_before.is_null() {
1123 if list1.back.is_null() {
1125 list1.front = cur2;
1126 list1.back = cur2;
1127 unsafe {
1128 (*cur2).prev = ptr::null_mut();
1129 (*cur2).next = ptr::null_mut();
1130 }
1131 } else {
1132 unsafe {
1133 (*cur2).prev = list1.back;
1134 (*cur2).next = ptr::null_mut();
1135 (*list1.back).next = cur2;
1136 }
1137 list1.back = cur2;
1138 }
1139 } else {
1140 unsafe {
1141 (*cur2).prev = (*insert_before).prev;
1142 (*cur2).next = insert_before;
1143 if !(*insert_before).prev.is_null() {
1144 (*(*insert_before).prev).next = cur2;
1145 } else {
1146 list1.front = cur2;
1147 }
1148 (*insert_before).prev = cur2;
1149 }
1150 }
1151
1152 list1.count += 1;
1153 cur2 = next2;
1154 }
1155
1156 list2.front = ptr::null_mut();
1158 list2.back = ptr::null_mut();
1159 list2.count = 0;
1160}
1161
1162#[cfg(test)]
1167mod tests {
1168 use super::*;
1169
1170 unsafe extern "C" fn int_compare(a: *const c_void, b: *const c_void) -> c_int {
1171 let ai = *(a as *const i32);
1172 let bi = *(b as *const i32);
1173 ai.cmp(&bi) as c_int
1174 }
1175
1176 #[test]
1177 fn test_list_create_delete() {
1178 unsafe {
1179 let list = list_create(None, None);
1180 assert!(!list.is_null());
1181 list_delete(list);
1182 }
1183 }
1184
1185 #[test]
1186 fn test_list_push_pop() {
1187 unsafe {
1188 let list = list_create(None, None);
1189 let v1 = &mut 1 as *mut c_int as *mut c_void;
1190 let v2 = &mut 2 as *mut c_int as *mut c_void;
1191
1192 list_push_back(list, v1);
1193 list_push_back(list, v2);
1194 assert_eq!(list_size(list), 2);
1195
1196 assert_eq!(*(list_front(list) as *const i32), 1);
1197 assert_eq!(*(list_back(list) as *const i32), 2);
1198
1199 list_pop_back(list);
1200 assert_eq!(list_size(list), 1);
1201 assert_eq!(*(list_back(list) as *const i32), 1);
1202
1203 list_pop_front(list);
1204 assert_eq!(list_size(list), 0);
1205 assert_eq!(list_empty(list), 1);
1206
1207 list_delete(list);
1208 }
1209 }
1210
1211 #[test]
1212 fn test_list_push_front() {
1213 unsafe {
1214 let list = list_create(None, None);
1215 let v1 = &mut 1 as *mut c_int as *mut c_void;
1216 let v2 = &mut 2 as *mut c_int as *mut c_void;
1217
1218 list_push_front(list, v1);
1219 list_push_front(list, v2);
1220 assert_eq!(*(list_front(list) as *const i32), 2);
1221 assert_eq!(*(list_back(list) as *const i32), 1);
1222
1223 list_delete(list);
1224 }
1225 }
1226
1227 #[test]
1228 fn test_list_insert_sorted() {
1229 unsafe {
1230 let list = list_create(None, Some(int_compare));
1231 let v2 = &mut 2 as *mut c_int as *mut c_void;
1232 let v1 = &mut 1 as *mut c_int as *mut c_void;
1233 let v3 = &mut 3 as *mut c_int as *mut c_void;
1234
1235 list_insert(list, v2);
1236 list_insert(list, v1);
1237 list_insert(list, v3);
1238
1239 assert_eq!(*(list_front(list) as *const i32), 1);
1241 assert_eq!(*(list_back(list) as *const i32), 3);
1242 assert_eq!(list_size(list), 3);
1243
1244 list_delete(list);
1245 }
1246 }
1247
1248 #[test]
1249 fn test_list_remove_first() {
1250 unsafe {
1251 let list = list_create(None, Some(int_compare));
1252 let v1 = &mut 1 as *mut c_int as *mut c_void;
1253 let v2 = &mut 2 as *mut c_int as *mut c_void;
1254
1255 list_push_back(list, v1);
1256 list_push_back(list, v2);
1257
1258 let one: i32 = 1;
1259 let result = list_remove_first(list, &one as *const i32 as *const c_void);
1260 assert_eq!(result, 0);
1261 assert_eq!(list_size(list), 1);
1262 assert_eq!(*(list_front(list) as *const i32), 2);
1263
1264 list_delete(list);
1265 }
1266 }
1267
1268 #[test]
1269 fn test_list_clear() {
1270 unsafe {
1271 let list = list_create(None, None);
1272 list_push_back(list, &mut 1 as *mut c_int as *mut c_void);
1273 list_push_back(list, &mut 2 as *mut c_int as *mut c_void);
1274 assert_eq!(list_size(list), 2);
1275
1276 list_clear(list);
1277 assert_eq!(list_empty(list), 1);
1278 assert_eq!(list_size(list), 0);
1279
1280 list_delete(list);
1281 }
1282 }
1283
1284 #[test]
1285 fn test_list_reverse() {
1286 unsafe {
1287 let list = list_create(None, None);
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 let v3 = &mut 3 as *mut c_int as *mut c_void;
1291
1292 list_push_back(list, v1);
1293 list_push_back(list, v2);
1294 list_push_back(list, v3);
1295
1296 list_reverse(list);
1297
1298 assert_eq!(*(list_front(list) as *const i32), 3);
1299 assert_eq!(*(list_back(list) as *const i32), 1);
1300
1301 list_delete(list);
1302 }
1303 }
1304
1305 #[test]
1306 fn test_list_null_handling() {
1307 unsafe {
1308 assert_eq!(list_empty(ptr::null_mut()), 1);
1309 assert_eq!(list_size(ptr::null_mut()), -1);
1310 assert!(list_front(ptr::null_mut()).is_null());
1311 assert!(list_back(ptr::null_mut()).is_null());
1312 list_delete(ptr::null_mut()); list_clear(ptr::null_mut()); list_pop_front(ptr::null_mut()); list_pop_back(ptr::null_mut()); }
1317 }
1318}