Skip to content

Commit

Permalink
libstd: Change slice_shift_char, shift_char, pop_char, `shift_b…
Browse files Browse the repository at this point in the history
…yte` and `pop_byte` to return an Option instead of failing
  • Loading branch information
pczarn committed Mar 10, 2014
1 parent 62f1d68 commit 0349f2a
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 43 deletions.
11 changes: 6 additions & 5 deletions src/libglob/lib.rs
Expand Up @@ -369,11 +369,11 @@ impl Pattern {
return EntirePatternDoesntMatch;
}

let (c, next) = file.slice_shift_char();
if require_literal(c) {
let (some_c, next) = file.slice_shift_char();
if require_literal(some_c.unwrap()) {
return SubPatternDoesntMatch;
}
prev_char.set(Some(c));
prev_char.set(some_c);
file = next;
}
}
Expand All @@ -382,7 +382,8 @@ impl Pattern {
return EntirePatternDoesntMatch;
}

let (c, next) = file.slice_shift_char();
let (some_c, next) = file.slice_shift_char();
let c = some_c.unwrap();
let matches = match *token {
AnyChar => {
!require_literal(c)
Expand All @@ -403,7 +404,7 @@ impl Pattern {
if !matches {
return SubPatternDoesntMatch;
}
prev_char.set(Some(c));
prev_char.set(some_c);
file = next;
}
}
Expand Down
87 changes: 53 additions & 34 deletions src/libstd/str.rs
Expand Up @@ -1355,6 +1355,7 @@ pub mod raw {
use libc;
use ptr;
use ptr::RawPtr;
use option::{Option, Some, None};
use str::{is_utf8, OwnedStr, StrSlice};
use vec;
use vec::{MutableVector, ImmutableVector, OwnedVector};
Expand Down Expand Up @@ -1465,22 +1466,28 @@ pub mod raw {

/// Removes the last byte from a string and returns it.
/// The caller must preserve the valid UTF-8 property.
pub unsafe fn pop_byte(s: &mut ~str) -> u8 {
pub unsafe fn pop_byte(s: &mut ~str) -> Option<u8> {
let len = s.len();
assert!((len > 0u));
let b = s[len - 1u];
s.set_len(len - 1);
return b;
if len == 0u {
return None;
} else {
let b = s[len - 1u];
s.set_len(len - 1);
return Some(b);
}
}

/// Removes the first byte from a string and returns it.
/// The caller must preserve the valid UTF-8 property.
pub unsafe fn shift_byte(s: &mut ~str) -> u8 {
pub unsafe fn shift_byte(s: &mut ~str) -> Option<u8> {
let len = s.len();
assert!((len > 0u));
let b = s[0];
*s = s.slice(1, len).to_owned();
return b;
if len == 0u {
return None;
} else {
let b = s[0];
*s = s.slice(1, len).to_owned();
return Some(b);
}
}

/// Access the str in its vector representation.
Expand Down Expand Up @@ -2291,7 +2298,7 @@ pub trait StrSlice<'a> {
/// assert_eq!(c, 'ö');
/// assert_eq!(s2, "we 老虎 Léopard");
/// ```
fn slice_shift_char(&self) -> (char, &'a str);
fn slice_shift_char(&self) -> (Option<char>, &'a str);

/// Levenshtein Distance between two strings.
fn lev_distance(&self, t: &str) -> uint;
Expand Down Expand Up @@ -2744,10 +2751,14 @@ impl<'a> StrSlice<'a> for &'a str {
}

#[inline]
fn slice_shift_char(&self) -> (char, &'a str) {
let CharRange {ch, next} = self.char_range_at(0u);
let next_s = unsafe { raw::slice_bytes(*self, next, self.len()) };
return (ch, next_s);
fn slice_shift_char(&self) -> (Option<char>, &'a str) {
if self.is_empty() {
return (None, *self);
} else {
let CharRange {ch, next} = self.char_range_at(0u);
let next_s = unsafe { raw::slice_bytes(*self, next, self.len()) };
return (Some(ch), next_s);
}
}

fn lev_distance(&self, t: &str) -> uint {
Expand Down Expand Up @@ -2815,14 +2826,14 @@ pub trait OwnedStr {
/// # Failure
///
/// If the string does not contain any characters
fn pop_char(&mut self) -> char;
fn pop_char(&mut self) -> Option<char>;

/// Remove the first character from a string and return it
///
/// # Failure
///
/// If the string does not contain any characters
fn shift_char(&mut self) -> char;
fn shift_char(&mut self) -> Option<char>;

/// Prepend a char to a string
fn unshift_char(&mut self, ch: char);
Expand Down Expand Up @@ -2925,19 +2936,26 @@ impl OwnedStr for ~str {
}

#[inline]
fn pop_char(&mut self) -> char {
fn pop_char(&mut self) -> Option<char> {
let end = self.len();
assert!(end > 0u);
let CharRange {ch, next} = self.char_range_at_reverse(end);
unsafe { self.set_len(next); }
return ch;
if end == 0u {
return None;
} else {
let CharRange {ch, next} = self.char_range_at_reverse(end);
unsafe { self.set_len(next); }
return Some(ch);
}
}

#[inline]
fn shift_char(&mut self) -> char {
let CharRange {ch, next} = self.char_range_at(0u);
*self = self.slice(next, self.len()).to_owned();
return ch;
fn shift_char(&mut self) -> Option<char> {
if self.is_empty() {
return None;
} else {
let CharRange {ch, next} = self.char_range_at(0u);
*self = self.slice(next, self.len()).to_owned();
return Some(ch);
}
}

#[inline]
Expand Down Expand Up @@ -3148,22 +3166,23 @@ mod tests {
let mut data = ~"ประเทศไทย中华";
let cc = data.pop_char();
assert_eq!(~"ประเทศไทย中", data);
assert_eq!('华', cc);
assert_eq!(Some('华'), cc);
}

#[test]
fn test_pop_char_2() {
let mut data2 = ~"华";
let cc2 = data2.pop_char();
assert_eq!(~"", data2);
assert_eq!('华', cc2);
assert_eq!(Some('华'), cc2);
}

#[test]
#[should_fail]
fn test_pop_char_fail() {
fn test_pop_char_empty() {
let mut data = ~"";
let _cc3 = data.pop_char();
let cc3 = data.pop_char();
assert_eq!(~"", data);
assert_eq!(None, cc3);
}

#[test]
Expand All @@ -3182,7 +3201,7 @@ mod tests {
let mut data = ~"ประเทศไทย中";
let cc = data.shift_char();
assert_eq!(~"ระเทศไทย中", data);
assert_eq!('ป', cc);
assert_eq!(Some('ป'), cc);
}

#[test]
Expand Down Expand Up @@ -3611,15 +3630,15 @@ mod tests {
let mut s = ~"ABC";
let b = unsafe{raw::shift_byte(&mut s)};
assert_eq!(s, ~"BC");
assert_eq!(b, 65u8);
assert_eq!(b, Some(65u8));
}

#[test]
fn test_pop_byte() {
let mut s = ~"ABC";
let b = unsafe{raw::pop_byte(&mut s)};
assert_eq!(s, ~"AB");
assert_eq!(b, 67u8);
assert_eq!(b, Some(67u8));
}

#[test]
Expand Down
8 changes: 4 additions & 4 deletions src/test/run-pass/utf8_chars.rs
Expand Up @@ -42,12 +42,12 @@ pub fn main() {
assert!((!str::is_utf8([0xf0_u8, 0xff_u8, 0xff_u8, 0x10_u8])));

let mut stack = ~"a×c€";
assert_eq!(stack.pop_char(), '€');
assert_eq!(stack.pop_char(), 'c');
assert_eq!(stack.pop_char(), Some('€'));
assert_eq!(stack.pop_char(), Some('c'));
stack.push_char('u');
assert!(stack == ~"a×u");
assert_eq!(stack.shift_char(), 'a');
assert_eq!(stack.shift_char(), '×');
assert_eq!(stack.shift_char(), Some('a'));
assert_eq!(stack.shift_char(), Some('×'));
stack.unshift_char('ß');
assert!(stack == ~"ßu");
}

0 comments on commit 0349f2a

Please sign in to comment.