Skip to content

Commit

Permalink
libstd: Implement StrBuf, a new string buffer type like Vec, and
Browse files Browse the repository at this point in the history
port all code over to use it.
  • Loading branch information
pcwalton authored and huonw committed Apr 10, 2014
1 parent 7fbcb40 commit d8e45ea
Show file tree
Hide file tree
Showing 66 changed files with 987 additions and 928 deletions.
7 changes: 4 additions & 3 deletions src/compiletest/runtest.rs
Expand Up @@ -31,6 +31,7 @@ use std::io::timer;
use std::io;
use std::os;
use std::str;
use std::strbuf::StrBuf;
use std::task;
use std::slice;
use test::MetricMap;
Expand Down Expand Up @@ -328,10 +329,10 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
}

let args = split_maybe_args(&config.target_rustcflags);
let mut tool_path:~str = ~"";
let mut tool_path = StrBuf::new();
for arg in args.iter() {
if arg.contains("android-cross-path=") {
tool_path = arg.replace("android-cross-path=","");
tool_path = StrBuf::from_str(arg.replace("android-cross-path=", ""));
break;
}
}
Expand All @@ -348,7 +349,7 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
let gdb_path = tool_path.append("/bin/arm-linux-androideabi-gdb");
let procsrv::Result{ out, err, status }=
procsrv::run("",
gdb_path,
gdb_path.as_slice(),
debugger_opts.as_slice(),
vec!((~"",~"")),
None)
Expand Down
4 changes: 3 additions & 1 deletion src/doc/tutorial.md
Expand Up @@ -1579,6 +1579,8 @@ allocated memory on the heap. A unique vector owns the elements it contains, so
the elements are mutable if the vector is mutable.

~~~
use std::strbuf::StrBuf;
// A dynamically sized vector (unique vector)
let mut numbers = ~[1, 2, 3];
numbers.push(4);
Expand All @@ -1589,7 +1591,7 @@ let more_numbers: ~[int] = numbers;
// The original `numbers` value can no longer be used, due to move semantics.
let mut string = ~"fo";
let mut string = StrBuf::from_str("fo");
string.push_char('o');
~~~

Expand Down
7 changes: 4 additions & 3 deletions src/libcollections/bitv.rs
Expand Up @@ -15,8 +15,9 @@ use std::cmp;
use std::iter::RandomAccessIterator;
use std::iter::{Rev, Enumerate, Repeat, Map, Zip};
use std::ops;
use std::uint;
use std::slice;
use std::strbuf::StrBuf;
use std::uint;

#[deriving(Clone)]
struct SmallBitv {
Expand Down Expand Up @@ -499,15 +500,15 @@ impl Bitv {
* character is either '0' or '1'.
*/
pub fn to_str(&self) -> ~str {
let mut rs = ~"";
let mut rs = StrBuf::new();
for i in self.iter() {
if i {
rs.push_char('1');
} else {
rs.push_char('0');
}
};
rs
rs.into_owned()
}


Expand Down
181 changes: 111 additions & 70 deletions src/libcollections/hashmap.rs
Expand Up @@ -795,6 +795,97 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
fn search(&self, k: &K) -> Option<table::FullIndex> {
self.search_hashed(&self.make_hash(k), k)
}

fn pop_internal(&mut self, starting_index: table::FullIndex) -> Option<V> {
let starting_probe = starting_index.raw_index();

let ending_probe = {
let mut probe = self.probe_next(starting_probe);
for _ in range(0u, self.table.size()) {
match self.table.peek(probe) {
table::Empty(_) => {}, // empty bucket. this is the end of our shifting.
table::Full(idx) => {
// Bucket that isn't us, which has a non-zero probe distance.
// This isn't the ending index, so keep searching.
if self.bucket_distance(&idx) != 0 {
probe = self.probe_next(probe);
continue;
}

// if we do have a bucket_distance of zero, we're at the end
// of what we need to shift.
}
}
break;
}

probe
};

let (_, _, retval) = self.table.take(starting_index);

let mut probe = starting_probe;
let mut next_probe = self.probe_next(probe);

// backwards-shift all the elements after our newly-deleted one.
while next_probe != ending_probe {
match self.table.peek(next_probe) {
table::Empty(_) => {
// nothing to shift in. just empty it out.
match self.table.peek(probe) {
table::Empty(_) => {},
table::Full(idx) => { self.table.take(idx); }
}
},
table::Full(next_idx) => {
// something to shift. move it over!
let next_hash = next_idx.hash();
let (_, next_key, next_val) = self.table.take(next_idx);
match self.table.peek(probe) {
table::Empty(idx) => {
self.table.put(idx, next_hash, next_key, next_val);
},
table::Full(idx) => {
let (emptyidx, _, _) = self.table.take(idx);
self.table.put(emptyidx, next_hash, next_key, next_val);
}
}
}
}

probe = next_probe;
next_probe = self.probe_next(next_probe);
}

// Done the backwards shift, but there's still an element left!
// Empty it out.
match self.table.peek(probe) {
table::Empty(_) => {},
table::Full(idx) => { self.table.take(idx); }
}

// Now we're done all our shifting. Return the value we grabbed
// earlier.
return Some(retval);
}

/// Like `pop`, but can operate on any type that is equivalent to a key.
#[experimental]
pub fn pop_equiv<Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
if self.table.size() == 0 {
return None
}

let potential_new_size = self.table.size() - 1;
self.make_some_room(potential_new_size);

let starting_index = match self.search_equiv(k) {
Some(idx) => idx,
None => return None,
};

self.pop_internal(starting_index)
}
}

impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> Container for HashMap<K, V, H> {
Expand Down Expand Up @@ -894,77 +985,9 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> MutableMap<K, V> for HashMap<K, V
None => return None,
};

let starting_probe = starting_index.raw_index();

let ending_probe = {
let mut probe = self.probe_next(starting_probe);
for _ in range(0u, self.table.size()) {
match self.table.peek(probe) {
table::Empty(_) => {}, // empty bucket. this is the end of our shifting.
table::Full(idx) => {
// Bucket that isn't us, which has a non-zero probe distance.
// This isn't the ending index, so keep searching.
if self.bucket_distance(&idx) != 0 {
probe = self.probe_next(probe);
continue;
}

// if we do have a bucket_distance of zero, we're at the end
// of what we need to shift.
}
}
break;
}

probe
};

let (_, _, retval) = self.table.take(starting_index);

let mut probe = starting_probe;
let mut next_probe = self.probe_next(probe);

// backwards-shift all the elements after our newly-deleted one.
while next_probe != ending_probe {
match self.table.peek(next_probe) {
table::Empty(_) => {
// nothing to shift in. just empty it out.
match self.table.peek(probe) {
table::Empty(_) => {},
table::Full(idx) => { self.table.take(idx); }
}
},
table::Full(next_idx) => {
// something to shift. move it over!
let next_hash = next_idx.hash();
let (_, next_key, next_val) = self.table.take(next_idx);
match self.table.peek(probe) {
table::Empty(idx) => {
self.table.put(idx, next_hash, next_key, next_val);
},
table::Full(idx) => {
let (emptyidx, _, _) = self.table.take(idx);
self.table.put(emptyidx, next_hash, next_key, next_val);
}
}
}
}

probe = next_probe;
next_probe = self.probe_next(next_probe);
}

// Done the backwards shift, but there's still an element left!
// Empty it out.
match self.table.peek(probe) {
table::Empty(_) => {},
table::Full(idx) => { self.table.take(idx); }
}

// Now we're done all our shifting. Return the value we grabbed
// earlier.
return Some(retval);
self.pop_internal(starting_index)
}

}

