about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorDylan Braithwaite <mail@dylanb.me>2014-05-08 21:42:40 +0100
committerDylan Braithwaite <mail@dylanb.me>2014-05-13 11:01:12 +0100
commit1ca6b2cc664610dbbe9de07864d2016ead422460 (patch)
treeff41aee522adb6f9a0df82ef8486c5186af9fc11 /src/libstd
parente16243816251d66eb823ba7199259fcaac7d0deb (diff)
downloadrust-1ca6b2cc664610dbbe9de07864d2016ead422460.tar.gz
rust-1ca6b2cc664610dbbe9de07864d2016ead422460.zip
Added functions pop_char and shift_char to StrBuf struct along with appropriate unit tests, using the same test case as push_char.
Changed StrBuf.shift_byte() that it no longer reallocates the buffer by just calling Vec.shift();

Added warning to shift_char()'s docs about it having to copy the whole buffer, as per the docs for
Vec.shift().
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/strbuf.rs61
1 files changed, 57 insertions, 4 deletions
diff --git a/src/libstd/strbuf.rs b/src/libstd/strbuf.rs
index 75008745cf3..575de89fae2 100644
--- a/src/libstd/strbuf.rs
+++ b/src/libstd/strbuf.rs
@@ -19,8 +19,9 @@ use iter::{Extendable, FromIterator, Iterator, range};
 use mem;
 use option::{None, Option, Some};
 use ptr::RawPtr;
+use ptr;
 use slice::{OwnedVector, Vector, CloneableVector};
-use str::{OwnedStr, Str, StrSlice, StrAllocating};
+use str::{CharRange, OwnedStr, Str, StrSlice, StrAllocating};
 use str;
 use vec::Vec;
 
@@ -215,19 +216,49 @@ impl StrBuf {
         Some(byte)
     }
 
+    /// Removes the last character from the string buffer and returns it. Returns `None` if this
+    /// string buffer is empty.
+    #[inline]
+    pub fn pop_char(&mut self) -> Option<char> {
+        let len = self.len();
+        if len == 0 {
+            return None
+        }
+
+        let CharRange {ch, next} = self.as_slice().char_range_at_reverse(len);
+        unsafe {
+            self.vec.set_len(next);
+        }
+        Some(ch)
+    }
+
     /// Removes the first byte from the string buffer and returns it. Returns `None` if this string
     /// buffer is empty.
     ///
     /// The caller must preserve the valid UTF-8 property.
     pub unsafe fn shift_byte(&mut self) -> Option<u8> {
+        self.vec.shift()
+    }
+
+    /// Removes the first character from the string buffer and returns it. Returns `None` if this
+    /// string buffer is empty.
+    ///
+    /// # Warning
+    ///
+    /// This is a O(n) operation as it requires copying every element in the buffer.
+    pub fn shift_char (&mut self) -> Option<char> {
         let len = self.len();
         if len == 0 {
             return None
         }
 
-        let byte = self.as_slice()[0];
-        *self = self.as_slice().slice(1, len).into_strbuf();
-        Some(byte)
+        let CharRange {ch, next} = self.as_slice().char_range_at(0);
+        let new_len = len - next;
+        unsafe {
+            ptr::copy_memory(self.vec.as_mut_ptr(), self.vec.as_ptr().offset(next as int), new_len);
+            self.vec.set_len(new_len);
+        }
+        Some(ch)
     }
 
     /// Views the string buffer as a mutable sequence of bytes.
@@ -358,6 +389,28 @@ mod tests {
     }
 
     #[test]
+    fn test_pop_char() {
+        let mut data = StrBuf::from_str("ประเทศไทย中华b¢€𤭢");
+        assert_eq!(data.pop_char().unwrap(), '𤭢'); // 4 bytes
+        assert_eq!(data.pop_char().unwrap(), '€'); // 3 bytes
+        assert_eq!(data.pop_char().unwrap(), '¢'); // 2 bytes
+        assert_eq!(data.pop_char().unwrap(), 'b'); // 1 bytes
+        assert_eq!(data.pop_char().unwrap(), '华');
+        assert_eq!(data.as_slice(), "ประเทศไทย中");
+    }
+
+    #[test]
+    fn test_shift_char() {
+        let mut data = StrBuf::from_str("𤭢€¢b华ประเทศไทย中");
+        assert_eq!(data.shift_char().unwrap(), '𤭢'); // 4 bytes
+        assert_eq!(data.shift_char().unwrap(), '€'); // 3 bytes
+        assert_eq!(data.shift_char().unwrap(), '¢'); // 2 bytes
+        assert_eq!(data.shift_char().unwrap(), 'b'); // 1 bytes
+        assert_eq!(data.shift_char().unwrap(), '华');
+        assert_eq!(data.as_slice(), "ประเทศไทย中");
+    }
+
+    #[test]
     fn test_str_truncate() {
         let mut s = StrBuf::from_str("12345");
         s.truncate(5);