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_walk(l: *mut List, walker: Option<xmlListWalker>, data: *mut c_void) {
167 if l.is_null() || walker.is_none() {
168 return;
169 }
170 let walker = walker.unwrap();
171
172 let list = unsafe { &*l };
173 let mut cur = list.front;
174 while !cur.is_null() {
175 let node = unsafe { &*cur };
176 if unsafe { walker(node.data, data) != 0 } {
177 break;
178 }
179 cur = node.next;
180 }
181}
182
183pub unsafe fn list_push_back(l: *mut List, data: *mut c_void) -> c_int {
197 if l.is_null() {
198 return -1;
199 }
200
201 let list = unsafe { &mut *l };
202
203 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
204 if node.is_null() {
205 return -1;
206 }
207
208 unsafe {
209 (*node).data = data;
210 (*node).prev = list.back;
211 (*node).next = ptr::null_mut();
212 }
213
214 if list.back.is_null() {
215 list.front = node;
216 list.back = node;
217 } else {
218 unsafe { (*list.back).next = node };
219 list.back = node;
220 }
221
222 list.count += 1;
223 0
224}
225
226pub unsafe fn list_push_front(l: *mut List, data: *mut c_void) -> c_int {
240 if l.is_null() {
241 return -1;
242 }
243
244 let list = unsafe { &mut *l };
245
246 let node = allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
247 if node.is_null() {
248 return -1;
249 }
250
251 unsafe {
252 (*node).data = data;
253 (*node).prev = ptr::null_mut();
254 (*node).next = list.front;
255 }
256
257 if list.front.is_null() {
258 list.front = node;
259 list.back = node;
260 } else {
261 unsafe { (*list.front).prev = node };
262 list.front = node;
263 }
264
265 list.count += 1;
266 0
267}
268
269pub unsafe fn list_pop_back(l: *mut List) {
281 if l.is_null() {
282 return;
283 }
284
285 let list = unsafe { &mut *l };
286 if list.back.is_null() {
287 return;
288 }
289
290 let node = list.back;
291 let prev = unsafe { (*node).prev };
292
293 if let Some(dealloc) = list.deallocator {
294 unsafe { dealloc((*node).data) };
295 }
296 unsafe { allocator::xmlFree(node as *mut c_void) };
297
298 list.back = prev;
299 if prev.is_null() {
300 list.front = ptr::null_mut();
301 } else {
302 unsafe { (*prev).next = ptr::null_mut() };
303 }
304
305 list.count = list.count.saturating_sub(1);
306}
307
308pub unsafe fn list_pop_front(l: *mut List) {
320 if l.is_null() {
321 return;
322 }
323
324 let list = unsafe { &mut *l };
325 if list.front.is_null() {
326 return;
327 }
328
329 let node = list.front;
330 let next = unsafe { (*node).next };
331
332 if let Some(dealloc) = list.deallocator {
333 unsafe { dealloc((*node).data) };
334 }
335 unsafe { allocator::xmlFree(node as *mut c_void) };
336
337 list.front = next;
338 if next.is_null() {
339 list.back = ptr::null_mut();
340 } else {
341 unsafe { (*next).prev = ptr::null_mut() };
342 }
343
344 list.count = list.count.saturating_sub(1);
345}
346
347pub unsafe fn list_insert(l: *mut List, data: *mut c_void) -> c_int {
362 if l.is_null() {
363 return -1;
364 }
365
366 let list = unsafe { &mut *l };
367
368 let comparator = match list.comparator {
370 Some(c) => c,
371 None => return list_push_back(l, data),
372 };
373
374 let mut cur = list.front;
376 while !cur.is_null() {
377 let node = unsafe { &*cur };
378 if unsafe { comparator(data as *const c_void, node.data as *const c_void) <= 0 } {
379 let new_node =
381 allocator::xmlMallocZero(size_of::<ListNode>() as usize) as *mut ListNode;
382 if new_node.is_null() {
383 return -1;
384 }
385 unsafe {
386 (*new_node).data = data;
387 (*new_node).prev = node.prev;
388 (*new_node).next = cur;
389 if !node.prev.is_null() {
390 (*node.prev).next = new_node;
391 } else {
392 list.front = new_node;
393 }
394 (*cur).prev = new_node;
395 }
396 list.count += 1;
397 return 0;
398 }
399 cur = node.next;
400 }
401
402 list_push_back(l, data)
404}
405
406pub unsafe fn list_append(l: *mut List, data: *mut c_void) -> c_int {
414 list_push_back(l, data)
415}
416
417pub unsafe fn list_remove_first(l: *mut List, data: *const c_void) -> c_int {
431 if l.is_null() {
432 return -1;
433 }
434
435 let list = unsafe { &mut *l };
436 let comparator = match list.comparator {
437 Some(c) => c,
438 None => return -1,
439 };
440
441 let mut cur = list.front;
442 while !cur.is_null() {
443 let node = unsafe { &*cur };
444 let next = node.next;
445 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
446 if !node.prev.is_null() {
448 unsafe { (*node.prev).next = node.next };
449 } else {
450 list.front = node.next;
451 }
452 if !node.next.is_null() {
453 unsafe { (*node.next).prev = node.prev };
454 } else {
455 list.back = node.prev;
456 }
457
458 if let Some(dealloc) = list.deallocator {
459 unsafe { dealloc(node.data) };
460 }
461 unsafe { allocator::xmlFree(cur as *mut c_void) };
462 list.count = list.count.saturating_sub(1);
463 return 0;
464 }
465 cur = next;
466 }
467
468 -1
469}
470
471pub unsafe fn list_remove_last(l: *mut List, data: *const c_void) -> c_int {
485 if l.is_null() {
486 return -1;
487 }
488
489 let list = unsafe { &mut *l };
490 let comparator = match list.comparator {
491 Some(c) => c,
492 None => return -1,
493 };
494
495 let mut cur = list.back;
496 while !cur.is_null() {
497 let node = unsafe { &*cur };
498 let prev = node.prev;
499 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
500 if !node.prev.is_null() {
502 unsafe { (*node.prev).next = node.next };
503 } else {
504 list.front = node.next;
505 }
506 if !node.next.is_null() {
507 unsafe { (*node.next).prev = node.prev };
508 } else {
509 list.back = node.prev;
510 }
511
512 if let Some(dealloc) = list.deallocator {
513 unsafe { dealloc(node.data) };
514 }
515 unsafe { allocator::xmlFree(cur as *mut c_void) };
516 list.count = list.count.saturating_sub(1);
517 return 0;
518 }
519 cur = prev;
520 }
521
522 -1
523}
524
525pub unsafe fn list_remove_all(l: *mut List, data: *const c_void) -> c_int {
539 if l.is_null() {
540 return 0;
541 }
542
543 let list = unsafe { &mut *l };
544 let comparator = match list.comparator {
545 Some(c) => c,
546 None => return 0,
547 };
548
549 let mut removed = 0;
550 let mut cur = list.front;
551
552 while !cur.is_null() {
553 let node = unsafe { &*cur };
554 let next = node.next;
555
556 if unsafe { comparator(node.data as *const c_void, data) == 0 } {
557 if !node.prev.is_null() {
559 unsafe { (*node.prev).next = node.next };
560 } else {
561 list.front = node.next;
562 }
563 if !node.next.is_null() {
564 unsafe { (*node.next).prev = node.prev };
565 } else {
566 list.back = node.prev;
567 }
568
569 if let Some(dealloc) = list.deallocator {
570 unsafe { dealloc(node.data) };
571 }
572 unsafe { allocator::xmlFree(cur as *mut c_void) };
573 list.count = list.count.saturating_sub(1);
574 removed += 1;
575 }
576
577 cur = next;
578 }
579
580 removed
581}
582
583pub unsafe fn list_clear(l: *mut List) {
595 if l.is_null() {
596 return;
597 }
598
599 let list = unsafe { &mut *l };
600 let mut cur = list.front;
601
602 while !cur.is_null() {
603 let next = unsafe { (*cur).next };
604 if let Some(dealloc) = list.deallocator {
605 unsafe { dealloc((*cur).data) };
606 }
607 unsafe { allocator::xmlFree(cur as *mut c_void) };
608 cur = next;
609 }
610
611 list.front = ptr::null_mut();
612 list.back = ptr::null_mut();
613 list.count = 0;
614}
615
616pub fn list_empty(l: *mut List) -> c_int {
626 if l.is_null() {
627 return 1;
628 }
629 let list = unsafe { &*l };
630 if list.front.is_null() {
631 1
632 } else {
633 0
634 }
635}
636
637pub fn list_front(l: *mut List) -> *mut c_void {
647 if l.is_null() {
648 return ptr::null_mut();
649 }
650 let list = unsafe { &*l };
651 if list.front.is_null() {
652 ptr::null_mut()
653 } else {
654 unsafe { (*list.front).data }
655 }
656}
657
658pub fn list_back(l: *mut List) -> *mut c_void {
668 if l.is_null() {
669 return ptr::null_mut();
670 }
671 let list = unsafe { &*l };
672 if list.back.is_null() {
673 ptr::null_mut()
674 } else {
675 unsafe { (*list.back).data }
676 }
677}
678
679pub fn list_size(l: *mut List) -> c_int {
689 if l.is_null() {
690 return -1;
691 }
692 let list = unsafe { &*l };
693 list.count as c_int
694}
695
696pub unsafe fn list_sort(l: *mut List) {
708 if l.is_null() {
709 return;
710 }
711
712 let list = unsafe { &mut *l };
713 if list.count <= 1 {
714 return;
715 }
716
717 let comparator = match list.comparator {
718 Some(c) => c,
719 None => return,
720 };
721
722 let mut nodes: Vec<*mut ListNode> = Vec::with_capacity(list.count);
724 let mut cur = list.front;
725 while !cur.is_null() {
726 nodes.push(cur);
727 cur = unsafe { (*cur).next };
728 }
729
730 for i in 0..nodes.len() {
732 for j in 0..nodes.len() - 1 - i {
733 let a = unsafe { &*nodes[j] };
734 let b = unsafe { &*nodes[j + 1] };
735 if unsafe { comparator(a.data as *const c_void, b.data as *const c_void) > 0 } {
736 nodes.swap(j, j + 1);
737 }
738 }
739 }
740
741 list.front = nodes[0];
743 list.back = nodes[nodes.len() - 1];
744
745 for i in 0..nodes.len() {
746 unsafe {
747 (*nodes[i]).prev = if i > 0 { nodes[i - 1] } else { ptr::null_mut() };
748 (*nodes[i]).next = if i + 1 < nodes.len() {
749 nodes[i + 1]
750 } else {
751 ptr::null_mut()
752 };
753 }
754 }
755}
756
757pub unsafe fn list_reverse(l: *mut List) {
769 if l.is_null() {
770 return;
771 }
772
773 let list = unsafe { &mut *l };
774
775 let mut cur = list.front;
776 list.front = list.back;
777 list.back = cur;
778
779 while !cur.is_null() {
780 let next = unsafe { (*cur).next };
781 unsafe {
782 (*cur).next = (*cur).prev;
783 (*cur).prev = next;
784 }
785 cur = next;
786 }
787}
788
789pub unsafe fn list_reverse_splice(l1: *mut List, l2: *mut List) {
801 if l1.is_null() || l2.is_null() {
802 return;
803 }
804
805 let list1 = unsafe { &mut *l1 };
806 let list2 = unsafe { &mut *l2 };
807
808 if list2.front.is_null() {
809 return;
810 }
811
812 list_reverse(l2);
814
815 unsafe {
817 (*list2.back).next = list1.front;
818 if !list1.front.is_null() {
819 (*list1.front).prev = list2.back;
820 } else {
821 list1.back = list2.back;
822 }
823 list1.front = list2.front;
824 }
825
826 list1.count += list2.count;
827
828 list2.front = ptr::null_mut();
830 list2.back = ptr::null_mut();
831 list2.count = 0;
832}
833
834pub unsafe fn list_merge(l1: *mut List, l2: *mut List) {
848 if l1.is_null() || l2.is_null() {
849 return;
850 }
851
852 let list1 = unsafe { &mut *l1 };
853 let list2 = unsafe { &mut *l2 };
854
855 if list2.front.is_null() {
856 return;
857 }
858
859 let comparator = match list1.comparator {
860 Some(c) => c,
861 None => {
862 if !list1.back.is_null() {
864 unsafe { (*list1.back).next = list2.front };
865 unsafe { (*list2.front).prev = list1.back };
866 } else {
867 list1.front = list2.front;
868 }
869 list1.back = list2.back;
870 list1.count += list2.count;
871 list2.front = ptr::null_mut();
872 list2.back = ptr::null_mut();
873 list2.count = 0;
874 return;
875 }
876 };
877
878 let mut cur2 = list2.front;
880 let mut insert_before = list1.front;
881
882 while !cur2.is_null() {
883 let next2 = unsafe { (*cur2).next };
884
885 while !insert_before.is_null() {
887 if unsafe {
888 comparator(
889 (*cur2).data as *const c_void,
890 (*insert_before).data as *const c_void,
891 ) <= 0
892 } {
893 break;
894 }
895 insert_before = unsafe { (*insert_before).next };
896 }
897
898 if insert_before.is_null() {
900 if list1.back.is_null() {
902 list1.front = cur2;
903 list1.back = cur2;
904 unsafe {
905 (*cur2).prev = ptr::null_mut();
906 (*cur2).next = ptr::null_mut();
907 }
908 } else {
909 unsafe {
910 (*cur2).prev = list1.back;
911 (*cur2).next = ptr::null_mut();
912 (*list1.back).next = cur2;
913 }
914 list1.back = cur2;
915 }
916 } else {
917 unsafe {
918 (*cur2).prev = (*insert_before).prev;
919 (*cur2).next = insert_before;
920 if !(*insert_before).prev.is_null() {
921 (*(*insert_before).prev).next = cur2;
922 } else {
923 list1.front = cur2;
924 }
925 (*insert_before).prev = cur2;
926 }
927 }
928
929 list1.count += 1;
930 cur2 = next2;
931 }
932
933 list2.front = ptr::null_mut();
935 list2.back = ptr::null_mut();
936 list2.count = 0;
937}
938
939#[cfg(test)]
944mod tests {
945 use super::*;
946
947 unsafe extern "C" fn int_compare(a: *const c_void, b: *const c_void) -> c_int {
948 let ai = *(a as *const i32);
949 let bi = *(b as *const i32);
950 ai.cmp(&bi) as c_int
951 }
952
953 #[test]
954 fn test_list_create_delete() {
955 unsafe {
956 let list = list_create(None, None);
957 assert!(!list.is_null());
958 list_delete(list);
959 }
960 }
961
962 #[test]
963 fn test_list_push_pop() {
964 unsafe {
965 let list = list_create(None, None);
966 let v1 = &mut 1 as *mut c_int as *mut c_void;
967 let v2 = &mut 2 as *mut c_int as *mut c_void;
968
969 list_push_back(list, v1);
970 list_push_back(list, v2);
971 assert_eq!(list_size(list), 2);
972
973 assert_eq!(*(list_front(list) as *const i32), 1);
974 assert_eq!(*(list_back(list) as *const i32), 2);
975
976 list_pop_back(list);
977 assert_eq!(list_size(list), 1);
978 assert_eq!(*(list_back(list) as *const i32), 1);
979
980 list_pop_front(list);
981 assert_eq!(list_size(list), 0);
982 assert_eq!(list_empty(list), 1);
983
984 list_delete(list);
985 }
986 }
987
988 #[test]
989 fn test_list_push_front() {
990 unsafe {
991 let list = list_create(None, None);
992 let v1 = &mut 1 as *mut c_int as *mut c_void;
993 let v2 = &mut 2 as *mut c_int as *mut c_void;
994
995 list_push_front(list, v1);
996 list_push_front(list, v2);
997 assert_eq!(*(list_front(list) as *const i32), 2);
998 assert_eq!(*(list_back(list) as *const i32), 1);
999
1000 list_delete(list);
1001 }
1002 }
1003
1004 #[test]
1005 fn test_list_insert_sorted() {
1006 unsafe {
1007 let list = list_create(None, Some(int_compare));
1008 let v2 = &mut 2 as *mut c_int as *mut c_void;
1009 let v1 = &mut 1 as *mut c_int as *mut c_void;
1010 let v3 = &mut 3 as *mut c_int as *mut c_void;
1011
1012 list_insert(list, v2);
1013 list_insert(list, v1);
1014 list_insert(list, v3);
1015
1016 assert_eq!(*(list_front(list) as *const i32), 1);
1018 assert_eq!(*(list_back(list) as *const i32), 3);
1019 assert_eq!(list_size(list), 3);
1020
1021 list_delete(list);
1022 }
1023 }
1024
1025 #[test]
1026 fn test_list_remove_first() {
1027 unsafe {
1028 let list = list_create(None, Some(int_compare));
1029 let v1 = &mut 1 as *mut c_int as *mut c_void;
1030 let v2 = &mut 2 as *mut c_int as *mut c_void;
1031
1032 list_push_back(list, v1);
1033 list_push_back(list, v2);
1034
1035 let one: i32 = 1;
1036 let result = list_remove_first(list, &one as *const i32 as *const c_void);
1037 assert_eq!(result, 0);
1038 assert_eq!(list_size(list), 1);
1039 assert_eq!(*(list_front(list) as *const i32), 2);
1040
1041 list_delete(list);
1042 }
1043 }
1044
1045 #[test]
1046 fn test_list_clear() {
1047 unsafe {
1048 let list = list_create(None, None);
1049 list_push_back(list, &mut 1 as *mut c_int as *mut c_void);
1050 list_push_back(list, &mut 2 as *mut c_int as *mut c_void);
1051 assert_eq!(list_size(list), 2);
1052
1053 list_clear(list);
1054 assert_eq!(list_empty(list), 1);
1055 assert_eq!(list_size(list), 0);
1056
1057 list_delete(list);
1058 }
1059 }
1060
1061 #[test]
1062 fn test_list_reverse() {
1063 unsafe {
1064 let list = list_create(None, None);
1065 let v1 = &mut 1 as *mut c_int as *mut c_void;
1066 let v2 = &mut 2 as *mut c_int as *mut c_void;
1067 let v3 = &mut 3 as *mut c_int as *mut c_void;
1068
1069 list_push_back(list, v1);
1070 list_push_back(list, v2);
1071 list_push_back(list, v3);
1072
1073 list_reverse(list);
1074
1075 assert_eq!(*(list_front(list) as *const i32), 3);
1076 assert_eq!(*(list_back(list) as *const i32), 1);
1077
1078 list_delete(list);
1079 }
1080 }
1081
1082 #[test]
1083 fn test_list_null_handling() {
1084 unsafe {
1085 assert_eq!(list_empty(ptr::null_mut()), 1);
1086 assert_eq!(list_size(ptr::null_mut()), -1);
1087 assert!(list_front(ptr::null_mut()).is_null());
1088 assert!(list_back(ptr::null_mut()).is_null());
1089 list_delete(ptr::null_mut()); list_clear(ptr::null_mut()); list_pop_front(ptr::null_mut()); list_pop_back(ptr::null_mut()); }
1094 }
1095}