Skip to content

Commit 890dbc1

Browse files
committed
libstd: Implement StrBuf, a new string buffer type like Vec, and
port all code over to use it.
1 parent e5f1b9f commit 890dbc1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+987
-927
lines changed

src/compiletest/runtest.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use std::io::timer;
3131
use std::io;
3232
use std::os;
3333
use std::str;
34+
use std::strbuf::StrBuf;
3435
use std::task;
3536
use std::slice;
3637
use test::MetricMap;
@@ -328,10 +329,10 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
328329
}
329330

330331
let args = split_maybe_args(&config.target_rustcflags);
331-
let mut tool_path:~str = ~"";
332+
let mut tool_path = StrBuf::new();
332333
for arg in args.iter() {
333334
if arg.contains("android-cross-path=") {
334-
tool_path = arg.replace("android-cross-path=","");
335+
tool_path = StrBuf::from_str(arg.replace("android-cross-path=", ""));
335336
break;
336337
}
337338
}
@@ -348,7 +349,7 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
348349
let gdb_path = tool_path.append("/bin/arm-linux-androideabi-gdb");
349350
let procsrv::Result{ out, err, status }=
350351
procsrv::run("",
351-
gdb_path,
352+
gdb_path.as_slice(),
352353
debugger_opts.as_slice(),
353354
vec!((~"",~"")),
354355
None)

src/doc/tutorial.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,8 @@ allocated memory on the heap. A unique vector owns the elements it contains, so
15791579
the elements are mutable if the vector is mutable.
15801580
15811581
~~~
1582+
use std::strbuf::StrBuf;
1583+
15821584
// A dynamically sized vector (unique vector)
15831585
let mut numbers = ~[1, 2, 3];
15841586
numbers.push(4);
@@ -1589,7 +1591,7 @@ let more_numbers: ~[int] = numbers;
15891591

15901592
// The original `numbers` value can no longer be used, due to move semantics.
15911593

1592-
let mut string = ~"fo";
1594+
let mut string = StrBuf::from_str("fo");
15931595
string.push_char('o');
15941596
~~~
15951597

src/libcollections/bitv.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ use std::cmp;
1515
use std::iter::RandomAccessIterator;
1616
use std::iter::{Rev, Enumerate, Repeat, Map, Zip};
1717
use std::ops;
18-
use std::uint;
1918
use std::slice;
19+
use std::strbuf::StrBuf;
20+
use std::uint;
2021

2122
#[deriving(Clone)]
2223
struct SmallBitv {
@@ -499,15 +500,15 @@ impl Bitv {
499500
* character is either '0' or '1'.
500501
*/
501502
pub fn to_str(&self) -> ~str {
502-
let mut rs = ~"";
503+
let mut rs = StrBuf::new();
503504
for i in self.iter() {
504505
if i {
505506
rs.push_char('1');
506507
} else {
507508
rs.push_char('0');
508509
}
509510
};
510-
rs
511+
rs.into_owned()
511512
}
512513

513514

src/libcollections/hashmap.rs

+111-70
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,97 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
794794
fn search(&self, k: &K) -> Option<table::FullIndex> {
795795
self.search_hashed(&self.make_hash(k), k)
796796
}
797+
798+
fn pop_internal(&mut self, starting_index: table::FullIndex) -> Option<V> {
799+
let starting_probe = starting_index.raw_index();
800+
801+
let ending_probe = {
802+
let mut probe = self.probe_next(starting_probe);
803+
for _ in range(0u, self.table.size()) {
804+
match self.table.peek(probe) {
805+
table::Empty(_) => {}, // empty bucket. this is the end of our shifting.
806+
table::Full(idx) => {
807+
// Bucket that isn't us, which has a non-zero probe distance.
808+
// This isn't the ending index, so keep searching.
809+
if self.bucket_distance(&idx) != 0 {
810+
probe = self.probe_next(probe);
811+
continue;
812+
}
813+
814+
// if we do have a bucket_distance of zero, we're at the end
815+
// of what we need to shift.
816+
}
817+
}
818+
break;
819+
}
820+
821+
probe
822+
};
823+
824+
let (_, _, retval) = self.table.take(starting_index);
825+
826+
let mut probe = starting_probe;
827+
let mut next_probe = self.probe_next(probe);
828+
829+
// backwards-shift all the elements after our newly-deleted one.
830+
while next_probe != ending_probe {
831+
match self.table.peek(next_probe) {
832+
table::Empty(_) => {
833+
// nothing to shift in. just empty it out.
834+
match self.table.peek(probe) {
835+
table::Empty(_) => {},
836+
table::Full(idx) => { self.table.take(idx); }
837+
}
838+
},
839+
table::Full(next_idx) => {
840+
// something to shift. move it over!
841+
let next_hash = next_idx.hash();
842+
let (_, next_key, next_val) = self.table.take(next_idx);
843+
match self.table.peek(probe) {
844+
table::Empty(idx) => {
845+
self.table.put(idx, next_hash, next_key, next_val);
846+
},
847+
table::Full(idx) => {
848+
let (emptyidx, _, _) = self.table.take(idx);
849+
self.table.put(emptyidx, next_hash, next_key, next_val);
850+
}
851+
}
852+
}
853+
}
854+
855+
probe = next_probe;
856+
next_probe = self.probe_next(next_probe);
857+
}
858+
859+
// Done the backwards shift, but there's still an element left!
860+
// Empty it out.
861+
match self.table.peek(probe) {
862+
table::Empty(_) => {},
863+
table::Full(idx) => { self.table.take(idx); }
864+
}
865+
866+
// Now we're done all our shifting. Return the value we grabbed
867+
// earlier.
868+
return Some(retval);
869+
}
870+
871+
/// Like `pop`, but can operate on any type that is equivalent to a key.
872+
#[experimental]
873+
pub fn pop_equiv<Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
874+
if self.table.size() == 0 {
875+
return None
876+
}
877+
878+
let potential_new_size = self.table.size() - 1;
879+
self.make_some_room(potential_new_size);
880+
881+
let starting_index = match self.search_equiv(k) {
882+
Some(idx) => idx,
883+
None => return None,
884+
};
885+
886+
self.pop_internal(starting_index)
887+
}
797888
}
798889

