Skip to content

Commit 5ad42b3

Browse files
committed
auto merge of #14052 : dylanbraithwaite/rust/char-fns-for-strbuf, r=alexcrichton
Added functions pop_char and shift_char to StrBuf along with unit tests, using the same test cases as push_char.
2 parents 4537f13 + 1ca6b2c commit 5ad42b3

File tree

1 file changed

+57
-4
lines changed

1 file changed

+57
-4
lines changed

src/libstd/strbuf.rs

+57-4
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ use iter::{Extendable, FromIterator, Iterator, range};
1919
use mem;
2020
use option::{None, Option, Some};
2121
use ptr::RawPtr;
22+
use ptr;
2223
use slice::{OwnedVector, Vector, CloneableVector};
23-
use str::{OwnedStr, Str, StrSlice, StrAllocating};
24+
use str::{CharRange, OwnedStr, Str, StrSlice, StrAllocating};
2425
use str;
2526
use vec::Vec;
2627

@@ -215,19 +216,49 @@ impl StrBuf {
215216
Some(byte)
216217
}
217218

219+
/// Removes the last character from the string buffer and returns it. Returns `None` if this
220+
/// string buffer is empty.
221+
#[inline]
222+
pub fn pop_char(&mut self) -> Option<char> {
223+
let len = self.len();
224+
if len == 0 {
225+
return None
226+
}
227+
228+
let CharRange {ch, next} = self.as_slice().char_range_at_reverse(len);
229+
unsafe {
230+
self.vec.set_len(next);
231+
}
232+
Some(ch)
233+
}
234+
218235
/// Removes the first byte from the string buffer and returns it. Returns `None` if this string
219236
/// buffer is empty.
220237
///
221238
/// The caller must preserve the valid UTF-8 property.
222239
pub unsafe fn shift_byte(&mut self) -> Option<u8> {
240+
self.vec.shift()
241+
}
242+
243+
/// Removes the first character from the string buffer and returns it. Returns `None` if this
244+
/// string buffer is empty.
245+
///
246+
/// # Warning
247+
///
248+
/// This is a O(n) operation as it requires copying every element in the buffer.
249+
pub fn shift_char (&mut self) -> Option<char> {
223250
let len = self.len();
224251
if len == 0 {
225252
return None
226253
}
227254

228-
let byte = self.as_slice()[0];
229-
*self = self.as_slice().slice(1, len).into_strbuf();
230-
Some(byte)
255+
let CharRange {ch, next} = self.as_slice().char_range_at(0);
256+
let new_len = len - next;
257+
unsafe {
258+
ptr::copy_memory(self.vec.as_mut_ptr(), self.vec.as_ptr().offset(next as int), new_len);
259+
self.vec.set_len(new_len);
260+
}
261+
Some(ch)
231262
}
232263

233264
/// Views the string buffer as a mutable sequence of bytes.
@@ -357,6 +388,28 @@ mod tests {
357388
assert_eq!(data.as_slice(), "ประเทศไทย中华b¢€𤭢");
358389
}
359390

391+
#[test]
392+
fn test_pop_char() {
393+
let mut data = StrBuf::from_str("ประเทศไทย中华b¢€𤭢");
394+
assert_eq!(data.pop_char().unwrap(), '𤭢'); // 4 bytes
395+
assert_eq!(data.pop_char().unwrap(), '€'); // 3 bytes
396+
assert_eq!(data.pop_char().unwrap(), '¢'); // 2 bytes
397+
assert_eq!(data.pop_char().unwrap(), 'b'); // 1 bytes
398+
assert_eq!(data.pop_char().unwrap(), '华');
399+
assert_eq!(data.as_slice(), "ประเทศไทย中");
400+
}
401+
402+
#[test]
403+
fn test_shift_char() {
404+
let mut data = StrBuf::from_str("𤭢€¢b华ประเทศไทย中");
405+
assert_eq!(data.shift_char().unwrap(), '𤭢'); // 4 bytes
406+
assert_eq!(data.shift_char().unwrap(), '€'); // 3 bytes
407+
assert_eq!(data.shift_char().unwrap(), '¢'); // 2 bytes
408+
assert_eq!(data.shift_char().unwrap(), 'b'); // 1 bytes
409+
assert_eq!(data.shift_char().unwrap(), '华');
410+
assert_eq!(data.as_slice(), "ประเทศไทย中");
411+
}
412+
360413
#[test]
361414
fn test_str_truncate() {
362415
let mut s = StrBuf::from_str("12345");

0 commit comments

Comments
 (0)