diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index ed8ba8105b1e..b197ea83fdc4 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -13,6 +13,7 @@ use std::cast; use std::cmp; +use std::ptr; use std::util; use std::iterator::FromIterator; @@ -20,18 +21,15 @@ use std::iterator::FromIterator; pub struct List { priv length: uint, priv list_head: Link, - priv list_tail: Rawlink, + priv list_tail: Rawlink>, } type Link = Option<~Node>; -type Rawlink = Option<&'static Node>; -// Rawlink uses &'static to have a small Option<&'> represenation. -// FIXME: Use a raw pointer like *mut Node if possible. -// FIXME: Causes infinite recursion in %? repr +struct Rawlink { priv p: *mut T } struct Node { priv next: Link, - priv prev: Rawlink, + priv prev: Rawlink>, priv value: T, } @@ -45,21 +43,21 @@ pub struct ForwardIterator<'self, T> { /// List reverse iterator pub struct ReverseIterator<'self, T> { priv list: &'self List, - priv next: Rawlink, + priv next: Rawlink>, priv nelem: uint, } /// List mutable iterator pub struct MutForwardIterator<'self, T> { priv list: &'self mut List, - priv curs: Rawlink, + priv curs: Rawlink>, priv nelem: uint, } /// List mutable reverse iterator pub struct MutReverseIterator<'self, T> { priv list: &'self mut List, - priv next: Rawlink, + priv next: Rawlink>, priv nelem: uint, } @@ -73,6 +71,33 @@ pub struct ConsumeRevIterator { priv list: List } +/// Rawlink is a type like Option but for holding a raw pointer +impl Rawlink { + /// Like Option::None for Rawlink + fn none() -> Rawlink { + Rawlink{p: ptr::mut_null()} + } + + /// Like Option::Some for Rawlink + fn some(n: &mut T) -> Rawlink { + Rawlink{p: ptr::to_mut_unsafe_ptr(n)} + } + + /// Convert the `Rawlink` into an Option value + fn resolve_immut(&self) -> Option<&T> { + unsafe { self.p.to_option() } + } + + /// Convert the `Rawlink` into an Option value + fn resolve(&mut self) -> Option<&mut T> { + if self.p.is_null() { + None + } else { + Some(unsafe { cast::transmute(self.p) }) + } + } +} + impl Container for List { /// O(1) fn is_empty(&self) -> bool { @@ -93,19 +118,11 @@ impl Mutable for List { } } -/// Cast the raw link into a borrowed ref -fn resolve_rawlink(lnk: &'static Node) -> &mut Node { - unsafe { cast::transmute_mut(lnk) } -} -fn rawlink(n: &mut Node) -> Rawlink { - Some(unsafe { cast::transmute(n) }) -} - impl List { /// Create an empty List #[inline] pub fn new() -> List { - List{list_head: None, list_tail: None, length: 0} + List{list_head: None, list_tail: Rawlink::none(), length: 0} } /// Provide a reference to the front element, or None if the list is empty @@ -123,17 +140,17 @@ impl List { /// Provide a reference to the back element, or None if the list is empty pub fn peek_back<'a>(&'a self) -> Option<&'a T> { - match self.list_tail { + match self.list_tail.resolve_immut() { None => None, - Some(tail) => Some(&resolve_rawlink(tail).value), + Some(tail) => Some(&tail.value), } } /// Provide a mutable reference to the back element, or None if the list is empty pub fn peek_back_mut<'a>(&'a mut self) -> Option<&'a mut T> { - match self.list_tail { + match self.list_tail.resolve() { None => None, - Some(tail) => Some(&mut resolve_rawlink(tail).value), + Some(tail) => Some(&mut tail.value), } } @@ -141,12 +158,11 @@ impl List { /// /// O(1) pub fn push_back(&mut self, elt: T) { - match self.list_tail { + match self.list_tail.resolve() { None => return self.push_front(elt), - Some(rtail) => { + Some(tail) => { let mut new_tail = ~Node{value: elt, next: None, prev: self.list_tail}; - self.list_tail = rawlink(new_tail); - let tail = resolve_rawlink(rtail); + self.list_tail = Rawlink::some(new_tail); tail.next = Some(new_tail); } } @@ -158,19 +174,18 @@ impl List { /// O(1) #[inline] pub fn pop_back(&mut self) -> Option { - match self.list_tail { + match self.list_tail.resolve() { None => None, - Some(rtail) => { + Some(tail) => { self.length -= 1; - let tail = resolve_rawlink(rtail); - let tail_own = match tail.prev { + let tail_own = match tail.prev.resolve() { None => { - self.list_tail = None; + self.list_tail = Rawlink::none(); self.list_head.swap_unwrap() }, - Some(rtail_prev) => { + Some(tail_prev) => { self.list_tail = tail.prev; - resolve_rawlink(rtail_prev).next.swap_unwrap() + tail_prev.next.swap_unwrap() } }; Some(tail_own.value) @@ -182,14 +197,14 @@ impl List { /// /// O(1) pub fn push_front(&mut self, elt: T) { - let mut new_head = ~Node{value: elt, next: None, prev: None}; + let mut new_head = ~Node{value: elt, next: None, prev: Rawlink::none()}; match self.list_head { None => { - self.list_tail = rawlink(new_head); + self.list_tail = Rawlink::some(new_head); self.list_head = Some(new_head); } Some(ref mut head) => { - head.prev = rawlink(new_head); + head.prev = Rawlink::some(new_head); util::swap(head, &mut new_head); head.next = Some(new_head); } @@ -208,12 +223,12 @@ impl List { match *head.swap_unwrap() { Node{value: value, next: Some(next), prev: _} => { let mut mnext = next; - mnext.prev = None; + mnext.prev = Rawlink::none(); *head = Some(mnext); Some(value) } Node{value: value, next: None, prev: _} => { - self.list_tail = None; + self.list_tail = Rawlink::none(); *head = None; Some(value) } @@ -226,14 +241,13 @@ impl List { /// /// O(1) pub fn append(&mut self, other: List) { - match self.list_tail { + match self.list_tail.resolve() { None => *self = other, - Some(rtail) => { + Some(tail) => { match other { List{list_head: None, list_tail: _, length: _} => return, List{list_head: Some(node), list_tail: o_tail, length: o_length} => { let mut lnk_node = node; - let tail = resolve_rawlink(rtail); lnk_node.prev = self.list_tail; tail.next = Some(lnk_node); self.list_tail = o_tail; @@ -301,7 +315,7 @@ impl List { /// Provide a forward iterator with mutable references pub fn mut_iter<'a>(&'a mut self) -> MutForwardIterator<'a, T> { - MutForwardIterator{nelem: self.len(), list: self, curs: None} + MutForwardIterator{nelem: self.len(), list: self, curs: Rawlink::none()} } /// Provide a reverse iterator with mutable references @@ -353,23 +367,23 @@ impl<'self, A> Iterator<&'self A> for ForwardIterator<'self, A> { impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> { #[inline] fn next(&mut self) -> Option<&'self mut A> { - match self.curs { + match self.curs.resolve() { None => { match self.list.list_head { None => None, Some(ref mut head) => { self.nelem -= 1; - self.curs = rawlink(&mut **head); + self.curs = Rawlink::some(*head); Some(&mut head.value) } } } - Some(rcurs) => { - match resolve_rawlink(rcurs).next { + Some(curs) => { + match curs.next { None => None, Some(ref mut head) => { self.nelem -= 1; - self.curs = rawlink(&mut **head); + self.curs = Rawlink::some(*head); Some(&mut head.value) } } @@ -385,11 +399,10 @@ impl<'self, A> Iterator<&'self mut A> for MutForwardIterator<'self, A> { impl<'self, A> Iterator<&'self A> for ReverseIterator<'self, A> { #[inline] fn next(&mut self) -> Option<&'self A> { - match self.next { + match self.next.resolve() { None => None, - Some(rnext) => { + Some(prev) => { self.nelem -= 1; - let prev = resolve_rawlink(rnext); self.next = prev.prev; Some(&prev.value) } @@ -404,11 +417,10 @@ impl<'self, A> Iterator<&'self A> for ReverseIterator<'self, A> { impl<'self, A> Iterator<&'self mut A> for MutReverseIterator<'self, A> { #[inline] fn next(&mut self) -> Option<&'self mut A> { - match self.next { + match self.next.resolve() { None => None, - Some(rnext) => { + Some(prev) => { self.nelem -= 1; - let prev = resolve_rawlink(rnext); self.next = prev.prev; Some(&mut prev.value) } @@ -428,19 +440,18 @@ trait ListInsertCursor { impl<'self, A> ListInsertCursor for MutForwardIterator<'self, A> { fn insert_before(&mut self, elt: A) { - match self.curs { + match self.curs.resolve() { None => self.list.push_front(elt), - Some(rcurs) => { - let node = resolve_rawlink(rcurs); - let prev_node = match node.prev { + Some(node) => { + let prev_node = match node.prev.resolve() { None => return self.list.push_front(elt), // at head - Some(rprev) => resolve_rawlink(rprev), + Some(prev) => prev, }; let mut node_own = prev_node.next.swap_unwrap(); let mut ins_node = ~Node{value: elt, next: None, - prev: rawlink(prev_node)}; - node_own.prev = rawlink(ins_node); + prev: Rawlink::some(prev_node)}; + node_own.prev = Rawlink::some(ins_node); ins_node.next = Some(node_own); prev_node.next = Some(ins_node); self.list.length += 1; @@ -497,11 +508,11 @@ fn check_links(list: &List) { Some(ref node) => node_ptr = &**node, } loop { - match (last_ptr, node_ptr.prev) { + match (last_ptr, node_ptr.prev.resolve_immut()) { (None , None ) => {} (None , _ ) => fail!("prev link for list_head"), (Some(p), Some(pptr)) => { - assert_eq!((p as *Node) as uint, pptr as *Node as uint); + assert_eq!(p as *Node, pptr as *Node); } _ => fail!("prev link is none, not good"), }