@@ -727,37 +727,80 @@ impl String {
727727 self . vec . remove ( 0 )
728728 }
729729
730- /// Removes the first character from the string buffer and returns it.
731- /// Returns `None` if this string buffer is empty.
730+ /// Deprecated, call `remove(0)` instead
731+ #[ deprecated = "call .remove(0) instead" ]
732+ pub fn shift_char ( & mut self ) -> Option < char > {
733+ self . remove ( 0 )
734+ }
735+
736+ /// Removes the character from the string buffer at byte position `idx` and
737+ /// returns it. Returns `None` if `idx` is out of bounds.
732738 ///
733739 /// # Warning
734740 ///
735- /// This is a O(n) operation as it requires copying every element in the buffer.
741+ /// This is a O(n) operation as it requires copying every element in the
742+ /// buffer.
743+ ///
744+ /// # Failure
745+ ///
746+ /// If `idx` does not lie on a character boundary, then this function will
747+ /// fail.
736748 ///
737749 /// # Example
738750 ///
739751 /// ```
740752 /// let mut s = String::from_str("foo");
741- /// assert_eq!(s.shift_char( ), Some('f'));
742- /// assert_eq!(s.shift_char( ), Some('o'));
743- /// assert_eq!(s.shift_char( ), Some('o'));
744- /// assert_eq!(s.shift_char( ), None);
753+ /// assert_eq!(s.remove(0 ), Some('f'));
754+ /// assert_eq!(s.remove(1 ), Some('o'));
755+ /// assert_eq!(s.remove(0 ), Some('o'));
756+ /// assert_eq!(s.remove(0 ), None);
745757 /// ```
746- pub fn shift_char ( & mut self ) -> Option < char > {
758+ #[ unstable = "the failure semantics of this function and return type \
759+ may change"]
760+ pub fn remove ( & mut self , idx : uint ) -> Option < char > {
747761 let len = self . len ( ) ;
748- if len == 0 {
749- return None
750- }
762+ if idx >= len { return None }
751763
752- let CharRange { ch, next} = self . as_slice ( ) . char_range_at ( 0 ) ;
753- let new_len = len - next;
764+ let CharRange { ch, next } = self . as_slice ( ) . char_range_at ( idx) ;
754765 unsafe {
755- ptr:: copy_memory ( self . vec . as_mut_ptr ( ) , self . vec . as_ptr ( ) . offset ( next as int ) , new_len) ;
756- self . vec . set_len ( new_len) ;
766+ ptr:: copy_memory ( self . vec . as_mut_ptr ( ) . offset ( idx as int ) ,
767+ self . vec . as_ptr ( ) . offset ( next as int ) ,
768+ len - next) ;
769+ self . vec . set_len ( len - ( next - idx) ) ;
757770 }
758771 Some ( ch)
759772 }
760773
774+ /// Insert a character into the string buffer at byte position `idx`.
775+ ///
776+ /// # Warning
777+ ///
778+ /// This is a O(n) operation as it requires copying every element in the
779+ /// buffer.
780+ ///
781+ /// # Failure
782+ ///
783+ /// If `idx` does not lie on a character boundary or is out of bounds, then
784+ /// this function will fail.
785+ pub fn insert ( & mut self , idx : uint , ch : char ) {
786+ let len = self . len ( ) ;
787+ assert ! ( idx <= len) ;
788+ assert ! ( self . as_slice( ) . is_char_boundary( idx) ) ;
789+ self . vec . reserve_additional ( 4 ) ;
790+ let mut bits = [ 0 , ..4 ] ;
791+ let amt = ch. encode_utf8 ( bits) . unwrap ( ) ;
792+
793+ unsafe {
794+ ptr:: copy_memory ( self . vec . as_mut_ptr ( ) . offset ( ( idx + amt) as int ) ,
795+ self . vec . as_ptr ( ) . offset ( idx as int ) ,
796+ len - idx) ;
797+ ptr:: copy_memory ( self . vec . as_mut_ptr ( ) . offset ( idx as int ) ,
798+ bits. as_ptr ( ) ,
799+ amt) ;
800+ self . vec . set_len ( len + amt) ;
801+ }
802+ }
803+
761804 /// Views the string buffer as a mutable sequence of bytes.
762805 ///
763806 /// This is unsafe because it does not check
@@ -1209,6 +1252,35 @@ mod tests {
12091252 assert_eq ! ( b. as_slice( ) , "1234522" ) ;
12101253 }
12111254
1255+ #[ test]
1256+ fn remove ( ) {
1257+ let mut s = "ศไทย中华Việt Nam; foobar" . to_string ( ) ; ;
1258+ assert_eq ! ( s. remove( 0 ) , Some ( 'ศ' ) ) ;
1259+ assert_eq ! ( s. len( ) , 33 ) ;
1260+ assert_eq ! ( s. as_slice( ) , "ไทย中华Việt Nam; foobar" ) ;
1261+ assert_eq ! ( s. remove( 33 ) , None ) ;
1262+ assert_eq ! ( s. remove( 300 ) , None ) ;
1263+ assert_eq ! ( s. remove( 17 ) , Some ( 'ệ' ) ) ;
1264+ assert_eq ! ( s. as_slice( ) , "ไทย中华Vit Nam; foobar" ) ;
1265+ }
1266+
1267+ #[ test] #[ should_fail]
1268+ fn remove_bad ( ) {
1269+ "ศ" . to_string ( ) . remove ( 1 ) ;
1270+ }
1271+
1272+ #[ test]
1273+ fn insert ( ) {
1274+ let mut s = "foobar" . to_string ( ) ;
1275+ s. insert ( 0 , 'ệ' ) ;
1276+ assert_eq ! ( s. as_slice( ) , "ệfoobar" ) ;
1277+ s. insert ( 6 , 'ย' ) ;
1278+ assert_eq ! ( s. as_slice( ) , "ệfooยbar" ) ;
1279+ }
1280+
1281+ #[ test] #[ should_fail] fn insert_bad1 ( ) { "" . to_string ( ) . insert ( 1 , 't' ) ; }
1282+ #[ test] #[ should_fail] fn insert_bad2 ( ) { "ệ" . to_string ( ) . insert ( 1 , 't' ) ; }
1283+
12121284 #[ bench]
12131285 fn bench_with_capacity ( b : & mut Bencher ) {
12141286 b. iter ( || {
0 commit comments