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 {
109 unsafe { dealloc((*cur).data) };
110 }
111 unsafe { allocator::xmlFree(cur as *mut c_void) };
112 cur = next;
113 }
114
115 drop(Box::from_raw(l));
116}
117
118pub unsafe fn list_search(l: *mut List, data: *const c_void) -> *mut c_void {
132 if l.is_null() {
133 return ptr::null_mut();
134 }
135
136 let list = unsafe { &*l };
137 let comparator = match list.comparator {
138 Some(c) => c,
139 None => return ptr::null_mut(),
140 };
141
142 let mut cur = list.front;
143 while !cur.is_null() {
144 let node = unsafe { &*cur };
145 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
146 return node.data;
147 }
148 cur = node.next;
149 }
150
151 ptr::null_mut()
152}
153
154pub unsafe fn list_end(l: *mut List) -> *mut c_void {
161 if l.is_null() {
162 return ptr::null_mut();
163 }
164 let list = unsafe { &*l };
165 if list.back.is_null() {
166 return ptr::null_mut();
167 }
168 unsafe { (*list.back).data }
169}
170
171pub unsafe fn list_reverse_search(l: *mut List, data: *const c_void) -> *mut c_void {
180 if l.is_null() {
181 return ptr::null_mut();
182 }
183 let list = unsafe { &*l };
184 let comparator = match list.comparator {
185 Some(c) => c,
186 None => return ptr::null_mut(),
187 };
188 let mut cur = list.back;
189 while !cur.is_null() {
190 let node_data = unsafe { (*cur).data };
192 if unsafe { comparator(node_data as *const c_void, data) } == 0 {
193 return node_data;
194 }
195 cur = unsafe { (*cur).prev };
196 }
197 ptr::null_mut()
198}
199
200pub unsafe fn list_reverse_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
208 if l.is_null() {
209 return;
210 }
211 let walker = match walker {
212 Some(w) => w,
213 None => return,
214 };
215 let list = unsafe { &*l };
216 let mut cur = list.back;
217 while !cur.is_null() {
218 let node_data = unsafe { (*cur).data };
220 if unsafe { walker(node_data, data) } != 0 {
221 return;
222 }
223 cur = unsafe { (*cur).prev };
224 }
225}
226
227pub unsafe fn list_dup(l: *mut List) -> *mut List {
235 if l.is_null() {
236 return ptr::null_mut();
237 }
238 let list = unsafe { &*l };
239 let new_list = Box::new(List {
240 front: ptr::null_mut(),
241 back: ptr::null_mut(),
242 count: 0,
243 deallocator: list.deallocator,
244 comparator: list.comparator,
245 });
246 let new_ptr = Box::into_raw(new_list);
247 let mut cur = list.front;
248 while !cur.is_null() {
249 let data = unsafe { (*cur).data };
251 if unsafe { list_push_back(new_ptr, data) } != 0 {
252 unsafe { list_delete(new_ptr) };
253 return ptr::null_mut();
254 }
255 cur = unsafe { (*cur).next };
256 }
257 new_ptr
258}
259
260pub unsafe fn list_copy(
270 l: *mut List,
271 copier: Option<unsafe extern "C" fn(*mut c_void) -> *mut c_void>,
272) -> c_int {
273 if l.is_null() {
274 return -1;
275 }
276 let copier = match copier {
277 Some(c) => c,
278 None => return -1,
279 };
280 let list = unsafe { &*l };
281 let new_list = Box::new(List {
282 front: ptr::null_mut(),
283 back: ptr::null_mut(),
284 count: 0,
285 deallocator: list.deallocator,
286 comparator: list.comparator,
287 });
288 let new_ptr = Box::into_raw(new_list);
289 let mut cur = list.front;
290 while !cur.is_null() {
291 let copied = unsafe { copier((*cur).data) };
293 if copied.is_null() {
294 unsafe { list_delete(new_ptr) };
295 return -1;
296 }
297 if unsafe { list_push_back(new_ptr, copied) } != 0 {
298 unsafe { list_delete(new_ptr) };
299 return -1;
300 }
301 cur = unsafe { (*cur).next };
302 }
303 unsafe {
305 list_clear(l);
306 let dst = &mut *l;
307 let src = &mut *new_ptr;
308 core::mem::swap(dst, src);
309 list_delete(new_ptr);
310 }
311 0
312}
313
314pub unsafe fn link_get_data(link: *mut c_void) -> *mut c_void {
320 if link.is_null() {
321 return ptr::null_mut();
322 }
323 unsafe { (*(link as *mut ListNode)).data }
324}
325
326pub unsafe fn list_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
339 if l.is_null() || walker.is_none() {
340 return;
341 }
342 let walker = walker.unwrap();
343
344 let list = unsafe { &*l };
345 let mut cur = list.front;
346 while !cur.is_null() {
347 let node = unsafe { &*cur };
348 if unsafe { walker(node.data, data) != 0 } {
349 break;
350 }
351 cur = node.next;
352 }
353}
354
355pub unsafe fn list_push_back(l: *mut List, data: *mut c_void) -> c_int {
369 if l.is_null() {
370 return -1;
371 }
372
373 let list = unsafe { &mut *l };
374
375 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
376 if node.is_null() {
377 return -1;
378 }
379
380 unsafe {
381 (*node).data = data;
382 (*node).prev = list.back;
383 (*node).next = ptr::null_mut();
384 }
385
386 if list.back.is_null() {
387 list.front = node;
388 list.back = node;
389 } else {
390 unsafe { (*list.back).next = node };
391 list.back = node;
392 }
393
394 list.count += 1;
395 0
396}
397
398pub unsafe fn list_push_front(l: *mut List, data: *mut c_void) -> c_int {
412 if l.is_null() {
413 return -1;
414 }
415
416 let list = unsafe { &mut *l };
417
418 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
419 if node.is_null() {
420 return -1;
421 }
422
423 unsafe {
424 (*node).data = data;
425 (*node).prev = ptr::null_mut();
426 (*node).next = list.front;
427 }
428
429 if list.front.is_null() {
430 list.front = node;
431 list.back = node;
432 } else {
433 unsafe { (*list.front).prev = node };
434 list.front = node;
435 }
436
437 list.count += 1;
438 0
439}
440
441pub unsafe fn list_pop_back(l: *mut List) {
453 if l.is_null() {
454 return;
455 }
456
457 let list = unsafe { &mut *l };
458 if list.back.is_null() {
459 return;
460 }
461
462 let node = list.back;
463 let prev = unsafe { (*node).prev };
464
465 if let Some(dealloc) = list.deallocator {
466 unsafe { dealloc((*node).data) };
467 }
468 unsafe { allocator::xmlFree(node as *mut c_void) };
469
470 list.back = prev;
471 if prev.is_null() {
472 list.front = ptr::null_mut();
473 } else {
474 unsafe { (*prev).next = ptr::null_mut() };
475 }
476
477 list.count = list.count.saturating_sub(1);
478}
479
480pub unsafe fn list_pop_front(l: *mut List) {
492 if l.is_null() {
493 return;
494 }
495
496 let list = unsafe { &mut *l };
497 if list.front.is_null() {
498 return;
499 }
500
501 let node = list.front;
502 let next = unsafe { (*node).next };
503
504 if let Some(dealloc) = list.deallocator {
505 unsafe { dealloc((*node).data) };
506 }
507 unsafe { allocator::xmlFree(node as *mut c_void) };
508
509 list.front = next;
510 if next.is_null() {
511 list.back = ptr::null_mut();
512 } else {
513 unsafe { (*next).prev = ptr::null_mut() };
514 }
515
516 list.count = list.count.saturating_sub(1);
517}
518
519pub unsafe fn list_insert(l: *mut List, data: *mut c_void) -> c_int {
534 if l.is_null() {
535 return -1;
536 }
537
538 let list = unsafe { &mut *l };
539
540 let comparator = match list.comparator {
542 Some(c) => c,
543 None => return list_push_back(l, data),
544 };
545
546 let mut cur = list.front;
548 while !cur.is_null() {
549 let node = unsafe { &*cur };
550 if unsafe { comparator(data as *const c_void, node.data as *const c_void) <= 0 } {
551 let new_node =
553 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
554 if new_node.is_null() {
555 return -1;
556 }
557 unsafe {
558 (*new_node).data = data;
559 (*new_node).prev = node.prev;
560 (*new_node).next = cur;
561 if !node.prev.is_null() {
562 (*node.prev).next = new_node;
563 } else {
564 list.front = new_node;
565 }
566 (*cur).prev = new_node;
567 }
568 list.count += 1;
569 return 0;
570 }
571 cur = node.next;
572 }
573
574 list_push_back(l, data)
576}
577
578pub unsafe fn list_append(l: *mut List, data: *mut c_void) -> c_int {
586 list_push_back(l, data)
587}
588
589pub unsafe fn list_remove_first(l: *mut List, data: *const c_void) -> c_int {
603 if l.is_null() {
604 return -1;
605 }
606
607 let list = unsafe { &mut *l };
608 let comparator = match list.comparator {
609 Some(c) => c,
610 None => return -1,
611 };
612
613 let mut cur = list.front;
614 while !cur.is_null() {
615 let node = unsafe { &*cur };
616 let next = node.next;
617 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
618 if !node.prev.is_null() {
620 unsafe { (*node.prev).next = node.next };
621 } else {
622 list.front = node.next;
623 }
624 if !node.next.is_null() {
625 unsafe { (*node.next).prev = node.prev };
626 } else {
627 list.back = node.prev;
628 }
629
630 if let Some(dealloc) = list.deallocator {
631 unsafe { dealloc(node.data) };
632 }
633 unsafe { allocator::xmlFree(cur as *mut c_void) };
634 list.count = list.count.saturating_sub(1);
635 return 0;
636 }
637 cur = next;
638 }
639
640 -1
641}
642
643pub unsafe fn list_remove_last(l: *mut List, data: *const c_void) -> c_int {
657 if l.is_null() {
658 return -1;
659 }
660
661 let list = unsafe { &mut *l };
662 let comparator = match list.comparator {
663 Some(c) => c,
664 None => return -1,
665 };
666
667 let mut cur = list.back;
668 while !cur.is_null() {
669 let node = unsafe { &*cur };
670 let prev = node.prev;
671 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
672 if !node.prev.is_null() {
674 unsafe { (*node.prev).next = node.next };
675 } else {
676 list.front = node.next;
677 }
678 if !node.next.is_null() {
679 unsafe { (*node.next).prev = node.prev };
680 } else {
681 list.back = node.prev;
682 }
683
684 if let Some(dealloc) = list.deallocator {
685 unsafe { dealloc(node.data) };
686 }
687 unsafe { allocator::xmlFree(cur as *mut c_void) };
688 list.count = list.count.saturating_sub(1);
689 return 0;
690 }
691 cur = prev;
692 }
693
694 -1
695}
696
697pub unsafe fn list_remove_all(l: *mut List, data: *const c_void) -> c_int {
711 if l.is_null() {
712 return 0;
713 }
714
715 let list = unsafe { &mut *l };
716 let comparator = match list.comparator {
717 Some(c) => c,
718 None => return 0,
719 };
720
721 let mut removed = 0;
722 let mut cur = list.front;
723
724 while !cur.is_null() {
725 let node = unsafe { &*cur };
726 let next = node.next;
727
728 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
729 if !node.prev.is_null() {
731 unsafe { (*node.prev).next = node.next };
732 } else {
733 list.front = node.next;
734 }
735 if !node.next.is_null() {
736 unsafe { (*node.next).prev = node.prev };
737 } else {
738 list.back = node.prev;
739 }
740
741 if let Some(dealloc) = list.deallocator {
742 unsafe { dealloc(node.data) };
743 }
744 unsafe { allocator::xmlFree(cur as *mut c_void) };
745 list.count = list.count.saturating_sub(1);
746 removed += 1;
747 }
748
749 cur = next;
750 }
751
752 removed
753}
754
755pub unsafe fn list_clear(l: *mut List) {
767 if l.is_null() {
768 return;
769 }
770
771 let list = unsafe { &mut *l };
772 let mut cur = list.front;
773
774 while !cur.is_null() {
775 let next = unsafe { (*cur).next };
776 if let Some(dealloc) = list.deallocator {
777 unsafe { dealloc((*cur).data) };
778 }
779 unsafe { allocator::xmlFree(cur as *mut c_void) };
780 cur = next;
781 }
782
783 list.front = ptr::null_mut();
784 list.back = ptr::null_mut();
785 list.count = 0;
786}
787
788pub fn list_empty(l: *mut List) -> c_int {
798 if l.is_null() {
799 return 1;
800 }
801 let list = unsafe { &*l };
802 if list.front.is_null() {
803 1
804 } else {
805 0
806 }
807}
808
809pub fn list_front(l: *mut List) -> *mut c_void {
819 if l.is_null() {
820 return ptr::null_mut();
821 }
822 let list = unsafe { &*l };
823 if list.front.is_null() {
824 ptr::null_mut()
825 } else {
826 unsafe { (*list.front).data }
827 }
828}
829
830pub fn list_back(l: *mut List) -> *mut c_void {
840 if l.is_null() {
841 return ptr::null_mut();
842 }
843 let list = unsafe { &*l };
844 if list.back.is_null() {
845 ptr::null_mut()
846 } else {
847 unsafe { (*list.back).data }
848 }
849}
850
851pub fn list_size(l: *mut List) -> c_int {
861 if l.is_null() {
862 return -1;
863 }
864 let list = unsafe { &*l };
865 list.count as c_int
866}
867
868pub unsafe fn list_sort(l: *mut List) {
880 if l.is_null() {
881 return;
882 }
883
884 let list = unsafe { &mut *l };
885 if list.count <= 1 {
886 return;
887 }
888
889 let comparator = match list.comparator {
890 Some(c) => c,
891 None => return,
892 };
893
894 let mut nodes: Vec<*mut ListNode> = Vec::with_capacity(list.count);
896 let mut cur = list.front;
897 while !cur.is_null() {
898 nodes.push(cur);
899 cur = unsafe { (*cur).next };
900 }
901
902 for i in 0..nodes.len() {
904 for j in 0..nodes.len() - 1 - i {
905 let a = unsafe { &*nodes[j] };
906 let b = unsafe { &*nodes[j + 1] };
907 if unsafe { comparator(a.data as *const c_void, b.data as *const c_void) > 0 } {
908 nodes.swap(j, j + 1);
909 }
910 }
911 }
912
913 list.front = nodes[0];
915 list.back = nodes[nodes.len() - 1];
916
917 for i in 0..nodes.len() {
918 unsafe {
919 (*nodes[i]).prev = if i > 0 { nodes[i - 1] } else { ptr::null_mut() };
920 (*nodes[i]).next = if i + 1 < nodes.len() {
921 nodes[i + 1]
922 } else {
923 ptr::null_mut()
924 };
925 }
926 }
927}
928
929pub unsafe fn list_reverse(l: *mut List) {
941 if l.is_null() {
942 return;
943 }
944
945 let list = unsafe { &mut *l };
946
947 let mut cur = list.front;
948 list.front = list.back;
949 list.back = cur;
950
951 while !cur.is_null() {
952 let next = unsafe { (*cur).next };
953 unsafe {
954 (*cur).next = (*cur).prev;
955 (*cur).prev = next;
956 }
957 cur = next;
958 }
959}
960
961pub unsafe fn list_reverse_splice(l1: *mut List, l2: *mut List) {
973 if l1.is_null() || l2.is_null() {
974 return;
975 }
976
977 let list1 = unsafe { &mut *l1 };
978 let list2 = unsafe { &mut *l2 };
979
980 if list2.front.is_null() {
981 return;
982 }
983
984 list_reverse(l2);
986
987 unsafe {
989 (*list2.back).next = list1.front;
990 if !list1.front.is_null() {
991 (*list1.front).prev = list2.back;
992 } else {
993 list1.back = list2.back;
994 }
995 list1.front = list2.front;
996 }
997
998 list1.count += list2.count;
999
1000 list2.front = ptr::null_mut();
1002 list2.back = ptr::null_mut();
1003 list2.count = 0;
1004}
1005
1006pub unsafe fn list_merge(l1: *mut List, l2: *mut List) {
1020 if l1.is_null() || l2.is_null() {
1021 return;
1022 }
1023
1024 let list1 = unsafe { &mut *l1 };
1025 let list2 = unsafe { &mut *l2 };
1026
1027 if list2.front.is_null() {
1028 return;
1029 }
1030
1031 let comparator = match list1.comparator {
1032 Some(c) => c,
1033 None => {
1034 if !list1.back.is_null() {
1036 unsafe { (*list1.back).next = list2.front };
1037 unsafe { (*list2.front).prev = list1.back };
1038 } else {
1039 list1.front = list2.front;
1040 }
1041 list1.back = list2.back;
1042 list1.count += list2.count;
1043 list2.front = ptr::null_mut();
1044 list2.back = ptr::null_mut();
1045 list2.count = 0;
1046 return;
1047 }
1048 };
1049
1050 let mut cur2 = list2.front;
1052 let mut insert_before = list1.front;
1053
1054 while !cur2.is_null() {
1055 let next2 = unsafe { (*cur2).next };
1056
1057 while !insert_before.is_null() {
1059 if unsafe {
1060 comparator(
1061 (*cur2).data as *const c_void,
1062 (*insert_before).data as *const c_void,
1063 ) <= 0
1064 } {
1065 break;
1066 }
1067 insert_before = unsafe { (*insert_before).next };
1068 }
1069
1070 if insert_before.is_null() {
1072 if list1.back.is_null() {
1074 list1.front = cur2;
1075 list1.back = cur2;
1076 unsafe {
1077 (*cur2).prev = ptr::null_mut();
1078 (*cur2).next = ptr::null_mut();
1079 }
1080 } else {
1081 unsafe {
1082 (*cur2).prev = list1.back;
1083 (*cur2).next = ptr::null_mut();
1084 (*list1.back).next = cur2;
1085 }
1086 list1.back = cur2;
1087 }
1088 } else {
1089 unsafe {
1090 (*cur2).prev = (*insert_before).prev;
1091 (*cur2).next = insert_before;
1092 if !(*insert_before).prev.is_null() {
1093 (*(*insert_before).prev).next = cur2;
1094 } else {
1095 list1.front = cur2;
1096 }
1097 (*insert_before).prev = cur2;
1098 }
1099 }
1100
1101 list1.count += 1;
1102 cur2 = next2;
1103 }
1104
1105 list2.front = ptr::null_mut();
1107 list2.back = ptr::null_mut();
1108 list2.count = 0;
1109}
1110
1111#[cfg(test)]
1116mod tests {
1117 use super::*;
1118
1119 unsafe extern "C" fn int_compare(a: *const c_void, b: *const c_void) -> c_int {
1120 let ai = *(a as *const i32);
1121 let bi = *(b as *const i32);
1122 ai.cmp(&bi) as c_int
1123 }
1124
1125 #[test]
1126 fn test_list_create_delete() {
1127 unsafe {
1128 let list = list_create(None, None);
1129 assert!(!list.is_null());
1130 list_delete(list);
1131 }
1132 }
1133
1134 #[test]
1135 fn test_list_push_pop() {
1136 unsafe {
1137 let list = list_create(None, None);
1138 let v1 = &mut 1 as *mut c_int as *mut c_void;
1139 let v2 = &mut 2 as *mut c_int as *mut c_void;
1140
1141 list_push_back(list, v1);
1142 list_push_back(list, v2);
1143 assert_eq!(list_size(list), 2);
1144
1145 assert_eq!(*(list_front(list) as *const i32), 1);
1146 assert_eq!(*(list_back(list) as *const i32), 2);
1147
1148 list_pop_back(list);
1149 assert_eq!(list_size(list), 1);
1150 assert_eq!(*(list_back(list) as *const i32), 1);
1151
1152 list_pop_front(list);
1153 assert_eq!(list_size(list), 0);
1154 assert_eq!(list_empty(list), 1);
1155
1156 list_delete(list);
1157 }
1158 }
1159
1160 #[test]
1161 fn test_list_push_front() {
1162 unsafe {
1163 let list = list_create(None, None);
1164 let v1 = &mut 1 as *mut c_int as *mut c_void;
1165 let v2 = &mut 2 as *mut c_int as *mut c_void;
1166
1167 list_push_front(list, v1);
1168 list_push_front(list, v2);
1169 assert_eq!(*(list_front(list) as *const i32), 2);
1170 assert_eq!(*(list_back(list) as *const i32), 1);
1171
1172 list_delete(list);
1173 }
1174 }
1175
1176 #[test]
1177 fn test_list_insert_sorted() {
1178 unsafe {
1179 let list = list_create(None, Some(int_compare));
1180 let v2 = &mut 2 as *mut c_int as *mut c_void;
1181 let v1 = &mut 1 as *mut c_int as *mut c_void;
1182 let v3 = &mut 3 as *mut c_int as *mut c_void;
1183
1184 list_insert(list, v2);
1185 list_insert(list, v1);
1186 list_insert(list, v3);
1187
1188 assert_eq!(*(list_front(list) as *const i32), 1);
1190 assert_eq!(*(list_back(list) as *const i32), 3);
1191 assert_eq!(list_size(list), 3);
1192
1193 list_delete(list);
1194 }
1195 }
1196
1197 #[test]
1198 fn test_list_remove_first() {
1199 unsafe {
1200 let list = list_create(None, Some(int_compare));
1201 let v1 = &mut 1 as *mut c_int as *mut c_void;
1202 let v2 = &mut 2 as *mut c_int as *mut c_void;
1203
1204 list_push_back(list, v1);
1205 list_push_back(list, v2);
1206
1207 let one: i32 = 1;
1208 let result = list_remove_first(list, &one as *const i32 as *const c_void);
1209 assert_eq!(result, 0);
1210 assert_eq!(list_size(list), 1);
1211 assert_eq!(*(list_front(list) as *const i32), 2);
1212
1213 list_delete(list);
1214 }
1215 }
1216
1217 #[test]
1218 fn test_list_clear() {
1219 unsafe {
1220 let list = list_create(None, None);
1221 list_push_back(list, &mut 1 as *mut c_int as *mut c_void);
1222 list_push_back(list, &mut 2 as *mut c_int as *mut c_void);
1223 assert_eq!(list_size(list), 2);
1224
1225 list_clear(list);
1226 assert_eq!(list_empty(list), 1);
1227 assert_eq!(list_size(list), 0);
1228
1229 list_delete(list);
1230 }
1231 }
1232
1233 #[test]
1234 fn test_list_reverse() {
1235 unsafe {
1236 let list = list_create(None, None);
1237 let v1 = &mut 1 as *mut c_int as *mut c_void;
1238 let v2 = &mut 2 as *mut c_int as *mut c_void;
1239 let v3 = &mut 3 as *mut c_int as *mut c_void;
1240
1241 list_push_back(list, v1);
1242 list_push_back(list, v2);
1243 list_push_back(list, v3);
1244
1245 list_reverse(list);
1246
1247 assert_eq!(*(list_front(list) as *const i32), 3);
1248 assert_eq!(*(list_back(list) as *const i32), 1);
1249
1250 list_delete(list);
1251 }
1252 }
1253
1254 #[test]
1255 fn test_list_null_handling() {
1256 unsafe {
1257 assert_eq!(list_empty(ptr::null_mut()), 1);
1258 assert_eq!(list_size(ptr::null_mut()), -1);
1259 assert!(list_front(ptr::null_mut()).is_null());
1260 assert!(list_back(ptr::null_mut()).is_null());
1261 list_delete(ptr::null_mut()); list_clear(ptr::null_mut()); list_pop_front(ptr::null_mut()); list_pop_back(ptr::null_mut()); }
1266 }
1267}