impl<K: Hash + TotalEq, V> HashMap<K, V, sip::SipHasher> {
Expand Down Expand Up @@ -1571,10 +1594,20 @@ pub type SetAlgebraItems<'a, T, H> =
#[cfg(test)]
mod test_map {
use super::HashMap;
use std::cmp::Equiv;
use std::iter::{Iterator,range_inclusive,range_step_inclusive};
use std::local_data;
use std::vec;

struct KindaIntLike(int);

impl Equiv<int> for KindaIntLike {
fn equiv(&self, other: &int) -> bool {
let KindaIntLike(this) = *self;
this == *other
}
}

#[test]
fn test_create_capacity_zero() {
let mut m = HashMap::with_capacity(0);
Expand Down Expand Up @@ -1814,6 +1847,14 @@ mod test_map {
assert_eq!(m.pop(&1), None);
}

#[test]
fn test_pop_equiv() {
let mut m = HashMap::new();
m.insert(1, 2);
assert_eq!(m.pop_equiv(&KindaIntLike(1), Some(2)));
assert_eq!(m.pop_equiv(&KindaIntLike(1), None));
}

#[test]
fn test_swap() {
let mut m = HashMap::new();
Expand Down
22 changes: 12 additions & 10 deletions src/libgetopts/lib.rs
Expand Up @@ -92,6 +92,7 @@
use std::cmp::Eq;
use std::result::{Err, Ok};
use std::result;
use std::strbuf::StrBuf;

/// Name of an option. Either a string or a single char.
#[deriving(Clone, Eq)]
Expand Down Expand Up @@ -664,7 +665,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str {
hasarg: hasarg,
..} = (*optref).clone();

let mut row = " ".repeat(4);
let mut row = StrBuf::from_owned_str(" ".repeat(4));

// short option
match short_name.len() {
Expand Down Expand Up @@ -700,7 +701,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str {

// FIXME: #5516 should be graphemes not codepoints
// here we just need to indent the start of the description
let rowlen = row.char_len();
let rowlen = row.as_slice().char_len();
if rowlen < 24 {
for _ in range(0, 24 - rowlen) {
row.push_char(' ');
Expand All @@ -710,15 +711,17 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str {
}

// Normalize desc to contain words separated by one space character
let mut desc_normalized_whitespace = ~"";
let mut desc_normalized_whitespace = StrBuf::new();
for word in desc.words() {
desc_normalized_whitespace.push_str(word);
desc_normalized_whitespace.push_char(' ');
}

// FIXME: #5516 should be graphemes not codepoints
let mut desc_rows = Vec::new();
each_split_within(desc_normalized_whitespace, 54, |substr| {
each_split_within(desc_normalized_whitespace.as_slice(),
54,
|substr| {
desc_rows.push(substr.to_owned());
true
});
Expand All @@ -727,14 +730,14 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str {
// wrapped description
row.push_str(desc_rows.connect(desc_sep));

row
row.into_owned()
});

format!("{}\n\nOptions:\n{}\n", brief, rows.collect::<Vec<~str> >().connect("\n"))
}

fn format_option(opt: &OptGroup) -> ~str {
let mut line = ~"";
let mut line = StrBuf::new();

if opt.occur != Req {
line.push_char('[');
Expand Down Expand Up @@ -767,15 +770,14 @@ fn format_option(opt: &OptGroup) -> ~str {
line.push_str("..");
}

line
line.into_owned()
}

/// Derive a short one-line usage summary from a set of long options.
pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> ~str {
let mut line = ~"Usage: " + program_name + " ";
let mut line = StrBuf::from_str("Usage: " + program_name + " ");
line.push_str(opts.iter().map(format_option).collect::<Vec<~str>>().connect(" "));
line
line.into_owned()
}


Expand Down
5 changes: 3 additions & 2 deletions src/libglob/lib.rs
Expand Up @@ -35,6 +35,7 @@ use std::cell::Cell;
use std::{cmp, os, path};
use std::io::fs;
use std::path::is_sep;
use std::strbuf::StrBuf;

/**
* An iterator that yields Paths from the filesystem that match a particular
Expand Down Expand Up @@ -308,7 +309,7 @@ impl Pattern {
* match the input string and nothing else.
*/
pub fn escape(s: &str) -> ~str {
let mut escaped = ~"";
let mut escaped = StrBuf::new();
for c in s.chars() {
match c {
// note that ! does not need escaping because it is only special inside brackets
Expand All @@ -322,7 +323,7 @@ impl Pattern {
}
}
}
escaped
escaped.into_owned()
}

/**
Expand Down

0 comments on commit d8e45ea

Please sign in to comment.