Skip to content

libstd: Implement StrBuf, a new string buffer type like Vec, and #13269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/compiletest/runtest.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,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 @@ -893,77 +984,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 @@ -1570,10 +1593,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 @@ -1813,6 +1846,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
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,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 @@ -666,7 +667,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 @@ -702,7 +703,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 @@ -712,15 +713,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 @@ -729,14 +732,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 @@ -769,15 +772,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
Original file line number Diff line number Diff line change
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 @@ -288,7 +289,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 @@ -302,7 +303,7 @@ impl Pattern {
}
}
}
escaped
escaped.into_owned()
}

/**
Expand Down
Loading