Skip to content

Commit 3fdd942

Browse files
committed
numfmt: replace double-reverse with forward pass in apply_grouping
Build the grouped string in a single forward pass using chunk iteration instead of reversing, inserting separators, then reversing again. This avoids an extra String allocation and collection.
1 parent 1873f00 commit 3fdd942

1 file changed

Lines changed: 17 additions & 11 deletions

File tree

src/uu/numfmt/src/format.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -206,20 +206,26 @@ fn apply_grouping(s: &str) -> String {
206206
return s.to_string();
207207
}
208208

209-
let mut grouped_rev = String::with_capacity(s.len() + (integer.len() / 3));
210-
for (idx, ch) in integer.chars().rev().enumerate() {
211-
if idx > 0 && idx % 3 == 0 {
212-
grouped_rev.push_str(grouping_separator);
213-
}
214-
grouped_rev.push(ch);
209+
let sep_len = grouping_separator.len();
210+
let num_seps = (integer.len() - 1) / 3;
211+
let mut grouped = String::with_capacity(sign.len() + integer.len() + num_seps * sep_len + if fraction.is_empty() { 0 } else { 1 + fraction.len() });
212+
grouped.push_str(sign);
213+
214+
let first_group = integer.len() % 3;
215+
let first_group = if first_group == 0 { 3 } else { first_group };
216+
grouped.push_str(&integer[..first_group]);
217+
for chunk in integer[first_group..].as_bytes().chunks(3) {
218+
grouped.push_str(grouping_separator);
219+
// SAFETY: integer is known to be valid UTF-8 ASCII digits
220+
grouped.push_str(std::str::from_utf8(chunk).unwrap());
215221
}
216-
let grouped_integer: String = grouped_rev.chars().rev().collect();
217222

218-
if fraction.is_empty() {
219-
format!("{sign}{grouped_integer}")
220-
} else {
221-
format!("{sign}{grouped_integer}.{fraction}")
223+
if !fraction.is_empty() {
224+
grouped.push('.');
225+
grouped.push_str(fraction);
222226
}
227+
228+
grouped
223229
}
224230

225231
fn next_field_index(s: &str) -> usize {

0 commit comments

Comments
 (0)