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(
321 l: *mut List,
322 copier: Option<unsafe extern "C" fn(*mut c_void) -> *mut c_void>,
323) -> c_int {
324 if l.is_null() {
325 return -1;
326 }
327 let copier = match copier {
328 Some(c) => c,
329 None => return -1,
330 };
331 let list = unsafe { &*l };
332 let new_list = Box::new(List {
333 front: ptr::null_mut(),
334 back: ptr::null_mut(),
335 count: 0,
336 deallocator: list.deallocator,
337 comparator: list.comparator,
338 });
339 let new_ptr = Box::into_raw(new_list);
340 let mut cur = list.front;
341 while !cur.is_null() {
342 let copied = unsafe { copier((*cur).data) };
344 if copied.is_null() {
345 unsafe { list_delete(new_ptr) };
346 return -1;
347 }
348 if unsafe { list_push_back(new_ptr, copied) } != 0 {
349 unsafe { list_delete(new_ptr) };
350 return -1;
351 }
352 cur = unsafe { (*cur).next };
353 }
354 unsafe {
356 list_clear(l);
357 let dst = &mut *l;
358 let src = &mut *new_ptr;
359 core::mem::swap(dst, src);
360 list_delete(new_ptr);
361 }
362 0
363}
364
365pub unsafe fn link_get_data(link: *mut c_void) -> *mut c_void {
371 if link.is_null() {
372 return ptr::null_mut();
373 }
374 unsafe { (*(link as *mut ListNode)).data }
375}
376
377pub unsafe fn list_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
390 if l.is_null() || walker.is_none() {
391 return;
392 }
393 let walker = walker.unwrap();
394
395 let list = unsafe { &*l };
396 let mut cur = list.front;
397 while !cur.is_null() {
398 let node = unsafe { &*cur };
399 if unsafe { walker(node.data, data) == 0 } {
401 break;
402 }
403 cur = node.next;
404 }
405}
406
407pub unsafe fn list_push_back(l: *mut List, data: *mut c_void) -> c_int {
421 if l.is_null() {
422 return -1;
423 }
424
425 let list = unsafe { &mut *l };
426
427 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
428 if node.is_null() {
429 return -1;
430 }
431
432 unsafe {
433 (*node).data = data;
434 (*node).prev = list.back;
435 (*node).next = ptr::null_mut();
436 }
437
438 if list.back.is_null() {
439 list.front = node;
440 list.back = node;
441 } else {
442 unsafe { (*list.back).next = node };
443 list.back = node;
444 }
445
446 list.count += 1;
447 0
448}
449
450pub unsafe fn list_push_front(l: *mut List, data: *mut c_void) -> c_int {
464 if l.is_null() {
465 return -1;
466 }
467
468 let list = unsafe { &mut *l };
469
470 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
471 if node.is_null() {
472 return -1;
473 }
474
475 unsafe {
476 (*node).data = data;
477 (*node).prev = ptr::null_mut();
478 (*node).next = list.front;
479 }
480
481 if list.front.is_null() {
482 list.front = node;
483 list.back = node;
484 } else {
485 unsafe { (*list.front).prev = node };
486 list.front = node;
487 }
488
489 list.count += 1;
490 0
491}
492
493pub unsafe fn list_pop_back(l: *mut List) {
505 if l.is_null() {
506 return;
507 }
508
509 let list = unsafe { &mut *l };
510 if list.back.is_null() {
511 return;
512 }
513
514 let node = list.back;
515 let prev = unsafe { (*node).prev };
516
517 if let Some(dealloc) = list.deallocator {
518 unsafe { dealloc((*node).data) };
519 }
520 unsafe { allocator::xmlFreeImpl(node as *mut c_void) };
521
522 list.back = prev;
523 if prev.is_null() {
524 list.front = ptr::null_mut();
525 } else {
526 unsafe { (*prev).next = ptr::null_mut() };
527 }
528
529 list.count = list.count.saturating_sub(1);
530}
531
532pub unsafe fn list_pop_front(l: *mut List) {
544 if l.is_null() {
545 return;
546 }
547
548 let list = unsafe { &mut *l };
549 if list.front.is_null() {
550 return;
551 }
552
553 let node = list.front;
554 let next = unsafe { (*node).next };
555
556 if let Some(dealloc) = list.deallocator {
557 unsafe { dealloc((*node).data) };
558 }
559 unsafe { allocator::xmlFreeImpl(node as *mut c_void) };
560
561 list.front = next;
562 if next.is_null() {
563 list.back = ptr::null_mut();
564 } else {
565 unsafe { (*next).prev = ptr::null_mut() };
566 }
567
568 list.count = list.count.saturating_sub(1);
569}
570
571pub unsafe fn list_insert(l: *mut List, data: *mut c_void) -> c_int {
586 if l.is_null() {
587 return -1;
588 }
589
590 let list = unsafe { &mut *l };
591
592 let comparator = match list.comparator {
594 Some(c) => c,
595 None => return list_push_back(l, data),
596 };
597
598 let mut cur = list.front;
600 while !cur.is_null() {
601 let node = unsafe { &*cur };
602 if unsafe { comparator(data as *const c_void, node.data as *const c_void) <= 0 } {
603 let new_node =
605 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
606 if new_node.is_null() {
607 return -1;
608 }
609 unsafe {
610 (*new_node).data = data;
611 (*new_node).prev = node.prev;
612 (*new_node).next = cur;
613 if !node.prev.is_null() {
614 (*node.prev).next = new_node;
615 } else {
616 list.front = new_node;
617 }
618 (*cur).prev = new_node;
619 }
620 list.count += 1;
621 return 0;
622 }
623 cur = node.next;
624 }
625
626 list_push_back(l, data)
628}
629
630pub unsafe fn list_append(l: *mut List, data: *mut c_void) -> c_int {
653 if l.is_null() {
657 return -1;
658 }
659 let comparator = unsafe { (*l).comparator };
660 match comparator {
661 None => unsafe { list_push_back(l, data) },
662 Some(cmp) => {
663 unsafe {
664 let mut cur = (*l).front;
665 while !cur.is_null() {
666 if cmp((*cur).data as *const c_void, data as *const c_void) > 0 {
667 break;
668 }
669 cur = (*cur).next;
670 }
671 let node =
673 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
674 if node.is_null() {
675 return -1;
676 }
677 (*node).data = data;
678 (*node).next = cur;
679 if cur.is_null() {
680 (*node).prev = (*l).back;
681 if !(*l).back.is_null() {
682 (*(*l).back).next = node;
683 }
684 (*l).back = node;
685 if (*l).front.is_null() {
686 (*l).front = node;
687 }
688 } else {
689 (*node).prev = (*cur).prev;
690 if !(*cur).prev.is_null() {
691 (*(*cur).prev).next = node;
692 } else {
693 (*l).front = node;
694 }
695 (*cur).prev = node;
696 }
697 }
698 0
699 }
700 }
701}
702
703pub unsafe fn list_remove_first(l: *mut List, data: *const c_void) -> c_int {
717 if l.is_null() {
718 return -1;
719 }
720
721 let list = unsafe { &mut *l };
722 let comparator = match list.comparator {
723 Some(c) => c,
724 None => return -1,
725 };
726
727 let mut cur = list.front;
728 while !cur.is_null() {
729 let node = unsafe { &*cur };
730 let next = node.next;
731 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
732 if !node.prev.is_null() {
734 unsafe { (*node.prev).next = node.next };
735 } else {
736 list.front = node.next;
737 }
738 if !node.next.is_null() {
739 unsafe { (*node.next).prev = node.prev };
740 } else {
741 list.back = node.prev;
742 }
743
744 if let Some(dealloc) = list.deallocator {
745 unsafe { dealloc(node.data) };
746 }
747 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
748 list.count = list.count.saturating_sub(1);
749 return 0;
750 }
751 cur = next;
752 }
753
754 -1
755}
756
757pub unsafe fn list_remove_last(l: *mut List, data: *const c_void) -> c_int {
771 if l.is_null() {
772 return -1;
773 }
774
775 let list = unsafe { &mut *l };
776 let comparator = match list.comparator {
777 Some(c) => c,
778 None => return -1,
779 };
780
781 let mut cur = list.back;
782 while !cur.is_null() {
783 let node = unsafe { &*cur };
784 let prev = node.prev;
785 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
786 if !node.prev.is_null() {
788 unsafe { (*node.prev).next = node.next };
789 } else {
790 list.front = node.next;
791 }
792 if !node.next.is_null() {
793 unsafe { (*node.next).prev = node.prev };
794 } else {
795 list.back = node.prev;
796 }
797
798 if let Some(dealloc) = list.deallocator {
799 unsafe { dealloc(node.data) };
800 }
801 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
802 list.count = list.count.saturating_sub(1);
803 return 0;
804 }
805 cur = prev;
806 }
807
808 -1
809}
810
811pub unsafe fn list_remove_all(l: *mut List, data: *const c_void) -> c_int {
825 if l.is_null() {
826 return 0;
827 }
828
829 let list = unsafe { &mut *l };
830 let comparator = match list.comparator {
831 Some(c) => c,
832 None => return 0,
833 };
834
835 let mut removed = 0;
836 let mut cur = list.front;
837
838 while !cur.is_null() {
839 let node = unsafe { &*cur };
840 let next = node.next;
841
842 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
843 if !node.prev.is_null() {
845 unsafe { (*node.prev).next = node.next };
846 } else {
847 list.front = node.next;
848 }
849 if !node.next.is_null() {
850 unsafe { (*node.next).prev = node.prev };
851 } else {
852 list.back = node.prev;
853 }
854
855 if let Some(dealloc) = list.deallocator {
856 unsafe { dealloc(node.data) };
857 }
858 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
859 list.count = list.count.saturating_sub(1);
860 removed += 1;
861 }
862
863 cur = next;
864 }
865
866 removed
867}
868
869pub unsafe fn list_clear(l: *mut List) {
881 if l.is_null() {
882 return;
883 }
884
885 let list = unsafe { &mut *l };
886 let mut cur = list.front;
887
888 while !cur.is_null() {
889 let next = unsafe { (*cur).next };
890 if let Some(dealloc) = list.deallocator {
891 unsafe { dealloc((*cur).data) };
892 }
893 unsafe { allocator::xmlFreeImpl(cur as *mut c_void) };
894 cur = next;
895 }
896
897 list.front = ptr::null_mut();
898 list.back = ptr::null_mut();
899 list.count = 0;
900}
901
902pub fn list_empty(l: *mut List) -> c_int {
912 if l.is_null() {
913 return 1;
914 }
915 let list = unsafe { &*l };
916 if list.front.is_null() {
917 1
918 } else {
919 0
920 }
921}
922
923pub fn list_front(l: *mut List) -> *mut c_void {
933 if l.is_null() {
934 return ptr::null_mut();
935 }
936 let list = unsafe { &*l };
937 if list.front.is_null() {
938 ptr::null_mut()
939 } else {
940 unsafe { (*list.front).data }
941 }
942}
943
944pub fn list_back(l: *mut List) -> *mut c_void {
954 if l.is_null() {
955 return ptr::null_mut();
956 }
957 let list = unsafe { &*l };
958 if list.back.is_null() {
959 ptr::null_mut()
960 } else {
961 unsafe { (*list.back).data }
962 }
963}
964
965pub fn list_size(l: *mut List) -> c_int {
975 if l.is_null() {
976 return -1;
977 }
978 let list = unsafe { &*l };
979 list.count as c_int
980}
981
982pub unsafe fn list_sort(l: *mut List) {
994 if l.is_null() {
995 return;
996 }
997
998 let list = unsafe { &mut *l };
999 if list.count <= 1 {
1000 return;
1001 }
1002
1003 let comparator = match list.comparator {
1004 Some(c) => c,
1005 None => return,
1006 };
1007
1008 let mut nodes: Vec<*mut ListNode> = Vec::with_capacity(list.count);
1010 let mut cur = list.front;
1011 while !cur.is_null() {
1012 nodes.push(cur);
1013 cur = unsafe { (*cur).next };
1014 }
1015
1016 for i in 0..nodes.len() {
1018 for j in 0..nodes.len() - 1 - i {
1019 let a = unsafe { &*nodes[j] };
1020 let b = unsafe { &*nodes[j + 1] };
1021 if unsafe { comparator(a.data as *const c_void, b.data as *const c_void) > 0 } {
1022 nodes.swap(j, j + 1);
1023 }
1024 }
1025 }
1026
1027 list.front = nodes[0];
1029 list.back = nodes[nodes.len() - 1];
1030
1031 for i in 0..nodes.len() {
1032 unsafe {
1033 (*nodes[i]).prev = if i > 0 { nodes[i - 1] } else { ptr::null_mut() };
1034 (*nodes[i]).next = if i + 1 < nodes.len() {
1035 nodes[i + 1]
1036 } else {
1037 ptr::null_mut()
1038 };
1039 }
1040 }
1041}
1042
1043pub unsafe fn list_reverse(l: *mut List) {
1055 if l.is_null() {
1056 return;
1057 }
1058
1059 let list = unsafe { &mut *l };
1060
1061 let mut cur = list.front;
1064 std::mem::swap(&mut list.front, &mut list.back);
1065
1066 while !cur.is_null() {
1067 let next = unsafe { (*cur).next };
1068 unsafe {
1069 (*cur).next = (*cur).prev;
1070 (*cur).prev = next;
1071 }
1072 cur = next;
1073 }
1074}
1075
1076pub unsafe fn list_reverse_splice(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 list_reverse(l2);
1101
1102 unsafe {
1104 (*list2.back).next = list1.front;
1105 if !list1.front.is_null() {
1106 (*list1.front).prev = list2.back;
1107 } else {
1108 list1.back = list2.back;
1109 }
1110 list1.front = list2.front;
1111 }
1112
1113 list1.count += list2.count;
1114
1115 list2.front = ptr::null_mut();
1117 list2.back = ptr::null_mut();
1118 list2.count = 0;
1119}
1120
1121pub unsafe fn list_merge(l1: *mut List, l2: *mut List) {
1135 if l1.is_null() || l2.is_null() {
1136 return;
1137 }
1138
1139 let list1 = unsafe { &mut *l1 };
1140 let list2 = unsafe { &mut *l2 };
1141
1142 if list2.front.is_null() {
1143 return;
1144 }
1145
1146 let comparator = match list1.comparator {
1147 Some(c) => c,
1148 None => {
1149 if !list1.back.is_null() {
1151 unsafe { (*list1.back).next = list2.front };
1152 unsafe { (*list2.front).prev = list1.back };
1153 } else {
1154 list1.front = list2.front;
1155 }
1156 list1.back = list2.back;
1157 list1.count += list2.count;
1158 list2.front = ptr::null_mut();
1159 list2.back = ptr::null_mut();
1160 list2.count = 0;
1161 return;
1162 }
1163 };
1164
1165 let mut cur2 = list2.front;
1167 let mut insert_before = list1.front;
1168
1169 while !cur2.is_null() {
1170 let next2 = unsafe { (*cur2).next };
1171
1172 while !insert_before.is_null() {
1174 if unsafe {
1175 comparator(
1176 (*cur2).data as *const c_void,
1177 (*insert_before).data as *const c_void,
1178 ) <= 0
1179 } {
1180 break;
1181 }
1182 insert_before = unsafe { (*insert_before).next };
1183 }
1184
1185 if insert_before.is_null() {
1187 if list1.back.is_null() {
1189 list1.front = cur2;
1190 list1.back = cur2;
1191 unsafe {
1192 (*cur2).prev = ptr::null_mut();
1193 (*cur2).next = ptr::null_mut();
1194 }
1195 } else {
1196 unsafe {
1197 (*cur2).prev = list1.back;
1198 (*cur2).next = ptr::null_mut();
1199 (*list1.back).next = cur2;
1200 }
1201 list1.back = cur2;
1202 }
1203 } else {
1204 unsafe {
1205 (*cur2).prev = (*insert_before).prev;
1206 (*cur2).next = insert_before;
1207 if !(*insert_before).prev.is_null() {
1208 (*(*insert_before).prev).next = cur2;
1209 } else {
1210 list1.front = cur2;
1211 }
1212 (*insert_before).prev = cur2;
1213 }
1214 }
1215
1216 list1.count += 1;
1217 cur2 = next2;
1218 }
1219
1220 list2.front = ptr::null_mut();
1222 list2.back = ptr::null_mut();
1223 list2.count = 0;
1224}
1225
1226#[cfg(test)]
1231mod tests {
1232 use super::*;
1233
1234 unsafe extern "C" fn int_compare(a: *const c_void, b: *const c_void) -> c_int {
1235 let ai = *(a as *const i32);
1236 let bi = *(b as *const i32);
1237 ai.cmp(&bi) as c_int
1238 }
1239
1240 #[test]
1241 fn test_list_create_delete() {
1242 unsafe {
1243 let list = list_create(None, None);
1244 assert!(!list.is_null());
1245 list_delete(list);
1246 }
1247 }
1248
1249 #[test]
1250 fn test_list_push_pop() {
1251 unsafe {
1252 let list = list_create(None, None);
1253 let v1 = &mut 1 as *mut c_int as *mut c_void;
1254 let v2 = &mut 2 as *mut c_int as *mut c_void;
1255
1256 list_push_back(list, v1);
1257 list_push_back(list, v2);
1258 assert_eq!(list_size(list), 2);
1259
1260 assert_eq!(*(list_front(list) as *const i32), 1);
1261 assert_eq!(*(list_back(list) as *const i32), 2);
1262
1263 list_pop_back(list);
1264 assert_eq!(list_size(list), 1);
1265 assert_eq!(*(list_back(list) as *const i32), 1);
1266
1267 list_pop_front(list);
1268 assert_eq!(list_size(list), 0);
1269 assert_eq!(list_empty(list), 1);
1270
1271 list_delete(list);
1272 }
1273 }
1274
1275 #[test]
1276 fn test_list_push_front() {
1277 unsafe {
1278 let list = list_create(None, None);
1279 let v1 = &mut 1 as *mut c_int as *mut c_void;
1280 let v2 = &mut 2 as *mut c_int as *mut c_void;
1281
1282 list_push_front(list, v1);
1283 list_push_front(list, v2);
1284 assert_eq!(*(list_front(list) as *const i32), 2);
1285 assert_eq!(*(list_back(list) as *const i32), 1);
1286
1287 list_delete(list);
1288 }
1289 }
1290
1291 #[test]
1292 fn test_list_insert_sorted() {
1293 unsafe {
1294 let list = list_create(None, Some(int_compare));
1295 let v2 = &mut 2 as *mut c_int as *mut c_void;
1296 let v1 = &mut 1 as *mut c_int as *mut c_void;
1297 let v3 = &mut 3 as *mut c_int as *mut c_void;
1298
1299 list_insert(list, v2);
1300 list_insert(list, v1);
1301 list_insert(list, v3);
1302
1303 assert_eq!(*(list_front(list) as *const i32), 1);
1305 assert_eq!(*(list_back(list) as *const i32), 3);
1306 assert_eq!(list_size(list), 3);
1307
1308 list_delete(list);
1309 }
1310 }
1311
1312 #[test]
1313 fn test_list_remove_first() {
1314 unsafe {
1315 let list = list_create(None, Some(int_compare));
1316 let v1 = &mut 1 as *mut c_int as *mut c_void;
1317 let v2 = &mut 2 as *mut c_int as *mut c_void;
1318
1319 list_push_back(list, v1);
1320 list_push_back(list, v2);
1321
1322 let one: i32 = 1;
1323 let result = list_remove_first(list, &one as *const i32 as *const c_void);
1324 assert_eq!(result, 0);
1325 assert_eq!(list_size(list), 1);
1326 assert_eq!(*(list_front(list) as *const i32), 2);
1327
1328 list_delete(list);
1329 }
1330 }
1331
1332 #[test]
1333 fn test_list_clear() {
1334 unsafe {
1335 let list = list_create(None, None);
1336 list_push_back(list, &mut 1 as *mut c_int as *mut c_void);
1337 list_push_back(list, &mut 2 as *mut c_int as *mut c_void);
1338 assert_eq!(list_size(list), 2);
1339
1340 list_clear(list);
1341 assert_eq!(list_empty(list), 1);
1342 assert_eq!(list_size(list), 0);
1343
1344 list_delete(list);
1345 }
1346 }
1347
1348 #[test]
1349 fn test_list_reverse() {
1350 unsafe {
1351 let list = list_create(None, None);
1352 let v1 = &mut 1 as *mut c_int as *mut c_void;
1353 let v2 = &mut 2 as *mut c_int as *mut c_void;
1354 let v3 = &mut 3 as *mut c_int as *mut c_void;
1355
1356 list_push_back(list, v1);
1357 list_push_back(list, v2);
1358 list_push_back(list, v3);
1359
1360 list_reverse(list);
1361
1362 assert_eq!(*(list_front(list) as *const i32), 3);
1363 assert_eq!(*(list_back(list) as *const i32), 1);
1364
1365 list_delete(list);
1366 }
1367 }
1368
1369 #[test]
1370 fn test_list_null_handling() {
1371 unsafe {
1372 assert_eq!(list_empty(ptr::null_mut()), 1);
1373 assert_eq!(list_size(ptr::null_mut()), -1);
1374 assert!(list_front(ptr::null_mut()).is_null());
1375 assert!(list_back(ptr::null_mut()).is_null());
1376 list_delete(ptr::null_mut()); list_clear(ptr::null_mut()); list_pop_front(ptr::null_mut()); list_pop_back(ptr::null_mut()); }
1381 }
1382}