Skip to content

Commit 1790400

Browse files
committed
auto merge of #7465 : alexcrichton/rust/issue-4432, r=cmr
This stems from trying to perform as few allocations as possible throughout the standard libraries. This specializes the `ToStr` implementation for floats/ints separately because it's known that ints will have a maximum length (whereas floats could be very very large). I also removed a `FIXME` to remove a malloc from the `to_str()` of floats in `repr.rs` because I think that this should be addressed elsewhere. I think that we may not be able to avoid it easily because floats can have such large representations, but regardless this should be a problem with the implementation of `float_to_str_bytes_common` now and not in the `Repr` module.
2 parents 2b3569a + d3155fa commit 1790400

File tree

12 files changed

+323
-253
lines changed

12 files changed

+323
-253
lines changed

src/libextra/terminfo/parm.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! Parameterized string expansion
1212
1313
use std::{char, vec, util};
14-
use std::num::strconv::{SignNone,SignNeg,SignAll,DigAll,to_str_bytes_common};
14+
use std::num::strconv::{SignNone,SignNeg,SignAll,int_to_str_bytes_common};
1515
use std::iterator::IteratorUtil;
1616

1717
#[deriving(Eq)]
@@ -469,14 +469,20 @@ priv fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
469469
FormatHex|FormatHEX => 16,
470470
FormatString => util::unreachable()
471471
};
472-
let (s,_) = match op {
472+
let mut s = ~[];
473+
match op {
473474
FormatDigit => {
474475
let sign = if flags.sign { SignAll } else { SignNeg };
475-
to_str_bytes_common(&d, radix, false, sign, DigAll)
476+
do int_to_str_bytes_common(d, radix, sign) |c| {
477+
s.push(c);
478+
}
479+
}
480+
_ => {
481+
do int_to_str_bytes_common(d as uint, radix, SignNone) |c| {
482+
s.push(c);
483+
}
476484
}
477-
_ => to_str_bytes_common(&(d as uint), radix, false, SignNone, DigAll)
478485
};
479-
let mut s = s;
480486
if flags.precision > s.len() {
481487
let mut s_ = vec::with_capacity(flags.precision);
482488
let n = flags.precision - s.len();

src/libstd/char.rs

Lines changed: 59 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@
1010

1111
//! Utilities for manipulating the char type
1212
13-
use container::Container;
1413
use option::{None, Option, Some};
15-
use str;
16-
use str::{StrSlice, OwnedStr};
17-
use u32;
18-
use uint;
14+
use int;
15+
use str::StrSlice;
1916
use unicode::{derived_property, general_category};
2017

18+
#[cfg(test)] use str::OwnedStr;
19+
2120
#[cfg(not(test))] use cmp::{Eq, Ord};
2221
#[cfg(not(test))] use num::Zero;
2322

@@ -202,21 +201,21 @@ pub fn from_digit(num: uint, radix: uint) -> Option<char> {
202201
/// - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN`
203202
/// - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN`
204203
///
205-
pub fn escape_unicode(c: char) -> ~str {
206-
let s = u32::to_str_radix(c as u32, 16u);
207-
let (c, pad) = cond!(
208-
(c <= '\xff') { ('x', 2u) }
209-
(c <= '\uffff') { ('u', 4u) }
210-
_ { ('U', 8u) }
204+
pub fn escape_unicode(c: char, f: &fn(char)) {
205+
// avoid calling str::to_str_radix because we don't really need to allocate
206+
// here.
207+
f('\\');
208+
let pad = cond!(
209+
(c <= '\xff') { f('x'); 2 }
210+
(c <= '\uffff') { f('u'); 4 }
211+
_ { f('U'); 8 }
211212
);
212-
assert!(s.len() <= pad);
213-
let mut out = ~"\\";
214-
out.push_str(str::from_char(c));
215-
for uint::range(s.len(), pad) |_| {
216-
out.push_str("0");
213+
for int::range_step(4 * (pad - 1), -1, -4) |offset| {
214+
match ((c as u32) >> offset) & 0xf {
215+
i @ 0 .. 9 => { f('0' + i as char); }
216+
i => { f('a' + (i - 10) as char); }
217+
}
217218
}
218-
out.push_str(s);
219-
out
220219
}
221220

222221
///
@@ -231,16 +230,16 @@ pub fn escape_unicode(c: char) -> ~str {
231230
/// - Any other chars in the range [0x20,0x7e] are not escaped.
232231
/// - Any other chars are given hex unicode escapes; see `escape_unicode`.
233232
///
234-
pub fn escape_default(c: char) -> ~str {
233+
pub fn escape_default(c: char, f: &fn(char)) {
235234
match c {
236-
'\t' => ~"\\t",
237-
'\r' => ~"\\r",
238-
'\n' => ~"\\n",
239-
'\\' => ~"\\\\",
240-
'\'' => ~"\\'",
241-
'"' => ~"\\\"",
242-
'\x20' .. '\x7e' => str::from_char(c),
243-
_ => c.escape_unicode(),
235+
'\t' => { f('\\'); f('t'); }
236+
'\r' => { f('\\'); f('r'); }
237+
'\n' => { f('\\'); f('n'); }
238+
'\\' => { f('\\'); f('\\'); }
239+
'\'' => { f('\\'); f('\''); }
240+
'"' => { f('\\'); f('"'); }
241+
'\x20' .. '\x7e' => { f(c); }
242+
_ => c.escape_unicode(f),
244243
}
245244
}
246245

@@ -274,8 +273,8 @@ pub trait Char {
274273
fn is_digit_radix(&self, radix: uint) -> bool;
275274
fn to_digit(&self, radix: uint) -> Option<uint>;
276275
fn from_digit(num: uint, radix: uint) -> Option<char>;
277-
fn escape_unicode(&self) -> ~str;
278-
fn escape_default(&self) -> ~str;
276+
fn escape_unicode(&self, f: &fn(char));
277+
fn escape_default(&self, f: &fn(char));
279278
fn len_utf8_bytes(&self) -> uint;
280279
}
281280

@@ -302,9 +301,9 @@ impl Char for char {
302301

303302
fn from_digit(num: uint, radix: uint) -> Option<char> { from_digit(num, radix) }
304303

305-
fn escape_unicode(&self) -> ~str { escape_unicode(*self) }
304+
fn escape_unicode(&self, f: &fn(char)) { escape_unicode(*self, f) }
306305

307-
fn escape_default(&self) -> ~str { escape_default(*self) }
306+
fn escape_default(&self, f: &fn(char)) { escape_default(*self, f) }
308307

309308
fn len_utf8_bytes(&self) -> uint { len_utf8_bytes(*self) }
310309
}
@@ -392,27 +391,37 @@ fn test_is_digit() {
392391

393392
#[test]
394393
fn test_escape_default() {
395-
assert_eq!('\n'.escape_default(), ~"\\n");
396-
assert_eq!('\r'.escape_default(), ~"\\r");
397-
assert_eq!('\''.escape_default(), ~"\\'");
398-
assert_eq!('"'.escape_default(), ~"\\\"");
399-
assert_eq!(' '.escape_default(), ~" ");
400-
assert_eq!('a'.escape_default(), ~"a");
401-
assert_eq!('~'.escape_default(), ~"~");
402-
assert_eq!('\x00'.escape_default(), ~"\\x00");
403-
assert_eq!('\x1f'.escape_default(), ~"\\x1f");
404-
assert_eq!('\x7f'.escape_default(), ~"\\x7f");
405-
assert_eq!('\xff'.escape_default(), ~"\\xff");
406-
assert_eq!('\u011b'.escape_default(), ~"\\u011b");
407-
assert_eq!('\U0001d4b6'.escape_default(), ~"\\U0001d4b6");
394+
fn string(c: char) -> ~str {
395+
let mut result = ~"";
396+
do escape_default(c) |c| { result.push_char(c); }
397+
return result;
398+
}
399+
assert_eq!(string('\n'), ~"\\n");
400+
assert_eq!(string('\r'), ~"\\r");
401+
assert_eq!(string('\''), ~"\\'");
402+
assert_eq!(string('"'), ~"\\\"");
403+
assert_eq!(string(' '), ~" ");
404+
assert_eq!(string('a'), ~"a");
405+
assert_eq!(string('~'), ~"~");
406+
assert_eq!(string('\x00'), ~"\\x00");
407+
assert_eq!(string('\x1f'), ~"\\x1f");
408+
assert_eq!(string('\x7f'), ~"\\x7f");
409+
assert_eq!(string('\xff'), ~"\\xff");
410+
assert_eq!(string('\u011b'), ~"\\u011b");
411+
assert_eq!(string('\U0001d4b6'), ~"\\U0001d4b6");
408412
}
409413
410414
#[test]
411415
fn test_escape_unicode() {
412-
assert_eq!('\x00'.escape_unicode(), ~"\\x00");
413-
assert_eq!('\n'.escape_unicode(), ~"\\x0a");
414-
assert_eq!(' '.escape_unicode(), ~"\\x20");
415-
assert_eq!('a'.escape_unicode(), ~"\\x61");
416-
assert_eq!('\u011b'.escape_unicode(), ~"\\u011b");
417-
assert_eq!('\U0001d4b6'.escape_unicode(), ~"\\U0001d4b6");
416+
fn string(c: char) -> ~str {
417+
let mut result = ~"";
418+
do escape_unicode(c) |c| { result.push_char(c); }
419+
return result;
420+
}
421+
assert_eq!(string('\x00'), ~"\\x00");
422+
assert_eq!(string('\n'), ~"\\x0a");
423+
assert_eq!(string(' '), ~"\\x20");
424+
assert_eq!(string('a'), ~"\\x61");
425+
assert_eq!(string('\u011b'), ~"\\u011b");
426+
assert_eq!(string('\U0001d4b6'), ~"\\U0001d4b6");
418427
}

src/libstd/num/f32.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -754,8 +754,8 @@ impl Float for f32 {
754754
///
755755
#[inline]
756756
pub fn to_str(num: f32) -> ~str {
757-
let (r, _) = strconv::to_str_common(
758-
&num, 10u, true, strconv::SignNeg, strconv::DigAll);
757+
let (r, _) = strconv::float_to_str_common(
758+
num, 10u, true, strconv::SignNeg, strconv::DigAll);
759759
r
760760
}
761761

@@ -768,8 +768,8 @@ pub fn to_str(num: f32) -> ~str {
768768
///
769769
#[inline]
770770
pub fn to_str_hex(num: f32) -> ~str {
771-
let (r, _) = strconv::to_str_common(
772-
&num, 16u, true, strconv::SignNeg, strconv::DigAll);
771+
let (r, _) = strconv::float_to_str_common(
772+
num, 16u, true, strconv::SignNeg, strconv::DigAll);
773773
r
774774
}
775775

@@ -789,8 +789,8 @@ pub fn to_str_hex(num: f32) -> ~str {
789789
///
790790
#[inline]
791791
pub fn to_str_radix(num: f32, rdx: uint) -> ~str {
792-
let (r, special) = strconv::to_str_common(
793-
&num, rdx, true, strconv::SignNeg, strconv::DigAll);
792+
let (r, special) = strconv::float_to_str_common(
793+
num, rdx, true, strconv::SignNeg, strconv::DigAll);
794794
if special { fail!("number has a special value, \
795795
try to_str_radix_special() if those are expected") }
796796
r
@@ -807,7 +807,7 @@ pub fn to_str_radix(num: f32, rdx: uint) -> ~str {
807807
///
808808
#[inline]
809809
pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
810-
strconv::to_str_common(&num, rdx, true,
810+
strconv::float_to_str_common(num, rdx, true,
811811
strconv::SignNeg, strconv::DigAll)
812812
}
813813

@@ -822,8 +822,8 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
822822
///
823823
#[inline]
824824
pub fn to_str_exact(num: f32, dig: uint) -> ~str {
825-
let (r, _) = strconv::to_str_common(
826-
&num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
825+
let (r, _) = strconv::float_to_str_common(
826+
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
827827
r
828828
}
829829

@@ -838,8 +838,8 @@ pub fn to_str_exact(num: f32, dig: uint) -> ~str {
838838
///
839839
#[inline]
840840
pub fn to_str_digits(num: f32, dig: uint) -> ~str {
841-
let (r, _) = strconv::to_str_common(
842-
&num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
841+
let (r, _) = strconv::float_to_str_common(
842+
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
843843
r
844844
}
845845

src/libstd/num/f64.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -796,8 +796,8 @@ impl Float for f64 {
796796
///
797797
#[inline]
798798
pub fn to_str(num: f64) -> ~str {
799-
let (r, _) = strconv::to_str_common(
800-
&num, 10u, true, strconv::SignNeg, strconv::DigAll);
799+
let (r, _) = strconv::float_to_str_common(
800+
num, 10u, true, strconv::SignNeg, strconv::DigAll);
801801
r
802802
}
803803

@@ -810,8 +810,8 @@ pub fn to_str(num: f64) -> ~str {
810810
///
811811
#[inline]
812812
pub fn to_str_hex(num: f64) -> ~str {
813-
let (r, _) = strconv::to_str_common(
814-
&num, 16u, true, strconv::SignNeg, strconv::DigAll);
813+
let (r, _) = strconv::float_to_str_common(
814+
num, 16u, true, strconv::SignNeg, strconv::DigAll);
815815
r
816816
}
817817

@@ -831,8 +831,8 @@ pub fn to_str_hex(num: f64) -> ~str {
831831
///
832832
#[inline]
833833
pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
834-
let (r, special) = strconv::to_str_common(
835-
&num, rdx, true, strconv::SignNeg, strconv::DigAll);
834+
let (r, special) = strconv::float_to_str_common(
835+
num, rdx, true, strconv::SignNeg, strconv::DigAll);
836836
if special { fail!("number has a special value, \
837837
try to_str_radix_special() if those are expected") }
838838
r
@@ -849,7 +849,7 @@ pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
849849
///
850850
#[inline]
851851
pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
852-
strconv::to_str_common(&num, rdx, true,
852+
strconv::float_to_str_common(num, rdx, true,
853853
strconv::SignNeg, strconv::DigAll)
854854
}
855855

@@ -864,8 +864,8 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
864864
///
865865
#[inline]
866866
pub fn to_str_exact(num: f64, dig: uint) -> ~str {
867-
let (r, _) = strconv::to_str_common(
868-
&num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
867+
let (r, _) = strconv::float_to_str_common(
868+
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
869869
r
870870
}
871871

@@ -880,8 +880,8 @@ pub fn to_str_exact(num: f64, dig: uint) -> ~str {
880880
///
881881
#[inline]
882882
pub fn to_str_digits(num: f64, dig: uint) -> ~str {
883-
let (r, _) = strconv::to_str_common(
884-
&num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
883+
let (r, _) = strconv::float_to_str_common(
884+
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
885885
r
886886
}
887887

src/libstd/num/float.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ pub mod consts {
101101
///
102102
#[inline]
103103
pub fn to_str(num: float) -> ~str {
104-
let (r, _) = strconv::to_str_common(
105-
&num, 10u, true, strconv::SignNeg, strconv::DigAll);
104+
let (r, _) = strconv::float_to_str_common(
105+
num, 10u, true, strconv::SignNeg, strconv::DigAll);
106106
r
107107
}
108108

@@ -115,8 +115,8 @@ pub fn to_str(num: float) -> ~str {
115115
///
116116
#[inline]
117117
pub fn to_str_hex(num: float) -> ~str {
118-
let (r, _) = strconv::to_str_common(
119-
&num, 16u, true, strconv::SignNeg, strconv::DigAll);
118+
let (r, _) = strconv::float_to_str_common(
119+
num, 16u, true, strconv::SignNeg, strconv::DigAll);
120120
r
121121
}
122122

@@ -136,8 +136,8 @@ pub fn to_str_hex(num: float) -> ~str {
136136
///
137137
#[inline]
138138
pub fn to_str_radix(num: float, radix: uint) -> ~str {
139-
let (r, special) = strconv::to_str_common(
140-
&num, radix, true, strconv::SignNeg, strconv::DigAll);
139+
let (r, special) = strconv::float_to_str_common(
140+
num, radix, true, strconv::SignNeg, strconv::DigAll);
141141
if special { fail!("number has a special value, \
142142
try to_str_radix_special() if those are expected") }
143143
r
@@ -154,7 +154,7 @@ pub fn to_str_radix(num: float, radix: uint) -> ~str {
154154
///
155155
#[inline]
156156
pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) {
157-
strconv::to_str_common(&num, radix, true,
157+
strconv::float_to_str_common(num, radix, true,
158158
strconv::SignNeg, strconv::DigAll)
159159
}
160160

@@ -169,8 +169,8 @@ pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) {
169169
///
170170
#[inline]
171171
pub fn to_str_exact(num: float, digits: uint) -> ~str {
172-
let (r, _) = strconv::to_str_common(
173-
&num, 10u, true, strconv::SignNeg, strconv::DigExact(digits));
172+
let (r, _) = strconv::float_to_str_common(
173+
num, 10u, true, strconv::SignNeg, strconv::DigExact(digits));
174174
r
175175
}
176176

@@ -185,8 +185,8 @@ pub fn to_str_exact(num: float, digits: uint) -> ~str {
185185
///
186186
#[inline]
187187
pub fn to_str_digits(num: float, digits: uint) -> ~str {
188-
let (r, _) = strconv::to_str_common(
189-
&num, 10u, true, strconv::SignNeg, strconv::DigMax(digits));
188+
let (r, _) = strconv::float_to_str_common(
189+
num, 10u, true, strconv::SignNeg, strconv::DigMax(digits));
190190
r
191191
}
192192

0 commit comments

Comments
 (0)