799890
impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> Container for HashMap<K, V, H> {
@@ -893,77 +984,9 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> MutableMap<K, V> for HashMap<K, V
893984
None => return None,
894985
};
895986

896-
let starting_probe = starting_index.raw_index();
897-
898-
let ending_probe = {
899-
let mut probe = self.probe_next(starting_probe);
900-
for _ in range(0u, self.table.size()) {
901-
match self.table.peek(probe) {
902-
table::Empty(_) => {}, // empty bucket. this is the end of our shifting.
903-
table::Full(idx) => {
904-
// Bucket that isn't us, which has a non-zero probe distance.
905-
// This isn't the ending index, so keep searching.
906-
if self.bucket_distance(&idx) != 0 {
907-
probe = self.probe_next(probe);
908-
continue;
909-
}
910-
911-
// if we do have a bucket_distance of zero, we're at the end
912-
// of what we need to shift.
913-
}
914-
}
915-
break;
916-
}
917-
918-
probe
919-
};
920-
921-
let (_, _, retval) = self.table.take(starting_index);
922-
923-
let mut probe = starting_probe;
924-
let mut next_probe = self.probe_next(probe);
925-
926-
// backwards-shift all the elements after our newly-deleted one.
927-
while next_probe != ending_probe {
928-
match self.table.peek(next_probe) {
929-
table::Empty(_) => {
930-
// nothing to shift in. just empty it out.
931-
match self.table.peek(probe) {
932-
table::Empty(_) => {},
933-
table::Full(idx) => { self.table.take(idx); }
934-
}
935-
},
936-
table::Full(next_idx) => {
937-
// something to shift. move it over!
938-
let next_hash = next_idx.hash();
939-
let (_, next_key, next_val) = self.table.take(next_idx);
940-
match self.table.peek(probe) {
941-
table::Empty(idx) => {
942-
self.table.put(idx, next_hash, next_key, next_val);
943-
},
944-
table::Full(idx) => {
945-
let (emptyidx, _, _) = self.table.take(idx);
946-
self.table.put(emptyidx, next_hash, next_key, next_val);
947-
}
948-
}
949-
}
950-
}
951-
952-
probe = next_probe;
953-
next_probe = self.probe_next(next_probe);
954-
}
955-
956-
// Done the backwards shift, but there's still an element left!
957-
// Empty it out.
958-
match self.table.peek(probe) {
959-
table::Empty(_) => {},
960-
table::Full(idx) => { self.table.take(idx); }
961-
}
962-
963-
// Now we're done all our shifting. Return the value we grabbed
964-
// earlier.
965-
return Some(retval);
987+
self.pop_internal(starting_index)
966988
}
989+
967990
}
968991

