mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2026-01-19 03:31:06 +00:00
printf: rustfmt pass
This commit is contained in:
parent
9242ba1db6
commit
5f88dfe12b
18 changed files with 1266 additions and 1345 deletions
|
|
@ -11,23 +11,22 @@ pub enum FieldType {
|
|||
Charf,
|
||||
}
|
||||
|
||||
/*
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum FChar {
|
||||
d,
|
||||
e,
|
||||
E,
|
||||
i,
|
||||
f,
|
||||
F,
|
||||
g,
|
||||
G,
|
||||
u,
|
||||
x,
|
||||
X,
|
||||
o
|
||||
}
|
||||
*/
|
||||
// #[allow(non_camel_case_types)]
|
||||
// pub enum FChar {
|
||||
// d,
|
||||
// e,
|
||||
// E,
|
||||
// i,
|
||||
// f,
|
||||
// F,
|
||||
// g,
|
||||
// G,
|
||||
// u,
|
||||
// x,
|
||||
// X,
|
||||
// o
|
||||
// }
|
||||
//
|
||||
|
||||
// a Sub Tokens' fields are stored
|
||||
// as a single object so they can be more simply
|
||||
|
|
@ -36,8 +35,7 @@ pub enum FChar {
|
|||
pub struct FormatField<'a> {
|
||||
pub min_width: Option<isize>,
|
||||
pub second_field: Option<u32>,
|
||||
pub field_char: & 'a char,
|
||||
pub field_type: & 'a FieldType,
|
||||
pub orig : & 'a String
|
||||
pub field_char: &'a char,
|
||||
pub field_type: &'a FieldType,
|
||||
pub orig: &'a String,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ pub struct FormatPrimitive {
|
|||
pub prefix: Option<String>,
|
||||
pub pre_decimal: Option<String>,
|
||||
pub post_decimal: Option<String>,
|
||||
pub suffix: Option<String>
|
||||
pub suffix: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for FormatPrimitive {
|
||||
|
|
@ -22,52 +22,46 @@ impl Default for FormatPrimitive {
|
|||
prefix: None,
|
||||
pre_decimal: None,
|
||||
post_decimal: None,
|
||||
suffix: None
|
||||
}
|
||||
suffix: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(PartialEq)]
|
||||
pub enum Base {
|
||||
Ten=10,
|
||||
Hex=16,
|
||||
Octal=8,
|
||||
Ten = 10,
|
||||
Hex = 16,
|
||||
Octal = 8,
|
||||
}
|
||||
|
||||
// information from the beginning of a numeric argument
|
||||
// the precedes the beginning of a numeric value
|
||||
pub struct InPrefix {
|
||||
pub radix_in : Base,
|
||||
pub sign : i8,
|
||||
pub offset : usize
|
||||
pub radix_in: Base,
|
||||
pub sign: i8,
|
||||
pub offset: usize,
|
||||
}
|
||||
|
||||
pub trait Formatter {
|
||||
// return a FormatPrimitive for
|
||||
// return a FormatPrimitive for
|
||||
// particular field char(s), given the argument
|
||||
// string and prefix information (sign, radix)
|
||||
fn get_primitive(
|
||||
&self,
|
||||
field: &FormatField,
|
||||
inprefix: &InPrefix,
|
||||
str_in: &str
|
||||
) -> Option<FormatPrimitive>;
|
||||
fn get_primitive(&self,
|
||||
field: &FormatField,
|
||||
inprefix: &InPrefix,
|
||||
str_in: &str)
|
||||
-> Option<FormatPrimitive>;
|
||||
// return a string from a formatprimitive,
|
||||
// given information about the field
|
||||
fn primitive_to_str(
|
||||
&self,
|
||||
prim: &FormatPrimitive,
|
||||
field: FormatField) -> String;
|
||||
fn primitive_to_str(&self, prim: &FormatPrimitive, field: FormatField) -> String;
|
||||
}
|
||||
pub fn get_it_at(offset: usize,
|
||||
str_in: &str) -> PutBackN<Chars> {
|
||||
pub fn get_it_at(offset: usize, str_in: &str) -> PutBackN<Chars> {
|
||||
PutBackN::new(str_in[offset..].chars())
|
||||
}
|
||||
|
||||
// TODO: put this somewhere better
|
||||
pub fn warn_incomplete_conv(pf_arg: &str) {
|
||||
//important: keep println here not print
|
||||
cli::err_msg(&format!("{}: value not completely converted",
|
||||
pf_arg))
|
||||
// important: keep println here not print
|
||||
cli::err_msg(&format!("{}: value not completely converted", pf_arg))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,21 @@
|
|||
pub fn arrnum_int_mult(
|
||||
arr_num : &Vec<u8>,
|
||||
basenum : u8,
|
||||
base_ten_int_fact : u8
|
||||
) -> Vec<u8> {
|
||||
let mut carry : u16 = 0;
|
||||
let mut rem : u16;
|
||||
let mut new_amount : u16;
|
||||
let fact : u16 = base_ten_int_fact as u16;
|
||||
let base : u16 = basenum as u16;
|
||||
|
||||
let mut ret_rev : Vec<u8> = Vec::new();
|
||||
pub fn arrnum_int_mult(arr_num: &Vec<u8>, basenum: u8, base_ten_int_fact: u8) -> Vec<u8> {
|
||||
let mut carry: u16 = 0;
|
||||
let mut rem: u16;
|
||||
let mut new_amount: u16;
|
||||
let fact: u16 = base_ten_int_fact as u16;
|
||||
let base: u16 = basenum as u16;
|
||||
|
||||
let mut ret_rev: Vec<u8> = Vec::new();
|
||||
let mut it = arr_num.iter().rev();
|
||||
loop {
|
||||
let i = it.next();
|
||||
match i {
|
||||
Some(u) => {
|
||||
new_amount = ((u.clone() as u16)*fact) + carry;
|
||||
new_amount = ((u.clone() as u16) * fact) + carry;
|
||||
rem = new_amount % base;
|
||||
carry = (new_amount - rem) / base;
|
||||
ret_rev.push(rem as u8)
|
||||
},
|
||||
}
|
||||
None => {
|
||||
while carry != 0 {
|
||||
rem = carry % base;
|
||||
|
|
@ -30,33 +26,31 @@ pub fn arrnum_int_mult(
|
|||
}
|
||||
}
|
||||
}
|
||||
let ret : Vec<u8> =
|
||||
ret_rev.iter().rev().map(|x| x.clone()).collect();
|
||||
let ret: Vec<u8> = ret_rev.iter().rev().map(|x| x.clone()).collect();
|
||||
ret
|
||||
}
|
||||
|
||||
pub struct Remainder<'a> {
|
||||
pub struct Remainder<'a> {
|
||||
pub position: usize,
|
||||
pub replace: Vec<u8>,
|
||||
pub arr_num: &'a Vec<u8>
|
||||
pub arr_num: &'a Vec<u8>,
|
||||
}
|
||||
|
||||
pub struct DivOut<'a> {
|
||||
pub quotient: u8,
|
||||
pub remainder: Remainder<'a>
|
||||
pub remainder: Remainder<'a>,
|
||||
}
|
||||
|
||||
pub fn arrnum_int_div_step<'a>(
|
||||
rem_in: Remainder<'a>,
|
||||
radix_in: u8,
|
||||
base_ten_int_divisor: u8,
|
||||
after_decimal: bool
|
||||
) -> DivOut<'a> {
|
||||
pub fn arrnum_int_div_step<'a>(rem_in: Remainder<'a>,
|
||||
radix_in: u8,
|
||||
base_ten_int_divisor: u8,
|
||||
after_decimal: bool)
|
||||
-> DivOut<'a> {
|
||||
|
||||
let mut rem_out = Remainder {
|
||||
position: rem_in.position,
|
||||
replace: Vec::new(),
|
||||
arr_num: rem_in.arr_num
|
||||
arr_num: rem_in.arr_num,
|
||||
};
|
||||
|
||||
let mut bufferval: u16 = 0;
|
||||
|
|
@ -65,17 +59,15 @@ pub fn arrnum_int_div_step<'a>(
|
|||
let mut traversed = 0;
|
||||
|
||||
let mut quotient = 0;
|
||||
let refd_vals = &rem_in.arr_num[rem_in.position+rem_in.replace.len()..];
|
||||
let refd_vals = &rem_in.arr_num[rem_in.position + rem_in.replace.len()..];
|
||||
let mut it_replace = rem_in.replace.iter();
|
||||
let mut it_f = refd_vals.iter();
|
||||
loop {
|
||||
let u = match it_replace.next() {
|
||||
Some(u_rep) => { u_rep.clone() as u16 }
|
||||
Some(u_rep) => u_rep.clone() as u16,
|
||||
None => {
|
||||
match it_f.next() {
|
||||
Some(u_orig) => {
|
||||
u_orig.clone() as u16
|
||||
}
|
||||
Some(u_orig) => u_orig.clone() as u16,
|
||||
None => {
|
||||
if !after_decimal {
|
||||
break;
|
||||
|
|
@ -89,104 +81,98 @@ pub fn arrnum_int_div_step<'a>(
|
|||
bufferval += u;
|
||||
if bufferval > divisor {
|
||||
while bufferval >= divisor {
|
||||
quotient+=1;
|
||||
quotient += 1;
|
||||
bufferval -= divisor;
|
||||
}
|
||||
rem_out.replace = if bufferval == 0 {
|
||||
Vec::new()
|
||||
} else {
|
||||
let remainder_as_arrnum = unsigned_to_arrnum(bufferval);
|
||||
let remainder_as_base_arrnum = base_conv_vec(
|
||||
&remainder_as_arrnum,
|
||||
10,
|
||||
radix_in
|
||||
);
|
||||
let remainder_as_base_arrnum = base_conv_vec(&remainder_as_arrnum, 10, radix_in);
|
||||
remainder_as_base_arrnum
|
||||
};
|
||||
rem_out.position += 1+(traversed - rem_out.replace.len());
|
||||
rem_out.position += 1 + (traversed - rem_out.replace.len());
|
||||
break;
|
||||
} else {
|
||||
bufferval *= base;
|
||||
bufferval *= base;
|
||||
}
|
||||
}
|
||||
DivOut { quotient: quotient, remainder: rem_out }
|
||||
}
|
||||
/*
|
||||
pub struct ArrFloat {
|
||||
pub leading_zeros: u8,
|
||||
pub values: Vec<u8>,
|
||||
pub basenum: u8
|
||||
}
|
||||
|
||||
pub struct ArrFloatDivOut {
|
||||
pub quotient: u8,
|
||||
pub remainder: ArrFloat
|
||||
}
|
||||
|
||||
pub fn arrfloat_int_div(
|
||||
arrfloat_in : &ArrFloat,
|
||||
base_ten_int_divisor : u8,
|
||||
precision : u16
|
||||
) -> DivOut {
|
||||
|
||||
let mut remainder = ArrFloat {
|
||||
basenum: arrfloat_in.basenum,
|
||||
leading_zeros: arrfloat_in.leading_zeroes,
|
||||
values: Vec<u8>::new()
|
||||
DivOut {
|
||||
quotient: quotient,
|
||||
remainder: rem_out,
|
||||
}
|
||||
let mut quotient = 0;
|
||||
|
||||
let mut bufferval : u16 = 0;
|
||||
let base : u16 = arrfloat_in.basenum as u16;
|
||||
let divisor : u16 = base_ten_int_divisor as u16;
|
||||
|
||||
let mut it_f = arrfloat_in.values.iter();
|
||||
let mut position = 0 + arrfloat_in.leading_zeroes as u16;
|
||||
let mut at_end = false;
|
||||
while position< precision {
|
||||
let next_digit = match it_f.next() {
|
||||
Some(c) => {}
|
||||
None => { 0 }
|
||||
}
|
||||
match u_cur {
|
||||
Some(u) => {
|
||||
bufferval += u.clone() as u16;
|
||||
if bufferval > divisor {
|
||||
while bufferval >= divisor {
|
||||
quotient+=1;
|
||||
bufferval -= divisor;
|
||||
}
|
||||
if bufferval == 0 {
|
||||
rem_out.position +=1;
|
||||
} else {
|
||||
rem_out.replace = Some(bufferval as u8);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
bufferval *= base;
|
||||
}
|
||||
},
|
||||
None => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
u_cur = it_f.next().clone();
|
||||
rem_out.position+=1;
|
||||
}
|
||||
ArrFloatDivOut { quotient: quotient, remainder: remainder }
|
||||
}
|
||||
*/
|
||||
pub fn arrnum_int_add(
|
||||
arrnum : &Vec<u8>,
|
||||
basenum : u8,
|
||||
base_ten_int_term : u8
|
||||
) -> Vec<u8> {
|
||||
let mut carry : u16 = base_ten_int_term as u16;
|
||||
let mut rem : u16;
|
||||
let mut new_amount : u16;
|
||||
let base : u16 = basenum as u16;
|
||||
|
||||
let mut ret_rev : Vec<u8> = Vec::new();
|
||||
// pub struct ArrFloat {
|
||||
// pub leading_zeros: u8,
|
||||
// pub values: Vec<u8>,
|
||||
// pub basenum: u8
|
||||
// }
|
||||
//
|
||||
// pub struct ArrFloatDivOut {
|
||||
// pub quotient: u8,
|
||||
// pub remainder: ArrFloat
|
||||
// }
|
||||
//
|
||||
// pub fn arrfloat_int_div(
|
||||
// arrfloat_in : &ArrFloat,
|
||||
// base_ten_int_divisor : u8,
|
||||
// precision : u16
|
||||
// ) -> DivOut {
|
||||
//
|
||||
// let mut remainder = ArrFloat {
|
||||
// basenum: arrfloat_in.basenum,
|
||||
// leading_zeros: arrfloat_in.leading_zeroes,
|
||||
// values: Vec<u8>::new()
|
||||
// }
|
||||
// let mut quotient = 0;
|
||||
//
|
||||
// let mut bufferval : u16 = 0;
|
||||
// let base : u16 = arrfloat_in.basenum as u16;
|
||||
// let divisor : u16 = base_ten_int_divisor as u16;
|
||||
//
|
||||
// let mut it_f = arrfloat_in.values.iter();
|
||||
// let mut position = 0 + arrfloat_in.leading_zeroes as u16;
|
||||
// let mut at_end = false;
|
||||
// while position< precision {
|
||||
// let next_digit = match it_f.next() {
|
||||
// Some(c) => {}
|
||||
// None => { 0 }
|
||||
// }
|
||||
// match u_cur {
|
||||
// Some(u) => {
|
||||
// bufferval += u.clone() as u16;
|
||||
// if bufferval > divisor {
|
||||
// while bufferval >= divisor {
|
||||
// quotient+=1;
|
||||
// bufferval -= divisor;
|
||||
// }
|
||||
// if bufferval == 0 {
|
||||
// rem_out.position +=1;
|
||||
// } else {
|
||||
// rem_out.replace = Some(bufferval as u8);
|
||||
// }
|
||||
// break;
|
||||
// } else {
|
||||
// bufferval *= base;
|
||||
// }
|
||||
// },
|
||||
// None => {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// u_cur = it_f.next().clone();
|
||||
// rem_out.position+=1;
|
||||
// }
|
||||
// ArrFloatDivOut { quotient: quotient, remainder: remainder }
|
||||
// }
|
||||
//
|
||||
pub fn arrnum_int_add(arrnum: &Vec<u8>, basenum: u8, base_ten_int_term: u8) -> Vec<u8> {
|
||||
let mut carry: u16 = base_ten_int_term as u16;
|
||||
let mut rem: u16;
|
||||
let mut new_amount: u16;
|
||||
let base: u16 = basenum as u16;
|
||||
|
||||
let mut ret_rev: Vec<u8> = Vec::new();
|
||||
let mut it = arrnum.iter().rev();
|
||||
loop {
|
||||
let i = it.next();
|
||||
|
|
@ -196,7 +182,7 @@ pub fn arrnum_int_add(
|
|||
rem = new_amount % base;
|
||||
carry = (new_amount - rem) / base;
|
||||
ret_rev.push(rem as u8)
|
||||
},
|
||||
}
|
||||
None => {
|
||||
while carry != 0 {
|
||||
rem = carry % base;
|
||||
|
|
@ -207,35 +193,23 @@ pub fn arrnum_int_add(
|
|||
}
|
||||
}
|
||||
}
|
||||
let ret : Vec<u8> =
|
||||
ret_rev.iter().rev().map(|x| x.clone()).collect();
|
||||
let ret: Vec<u8> = ret_rev.iter().rev().map(|x| x.clone()).collect();
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn base_conv_vec(
|
||||
src : &Vec<u8>,
|
||||
radix_src : u8,
|
||||
radix_dest : u8
|
||||
) -> Vec<u8> {
|
||||
let mut result : Vec<u8> = Vec::new();
|
||||
pub fn base_conv_vec(src: &Vec<u8>, radix_src: u8, radix_dest: u8) -> Vec<u8> {
|
||||
let mut result: Vec<u8> = Vec::new();
|
||||
result.push(0);
|
||||
for i in src {
|
||||
result = arrnum_int_mult(&result,
|
||||
radix_dest, radix_src);
|
||||
result = arrnum_int_add(
|
||||
&result,
|
||||
radix_dest,
|
||||
i.clone()
|
||||
);
|
||||
result = arrnum_int_mult(&result, radix_dest, radix_src);
|
||||
result = arrnum_int_add(&result, radix_dest, i.clone());
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn unsigned_to_arrnum(
|
||||
src : u16
|
||||
) -> Vec<u8> {
|
||||
let mut result : Vec<u8> = Vec::new();
|
||||
let mut src_tmp : u16 = src.clone();
|
||||
pub fn unsigned_to_arrnum(src: u16) -> Vec<u8> {
|
||||
let mut result: Vec<u8> = Vec::new();
|
||||
let mut src_tmp: u16 = src.clone();
|
||||
while src_tmp > 0 {
|
||||
result.push((src_tmp % 10) as u8);
|
||||
src_tmp /= 10;
|
||||
|
|
@ -245,50 +219,44 @@ pub fn unsigned_to_arrnum(
|
|||
}
|
||||
|
||||
|
||||
//temporary needs-improvement-function
|
||||
// temporary needs-improvement-function
|
||||
#[allow(unused_variables)]
|
||||
pub fn base_conv_float(
|
||||
src : &Vec<u8>,
|
||||
radix_src : u8,
|
||||
radix_dest : u8
|
||||
) -> f64 {
|
||||
//it would require a lot of addl code
|
||||
pub fn base_conv_float(src: &Vec<u8>, radix_src: u8, radix_dest: u8) -> f64 {
|
||||
// it would require a lot of addl code
|
||||
// to implement this for arbitrary string input.
|
||||
//until then, the below operates as an outline
|
||||
// until then, the below operates as an outline
|
||||
// of how it would work.
|
||||
let mut result : Vec<u8> = Vec::new();
|
||||
let mut result: Vec<u8> = Vec::new();
|
||||
result.push(0);
|
||||
let mut factor : f64 = 1.;
|
||||
let radix_src_float : f64 = radix_src as f64;
|
||||
let mut factor: f64 = 1.;
|
||||
let radix_src_float: f64 = radix_src as f64;
|
||||
let mut i = 0;
|
||||
let mut r :f64 = 0 as f64;
|
||||
let mut r: f64 = 0 as f64;
|
||||
for u in src {
|
||||
if i > 15 { break; }
|
||||
i+=1;
|
||||
if i > 15 {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
factor /= radix_src_float;
|
||||
r += factor * (u.clone() as f64)
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
pub fn str_to_arrnum(
|
||||
src: &str,
|
||||
radix_def_src : &RadixDef
|
||||
) -> Vec<u8> {
|
||||
let mut intermed_in : Vec<u8> = Vec::new();
|
||||
pub fn str_to_arrnum(src: &str, radix_def_src: &RadixDef) -> Vec<u8> {
|
||||
let mut intermed_in: Vec<u8> = Vec::new();
|
||||
for c in src.chars() {
|
||||
match radix_def_src.from_char::<>(c) {
|
||||
Some(u) => { intermed_in.push(u); }
|
||||
match radix_def_src.from_char(c) {
|
||||
Some(u) => {
|
||||
intermed_in.push(u);
|
||||
}
|
||||
None => {} //todo err msg on incorrect
|
||||
}
|
||||
}
|
||||
intermed_in
|
||||
}
|
||||
|
||||
pub fn arrnum_to_str(
|
||||
src: &Vec<u8>,
|
||||
radix_def_dest : &RadixDef
|
||||
) -> String {
|
||||
pub fn arrnum_to_str(src: &Vec<u8>, radix_def_dest: &RadixDef) -> String {
|
||||
let mut str_out = String::new();
|
||||
for u in src.iter() {
|
||||
match radix_def_dest.from_u8(u.clone()) {
|
||||
|
|
@ -302,64 +270,61 @@ pub fn arrnum_to_str(
|
|||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn base_conv_str(
|
||||
src: &str,
|
||||
radix_def_src : &RadixDef,
|
||||
radix_def_dest : &RadixDef
|
||||
) -> String {
|
||||
let intermed_in : Vec<u8> =
|
||||
str_to_arrnum(src, radix_def_src);
|
||||
let intermed_out = base_conv_vec(
|
||||
&intermed_in,
|
||||
radix_def_src.get_max(),
|
||||
radix_def_dest.get_max(),
|
||||
);
|
||||
pub fn base_conv_str(src: &str, radix_def_src: &RadixDef, radix_def_dest: &RadixDef) -> String {
|
||||
let intermed_in: Vec<u8> = str_to_arrnum(src, radix_def_src);
|
||||
let intermed_out = base_conv_vec(&intermed_in,
|
||||
radix_def_src.get_max(),
|
||||
radix_def_dest.get_max());
|
||||
arrnum_to_str(&intermed_out, radix_def_dest)
|
||||
}
|
||||
|
||||
pub trait RadixDef {
|
||||
fn get_max (&self) -> u8;
|
||||
fn from_char (&self, x:char) -> Option<u8>;
|
||||
fn from_u8 (&self, x:u8) -> Option<char>;
|
||||
fn get_max(&self) -> u8;
|
||||
fn from_char(&self, x: char) -> Option<u8>;
|
||||
fn from_u8(&self, x: u8) -> Option<char>;
|
||||
}
|
||||
pub struct RadixTen;
|
||||
|
||||
const ZERO_ASC : u8 = '0' as u8;
|
||||
const UPPER_A_ASC : u8 = 'A' as u8;
|
||||
const LOWER_A_ASC : u8 = 'a' as u8;
|
||||
const ZERO_ASC: u8 = '0' as u8;
|
||||
const UPPER_A_ASC: u8 = 'A' as u8;
|
||||
const LOWER_A_ASC: u8 = 'a' as u8;
|
||||
|
||||
impl RadixDef for RadixTen {
|
||||
fn get_max(&self) -> u8 { 10 }
|
||||
fn from_char (&self, c:char) -> Option<u8> {
|
||||
fn get_max(&self) -> u8 {
|
||||
10
|
||||
}
|
||||
fn from_char(&self, c: char) -> Option<u8> {
|
||||
match c {
|
||||
'0'...'9' => Some(c as u8 - ZERO_ASC),
|
||||
_ => None
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn from_u8 (&self, u:u8) -> Option<char> {
|
||||
fn from_u8(&self, u: u8) -> Option<char> {
|
||||
match u {
|
||||
0...9 => Some((ZERO_ASC + u) as char),
|
||||
_ => None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct RadixHex;
|
||||
impl RadixDef for RadixHex {
|
||||
fn get_max(&self) -> u8 { 16 }
|
||||
fn from_char (&self, c:char) -> Option<u8> {
|
||||
fn get_max(&self) -> u8 {
|
||||
16
|
||||
}
|
||||
fn from_char(&self, c: char) -> Option<u8> {
|
||||
match c {
|
||||
'0'...'9' => Some(c as u8 - ZERO_ASC),
|
||||
'A'...'F' => Some(c as u8 +10 - UPPER_A_ASC),
|
||||
'a'...'f' => Some(c as u8 +10 - LOWER_A_ASC),
|
||||
_ => None
|
||||
'A'...'F' => Some(c as u8 + 10 - UPPER_A_ASC),
|
||||
'a'...'f' => Some(c as u8 + 10 - LOWER_A_ASC),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn from_u8 (&self, u:u8) -> Option<char> {
|
||||
fn from_u8(&self, u: u8) -> Option<char> {
|
||||
match u {
|
||||
0...9 => Some((ZERO_ASC + u) as char),
|
||||
10...15 => Some((UPPER_A_ASC + (u-10)) as char),
|
||||
_ => None
|
||||
}
|
||||
10...15 => Some((UPPER_A_ASC + (u - 10)) as char),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,61 +4,52 @@ use super::*;
|
|||
|
||||
#[test]
|
||||
fn test_arrnum_int_mult() {
|
||||
//(in base 10) 12 * 4 = 48
|
||||
let factor : Vec<u8> = vec!(1, 2);
|
||||
// (in base 10) 12 * 4 = 48
|
||||
let factor: Vec<u8> = vec![1, 2];
|
||||
let base_num = 10;
|
||||
let base_ten_int_fact : u8 = 4;
|
||||
let should_output : Vec<u8> = vec![4, 8];
|
||||
|
||||
let product = arrnum_int_mult(&factor,
|
||||
base_num, base_ten_int_fact);
|
||||
let base_ten_int_fact: u8 = 4;
|
||||
let should_output: Vec<u8> = vec![4, 8];
|
||||
|
||||
let product = arrnum_int_mult(&factor, base_num, base_ten_int_fact);
|
||||
assert!(product == should_output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arrnum_int_non_base_10() {
|
||||
//(in base 3)
|
||||
// (in base 3)
|
||||
// 5 * 4 = 20
|
||||
let factor : Vec<u8> = vec![1, 2];
|
||||
let factor: Vec<u8> = vec![1, 2];
|
||||
let base_num = 3;
|
||||
let base_ten_int_fact : u8 = 4;
|
||||
let should_output : Vec<u8> = vec![2,0,2];
|
||||
|
||||
let product = arrnum_int_mult(&factor,
|
||||
base_num, base_ten_int_fact);
|
||||
let base_ten_int_fact: u8 = 4;
|
||||
let should_output: Vec<u8> = vec![2, 0, 2];
|
||||
|
||||
let product = arrnum_int_mult(&factor, base_num, base_ten_int_fact);
|
||||
assert!(product == should_output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arrnum_int_div_shortcircuit() {
|
||||
//(
|
||||
let arrnum : Vec<u8> = vec![5,5,5,5,0];
|
||||
// (
|
||||
let arrnum: Vec<u8> = vec![5, 5, 5, 5, 0];
|
||||
let base_num = 10;
|
||||
let base_ten_int_divisor : u8 = 41;
|
||||
let base_ten_int_divisor: u8 = 41;
|
||||
let remainder_passed_in = Remainder {
|
||||
position : 1,
|
||||
replace : vec![1,3],
|
||||
arr_num : &arrnum
|
||||
position: 1,
|
||||
replace: vec![1, 3],
|
||||
arr_num: &arrnum,
|
||||
};
|
||||
|
||||
//the "replace" should mean the number being divided
|
||||
// the "replace" should mean the number being divided
|
||||
// is 1350, the first time you can get 41 to go into
|
||||
// 1350, its at 135, where you can get a quotient of
|
||||
// 3 and a remainder of 12;
|
||||
|
||||
let quotient_should_be : u8 = 3;
|
||||
let remainder_position_should_be : usize = 3;
|
||||
let quotient_should_be: u8 = 3;
|
||||
let remainder_position_should_be: usize = 3;
|
||||
let remainder_replace_should_be = vec![1, 2];
|
||||
|
||||
let result = arrnum_int_div_step(remainder_passed_in,
|
||||
base_num,
|
||||
base_ten_int_divisor,
|
||||
false
|
||||
|
||||
);
|
||||
|
||||
let result = arrnum_int_div_step(remainder_passed_in, base_num, base_ten_int_divisor, false);
|
||||
assert!(quotient_should_be == result.quotient);
|
||||
assert!(remainder_position_should_be ==
|
||||
result.remainder.position);
|
||||
assert!(remainder_replace_should_be ==
|
||||
result.remainder.replace);
|
||||
}
|
||||
assert!(remainder_position_should_be == result.remainder.position);
|
||||
assert!(remainder_replace_should_be == result.remainder.replace);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
//! formatter for %a %F C99 Hex-floating-point subs
|
||||
use super::super::format_field::FormatField;
|
||||
use super::super::formatter::{InPrefix,FormatPrimitive,Formatter};
|
||||
use super::float_common::{FloatAnalysis,
|
||||
primitive_to_str_common};
|
||||
use super::super::formatter::{InPrefix, FormatPrimitive, Formatter};
|
||||
use super::float_common::{FloatAnalysis, primitive_to_str_common};
|
||||
use super::base_conv;
|
||||
use super::base_conv::{RadixDef};
|
||||
use super::base_conv::RadixDef;
|
||||
|
||||
|
||||
pub struct CninetyNineHexFloatf {
|
||||
as_num : f64
|
||||
as_num: f64,
|
||||
}
|
||||
impl CninetyNineHexFloatf {
|
||||
pub fn new() -> CninetyNineHexFloatf {
|
||||
|
|
@ -17,86 +16,77 @@ impl CninetyNineHexFloatf {
|
|||
}
|
||||
|
||||
impl Formatter for CninetyNineHexFloatf {
|
||||
fn get_primitive(
|
||||
&self,
|
||||
field : &FormatField,
|
||||
inprefix : &InPrefix,
|
||||
str_in : &str
|
||||
) -> Option<FormatPrimitive> {
|
||||
let second_field = field.second_field.unwrap_or(6)+1;
|
||||
let analysis = FloatAnalysis::analyze(
|
||||
&str_in,
|
||||
inprefix,
|
||||
Some(second_field as usize),
|
||||
None,
|
||||
true);
|
||||
let f = get_primitive_hex(
|
||||
inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
*field.field_char == 'A');
|
||||
fn get_primitive(&self,
|
||||
field: &FormatField,
|
||||
inprefix: &InPrefix,
|
||||
str_in: &str)
|
||||
-> Option<FormatPrimitive> {
|
||||
let second_field = field.second_field.unwrap_or(6) + 1;
|
||||
let analysis = FloatAnalysis::analyze(&str_in,
|
||||
inprefix,
|
||||
Some(second_field as usize),
|
||||
None,
|
||||
true);
|
||||
let f = get_primitive_hex(inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
*field.field_char == 'A');
|
||||
Some(f)
|
||||
}
|
||||
fn primitive_to_str(
|
||||
&self,
|
||||
prim: &FormatPrimitive,
|
||||
field: FormatField) -> String {
|
||||
primitive_to_str_common(
|
||||
prim,
|
||||
&field
|
||||
)
|
||||
fn primitive_to_str(&self, prim: &FormatPrimitive, field: FormatField) -> String {
|
||||
primitive_to_str_common(prim, &field)
|
||||
}
|
||||
}
|
||||
|
||||
//c99 hex has unique requirements of all floating point subs in pretty much every part of building a primitive, from prefix and suffix to need for base conversion (in all other cases if you don't have decimal you must have decimal, here it's the other way around)
|
||||
// c99 hex has unique requirements of all floating point subs in pretty much every part of building a primitive, from prefix and suffix to need for base conversion (in all other cases if you don't have decimal you must have decimal, here it's the other way around)
|
||||
|
||||
// on the todo list is to have a trait for get_primitive that is implemented by each float formatter and can override a default. when that happens we can take the parts of get_primitive_dec specific to dec and spin them out to their own functions that can be overriden.
|
||||
#[allow(unused_variables)]
|
||||
#[allow(unused_assignments)]
|
||||
fn get_primitive_hex(
|
||||
inprefix : &InPrefix,
|
||||
str_in : &str,
|
||||
analysis : &FloatAnalysis,
|
||||
last_dec_place : usize,
|
||||
capitalized : bool
|
||||
) -> FormatPrimitive {
|
||||
|
||||
let mut f : FormatPrimitive = Default::default();
|
||||
f.prefix = Some(String::from(
|
||||
if inprefix.sign == -1 { "-0x" } else { "0x" }));
|
||||
fn get_primitive_hex(inprefix: &InPrefix,
|
||||
str_in: &str,
|
||||
analysis: &FloatAnalysis,
|
||||
last_dec_place: usize,
|
||||
capitalized: bool)
|
||||
-> FormatPrimitive {
|
||||
|
||||
let mut f: FormatPrimitive = Default::default();
|
||||
f.prefix = Some(String::from(if inprefix.sign == -1 {
|
||||
"-0x"
|
||||
} else {
|
||||
"0x"
|
||||
}));
|
||||
|
||||
// assign the digits before and after the decimal points
|
||||
// to separate slices. If no digits after decimal point,
|
||||
// assign 0
|
||||
let (mut first_segment_raw, second_segment_raw) =
|
||||
match analysis.decimal_pos {
|
||||
Some(pos) => {
|
||||
(&str_in[..pos], &str_in[pos+1..])
|
||||
},
|
||||
None => { (&str_in[..], "0") }
|
||||
};
|
||||
let (mut first_segment_raw, second_segment_raw) = match analysis.decimal_pos {
|
||||
Some(pos) => (&str_in[..pos], &str_in[pos + 1..]),
|
||||
None => (&str_in[..], "0"),
|
||||
};
|
||||
if first_segment_raw.len() == 0 {
|
||||
first_segment_raw = "0";
|
||||
}
|
||||
// convert to string, hexifying if input is in dec.
|
||||
/*let (first_segment, second_segment) =
|
||||
match inprefix.radix_in {
|
||||
Base::Ten => {
|
||||
(to_hex(first_segment_raw, true),
|
||||
to_hex(second_segment_raw, false))
|
||||
}
|
||||
_ => {
|
||||
(String::from(first_segment_raw),
|
||||
String::from(second_segment_raw))
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
f.pre_decimal = Some(first_segment);
|
||||
f.post_decimal = Some(second_segment);
|
||||
*/
|
||||
//TODO actual conversion, make sure to get back mantissa.
|
||||
// let (first_segment, second_segment) =
|
||||
// match inprefix.radix_in {
|
||||
// Base::Ten => {
|
||||
// (to_hex(first_segment_raw, true),
|
||||
// to_hex(second_segment_raw, false))
|
||||
// }
|
||||
// _ => {
|
||||
// (String::from(first_segment_raw),
|
||||
// String::from(second_segment_raw))
|
||||
// }
|
||||
// };
|
||||
//
|
||||
//
|
||||
// f.pre_decimal = Some(first_segment);
|
||||
// f.post_decimal = Some(second_segment);
|
||||
//
|
||||
|
||||
// TODO actual conversion, make sure to get back mantissa.
|
||||
// for hex to hex, it's really just a matter of moving the
|
||||
// decimal point and calculating the mantissa by its initial
|
||||
// position and its moves, with every position counting for
|
||||
|
|
@ -109,10 +99,14 @@ fn get_primitive_hex(
|
|||
// the hex float name may be a bit misleading in terms of how to go about the
|
||||
// conversion. The best way to do it is to just convert the floatnum
|
||||
// directly to base 2 and then at the end translate back to hex.
|
||||
let mantissa=0;
|
||||
let mantissa = 0;
|
||||
f.suffix = Some({
|
||||
let ind = if capitalized { "P" } else { "p" };
|
||||
if mantissa >=0 {
|
||||
let ind = if capitalized {
|
||||
"P"
|
||||
} else {
|
||||
"p"
|
||||
};
|
||||
if mantissa >= 0 {
|
||||
format!("{}+{}", ind, mantissa)
|
||||
} else {
|
||||
format!("{}{}", ind, mantissa)
|
||||
|
|
@ -121,25 +115,19 @@ fn get_primitive_hex(
|
|||
f
|
||||
}
|
||||
|
||||
fn to_hex(
|
||||
src: &str,
|
||||
before_decimal: bool
|
||||
) -> String {
|
||||
let rten = base_conv::RadixTen;
|
||||
fn to_hex(src: &str, before_decimal: bool) -> String {
|
||||
let rten = base_conv::RadixTen;
|
||||
let rhex = base_conv::RadixHex;
|
||||
if before_decimal {
|
||||
base_conv::base_conv_str(src, &rten, &rhex)
|
||||
} else {
|
||||
let as_arrnum_ten =base_conv::str_to_arrnum(src, &rten);
|
||||
let s = format!("{}", base_conv::base_conv_float(
|
||||
&as_arrnum_ten,
|
||||
rten.get_max(),
|
||||
rhex.get_max()
|
||||
));
|
||||
let as_arrnum_ten = base_conv::str_to_arrnum(src, &rten);
|
||||
let s = format!("{}",
|
||||
base_conv::base_conv_float(&as_arrnum_ten, rten.get_max(), rhex.get_max()));
|
||||
if s.len() > 2 {
|
||||
String::from(&s[2..])
|
||||
} else {
|
||||
//zero
|
||||
// zero
|
||||
s
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,27 @@
|
|||
//! formatter for %g %G decimal subs
|
||||
use super::super::format_field::FormatField;
|
||||
use super::super::formatter::{InPrefix,FormatPrimitive,Formatter};
|
||||
use super::float_common::{FloatAnalysis,
|
||||
get_primitive_dec,
|
||||
primitive_to_str_common};
|
||||
use super::super::formatter::{InPrefix, FormatPrimitive, Formatter};
|
||||
use super::float_common::{FloatAnalysis, get_primitive_dec, primitive_to_str_common};
|
||||
|
||||
fn get_len_fprim(
|
||||
fprim : &FormatPrimitive
|
||||
) -> usize {
|
||||
fn get_len_fprim(fprim: &FormatPrimitive) -> usize {
|
||||
let mut len = 0;
|
||||
if let Some(ref s) = fprim.prefix { len += s.len(); }
|
||||
if let Some(ref s) = fprim.pre_decimal { len += s.len(); }
|
||||
if let Some(ref s) = fprim.post_decimal { len += s.len(); }
|
||||
if let Some(ref s) = fprim.suffix { len += s.len(); }
|
||||
if let Some(ref s) = fprim.prefix {
|
||||
len += s.len();
|
||||
}
|
||||
if let Some(ref s) = fprim.pre_decimal {
|
||||
len += s.len();
|
||||
}
|
||||
if let Some(ref s) = fprim.post_decimal {
|
||||
len += s.len();
|
||||
}
|
||||
if let Some(ref s) = fprim.suffix {
|
||||
len += s.len();
|
||||
}
|
||||
len
|
||||
}
|
||||
|
||||
pub struct Decf {
|
||||
as_num : f64
|
||||
as_num: f64,
|
||||
}
|
||||
impl Decf {
|
||||
pub fn new() -> Decf {
|
||||
|
|
@ -25,62 +29,55 @@ impl Decf {
|
|||
}
|
||||
}
|
||||
impl Formatter for Decf {
|
||||
fn get_primitive(
|
||||
&self,
|
||||
field : &FormatField,
|
||||
inprefix : &InPrefix,
|
||||
str_in : &str
|
||||
) -> Option<FormatPrimitive> {
|
||||
let second_field = field.second_field.unwrap_or(6)+1;
|
||||
//default to scif interp. so as to not truncate input vals
|
||||
//(that would be displayed in scif) based on relation to decimal place
|
||||
let analysis = FloatAnalysis::analyze(
|
||||
str_in,
|
||||
inprefix,
|
||||
Some(second_field as usize+1),
|
||||
None,
|
||||
false);
|
||||
let mut f_sci = get_primitive_dec(
|
||||
inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
Some(*field.field_char == 'G'));
|
||||
//strip trailing zeroes
|
||||
fn get_primitive(&self,
|
||||
field: &FormatField,
|
||||
inprefix: &InPrefix,
|
||||
str_in: &str)
|
||||
-> Option<FormatPrimitive> {
|
||||
let second_field = field.second_field.unwrap_or(6) + 1;
|
||||
// default to scif interp. so as to not truncate input vals
|
||||
// (that would be displayed in scif) based on relation to decimal place
|
||||
let analysis = FloatAnalysis::analyze(str_in,
|
||||
inprefix,
|
||||
Some(second_field as usize + 1),
|
||||
None,
|
||||
false);
|
||||
let mut f_sci = get_primitive_dec(inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
Some(*field.field_char == 'G'));
|
||||
// strip trailing zeroes
|
||||
match f_sci.post_decimal.clone() {
|
||||
Some(ref post_dec) => {
|
||||
let mut i = post_dec.len();
|
||||
{
|
||||
let mut it = post_dec.chars();
|
||||
while let Some(c) = it.next_back() {
|
||||
if c != '0' { break; }
|
||||
i-=1;
|
||||
if c != '0' {
|
||||
break;
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
if i != post_dec.len() {
|
||||
f_sci.post_decimal =
|
||||
Some(String::from(&post_dec[0..i]));
|
||||
f_sci.post_decimal = Some(String::from(&post_dec[0..i]));
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
let f_fl = get_primitive_dec(
|
||||
inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
None);
|
||||
let f_fl = get_primitive_dec(inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
None);
|
||||
Some(if get_len_fprim(&f_fl) >= get_len_fprim(&f_sci) {
|
||||
f_sci
|
||||
} else { f_fl })
|
||||
} else {
|
||||
f_fl
|
||||
})
|
||||
}
|
||||
fn primitive_to_str(
|
||||
&self,
|
||||
prim: &FormatPrimitive,
|
||||
field: FormatField) -> String {
|
||||
primitive_to_str_common(
|
||||
prim,
|
||||
&field
|
||||
)
|
||||
fn primitive_to_str(&self, prim: &FormatPrimitive, field: FormatField) -> String {
|
||||
primitive_to_str_common(prim, &field)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use super::super::format_field::{FormatField};
|
||||
use super::super::formatter::{InPrefix,Base,FormatPrimitive,warn_incomplete_conv,get_it_at};
|
||||
use super::super::format_field::FormatField;
|
||||
use super::super::formatter::{InPrefix, Base, FormatPrimitive, warn_incomplete_conv, get_it_at};
|
||||
use super::base_conv;
|
||||
use super::base_conv::{RadixDef};
|
||||
use super::base_conv::RadixDef;
|
||||
|
||||
// if the memory, copy, and comparison cost of chars
|
||||
// becomes an issue, we can always operate in vec<u8> here
|
||||
|
|
@ -9,42 +9,40 @@ use super::base_conv::{RadixDef};
|
|||
|
||||
pub struct FloatAnalysis {
|
||||
pub len_important: usize,
|
||||
//none means no decimal point.
|
||||
// none means no decimal point.
|
||||
pub decimal_pos: Option<usize>,
|
||||
pub follow: Option<char>
|
||||
pub follow: Option<char>,
|
||||
}
|
||||
fn has_enough_digits(
|
||||
hex_input: bool,
|
||||
hex_output: bool,
|
||||
string_position: usize,
|
||||
starting_position: usize,
|
||||
limit: usize,
|
||||
) -> bool {
|
||||
//-1s are for rounding
|
||||
fn has_enough_digits(hex_input: bool,
|
||||
hex_output: bool,
|
||||
string_position: usize,
|
||||
starting_position: usize,
|
||||
limit: usize)
|
||||
-> bool {
|
||||
// -1s are for rounding
|
||||
if hex_output {
|
||||
if hex_input {
|
||||
((string_position-1) - starting_position >= limit)
|
||||
((string_position - 1) - starting_position >= limit)
|
||||
} else {
|
||||
false //undecidable without converting
|
||||
}
|
||||
} else {
|
||||
if hex_input {
|
||||
((((string_position-1) - starting_position)*9)/8 >= limit)
|
||||
((((string_position - 1) - starting_position) * 9) / 8 >= limit)
|
||||
} else {
|
||||
((string_position-1) - starting_position >= limit)
|
||||
}
|
||||
((string_position - 1) - starting_position >= limit)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl FloatAnalysis {
|
||||
pub fn analyze(
|
||||
str_in: &str,
|
||||
inprefix: &InPrefix,
|
||||
max_sd_opt: Option<usize>,
|
||||
max_after_dec_opt: Option<usize>,
|
||||
hex_output: bool
|
||||
) -> FloatAnalysis {
|
||||
pub fn analyze(str_in: &str,
|
||||
inprefix: &InPrefix,
|
||||
max_sd_opt: Option<usize>,
|
||||
max_after_dec_opt: Option<usize>,
|
||||
hex_output: bool)
|
||||
-> FloatAnalysis {
|
||||
// this fn assumes
|
||||
// the input string
|
||||
// has no leading spaces or 0s
|
||||
|
|
@ -52,91 +50,92 @@ impl FloatAnalysis {
|
|||
let mut ret = FloatAnalysis {
|
||||
len_important: 0,
|
||||
decimal_pos: None,
|
||||
follow: None
|
||||
follow: None,
|
||||
};
|
||||
let hex_input = match inprefix.radix_in {
|
||||
Base::Hex => { true }
|
||||
Base::Ten => { false }
|
||||
Base::Octal => { panic!("this should never happen: floats should never receive octal input"); }
|
||||
Base::Hex => true,
|
||||
Base::Ten => false,
|
||||
Base::Octal => {
|
||||
panic!("this should never happen: floats should never receive octal input");
|
||||
}
|
||||
};
|
||||
let mut i=0;
|
||||
let mut pos_before_first_nonzero_after_decimal : Option<usize> = None;
|
||||
while let Some(c) = str_it.next() { match c{
|
||||
e @ '0'...'9' | e @ 'A'...'F' | e @ 'a'...'f' => {
|
||||
if !hex_input {
|
||||
match e {
|
||||
'0'...'9' => {},
|
||||
_ => {
|
||||
warn_incomplete_conv(str_in);
|
||||
let mut i = 0;
|
||||
let mut pos_before_first_nonzero_after_decimal: Option<usize> = None;
|
||||
while let Some(c) = str_it.next() {
|
||||
match c {
|
||||
e @ '0'...'9' | e @ 'A'...'F' | e @ 'a'...'f' => {
|
||||
if !hex_input {
|
||||
match e {
|
||||
'0'...'9' => {}
|
||||
_ => {
|
||||
warn_incomplete_conv(str_in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ret.decimal_pos.is_some() &&
|
||||
pos_before_first_nonzero_after_decimal.is_none() &&
|
||||
e != '0' {
|
||||
pos_before_first_nonzero_after_decimal = Some(i - 1);
|
||||
}
|
||||
if let Some(max_sd) = max_sd_opt {
|
||||
if i == max_sd {
|
||||
// follow is used in cases of %g
|
||||
// where the character right after the last
|
||||
// sd is considered is rounded affecting
|
||||
// the previous digit in 1/2 of instances
|
||||
ret.follow = Some(e);
|
||||
} else if ret.decimal_pos.is_some() && i > max_sd {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(max_after_dec) = max_after_dec_opt {
|
||||
if let Some(p) = ret.decimal_pos {
|
||||
if has_enough_digits(hex_input, hex_output, i, p, max_after_dec) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if let Some(max_sd) = max_sd_opt {
|
||||
if let Some(p) = pos_before_first_nonzero_after_decimal {
|
||||
if has_enough_digits(hex_input, hex_output, i, p, max_sd) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ret.decimal_pos.is_some() && pos_before_first_nonzero_after_decimal.is_none() && e != '0' {
|
||||
pos_before_first_nonzero_after_decimal = Some(i-1);
|
||||
}
|
||||
if let Some(max_sd) = max_sd_opt {
|
||||
if i == max_sd {
|
||||
//follow is used in cases of %g
|
||||
//where the character right after the last
|
||||
//sd is considered is rounded affecting
|
||||
//the previous digit in 1/2 of instances
|
||||
ret.follow = Some(e);
|
||||
} else if ret.decimal_pos.is_some() && i > max_sd {
|
||||
'.' => {
|
||||
if ret.decimal_pos.is_none() {
|
||||
ret.decimal_pos = Some(i);
|
||||
} else {
|
||||
warn_incomplete_conv(str_in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(max_after_dec) = max_after_dec_opt {
|
||||
if let Some(p) = ret.decimal_pos {
|
||||
if has_enough_digits(hex_input, hex_output, i, p, max_after_dec) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if let Some(max_sd) = max_sd_opt {
|
||||
if let Some(p) = pos_before_first_nonzero_after_decimal {
|
||||
if has_enough_digits(hex_input, hex_output, i, p, max_sd) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'.' => {
|
||||
if ret.decimal_pos.is_none() {
|
||||
ret.decimal_pos = Some(i);
|
||||
} else {
|
||||
_ => {
|
||||
warn_incomplete_conv(str_in);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warn_incomplete_conv(str_in);
|
||||
break;
|
||||
}
|
||||
}; i+=1; }
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
ret.len_important = i;
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
fn de_hex(
|
||||
src: &str,
|
||||
before_decimal: bool
|
||||
) -> String {
|
||||
let rten = base_conv::RadixTen;
|
||||
fn de_hex(src: &str, before_decimal: bool) -> String {
|
||||
let rten = base_conv::RadixTen;
|
||||
let rhex = base_conv::RadixHex;
|
||||
if before_decimal {
|
||||
base_conv::base_conv_str(src, &rhex, &rten)
|
||||
} else {
|
||||
let as_arrnum_hex =base_conv::str_to_arrnum(src, &rhex);
|
||||
let s = format!("{}", base_conv::base_conv_float(
|
||||
&as_arrnum_hex,
|
||||
rhex.get_max(),
|
||||
rten.get_max()
|
||||
));
|
||||
let as_arrnum_hex = base_conv::str_to_arrnum(src, &rhex);
|
||||
let s = format!("{}",
|
||||
base_conv::base_conv_float(&as_arrnum_hex, rhex.get_max(), rten.get_max()));
|
||||
if s.len() > 2 {
|
||||
String::from(&s[2..])
|
||||
} else {
|
||||
//zero
|
||||
// zero
|
||||
s
|
||||
}
|
||||
}
|
||||
|
|
@ -147,27 +146,25 @@ fn de_hex(
|
|||
// bumps the last digit up one,
|
||||
// and if the digit was nine
|
||||
// propagate to the next, etc.
|
||||
fn _round_str_from(
|
||||
in_str : &str,
|
||||
position : usize
|
||||
) -> (String, bool) {
|
||||
|
||||
let mut it=in_str[0..position].chars();
|
||||
fn _round_str_from(in_str: &str, position: usize) -> (String, bool) {
|
||||
|
||||
let mut it = in_str[0..position].chars();
|
||||
let mut rev = String::new();
|
||||
let mut i = position;
|
||||
let mut finished_in_dec=false;
|
||||
while let Some(c)=it.next_back() {
|
||||
i-=1;
|
||||
let mut finished_in_dec = false;
|
||||
while let Some(c) = it.next_back() {
|
||||
i -= 1;
|
||||
match c {
|
||||
'9' => { rev.push('0'); }
|
||||
'9' => {
|
||||
rev.push('0');
|
||||
}
|
||||
e @ _ => {
|
||||
rev.push(
|
||||
((e as u8)+1) as char);
|
||||
rev.push(((e as u8) + 1) as char);
|
||||
finished_in_dec = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut fwd = String::from(&in_str[0..i]);
|
||||
for ch in rev.chars().rev() {
|
||||
fwd.push(ch);
|
||||
|
|
@ -175,148 +172,137 @@ fn _round_str_from(
|
|||
(fwd, finished_in_dec)
|
||||
}
|
||||
|
||||
fn round_terminal_digit(
|
||||
before_dec: String,
|
||||
after_dec: String,
|
||||
position: usize
|
||||
) -> (String, String) {
|
||||
|
||||
fn round_terminal_digit(before_dec: String,
|
||||
after_dec: String,
|
||||
position: usize)
|
||||
-> (String, String) {
|
||||
|
||||
if position < after_dec.len() {
|
||||
let digit_at_pos:char;
|
||||
let digit_at_pos: char;
|
||||
{
|
||||
digit_at_pos=(&after_dec[position..position+1])
|
||||
.chars().next().expect("");
|
||||
digit_at_pos = (&after_dec[position..position + 1])
|
||||
.chars()
|
||||
.next()
|
||||
.expect("");
|
||||
}
|
||||
match digit_at_pos {
|
||||
'5'...'9' => {
|
||||
let (new_after_dec, finished_in_dec) =
|
||||
_round_str_from(&after_dec, position);
|
||||
'5'...'9' => {
|
||||
let (new_after_dec, finished_in_dec) = _round_str_from(&after_dec, position);
|
||||
if finished_in_dec {
|
||||
return (before_dec, new_after_dec)
|
||||
return (before_dec, new_after_dec);
|
||||
} else {
|
||||
let (new_before_dec, _) =
|
||||
_round_str_from(&before_dec,
|
||||
before_dec.len());
|
||||
return (new_before_dec, new_after_dec)
|
||||
let (new_before_dec, _) = _round_str_from(&before_dec, before_dec.len());
|
||||
return (new_before_dec, new_after_dec);
|
||||
}
|
||||
//TODO
|
||||
},
|
||||
_ =>{ }
|
||||
}
|
||||
}
|
||||
(before_dec, after_dec)
|
||||
// TODO
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
(before_dec, after_dec)
|
||||
}
|
||||
|
||||
pub fn get_primitive_dec(
|
||||
inprefix : &InPrefix,
|
||||
str_in : &str,
|
||||
analysis : &FloatAnalysis,
|
||||
last_dec_place : usize,
|
||||
sci_mode : Option<bool>
|
||||
) -> FormatPrimitive {
|
||||
let mut f : FormatPrimitive = Default::default();
|
||||
pub fn get_primitive_dec(inprefix: &InPrefix,
|
||||
str_in: &str,
|
||||
analysis: &FloatAnalysis,
|
||||
last_dec_place: usize,
|
||||
sci_mode: Option<bool>)
|
||||
-> FormatPrimitive {
|
||||
let mut f: FormatPrimitive = Default::default();
|
||||
|
||||
//add negative sign section
|
||||
// add negative sign section
|
||||
if inprefix.sign == -1 {
|
||||
f.prefix = Some(String::from("-"));
|
||||
}
|
||||
|
||||
|
||||
// assign the digits before and after the decimal points
|
||||
// to separate slices. If no digits after decimal point,
|
||||
// assign 0
|
||||
let (mut first_segment_raw, second_segment_raw) =
|
||||
match analysis.decimal_pos {
|
||||
Some(pos) => {
|
||||
(&str_in[..pos], &str_in[pos+1..])
|
||||
},
|
||||
None => { (&str_in[..], "0") }
|
||||
};
|
||||
let (mut first_segment_raw, second_segment_raw) = match analysis.decimal_pos {
|
||||
Some(pos) => (&str_in[..pos], &str_in[pos + 1..]),
|
||||
None => (&str_in[..], "0"),
|
||||
};
|
||||
if first_segment_raw.len() == 0 {
|
||||
first_segment_raw = "0";
|
||||
}
|
||||
// convert to string, de_hexifying if input is in hex.
|
||||
let (first_segment, second_segment) =
|
||||
match inprefix.radix_in {
|
||||
Base::Hex => {
|
||||
(de_hex(first_segment_raw, true),
|
||||
de_hex(second_segment_raw, false))
|
||||
}
|
||||
_ => {
|
||||
(String::from(first_segment_raw),
|
||||
String::from(second_segment_raw))
|
||||
}
|
||||
};
|
||||
let (pre_dec_unrounded, post_dec_unrounded, mantissa) =
|
||||
if sci_mode.is_some() {
|
||||
if first_segment.len() > 1 {
|
||||
let mut post_dec = String::from(&first_segment[1..]);
|
||||
post_dec.push_str(&second_segment);
|
||||
(String::from(&first_segment[0..1]),
|
||||
post_dec,
|
||||
first_segment.len() as isize -1)
|
||||
} else {
|
||||
match first_segment.chars().next() {
|
||||
Some('0') => {
|
||||
let mut it = second_segment.chars().enumerate();
|
||||
let mut m : isize = 0;
|
||||
let mut pre = String::from("0");
|
||||
let mut post = String::from("0");
|
||||
while let Some((i,c)) = it.next() { match c {
|
||||
let (first_segment, second_segment) = match inprefix.radix_in {
|
||||
Base::Hex => {
|
||||
(de_hex(first_segment_raw, true),
|
||||
de_hex(second_segment_raw, false))
|
||||
}
|
||||
_ => {
|
||||
(String::from(first_segment_raw),
|
||||
String::from(second_segment_raw))
|
||||
}
|
||||
};
|
||||
let (pre_dec_unrounded, post_dec_unrounded, mantissa) = if sci_mode.is_some() {
|
||||
if first_segment.len() > 1 {
|
||||
let mut post_dec = String::from(&first_segment[1..]);
|
||||
post_dec.push_str(&second_segment);
|
||||
(String::from(&first_segment[0..1]),
|
||||
post_dec,
|
||||
first_segment.len() as isize - 1)
|
||||
} else {
|
||||
match first_segment.chars().next() {
|
||||
Some('0') => {
|
||||
let mut it = second_segment.chars().enumerate();
|
||||
let mut m: isize = 0;
|
||||
let mut pre = String::from("0");
|
||||
let mut post = String::from("0");
|
||||
while let Some((i, c)) = it.next() {
|
||||
match c {
|
||||
'0' => {}
|
||||
_ => {
|
||||
m=((i as isize)+1) * -1;
|
||||
pre = String::from(
|
||||
&second_segment[i..i+1]);
|
||||
post = String::from(
|
||||
&second_segment[i+1..]);
|
||||
m = ((i as isize) + 1) * -1;
|
||||
pre = String::from(&second_segment[i..i + 1]);
|
||||
post = String::from(&second_segment[i + 1..]);
|
||||
break;
|
||||
}
|
||||
} }
|
||||
(pre, post, m)
|
||||
},
|
||||
Some(_) => {
|
||||
(first_segment, second_segment, 0)
|
||||
},
|
||||
None => {
|
||||
panic!(
|
||||
"float_common: no chars in first segment.");
|
||||
}
|
||||
}
|
||||
(pre, post, m)
|
||||
}
|
||||
Some(_) => (first_segment, second_segment, 0),
|
||||
None => {
|
||||
panic!("float_common: no chars in first segment.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(first_segment, second_segment, 0)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
(first_segment, second_segment, 0)
|
||||
};
|
||||
|
||||
let (pre_dec_draft, post_dec_draft) =
|
||||
round_terminal_digit(pre_dec_unrounded,
|
||||
post_dec_unrounded,
|
||||
last_dec_place-1);
|
||||
|
||||
f.pre_decimal=Some(pre_dec_draft);
|
||||
f.post_decimal=Some(post_dec_draft);
|
||||
let (pre_dec_draft, post_dec_draft) = round_terminal_digit(pre_dec_unrounded,
|
||||
post_dec_unrounded,
|
||||
last_dec_place - 1);
|
||||
|
||||
f.pre_decimal = Some(pre_dec_draft);
|
||||
f.post_decimal = Some(post_dec_draft);
|
||||
if let Some(capitalized) = sci_mode {
|
||||
let si_ind = if capitalized { 'E' } else { 'e' };
|
||||
f.suffix=Some(if mantissa >=0 {
|
||||
let si_ind = if capitalized {
|
||||
'E'
|
||||
} else {
|
||||
'e'
|
||||
};
|
||||
f.suffix = Some(if mantissa >= 0 {
|
||||
format!("{}+{:02}", si_ind, mantissa)
|
||||
} else {
|
||||
//negative sign is considered in format!s
|
||||
// negative sign is considered in format!s
|
||||
// leading zeroes
|
||||
format!("{}{:03}", si_ind, mantissa)
|
||||
});
|
||||
}
|
||||
|
||||
f
|
||||
|
||||
f
|
||||
}
|
||||
|
||||
pub fn primitive_to_str_common(
|
||||
prim: &FormatPrimitive,
|
||||
field: &FormatField
|
||||
) -> String {
|
||||
pub fn primitive_to_str_common(prim: &FormatPrimitive, field: &FormatField) -> String {
|
||||
let mut final_str = String::new();
|
||||
match prim.prefix {
|
||||
Some(ref prefix) => {
|
||||
final_str.push_str(&prefix);
|
||||
},
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
match prim.pre_decimal {
|
||||
|
|
@ -324,7 +310,8 @@ pub fn primitive_to_str_common(
|
|||
final_str.push_str(&pre_decimal);
|
||||
}
|
||||
None => {
|
||||
panic!("error, format primitives provided to int, will, incidentally under correct behavior, always have a pre_dec value.");
|
||||
panic!("error, format primitives provided to int, will, incidentally under correct \
|
||||
behavior, always have a pre_dec value.");
|
||||
}
|
||||
}
|
||||
let decimal_places = field.second_field.unwrap_or(6);
|
||||
|
|
@ -332,36 +319,35 @@ pub fn primitive_to_str_common(
|
|||
Some(ref post_decimal) => {
|
||||
if post_decimal.len() > 0 && decimal_places > 0 {
|
||||
final_str.push('.');
|
||||
let len_avail=post_decimal.len() as u32;
|
||||
|
||||
let len_avail = post_decimal.len() as u32;
|
||||
|
||||
if decimal_places >= len_avail {
|
||||
//println!("dec {}, len avail {}", decimal_places, len_avail);
|
||||
// println!("dec {}, len avail {}", decimal_places, len_avail);
|
||||
final_str.push_str(post_decimal);
|
||||
|
||||
if *field.field_char != 'g' &&
|
||||
*field.field_char != 'G' {
|
||||
if *field.field_char != 'g' && *field.field_char != 'G' {
|
||||
let diff = decimal_places - len_avail;
|
||||
for _ in 0..diff {
|
||||
final_str.push('0');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//println!("printing to only {}", decimal_places);
|
||||
final_str.push_str(
|
||||
&post_decimal[0..decimal_places as usize]);
|
||||
// println!("printing to only {}", decimal_places);
|
||||
final_str.push_str(&post_decimal[0..decimal_places as usize]);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
panic!("error, format primitives provided to int, will, incidentally under correct behavior, always have a pre_dec value.");
|
||||
panic!("error, format primitives provided to int, will, incidentally under correct \
|
||||
behavior, always have a pre_dec value.");
|
||||
}
|
||||
}
|
||||
match prim.suffix {
|
||||
Some(ref suffix) => {
|
||||
final_str.push_str(suffix);
|
||||
},
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
|
||||
final_str
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
//! formatter for %f %F common-notation floating-point subs
|
||||
use super::super::format_field::FormatField;
|
||||
use super::super::formatter::{InPrefix,FormatPrimitive,Formatter};
|
||||
use super::float_common::{FloatAnalysis,
|
||||
get_primitive_dec,
|
||||
primitive_to_str_common};
|
||||
use super::super::formatter::{InPrefix, FormatPrimitive, Formatter};
|
||||
use super::float_common::{FloatAnalysis, get_primitive_dec, primitive_to_str_common};
|
||||
|
||||
pub struct Floatf {
|
||||
as_num : f64
|
||||
as_num: f64,
|
||||
}
|
||||
impl Floatf {
|
||||
pub fn new() -> Floatf {
|
||||
|
|
@ -14,35 +12,25 @@ impl Floatf {
|
|||
}
|
||||
}
|
||||
impl Formatter for Floatf {
|
||||
fn get_primitive(
|
||||
&self,
|
||||
field : &FormatField,
|
||||
inprefix : &InPrefix,
|
||||
str_in : &str
|
||||
) -> Option<FormatPrimitive> {
|
||||
let second_field = field.second_field.unwrap_or(6)+1;
|
||||
let analysis = FloatAnalysis::analyze(
|
||||
&str_in,
|
||||
inprefix,
|
||||
None,
|
||||
Some(second_field as usize),
|
||||
false);
|
||||
let f = get_primitive_dec(
|
||||
inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
None);
|
||||
fn get_primitive(&self,
|
||||
field: &FormatField,
|
||||
inprefix: &InPrefix,
|
||||
str_in: &str)
|
||||
-> Option<FormatPrimitive> {
|
||||
let second_field = field.second_field.unwrap_or(6) + 1;
|
||||
let analysis = FloatAnalysis::analyze(&str_in,
|
||||
inprefix,
|
||||
None,
|
||||
Some(second_field as usize),
|
||||
false);
|
||||
let f = get_primitive_dec(inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
None);
|
||||
Some(f)
|
||||
}
|
||||
fn primitive_to_str(
|
||||
&self,
|
||||
prim: &FormatPrimitive,
|
||||
field: FormatField) -> String {
|
||||
primitive_to_str_common(
|
||||
prim,
|
||||
&field
|
||||
)
|
||||
fn primitive_to_str(&self, prim: &FormatPrimitive, field: FormatField) -> String {
|
||||
primitive_to_str_common(prim, &field)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,23 +4,24 @@
|
|||
use std::u64;
|
||||
use std::i64;
|
||||
use super::super::format_field::FormatField;
|
||||
use super::super::formatter::{InPrefix,FormatPrimitive,Base,Formatter,warn_incomplete_conv,get_it_at};
|
||||
use super::super::formatter::{InPrefix, FormatPrimitive, Base, Formatter, warn_incomplete_conv,
|
||||
get_it_at};
|
||||
|
||||
pub struct Intf {
|
||||
a : u32
|
||||
a: u32,
|
||||
}
|
||||
|
||||
// see the Intf::analyze() function below
|
||||
struct IntAnalysis {
|
||||
check_past_max : bool,
|
||||
past_max : bool,
|
||||
check_past_max: bool,
|
||||
past_max: bool,
|
||||
is_zero: bool,
|
||||
len_digits: u8
|
||||
len_digits: u8,
|
||||
}
|
||||
|
||||
impl Intf {
|
||||
pub fn new() -> Intf {
|
||||
Intf { a:0 }
|
||||
Intf { a: 0 }
|
||||
}
|
||||
// take a ref to argument string, and basic information
|
||||
// about prefix (offset, radix, sign), and analyze string
|
||||
|
|
@ -34,78 +35,79 @@ impl Intf {
|
|||
// is_zero: true if number is zero, false otherwise
|
||||
// len_digits: length of digits used to create the int
|
||||
// important, for example, if we run into a non-valid character
|
||||
fn analyze(
|
||||
str_in: &str,
|
||||
signed_out: bool,
|
||||
inprefix: &InPrefix
|
||||
) -> IntAnalysis {
|
||||
fn analyze(str_in: &str, signed_out: bool, inprefix: &InPrefix) -> IntAnalysis {
|
||||
// the maximum number of digits we could conceivably
|
||||
// have before the decimal point without exceeding the
|
||||
// max
|
||||
let mut str_it = get_it_at(inprefix.offset, str_in);
|
||||
let max_sd_in =
|
||||
if signed_out {
|
||||
match inprefix.radix_in {
|
||||
Base::Ten => 19,
|
||||
Base::Octal => 21,
|
||||
Base::Hex => 16
|
||||
}
|
||||
} else {
|
||||
match inprefix.radix_in {
|
||||
Base::Ten => 20,
|
||||
Base::Octal => 22,
|
||||
Base::Hex => 16
|
||||
}
|
||||
};
|
||||
let max_sd_in = if signed_out {
|
||||
match inprefix.radix_in {
|
||||
Base::Ten => 19,
|
||||
Base::Octal => 21,
|
||||
Base::Hex => 16,
|
||||
}
|
||||
} else {
|
||||
match inprefix.radix_in {
|
||||
Base::Ten => 20,
|
||||
Base::Octal => 22,
|
||||
Base::Hex => 16,
|
||||
}
|
||||
};
|
||||
let mut ret = IntAnalysis {
|
||||
check_past_max: false,
|
||||
past_max: false,
|
||||
is_zero: false,
|
||||
len_digits : 0
|
||||
len_digits: 0,
|
||||
};
|
||||
|
||||
// todo turn this to a while let now that we know
|
||||
// no special behavior on EOI break
|
||||
loop {
|
||||
let c_opt = str_it.next();
|
||||
if let Some(c) = c_opt { match c {
|
||||
'0'...'9' | 'a'...'f' | 'A'...'F' => {
|
||||
if ret.len_digits == 0 && c == '0' {
|
||||
ret.is_zero = true;
|
||||
} else if ret.is_zero {
|
||||
ret.is_zero = false;
|
||||
}
|
||||
ret.len_digits += 1;
|
||||
if ret.len_digits == max_sd_in {
|
||||
if let Some(next_ch) = str_it.next() {
|
||||
match next_ch {
|
||||
'0'...'9' => {
|
||||
ret.past_max = true;
|
||||
if let Some(c) = c_opt {
|
||||
match c {
|
||||
'0'...'9' | 'a'...'f' | 'A'...'F' => {
|
||||
if ret.len_digits == 0 && c == '0' {
|
||||
ret.is_zero = true;
|
||||
} else if ret.is_zero {
|
||||
ret.is_zero = false;
|
||||
}
|
||||
ret.len_digits += 1;
|
||||
if ret.len_digits == max_sd_in {
|
||||
if let Some(next_ch) = str_it.next() {
|
||||
match next_ch {
|
||||
'0'...'9' => {
|
||||
ret.past_max = true;
|
||||
}
|
||||
_ => {
|
||||
// force conversion
|
||||
// to check if its above max.
|
||||
// todo: spin out convert
|
||||
// into fn, call it here to try
|
||||
// read val, on Ok()
|
||||
// save val for reuse later
|
||||
// that way on same-base in and out
|
||||
// we don't needlessly convert int
|
||||
// to str, we can just copy it over.
|
||||
ret.check_past_max = true;
|
||||
str_it.put_back(next_ch);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// force conversion
|
||||
// to check if its above max.
|
||||
// todo: spin out convert
|
||||
// into fn, call it here to try
|
||||
// read val, on Ok()
|
||||
// save val for reuse later
|
||||
// that way on same-base in and out
|
||||
// we don't needlessly convert int
|
||||
// to str, we can just copy it over.
|
||||
ret.check_past_max = true;
|
||||
str_it.put_back(next_ch);
|
||||
if ret.past_max {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret.check_past_max = true;
|
||||
}
|
||||
if ret.past_max { break; }
|
||||
} else { ret.check_past_max = true; }
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warn_incomplete_conv(str_in);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warn_incomplete_conv(str_in);
|
||||
break;
|
||||
}
|
||||
} } else {
|
||||
//breaks on EOL
|
||||
} else {
|
||||
// breaks on EOL
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -113,22 +115,21 @@ impl Intf {
|
|||
}
|
||||
// get a FormatPrimitive of the maximum value for the field char
|
||||
// and given sign
|
||||
fn get_max(
|
||||
fchar : char,
|
||||
sign : i8
|
||||
) -> FormatPrimitive {
|
||||
let mut fmt_prim : FormatPrimitive = Default::default();
|
||||
fn get_max(fchar: char, sign: i8) -> FormatPrimitive {
|
||||
let mut fmt_prim: FormatPrimitive = Default::default();
|
||||
fmt_prim.pre_decimal = Some(String::from(match fchar {
|
||||
'd' | 'i' => match sign {
|
||||
1 => "9223372036854775807",
|
||||
_ => {
|
||||
fmt_prim.prefix = Some(String::from("-"));
|
||||
"9223372036854775808"
|
||||
'd' | 'i' => {
|
||||
match sign {
|
||||
1 => "9223372036854775807",
|
||||
_ => {
|
||||
fmt_prim.prefix = Some(String::from("-"));
|
||||
"9223372036854775808"
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
'x' | 'X' => "ffffffffffffffff",
|
||||
'o' => "1777777777777777777777",
|
||||
'u' | _ => "18446744073709551615"
|
||||
'u' | _ => "18446744073709551615",
|
||||
}));
|
||||
fmt_prim
|
||||
}
|
||||
|
|
@ -147,102 +148,90 @@ impl Intf {
|
|||
// - if the string falls outside bounds:
|
||||
// for i64 output, the int minimum or int max (depending on sign)
|
||||
// for u64 output, the u64 max in the output radix
|
||||
fn conv_from_segment(
|
||||
segment : &str,
|
||||
radix_in : Base,
|
||||
fchar : char,
|
||||
sign : i8,
|
||||
) ->
|
||||
FormatPrimitive
|
||||
{
|
||||
fn conv_from_segment(segment: &str, radix_in: Base, fchar: char, sign: i8) -> FormatPrimitive {
|
||||
match fchar {
|
||||
'i' | 'd' => {
|
||||
match i64::from_str_radix(segment, radix_in as u32) {
|
||||
Ok(i) => {
|
||||
let mut fmt_prim : FormatPrimitive =
|
||||
Default::default();
|
||||
let mut fmt_prim: FormatPrimitive = Default::default();
|
||||
if sign == -1 {
|
||||
fmt_prim.prefix = Some(String::from("-"));
|
||||
}
|
||||
fmt_prim.pre_decimal =
|
||||
Some(format!("{}", i));
|
||||
fmt_prim.pre_decimal = Some(format!("{}", i));
|
||||
fmt_prim
|
||||
}
|
||||
Err(_) => Intf::get_max(fchar, sign)
|
||||
Err(_) => Intf::get_max(fchar, sign),
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
match u64::from_str_radix(segment, radix_in as u32) {
|
||||
Ok(u) => {
|
||||
let mut fmt_prim : FormatPrimitive =
|
||||
Default::default();
|
||||
let u_f =
|
||||
if sign == -1 { u64::MAX - (u -1)
|
||||
} else { u };
|
||||
let mut fmt_prim: FormatPrimitive = Default::default();
|
||||
let u_f = if sign == -1 {
|
||||
u64::MAX - (u - 1)
|
||||
} else {
|
||||
u
|
||||
};
|
||||
fmt_prim.pre_decimal = Some(match fchar {
|
||||
'X' => format!("{:X}", u_f),
|
||||
'x' => format!("{:x}", u_f),
|
||||
'o' => format!("{:o}", u_f),
|
||||
_ => format!("{}", u_f)
|
||||
_ => format!("{}", u_f),
|
||||
});
|
||||
fmt_prim
|
||||
}
|
||||
Err(_) => Intf::get_max(fchar, sign)
|
||||
Err(_) => Intf::get_max(fchar, sign),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Formatter for Intf {
|
||||
fn get_primitive(
|
||||
&self,
|
||||
field : &FormatField,
|
||||
inprefix : &InPrefix,
|
||||
str_in : &str
|
||||
) -> Option<FormatPrimitive> {
|
||||
fn get_primitive(&self,
|
||||
field: &FormatField,
|
||||
inprefix: &InPrefix,
|
||||
str_in: &str)
|
||||
-> Option<FormatPrimitive> {
|
||||
|
||||
let begin = inprefix.offset;
|
||||
|
||||
//get information about the string. see Intf::Analyze
|
||||
// get information about the string. see Intf::Analyze
|
||||
// def above.
|
||||
let convert_hints = Intf::analyze(str_in,
|
||||
*field.field_char == 'i' || *field.field_char == 'd',
|
||||
inprefix);
|
||||
//We always will have a formatprimitive to return
|
||||
// We always will have a formatprimitive to return
|
||||
Some(if convert_hints.len_digits == 0 || convert_hints.is_zero {
|
||||
//if non-digit or end is reached before a non-zero digit
|
||||
let mut fmt_prim : FormatPrimitive = Default::default();
|
||||
fmt_prim.pre_decimal=Some(String::from("0"));
|
||||
// if non-digit or end is reached before a non-zero digit
|
||||
let mut fmt_prim: FormatPrimitive = Default::default();
|
||||
fmt_prim.pre_decimal = Some(String::from("0"));
|
||||
fmt_prim
|
||||
} else if ! convert_hints.past_max {
|
||||
//if the number is or may be below the bounds limit
|
||||
} else if !convert_hints.past_max {
|
||||
// if the number is or may be below the bounds limit
|
||||
let radix_out = match *field.field_char {
|
||||
'd' | 'i' | 'u' => Base::Ten,
|
||||
'x' | 'X' => Base::Hex,
|
||||
'o' | _ => Base::Octal
|
||||
'o' | _ => Base::Octal,
|
||||
};
|
||||
let radix_mismatch = ! radix_out.eq(&inprefix.radix_in);
|
||||
let decr_from_max :bool = inprefix.sign == -1 &&
|
||||
*field.field_char !='i';
|
||||
let radix_mismatch = !radix_out.eq(&inprefix.radix_in);
|
||||
let decr_from_max: bool = inprefix.sign == -1 && *field.field_char != 'i';
|
||||
let end = begin + convert_hints.len_digits as usize;
|
||||
|
||||
// convert to int if any one of these is true:
|
||||
// - number of digits in int indicates it may be past max
|
||||
// - we're subtracting from the max
|
||||
// - we're converting the base
|
||||
if convert_hints.check_past_max
|
||||
|| decr_from_max || radix_mismatch {
|
||||
//radix of in and out is the same.
|
||||
if convert_hints.check_past_max || decr_from_max || radix_mismatch {
|
||||
// radix of in and out is the same.
|
||||
let segment = String::from(&str_in[begin..end]);
|
||||
let m = Intf::conv_from_segment(
|
||||
&segment,
|
||||
inprefix.radix_in.clone(),
|
||||
*field.field_char,
|
||||
inprefix.sign);
|
||||
let m = Intf::conv_from_segment(&segment,
|
||||
inprefix.radix_in.clone(),
|
||||
*field.field_char,
|
||||
inprefix.sign);
|
||||
m
|
||||
} else {
|
||||
//otherwise just do a straight string copy.
|
||||
let mut fmt_prim : FormatPrimitive = Default::default();
|
||||
// otherwise just do a straight string copy.
|
||||
let mut fmt_prim: FormatPrimitive = Default::default();
|
||||
|
||||
// this is here and not earlier because
|
||||
// zero doesn't get a sign, and conv_from_segment
|
||||
|
|
@ -251,28 +240,24 @@ impl Formatter for Intf {
|
|||
|
||||
fmt_prim.prefix = Some(String::from("-"));
|
||||
}
|
||||
fmt_prim.pre_decimal = Some(String::from
|
||||
(&str_in[begin..end]));
|
||||
fmt_prim.pre_decimal = Some(String::from(&str_in[begin..end]));
|
||||
fmt_prim
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Intf::get_max(*field.field_char, inprefix.sign)
|
||||
})
|
||||
|
||||
}
|
||||
fn primitive_to_str(
|
||||
&self,
|
||||
prim: &FormatPrimitive,
|
||||
field: FormatField) -> String {
|
||||
let mut finalstr : String = String::new();
|
||||
fn primitive_to_str(&self, prim: &FormatPrimitive, field: FormatField) -> String {
|
||||
let mut finalstr: String = String::new();
|
||||
match prim.prefix {
|
||||
Some(ref prefix) => {
|
||||
finalstr.push_str(&prefix);
|
||||
},
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
//integral second fields is zero-padded minimum-width
|
||||
//which gets handled before general minimum-width
|
||||
// integral second fields is zero-padded minimum-width
|
||||
// which gets handled before general minimum-width
|
||||
match prim.pre_decimal {
|
||||
Some(ref pre_decimal) => {
|
||||
match field.second_field {
|
||||
|
|
@ -286,10 +271,11 @@ impl Formatter for Intf {
|
|||
}
|
||||
None => {}
|
||||
}
|
||||
finalstr.push_str(&pre_decimal);
|
||||
finalstr.push_str(&pre_decimal);
|
||||
}
|
||||
None => {
|
||||
panic!("error, format primitives provided to int, will, incidentally under correct behavior, always have a pre_dec value.");
|
||||
panic!("error, format primitives provided to int, will, incidentally under \
|
||||
correct behavior, always have a pre_dec value.");
|
||||
}
|
||||
}
|
||||
finalstr
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
//! formatter for %e %E scientific notation subs
|
||||
use super::super::format_field::FormatField;
|
||||
use super::super::formatter::{InPrefix,FormatPrimitive,Formatter};
|
||||
use super::float_common::{FloatAnalysis,
|
||||
get_primitive_dec,
|
||||
primitive_to_str_common};
|
||||
use super::super::formatter::{InPrefix, FormatPrimitive, Formatter};
|
||||
use super::float_common::{FloatAnalysis, get_primitive_dec, primitive_to_str_common};
|
||||
|
||||
pub struct Scif {
|
||||
as_num : f64
|
||||
as_num: f64,
|
||||
}
|
||||
impl Scif {
|
||||
pub fn new() -> Scif {
|
||||
|
|
@ -14,34 +12,25 @@ impl Scif {
|
|||
}
|
||||
}
|
||||
impl Formatter for Scif {
|
||||
fn get_primitive(
|
||||
&self,
|
||||
field : &FormatField,
|
||||
inprefix : &InPrefix,
|
||||
str_in : &str
|
||||
) -> Option<FormatPrimitive> {
|
||||
let second_field = field.second_field.unwrap_or(6)+1;
|
||||
let analysis = FloatAnalysis::analyze(
|
||||
str_in,
|
||||
inprefix,
|
||||
Some(second_field as usize+1),
|
||||
None,
|
||||
false);
|
||||
let f = get_primitive_dec(
|
||||
inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
Some(*field.field_char == 'E'));
|
||||
fn get_primitive(&self,
|
||||
field: &FormatField,
|
||||
inprefix: &InPrefix,
|
||||
str_in: &str)
|
||||
-> Option<FormatPrimitive> {
|
||||
let second_field = field.second_field.unwrap_or(6) + 1;
|
||||
let analysis = FloatAnalysis::analyze(str_in,
|
||||
inprefix,
|
||||
Some(second_field as usize + 1),
|
||||
None,
|
||||
false);
|
||||
let f = get_primitive_dec(inprefix,
|
||||
&str_in[inprefix.offset..],
|
||||
&analysis,
|
||||
second_field as usize,
|
||||
Some(*field.field_char == 'E'));
|
||||
Some(f)
|
||||
}
|
||||
fn primitive_to_str(
|
||||
&self,
|
||||
prim: &FormatPrimitive,
|
||||
field: FormatField) -> String {
|
||||
primitive_to_str_common(
|
||||
prim,
|
||||
&field
|
||||
)
|
||||
fn primitive_to_str(&self, prim: &FormatPrimitive, field: FormatField) -> String {
|
||||
primitive_to_str_common(prim, &field)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use super::formatters::scif::Scif;
|
|||
use super::formatters::decf::Decf;
|
||||
|
||||
pub fn warn_expected_numeric(pf_arg: &String) {
|
||||
//important: keep println here not print
|
||||
// important: keep println here not print
|
||||
cli::err_msg(&format!("{}: expected a numeric value", pf_arg));
|
||||
}
|
||||
|
||||
|
|
@ -24,8 +24,10 @@ fn warn_char_constant_ign(remaining_bytes: Vec<u8>) {
|
|||
Err(e) => {
|
||||
match e {
|
||||
env::VarError::NotPresent => {
|
||||
cli::err_msg(&format!("warning: {:?}: character(s) following character constant have been ignored", &*remaining_bytes));
|
||||
},
|
||||
cli::err_msg(&format!("warning: {:?}: character(s) following character \
|
||||
constant have been ignored",
|
||||
&*remaining_bytes));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,11 +37,9 @@ fn warn_char_constant_ign(remaining_bytes: Vec<u8>) {
|
|||
// this function looks at the first few
|
||||
// characters of an argument and returns a value if we can learn
|
||||
// a value from that (e.g. no argument? return 0, char constant? ret value)
|
||||
fn get_provided(
|
||||
str_in_opt : Option<&String>
|
||||
) -> Option<u8> {
|
||||
const C_S_QUOTE: u8=39;
|
||||
const C_D_QUOTE: u8=34;
|
||||
fn get_provided(str_in_opt: Option<&String>) -> Option<u8> {
|
||||
const C_S_QUOTE: u8 = 39;
|
||||
const C_D_QUOTE: u8 = 34;
|
||||
match str_in_opt {
|
||||
Some(str_in) => {
|
||||
let mut byte_it = str_in.bytes();
|
||||
|
|
@ -48,31 +48,34 @@ fn get_provided(
|
|||
C_S_QUOTE | C_D_QUOTE => {
|
||||
return Some(match byte_it.next() {
|
||||
Some(second_byte) => {
|
||||
let mut ignored : Vec<u8> = Vec::new();
|
||||
while let Some(cont)=byte_it.next() {
|
||||
let mut ignored: Vec<u8> = Vec::new();
|
||||
while let Some(cont) = byte_it.next() {
|
||||
ignored.push(cont);
|
||||
}
|
||||
if ignored.len() > 0 {
|
||||
warn_char_constant_ign(ignored);
|
||||
}
|
||||
second_byte as u8
|
||||
},
|
||||
//no byte after quote
|
||||
}
|
||||
// no byte after quote
|
||||
None => {
|
||||
let so_far =
|
||||
(qchar as u8 as char).to_string();
|
||||
let so_far = (qchar as u8 as char).to_string();
|
||||
warn_expected_numeric(&so_far);
|
||||
0 as u8
|
||||
}
|
||||
});
|
||||
},
|
||||
//first byte is not quote
|
||||
_ => { return None; }
|
||||
//no first byte
|
||||
}
|
||||
// first byte is not quote
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
// no first byte
|
||||
}
|
||||
} else { Some(0 as u8) }
|
||||
} else {
|
||||
Some(0 as u8)
|
||||
}
|
||||
}
|
||||
None =>{ Some(0) }
|
||||
None => Some(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,27 +84,39 @@ fn get_provided(
|
|||
// a base,
|
||||
// and an offset for index after all
|
||||
// initial spacing, sign, base prefix, and leading zeroes
|
||||
fn get_inprefix(
|
||||
str_in : &String,
|
||||
field_type : &FieldType
|
||||
) -> InPrefix {
|
||||
fn get_inprefix(str_in: &String, field_type: &FieldType) -> InPrefix {
|
||||
let mut str_it = str_in.chars();
|
||||
let mut ret = InPrefix { radix_in: Base::Ten, sign: 1, offset: 0 };
|
||||
let mut ret = InPrefix {
|
||||
radix_in: Base::Ten,
|
||||
sign: 1,
|
||||
offset: 0,
|
||||
};
|
||||
let mut topchar = str_it.next().clone();
|
||||
//skip spaces and ensure topchar is the first non-space char
|
||||
// skip spaces and ensure topchar is the first non-space char
|
||||
// (or None if none exists)
|
||||
loop {
|
||||
match topchar
|
||||
{
|
||||
Some(' ')=>{ret.offset+=1; topchar=str_it.next();},
|
||||
_=>{ break; }
|
||||
}
|
||||
match topchar {
|
||||
Some(' ') => {
|
||||
ret.offset += 1;
|
||||
topchar = str_it.next();
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//parse sign
|
||||
// parse sign
|
||||
match topchar {
|
||||
Some('+')=>{ ret.offset+=1; topchar=str_it.next(); }
|
||||
Some('-')=>{ ret.sign = -1; ret.offset+=1; topchar=str_it.next(); }
|
||||
_=>{}
|
||||
Some('+') => {
|
||||
ret.offset += 1;
|
||||
topchar = str_it.next();
|
||||
}
|
||||
Some('-') => {
|
||||
ret.sign = -1;
|
||||
ret.offset += 1;
|
||||
topchar = str_it.next();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// we want to exit with offset being
|
||||
// the index of the first non-zero
|
||||
|
|
@ -128,20 +143,20 @@ fn get_inprefix(
|
|||
ret.offset += 2;
|
||||
ret.radix_in = Base::Hex;
|
||||
do_clean_lead_zeroes = true;
|
||||
},
|
||||
}
|
||||
e @ '0'...'9' => {
|
||||
ret.offset+=1;
|
||||
ret.offset += 1;
|
||||
match *field_type {
|
||||
FieldType::Intf => {
|
||||
FieldType::Intf => {
|
||||
ret.radix_in = Base::Octal;
|
||||
},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if e == '0' {
|
||||
do_clean_lead_zeroes = true;
|
||||
}
|
||||
}
|
||||
_=>{}
|
||||
_ => {}
|
||||
}
|
||||
if do_clean_lead_zeroes {
|
||||
let mut first = true;
|
||||
|
|
@ -159,22 +174,26 @@ fn get_inprefix(
|
|||
// current offset is not the final offset.
|
||||
match ch_zero {
|
||||
'0' => {
|
||||
if !(is_hex && first) { ret.offset+=1; }
|
||||
},
|
||||
//if decimal, keep last zero if one exists
|
||||
//(it's possible for last zero to
|
||||
if !(is_hex && first) {
|
||||
ret.offset += 1;
|
||||
}
|
||||
}
|
||||
// if decimal, keep last zero if one exists
|
||||
// (it's possible for last zero to
|
||||
// not exist at this branch if we're in hex input)
|
||||
'.' => {
|
||||
break
|
||||
},
|
||||
//other digit, etc.
|
||||
'.' => break,
|
||||
// other digit, etc.
|
||||
_ => {
|
||||
if !(is_hex && first) { ret.offset+=1; }
|
||||
break
|
||||
if !(is_hex && first) {
|
||||
ret.offset += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if first { first = false; }
|
||||
|
||||
if first {
|
||||
first = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -185,12 +204,9 @@ fn get_inprefix(
|
|||
// this is the function a Sub's print will delegate to
|
||||
// if it is a numeric field, passing the field details
|
||||
// and an iterator to the argument
|
||||
pub fn num_format(
|
||||
field: &FormatField,
|
||||
in_str_opt: Option<&String>
|
||||
) -> Option<String> {
|
||||
pub fn num_format(field: &FormatField, in_str_opt: Option<&String>) -> Option<String> {
|
||||
|
||||
|
||||
|
||||
let fchar = field.field_char.clone();
|
||||
|
||||
// num format mainly operates by further delegating to one of
|
||||
|
|
@ -198,13 +214,15 @@ pub fn num_format(
|
|||
// see formatter.rs for more details
|
||||
|
||||
// to do switch to static dispatch
|
||||
let fmtr : Box<Formatter> = match *field.field_type {
|
||||
let fmtr: Box<Formatter> = match *field.field_type {
|
||||
FieldType::Intf => Box::new(Intf::new()),
|
||||
FieldType::Floatf => Box::new(Floatf::new()),
|
||||
FieldType::CninetyNineHexFloatf => Box::new(CninetyNineHexFloatf::new()),
|
||||
FieldType::Scif => Box::new(Scif::new()),
|
||||
FieldType::Decf => Box::new(Decf::new()),
|
||||
_ => { panic!("asked to do num format with non-num fieldtype"); }
|
||||
_ => {
|
||||
panic!("asked to do num format with non-num fieldtype");
|
||||
}
|
||||
};
|
||||
let prim_opt=
|
||||
// if we can get an assumed value from looking at the first
|
||||
|
|
@ -258,13 +276,8 @@ pub fn num_format(
|
|||
};
|
||||
// if we have a formatPrimitive, print its results
|
||||
// according to the field-char appropriate Formatter
|
||||
if let Some(prim) = prim_opt {
|
||||
Some(
|
||||
fmtr.primitive_to_str(
|
||||
&prim,
|
||||
field.clone()
|
||||
)
|
||||
)
|
||||
if let Some(prim) = prim_opt {
|
||||
Some(fmtr.primitive_to_str(&prim, field.clone()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue