From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/rowan/src/sll.rs | 129 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 vendor/rowan/src/sll.rs (limited to 'vendor/rowan/src/sll.rs') diff --git a/vendor/rowan/src/sll.rs b/vendor/rowan/src/sll.rs new file mode 100644 index 000000000..87d2f1f31 --- /dev/null +++ b/vendor/rowan/src/sll.rs @@ -0,0 +1,129 @@ +//! Sorted Linked List + +use std::{cell::Cell, cmp::Ordering, ptr}; + +use crate::utility_types::Delta; +pub(crate) unsafe trait Elem { + fn prev(&self) -> &Cell<*const Self>; + fn next(&self) -> &Cell<*const Self>; + fn key(&self) -> &Cell; +} + +pub(crate) enum AddToSllResult<'a, E: Elem> { + NoHead, + EmptyHead(&'a Cell<*const E>), + SmallerThanHead(&'a Cell<*const E>), + SmallerThanNotHead(*const E), + AlreadyInSll(*const E), +} + +impl<'a, E: Elem> AddToSllResult<'a, E> { + pub(crate) fn add_to_sll(&self, elem_ptr: *const E) { + unsafe { + (*elem_ptr).prev().set(elem_ptr); + (*elem_ptr).next().set(elem_ptr); + + match self { + // Case 1: empty head, replace it. + AddToSllResult::EmptyHead(head) => head.set(elem_ptr), + + // Case 2: we are smaller than the head, replace it. + AddToSllResult::SmallerThanHead(head) => { + let old_head = head.get(); + let prev = (*old_head).prev().replace(elem_ptr); + (*prev).next().set(elem_ptr); + (*elem_ptr).next().set(old_head); + (*elem_ptr).prev().set(prev); + head.set(elem_ptr); + } + + // Case 3: insert in place found by looping + AddToSllResult::SmallerThanNotHead(curr) => { + let next = (**curr).next().replace(elem_ptr); + (*next).prev().set(elem_ptr); + (*elem_ptr).prev().set(*curr); + (*elem_ptr).next().set(next); + } + AddToSllResult::NoHead | AddToSllResult::AlreadyInSll(_) => (), + } + } + } +} + +#[cold] +pub(crate) fn init<'a, E: Elem>( + head: Option<&'a Cell<*const E>>, + elem: &E, +) -> AddToSllResult<'a, E> { + if let Some(head) = head { + link(head, elem) + } else { + AddToSllResult::NoHead + } +} + +#[cold] +pub(crate) fn unlink(head: &Cell<*const E>, elem: &E) { + debug_assert!(!head.get().is_null(), "invalid linked list head"); + + let elem_ptr: *const E = elem; + + let prev = elem.prev().replace(elem_ptr); + let next = elem.next().replace(elem_ptr); + unsafe { + debug_assert_eq!((*prev).next().get(), elem_ptr, "invalid linked list links"); + debug_assert_eq!((*next).prev().get(), elem_ptr, "invalid linked list links"); + (*prev).next().set(next); + (*next).prev().set(prev); + } + + if head.get() == elem_ptr { + head.set(if next == elem_ptr { ptr::null() } else { next }) + } +} + +#[cold] +pub(crate) fn link<'a, E: Elem>(head: &'a Cell<*const E>, elem: &E) -> AddToSllResult<'a, E> { + unsafe { + let old_head = head.get(); + // Case 1: empty head, replace it. + if old_head.is_null() { + return AddToSllResult::EmptyHead(head); + } + + // Case 2: we are smaller than the head, replace it. + if elem.key() < (*old_head).key() { + return AddToSllResult::SmallerThanHead(head); + } + + // Case 3: loop *backward* until we find insertion place. Because of + // Case 2, we can't loop beyond the head. + let mut curr = (*old_head).prev().get(); + loop { + match (*curr).key().cmp(elem.key()) { + Ordering::Less => return AddToSllResult::SmallerThanNotHead(curr), + Ordering::Equal => return AddToSllResult::AlreadyInSll(curr), + Ordering::Greater => curr = (*curr).prev().get(), + } + } + } +} + +pub(crate) fn adjust(elem: &E, from: u32, by: Delta) { + let elem_ptr: *const E = elem; + + unsafe { + let mut curr = elem_ptr; + loop { + let mut key = (*curr).key().get(); + if key >= from { + key += by; + (*curr).key().set(key); + } + curr = (*curr).next().get(); + if curr == elem_ptr { + break; + } + } + } +} -- cgit v1.2.3