969992
impl<K: Hash + TotalEq, V> HashMap<K, V, sip::SipHasher> {
@@ -1570,10 +1593,20 @@ pub type SetAlgebraItems<'a, T, H> =
15701593
#[cfg(test)]
15711594
mod test_map {
15721595
use super::HashMap;
1596+
use std::cmp::Equiv;
15731597
use std::iter::{Iterator,range_inclusive,range_step_inclusive};
15741598
use std::local_data;
15751599
use std::vec;
15761600

1601+
struct KindaIntLike(int);
1602+
1603+
impl Equiv<int> for KindaIntLike {
1604+
fn equiv(&self, other: &int) -> bool {
1605+
let KindaIntLike(this) = *self;
1606+
this == *other
1607+
}
1608+
}
1609+
15771610
#[test]
15781611
fn test_create_capacity_zero() {
15791612
let mut m = HashMap::with_capacity(0);
@@ -1813,6 +1846,14 @@ mod test_map {
18131846
assert_eq!(m.pop(&1), None);
18141847
}
18151848

1849+
#[test]
1850+
fn test_pop_equiv() {
1851+
let mut m = HashMap::new();
1852+
m.insert(1, 2);
1853+
assert_eq!(m.pop_equiv(&KindaIntLike(1), Some(2)));
1854+
assert_eq!(m.pop_equiv(&KindaIntLike(1), None));
1855+
}
1856+
18161857
#[test]
18171858
fn test_swap() {
18181859
let mut m = HashMap::new();

src/libgetopts/lib.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
use std::cmp::Eq;
9595
use std::result::{Err, Ok};
9696
use std::result;
97+
use std::strbuf::StrBuf;
9798

9899
/// Name of an option. Either a string or a single char.
99100
#[deriving(Clone, Eq)]
@@ -666,7 +667,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str {
666667
hasarg: hasarg,
667668
..} = (*optref).clone();
668669

669-
let mut row = " ".repeat(4);
670+
let mut row = StrBuf::from_owned_str(" ".repeat(4));
670671

671672
// short option
672673
match short_name.len() {
@@ -702,7 +703,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str {
702703

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

714715
// Normalize desc to contain words separated by one space character
715-
let mut desc_normalized_whitespace = ~"";
716+
let mut desc_normalized_whitespace = StrBuf::new();
716717
for word in desc.words() {
717718
desc_normalized_whitespace.push_str(word);
718719
desc_normalized_whitespace.push_char(' ');
719720
}
720721

721722
// FIXME: #5516 should be graphemes not codepoints
722723
let mut desc_rows = Vec::new();
723-
each_split_within(desc_normalized_whitespace, 54, |substr| {
724+
each_split_within(desc_normalized_whitespace.as_slice(),
725+
54,
726+
|substr| {
724727
desc_rows.push(substr.to_owned());
725728
true
726729
});
@@ -729,14 +732,14 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str {
729732
// wrapped description
730733
row.push_str(desc_rows.connect(desc_sep));
731734

732-
row
735+
row.into_owned()
733736
});
734737

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

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

741744
if opt.occur != Req {
742745
line.push_char('[');
@@ -769,15 +772,14 @@ fn format_option(opt: &OptGroup) -> ~str {
769772
line.push_str("..");
770773
}
771774

772-
line
775+
line.into_owned()
773776
}
774777

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

783785

src/libglob/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use std::cell::Cell;
3535
use std::{cmp, os, path};
3636
use std::io::fs;
3737
use std::path::is_sep;
38+
use std::strbuf::StrBuf;
3839

3940
/**
4041
* An iterator that yields Paths from the filesystem that match a particular
@@ -288,7 +289,7 @@ impl Pattern {
288289
* match the input string and nothing else.
289290
*/
290291
pub fn escape(s: &str) -> ~str {
291-
let mut escaped = ~"";
292+
let mut escaped = StrBuf::new();
292293
for c in s.chars() {
293294
match c {
294295
// note that ! does not need escaping because it is only special inside brackets
@@ -302,7 +303,7 @@ impl Pattern {
302303
}
303304
}
304305
}
305-
escaped
306+
escaped.into_owned()
306307
}
307308

308309
/**

0 commit comments

Comments
 (0)