diff options
| author | Dylan Braithwaite <mail@dylanb.me> | 2014-05-08 21:42:40 +0100 |
|---|---|---|
| committer | Dylan Braithwaite <mail@dylanb.me> | 2014-05-13 11:01:12 +0100 |
| commit | 1ca6b2cc664610dbbe9de07864d2016ead422460 (patch) | |
| tree | ff41aee522adb6f9a0df82ef8486c5186af9fc11 /src/libstd | |
| parent | e16243816251d66eb823ba7199259fcaac7d0deb (diff) | |
| download | rust-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.rs | 61 |
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); |
