Skip to content

Commit cea8def

Browse files
committed
auto merge of #13440 : huonw/rust/strbuf, r=alexcrichton
libstd: Implement `StrBuf`, a new string buffer type like `Vec`, and port all code over to use it. Rebased & tests-fixed version of #13269
2 parents 0156af1 + def90f4 commit cea8def

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

+1067
-980
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

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

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

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

970993
impl<K: Hash + TotalEq, V> HashMap<K, V, sip::SipHasher> {
@@ -1571,10 +1594,27 @@ pub type SetAlgebraItems<'a, T, H> =
15711594
#[cfg(test)]
15721595
mod test_map {
15731596
use super::HashMap;
1597+
use std::cmp::Equiv;
1598+
use std::hash::Hash;
15741599
use std::iter::{Iterator,range_inclusive,range_step_inclusive};
15751600
use std::local_data;
15761601
use std::vec;
15771602

1603+
struct KindaIntLike(int);
1604+
1605+
impl Equiv<int> for KindaIntLike {
1606+
fn equiv(&self, other: &int) -> bool {
1607+
let KindaIntLike(this) = *self;
1608+
this == *other
1609+
}
1610+
}
1611+
impl<S: Writer> Hash<S> for KindaIntLike {
1612+
fn hash(&self, state: &mut S) {
1613+
let KindaIntLike(this) = *self;
1614+
this.hash(state)
1615+
}
1616+
}
1617+
15781618
#[test]
15791619
fn test_create_capacity_zero() {
15801620
let mut m = HashMap::with_capacity(0);
@@ -1814,6 +1854,15 @@ mod test_map {
18141854
assert_eq!(m.pop(&1), None);
18151855
}
18161856

1857+
#[test]
1858+
#[allow(experimental)]
1859+
fn test_pop_equiv() {
1860+
let mut m = HashMap::new();
1861+
m.insert(1, 2);
1862+
assert_eq!(m.pop_equiv(&KindaIntLike(1)), Some(2));
1863+
assert_eq!(m.pop_equiv(&KindaIntLike(1)), None);
1864+
}
1865+
18171866
#[test]
18181867
fn test_swap() {
18191868
let mut m = HashMap::new();

src/libgetopts/lib.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
use std::cmp::Eq;
9393
use std::result::{Err, Ok};
9494
use std::result;
95+
use std::strbuf::StrBuf;
9596

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

667-
let mut row = " ".repeat(4);
668+
let mut row = StrBuf::from_owned_str(" ".repeat(4));
668669

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

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

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

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

730-
row
733+
row.into_owned()
731734
});
732735

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

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

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

770-
line
773+
line.into_owned()
771774
}
772775

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

781783

0 commit comments

Comments
 (0)