mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-30 20:47:46 +00:00
Fix bug in human_numeric convert
This commit is contained in:
parent
cb0c667da5
commit
094d9a9e47
4 changed files with 33 additions and 36 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -1432,6 +1432,9 @@ name = "smallvec"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
|
|
|
@ -23,7 +23,7 @@ clap = "2.33"
|
||||||
fnv = "1.0.7"
|
fnv = "1.0.7"
|
||||||
itertools = "0.10.0"
|
itertools = "0.10.0"
|
||||||
semver = "0.9.0"
|
semver = "0.9.0"
|
||||||
smallvec = "1.6.1"
|
smallvec = { version="1.6.1", features=["serde"] }
|
||||||
unicode-width = "0.1.8"
|
unicode-width = "0.1.8"
|
||||||
uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["fs"] }
|
uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["fs"] }
|
||||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
|
@ -27,7 +27,7 @@ use rand::distributions::Alphanumeric;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use serde::{Deserializer, Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::BinaryHeap;
|
use std::collections::BinaryHeap;
|
||||||
|
@ -41,6 +41,7 @@ use std::ops::Range;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
use uucore::fs::is_stdin_interactive; // for Iterator::dedup()
|
use uucore::fs::is_stdin_interactive; // for Iterator::dedup()
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
static NAME: &str = "sort";
|
static NAME: &str = "sort";
|
||||||
static ABOUT: &str = "Display sorted concatenation of all FILE(s).";
|
static ABOUT: &str = "Display sorted concatenation of all FILE(s).";
|
||||||
|
@ -133,22 +134,20 @@ impl GlobalSettings {
|
||||||
// It's back to do conversions for command line opts!
|
// It's back to do conversions for command line opts!
|
||||||
// Probably want to do through numstrcmp somehow now?
|
// Probably want to do through numstrcmp somehow now?
|
||||||
fn human_numeric_convert(a: &str) -> usize {
|
fn human_numeric_convert(a: &str) -> usize {
|
||||||
let num_part = leading_num_common(a);
|
let num_str = &a[get_leading_gen(a)];
|
||||||
let (_, s) = a.split_at(num_part.len());
|
let (_, suf_str) = a.split_at(num_str.len());
|
||||||
let num_part = permissive_f64_parse(num_part);
|
let num_usize = num_str.parse::<usize>().expect("Error parsing buffer size: ");
|
||||||
let suffix = match s.parse().unwrap_or('\0') {
|
let suf_usize: usize = match suf_str.to_uppercase().as_str() {
|
||||||
// SI Units
|
// SI Units
|
||||||
'K' | 'k' => 1E3,
|
"K" => 1000usize,
|
||||||
'M' => 1E6,
|
"M" => 1000000usize,
|
||||||
'G' => 1E9,
|
"G" => 1000000000usize,
|
||||||
'T' => 1E12,
|
"T" => 1000000000000usize,
|
||||||
'P' => 1E15,
|
"P" => 1000000000000000usize,
|
||||||
'E' => 1E18,
|
"E" => 1000000000000000000usize,
|
||||||
'Z' => 1E21,
|
_ => 1usize,
|
||||||
'Y' => 1E24,
|
|
||||||
_ => 1f64,
|
|
||||||
};
|
};
|
||||||
num_part as usize * suffix as usize
|
num_usize * suf_usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,22 +235,13 @@ impl SelectionRange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
enum NumCache {
|
enum NumCache {
|
||||||
#[serde(deserialize_with="bailout_parse_f64")]
|
|
||||||
AsF64(GeneralF64ParseResult),
|
AsF64(GeneralF64ParseResult),
|
||||||
WithInfo(NumInfo),
|
WithInfo(NumInfo),
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only used when serde can't parse a null value
|
|
||||||
fn bailout_parse_f64<'de, D>(d: D) -> Result<f64, D::Error> where D: Deserializer<'de> {
|
|
||||||
Deserialize::deserialize(d)
|
|
||||||
.map(|x: Option<_>| {
|
|
||||||
x.unwrap_or(0f64)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NumCache {
|
impl NumCache {
|
||||||
fn as_f64(&self) -> GeneralF64ParseResult {
|
fn as_f64(&self) -> GeneralF64ParseResult {
|
||||||
match self {
|
match self {
|
||||||
|
@ -266,7 +256,7 @@ impl NumCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
struct Selection {
|
struct Selection {
|
||||||
range: SelectionRange,
|
range: SelectionRange,
|
||||||
num_cache: NumCache,
|
num_cache: NumCache,
|
||||||
|
@ -1218,7 +1208,7 @@ fn exec(files: Vec<String>, settings: GlobalSettings) -> i32 {
|
||||||
if settings.merge {
|
if settings.merge {
|
||||||
if settings.unique {
|
if settings.unique {
|
||||||
print_sorted(
|
print_sorted(
|
||||||
file_merger.dedup_by(|a, b| compare_by(a, b, settings) == Ordering::Equal),
|
file_merger.dedup_by(|a, b| compare_by(a, b, &settings) == Ordering::Equal),
|
||||||
&settings,
|
&settings,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1228,7 +1218,7 @@ fn exec(files: Vec<String>, settings: GlobalSettings) -> i32 {
|
||||||
print_sorted(
|
print_sorted(
|
||||||
lines
|
lines
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.dedup_by(|a, b| compare_by(a, b, settings) == Ordering::Equal),
|
.dedup_by(|a, b| compare_by(a, b, &settings) == Ordering::Equal),
|
||||||
&settings,
|
&settings,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1303,11 +1293,15 @@ fn compare_by(a: &Line, b: &Line, global_settings: &GlobalSettings) -> Ordering
|
||||||
// serde JSON has issues with f64 null values, so caching them won't work for us with ext sort
|
// serde JSON has issues with f64 null values, so caching them won't work for us with ext sort
|
||||||
SortMode::GeneralNumeric =>
|
SortMode::GeneralNumeric =>
|
||||||
if global_settings.buffer_size == DEFAULT_BUF_SIZE {
|
if global_settings.buffer_size == DEFAULT_BUF_SIZE {
|
||||||
general_numeric_compare(a_selection.num_cache.as_f64(),
|
general_numeric_compare(
|
||||||
b_selection.num_cache.as_f64())
|
a_selection.num_cache.as_f64(),
|
||||||
|
b_selection.num_cache.as_f64()
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
general_numeric_compare(permissive_f64_parse(get_leading_gen(a_str)),
|
general_numeric_compare(
|
||||||
permissive_f64_parse(get_leading_gen(b_str)))
|
general_f64_parse(&a_str[get_leading_gen(a_str)]),
|
||||||
|
general_f64_parse(&b_str[get_leading_gen(b_str)])
|
||||||
|
)
|
||||||
},
|
},
|
||||||
SortMode::Month => month_compare(a_str, b_str),
|
SortMode::Month => month_compare(a_str, b_str),
|
||||||
SortMode::Version => version_compare(a_str, b_str),
|
SortMode::Version => version_compare(a_str, b_str),
|
||||||
|
@ -1385,7 +1379,7 @@ fn get_leading_gen(input: &str) -> Range<usize> {
|
||||||
leading_whitespace_len..input.len()
|
leading_whitespace_len..input.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, PartialOrd)]
|
#[derive(Serialize, Deserialize, Copy, Clone, PartialEq, PartialOrd)]
|
||||||
enum GeneralF64ParseResult {
|
enum GeneralF64ParseResult {
|
||||||
Invalid,
|
Invalid,
|
||||||
NaN,
|
NaN,
|
||||||
|
|
|
@ -33,7 +33,7 @@ fn test_helper(file_name: &str, args: &str) {
|
||||||
fn test_larger_than_specified_segment() {
|
fn test_larger_than_specified_segment() {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
.arg("-n")
|
.arg("-n")
|
||||||
.arg("-S 50K")
|
.arg("-S 50M")
|
||||||
.arg("ext_sort.txt")
|
.arg("ext_sort.txt")
|
||||||
.succeeds()
|
.succeeds()
|
||||||
.stdout_is_fixture(format!("{}", "ext_sort.expected"));
|
.stdout_is_fixture(format!("{}", "ext_sort.expected"));
|
||||||
|
@ -67,7 +67,7 @@ fn test_extsort_as64_bailout() {
|
||||||
.arg("-S 10K")
|
.arg("-S 10K")
|
||||||
.arg("multiple_decimals_general.txt")
|
.arg("multiple_decimals_general.txt")
|
||||||
.succeeds()
|
.succeeds()
|
||||||
.stdout_is("\n\n\n\n\n\n\n\nCARAvan\n-2028789030\n-896689\n-8.90880\n-1\n-.05\n000\n00000001\n1\n1.040000000\n1.444\n1.58590\n8.013\n45\n46.89\n576,446.88800000\n576,446.890\n 4567.\n4567.1\n4567.34\n\t\t\t\t\t\t\t\t\t\t4567..457\n\t\t\t\t37800\n\t\t\t\t\t\t45670.89079.098\n\t\t\t\t\t\t45670.89079.1\n4798908.340000000000\n4798908.45\n4798908.8909800\n");
|
.stdout_is_fixture("multiple_decimals_general.expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue