strconv: vfmt everything

pull/10508/head
Delyan Angelov 2021-06-18 17:59:56 +03:00
parent 5dff8dc097
commit de384f1cc8
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
17 changed files with 1544 additions and 1252 deletions

View File

@ -43,7 +43,6 @@ const (
'vlib/',
]
vfmt_known_failing_exceptions = arrays.merge(verify_known_failing_exceptions, [
'vlib/strconv/' /* prevent conflicts, till the new pure V string interpolation is merged */,
'vlib/term/ui/input.v' /* comment after a struct embed is removed */,
'vlib/regex/regex_test.v' /* contains meaningfull formatting of the test case data */,
'vlib/readline/readline_test.v' /* vfmt eats `{ Readline }` from `import readline { Readline }` */,

View File

@ -414,7 +414,6 @@ Public functions
// atof64 return a f64 from a string doing a parsing operation
pub fn atof64(s string) f64 {
mut pn := PrepNumber{}
mut res_parsing := 0
mut res := Float64u{}

View File

@ -1,4 +1,5 @@
import strconv
/**********************************************************************
*
* String to float Test
@ -18,7 +19,7 @@ fn test_atof() {
-0.004,
0.0,
-0.0,
31234567890123
31234567890123,
]
// strings
@ -33,28 +34,27 @@ fn test_atof() {
]
// check conversion case 1 string <=> string
for c,x in src_num {
for c, x in src_num {
// slow atof
assert strconv.atof64(src_num_str[c]).strlong() == x.strlong()
// quick atof
mut s1 := (strconv.atof_quick(src_num_str[c]).str())
mut s2 := (x.str())
delta := s1.f64() - s2.f64()
//println("$s1 $s2 $delta")
// println("$s1 $s2 $delta")
assert delta < f64(1e-16)
// test C.atof
n1 := x.strsci(18)
n2 := f64(C.atof(&char(src_num_str[c].str))).strsci(18)
//println("$n1 $n2")
// println("$n1 $n2")
assert n1 == n2
}
// check conversion case 2 string <==> f64
// we don't test atof_quick beacuse we already know the rounding error
for c,x in src_num_str {
for c, x in src_num_str {
b := src_num[c].strlong()
a1 := strconv.atof64(x).strlong()
assert a1 == b
@ -62,14 +62,14 @@ fn test_atof() {
// special cases
mut f1 := f64(0.0)
mut ptr := unsafe {&u64(&f1)}
ptr = unsafe {&u64(&f1)}
mut ptr := unsafe { &u64(&f1) }
ptr = unsafe { &u64(&f1) }
// double_plus_zero
f1=0.0
f1 = 0.0
assert *ptr == u64(0x0000000000000000)
// double_minus_zero
f1=-0.0
f1 = -0.0
assert *ptr == u64(0x8000000000000000)
println("DONE!")
println('DONE!')
}

File diff suppressed because one or more lines are too long

View File

@ -69,15 +69,15 @@ pub fn common_parse_uint2(s string, _base int, _bit_size int) (u64, int) {
return u64(0), -1
}
if bit_size == 0 {
bit_size = int_size
bit_size = strconv.int_size
} else if bit_size < 0 || bit_size > 64 {
// return error('parse_uint: bitsize error $s - $bit_size')
return u64(0), -2
}
// Cutoff is the smallest number such that cutoff*base > maxUint64.
// Use compile-time constants for common cases.
cutoff := max_u64 / u64(base) + u64(1)
max_val := if bit_size == 64 { max_u64 } else { (u64(1) << u64(bit_size)) - u64(1) }
cutoff := strconv.max_u64 / u64(base) + u64(1)
max_val := if bit_size == 64 { strconv.max_u64 } else { (u64(1) << u64(bit_size)) - u64(1) }
mut n := u64(0)
for i in start_index .. s.len {
c := s[i]
@ -144,7 +144,7 @@ pub fn common_parse_int(_s string, base int, _bit_size int, error_on_non_digit b
return i64(0)
}
if bit_size == 0 {
bit_size = int_size
bit_size = strconv.int_size
}
// TODO: check should u64(bit_size-1) be size of int (32)?
cutoff := u64(1) << u64(bit_size - 1)
@ -156,11 +156,7 @@ pub fn common_parse_int(_s string, base int, _bit_size int, error_on_non_digit b
// return error('parse_int: range error $s0')
return -i64(cutoff)
}
return if neg {
-i64(un)
} else {
i64(un)
}
return if neg { -i64(un) } else { i64(un) }
}
// parse_int interprets a string s in the given base (0, 2 to 36) and
@ -184,9 +180,8 @@ pub fn atoi(s string) ?int {
if s == '' {
return error('strconv.atoi: parsing "$s": invalid syntax ')
}
if (int_size == 32 && (0 < s.len &&
s.len < 10)) ||
(int_size == 64 && (0 < s.len && s.len < 19)) {
if (strconv.int_size == 32 && (0 < s.len && s.len < 10))
|| (strconv.int_size == 64 && (0 < s.len && s.len < 19)) {
// Fast path for small integers that fit int type.
mut start_idx := 0
if s[0] == `-` || s[0] == `+` {
@ -205,11 +200,7 @@ pub fn atoi(s string) ?int {
}
n = n * 10 + int(ch)
}
return if s[0] == `-` {
-n
} else {
n
}
return if s[0] == `-` { -n } else { n }
}
// Slow path for invalid, big, or underscored integers.
int64 := parse_int(s, 10, 0)
@ -233,8 +224,8 @@ fn underscore_ok(s string) bool {
}
// Optional base prefix.
mut hex := false
if s.len - i >= 2 && s[i] == `0` &&
(byte_to_lower(s[i + 1]) == `b` || byte_to_lower(s[i + 1]) == `o` || byte_to_lower(s[i + 1]) == `x`) {
if s.len - i >= 2 && s[i] == `0` && (byte_to_lower(s[i + 1]) == `b`
|| byte_to_lower(s[i + 1]) == `o` || byte_to_lower(s[i + 1]) == `x`) {
saw = `0` // base prefix counts as a digit for "underscore as digit separator"
hex = byte_to_lower(s[i + 1]) == `x`
i += 2
@ -242,8 +233,8 @@ fn underscore_ok(s string) bool {
// Number proper.
for ; i < s.len; i++ {
// Digits are always okay.
if (`0` <= s[i] && s[i] <= `9`) ||
(hex && `a` <= byte_to_lower(s[i]) && byte_to_lower(s[i]) <= `f`) {
if (`0` <= s[i] && s[i] <= `9`) || (hex && `a` <= byte_to_lower(s[i])
&& byte_to_lower(s[i]) <= `f`) {
saw = `0`
continue
}

View File

@ -1,4 +1,5 @@
module strconv
/*=============================================================================
f32 to string
@ -20,7 +21,7 @@ https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea
=============================================================================*/
// pow of ten table used by n_digit reduction
const(
const (
ten_pow_table_32 = [
u32(1),
u32(10),
@ -40,34 +41,34 @@ const(
//=============================================================================
// Conversion Functions
//=============================================================================
const(
mantbits32 = u32(23)
expbits32 = u32(8)
bias32 = 127 // f32 exponent bias
maxexp32 = 255
const (
mantbits32 = u32(23)
expbits32 = u32(8)
bias32 = 127 // f32 exponent bias
maxexp32 = 255
)
// max 46 char
// -3.40282346638528859811704183484516925440e+38
[direct_array_access]
pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string {
n_digit := i_n_digit + 1
pad_digit := i_pad_digit + 1
mut out := d.m
//mut out_len := decimal_len_32(out)
mut out_len := dec_digits(out)
n_digit := i_n_digit + 1
pad_digit := i_pad_digit + 1
mut out := d.m
// mut out_len := decimal_len_32(out)
mut out_len := dec_digits(out)
out_len_original := out_len
mut fw_zeros := 0
if pad_digit > out_len {
fw_zeros = pad_digit -out_len
fw_zeros = pad_digit - out_len
}
mut buf := []byte{len:int(out_len + 5 + 1 +1)} // sign + mant_len + . + e + e_sign + exp_len(2) + \0}
mut buf := []byte{len: int(out_len + 5 + 1 + 1)} // sign + mant_len + . + e + e_sign + exp_len(2) + \0}
mut i := 0
if neg {
buf[i]=`-`
buf[i] = `-`
i++
}
@ -77,16 +78,16 @@ pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string
}
if n_digit < out_len {
//println("orig: ${out_len_original}")
out += ten_pow_table_32[out_len - n_digit - 1] * 5 // round to up
out /= ten_pow_table_32[out_len - n_digit]
// println("orig: ${out_len_original}")
out += strconv.ten_pow_table_32[out_len - n_digit - 1] * 5 // round to up
out /= strconv.ten_pow_table_32[out_len - n_digit]
out_len = n_digit
}
y := i + out_len
mut x := 0
for x < (out_len-disp-1) {
buf[y - x] = `0` + byte(out%10)
for x < (out_len - disp - 1) {
buf[y - x] = `0` + byte(out % 10)
out /= 10
i++
x++
@ -95,8 +96,8 @@ pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string
// no decimal digits needed, end here
if i_n_digit == 0 {
unsafe {
buf[i]=0
return tos(byteptr(&buf[0]), i)
buf[i] = 0
return tos(&byte(&buf[0]), i)
}
}
@ -106,8 +107,8 @@ pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string
i++
}
if y-x >= 0 {
buf[y - x] = `0` + byte(out%10)
if y - x >= 0 {
buf[y - x] = `0` + byte(out % 10)
i++
}
@ -117,42 +118,42 @@ pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string
fw_zeros--
}
buf[i]=`e`
buf[i] = `e`
i++
mut exp := d.e + out_len_original - 1
if exp < 0 {
buf[i]=`-`
buf[i] = `-`
i++
exp = -exp
} else {
buf[i]=`+`
buf[i] = `+`
i++
}
// Always print two digits to match strconv's formatting.
d1 := exp % 10
d0 := exp / 10
buf[i]=`0` + byte(d0)
buf[i] = `0` + byte(d0)
i++
buf[i]=`0` + byte(d1)
buf[i] = `0` + byte(d1)
i++
buf[i]=0
buf[i] = 0
return unsafe {
tos(byteptr(&buf[0]), i)
tos(&byte(&buf[0]), i)
}
}
fn f32_to_decimal_exact_int(i_mant u32, exp u32) (Dec32,bool) {
fn f32_to_decimal_exact_int(i_mant u32, exp u32) (Dec32, bool) {
mut d := Dec32{}
e := exp - bias32
if e > mantbits32 {
e := exp - strconv.bias32
if e > strconv.mantbits32 {
return d, false
}
shift := mantbits32 - e
shift := strconv.mantbits32 - e
mant := i_mant | 0x0080_0000 // implicit 1
//mant := i_mant | (1 << mantbits32) // implicit 1
// mant := i_mant | (1 << mantbits32) // implicit 1
d.m = mant >> shift
if (d.m << shift) != mant {
return d, false
@ -170,28 +171,28 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
if exp == 0 {
// We subtract 2 so that the bounds computation has
// 2 additional bits.
e2 = 1 - bias32 - int(mantbits32) - 2
e2 = 1 - strconv.bias32 - int(strconv.mantbits32) - 2
m2 = mant
} else {
e2 = int(exp) - bias32 - int(mantbits32) - 2
m2 = (u32(1) << mantbits32) | mant
e2 = int(exp) - strconv.bias32 - int(strconv.mantbits32) - 2
m2 = (u32(1) << strconv.mantbits32) | mant
}
even := (m2 & 1) == 0
even := (m2 & 1) == 0
accept_bounds := even
// Step 2: Determine the interval of valid decimal representations.
mv := u32(4 * m2)
mp := u32(4 * m2 + 2)
mv := u32(4 * m2)
mp := u32(4 * m2 + 2)
mm_shift := bool_to_u32(mant != 0 || exp <= 1)
mm := u32(4 * m2 - 1 - mm_shift)
mm := u32(4 * m2 - 1 - mm_shift)
mut vr := u32(0)
mut vp := u32(0)
mut vm := u32(0)
mut e10 := 0
mut vr := u32(0)
mut vp := u32(0)
mut vm := u32(0)
mut e10 := 0
mut vm_is_trailing_zeros := false
mut vr_is_trailing_zeros := false
mut last_removed_digit := byte(0)
mut last_removed_digit := byte(0)
if e2 >= 0 {
q := log10_pow2(e2)
@ -202,7 +203,7 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
vr = mul_pow5_invdiv_pow2(mv, q, i)
vp = mul_pow5_invdiv_pow2(mp, q, i)
vm = mul_pow5_invdiv_pow2(mm, q, i)
if q != 0 && (vp-1)/10 <= vm/10 {
if q != 0 && (vp - 1) / 10 <= vm / 10 {
// We need to know one removed digit even if we are not
// going to loop below. We could use q = X - 1 above,
// except that would require 33 bits for the result, and
@ -232,7 +233,7 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
vr = mul_pow5_div_pow2(mv, u32(i), j)
vp = mul_pow5_div_pow2(mp, u32(i), j)
vm = mul_pow5_div_pow2(mm, u32(i), j)
if q != 0 && ((vp-1)/10) <= vm/10 {
if q != 0 && ((vp - 1) / 10) <= vm / 10 {
j = int(q) - 1 - (pow5_bits(i + 1) - pow5_num_bits_32)
last_removed_digit = byte(mul_pow5_div_pow2(mv, u32(i + 1), j) % 10)
}
@ -258,10 +259,10 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
// Step 4: Find the shortest decimal representation
// in the interval of valid representations.
mut removed := 0
mut out := u32(0)
mut out := u32(0)
if vm_is_trailing_zeros || vr_is_trailing_zeros {
// General case, which happens rarely (~4.0%).
for vp/10 > vm/10 {
for vp / 10 > vm / 10 {
vm_is_trailing_zeros = vm_is_trailing_zeros && (vm % 10) == 0
vr_is_trailing_zeros = vr_is_trailing_zeros && (last_removed_digit == 0)
last_removed_digit = byte(vr % 10)
@ -271,7 +272,7 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
removed++
}
if vm_is_trailing_zeros {
for vm%10 == 0 {
for vm % 10 == 0 {
vr_is_trailing_zeros = vr_is_trailing_zeros && (last_removed_digit == 0)
last_removed_digit = byte(vr % 10)
vr /= 10
@ -294,7 +295,7 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
// Specialized for the common case (~96.0%). Percentages below
// are relative to this. Loop iterations below (approximately):
// 0: 13.6%, 1: 70.7%, 2: 14.1%, 3: 1.39%, 4: 0.14%, 5+: 0.01%
for vp/10 > vm/10 {
for vp / 10 > vm / 10 {
last_removed_digit = byte(vr % 10)
vr /= 10
vp /= 10
@ -306,7 +307,10 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
out = vr + bool_to_u32(vr == vm || last_removed_digit >= 5)
}
return Dec32{m: out e: e10 + removed}
return Dec32{
m: out
e: e10 + removed
}
}
//=============================================================================
@ -317,52 +321,52 @@ fn f32_to_decimal(mant u32, exp u32) Dec32 {
pub fn f32_to_str(f f32, n_digit int) string {
mut u1 := Uf32{}
u1.f = f
u := unsafe {u1.u}
u := unsafe { u1.u }
neg := (u >> (mantbits32 + expbits32)) != 0
mant := u & ((u32(1) << mantbits32) - u32(1))
exp := (u >> mantbits32) & ((u32(1) << expbits32) - u32(1))
neg := (u >> (strconv.mantbits32 + strconv.expbits32)) != 0
mant := u & ((u32(1) << strconv.mantbits32) - u32(1))
exp := (u >> strconv.mantbits32) & ((u32(1) << strconv.expbits32) - u32(1))
//println("${neg} ${mant} e ${exp-bias32}")
// println("${neg} ${mant} e ${exp-bias32}")
// Exit early for easy cases.
if (exp == maxexp32) || (exp == 0 && mant == 0) {
if (exp == strconv.maxexp32) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0)
}
mut d, ok := f32_to_decimal_exact_int(mant, exp)
if !ok {
//println("with exp form")
// println("with exp form")
d = f32_to_decimal(mant, exp)
}
//println("${d.m} ${d.e}")
return d.get_string_32(neg, n_digit,0)
// println("${d.m} ${d.e}")
return d.get_string_32(neg, n_digit, 0)
}
// f32_to_str return a string in scientific notation with max n_digit after the dot
pub fn f32_to_str_pad(f f32, n_digit int) string {
mut u1 := Uf32{}
u1.f = f
u := unsafe {u1.u}
u := unsafe { u1.u }
neg := (u >> (mantbits32 + expbits32)) != 0
mant := u & ((u32(1) << mantbits32) - u32(1))
exp := (u >> mantbits32) & ((u32(1) << expbits32) - u32(1))
neg := (u >> (strconv.mantbits32 + strconv.expbits32)) != 0
mant := u & ((u32(1) << strconv.mantbits32) - u32(1))
exp := (u >> strconv.mantbits32) & ((u32(1) << strconv.expbits32) - u32(1))
//println("${neg} ${mant} e ${exp-bias32}")
// println("${neg} ${mant} e ${exp-bias32}")
// Exit early for easy cases.
if (exp == maxexp32) || (exp == 0 && mant == 0) {
if (exp == strconv.maxexp32) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0)
}
mut d, ok := f32_to_decimal_exact_int(mant, exp)
if !ok {
//println("with exp form")
// println("with exp form")
d = f32_to_decimal(mant, exp)
}
//println("${d.m} ${d.e}")
// println("${d.m} ${d.e}")
return d.get_string_32(neg, n_digit, n_digit)
}

View File

@ -1,4 +1,5 @@
module strconv
/*=============================================================================
f64 to string
@ -20,7 +21,7 @@ https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea
=============================================================================*/
// pow of ten table used by n_digit reduction
const(
const (
ten_pow_table_64 = [
u64(1),
u64(10),
@ -48,21 +49,21 @@ const(
//=============================================================================
// Conversion Functions
//=============================================================================
const(
mantbits64 = u32(52)
expbits64 = u32(11)
bias64 = 1023 // f64 exponent bias
maxexp64 = 2047
const (
mantbits64 = u32(52)
expbits64 = u32(11)
bias64 = 1023 // f64 exponent bias
maxexp64 = 2047
)
[direct_array_access]
fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
mut n_digit := i_n_digit + 1
pad_digit := i_pad_digit + 1
mut out := d.m
mut d_exp := d.e
mut n_digit := i_n_digit + 1
pad_digit := i_pad_digit + 1
mut out := d.m
mut d_exp := d.e
// mut out_len := decimal_len_64(out)
mut out_len := dec_digits(out)
mut out_len := dec_digits(out)
out_len_original := out_len
mut fw_zeros := 0
@ -70,7 +71,7 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
fw_zeros = pad_digit - out_len
}
mut buf := []byte{len:(out_len + 6 + 1 +1 + fw_zeros)} // sign + mant_len + . + e + e_sign + exp_len(2) + \0}
mut buf := []byte{len: (out_len + 6 + 1 + 1 + fw_zeros)} // sign + mant_len + . + e + e_sign + exp_len(2) + \0}
mut i := 0
if neg {
@ -85,19 +86,19 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
// rounding last used digit
if n_digit < out_len {
//println("out:[$out]")
out += ten_pow_table_64[out_len - n_digit - 1] * 5 // round to up
out /= ten_pow_table_64[out_len - n_digit]
//println("out1:[$out] ${d.m / ten_pow_table_64[out_len - n_digit ]}")
if d.m / ten_pow_table_64[out_len - n_digit] < out {
// println("out:[$out]")
out += strconv.ten_pow_table_64[out_len - n_digit - 1] * 5 // round to up
out /= strconv.ten_pow_table_64[out_len - n_digit]
// println("out1:[$out] ${d.m / ten_pow_table_64[out_len - n_digit ]}")
if d.m / strconv.ten_pow_table_64[out_len - n_digit] < out {
d_exp++
n_digit++
}
//println("cmp: ${d.m/ten_pow_table_64[out_len - n_digit ]} ${out/ten_pow_table_64[out_len - n_digit ]}")
// println("cmp: ${d.m/ten_pow_table_64[out_len - n_digit ]} ${out/ten_pow_table_64[out_len - n_digit ]}")
out_len = n_digit
//println("orig: ${out_len_original} new len: ${out_len} out:[$out]")
// println("orig: ${out_len_original} new len: ${out_len} out:[$out]")
}
y := i + out_len
@ -112,8 +113,8 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
// no decimal digits needed, end here
if i_n_digit == 0 {
unsafe {
buf[i]=0
return tos(byteptr(&buf[0]), i)
buf[i] = 0
return tos(&byte(&buf[0]), i)
}
}
@ -123,7 +124,7 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
i++
}
if y-x >= 0 {
if y - x >= 0 {
buf[y - x] = `0` + byte(out % 10)
i++
}
@ -134,16 +135,16 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
fw_zeros--
}
buf[i]=`e`
buf[i] = `e`
i++
mut exp := d_exp + out_len_original - 1
if exp < 0 {
buf[i]=`-`
buf[i] = `-`
i++
exp = -exp
} else {
buf[i]=`+`
buf[i] = `+`
i++
}
@ -153,29 +154,29 @@ fn (d Dec64) get_string_64(neg bool, i_n_digit int, i_pad_digit int) string {
d1 := exp % 10
d0 := exp / 10
if d0 > 0 {
buf[i]=`0` + byte(d0)
buf[i] = `0` + byte(d0)
i++
}
buf[i]=`0` + byte(d1)
buf[i] = `0` + byte(d1)
i++
buf[i]=`0` + byte(d2)
buf[i] = `0` + byte(d2)
i++
buf[i]=0
buf[i] = 0
return unsafe {
tos(byteptr(&buf[0]), i)
tos(&byte(&buf[0]), i)
}
}
fn f64_to_decimal_exact_int(i_mant u64, exp u64) (Dec64, bool) {
mut d := Dec64{}
e := exp - bias64
if e > mantbits64 {
e := exp - strconv.bias64
if e > strconv.mantbits64 {
return d, false
}
shift := mantbits64 - e
mant := i_mant | u64(0x0010_0000_0000_0000) // implicit 1
//mant := i_mant | (1 << mantbits64) // implicit 1
shift := strconv.mantbits64 - e
mant := i_mant | u64(0x0010_0000_0000_0000) // implicit 1
// mant := i_mant | (1 << mantbits64) // implicit 1
d.m = mant >> shift
if (d.m << shift) != mant {
return d, false
@ -194,24 +195,24 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
if exp == 0 {
// We subtract 2 so that the bounds computation has
// 2 additional bits.
e2 = 1 - bias64 - int(mantbits64) - 2
e2 = 1 - strconv.bias64 - int(strconv.mantbits64) - 2
m2 = mant
} else {
e2 = int(exp) - bias64 - int(mantbits64) - 2
m2 = (u64(1) << mantbits64) | mant
e2 = int(exp) - strconv.bias64 - int(strconv.mantbits64) - 2
m2 = (u64(1) << strconv.mantbits64) | mant
}
even := (m2 & 1) == 0
even := (m2 & 1) == 0
accept_bounds := even
// Step 2: Determine the interval of valid decimal representations.
mv := u64(4 * m2)
mv := u64(4 * m2)
mm_shift := bool_to_u64(mant != 0 || exp <= 1)
// Step 3: Convert to a decimal power base uing 128-bit arithmetic.
mut vr := u64(0)
mut vp := u64(0)
mut vm := u64(0)
mut e10 := 0
mut vr := u64(0)
mut vp := u64(0)
mut vm := u64(0)
mut e10 := 0
mut vm_is_trailing_zeros := false
mut vr_is_trailing_zeros := false
@ -223,8 +224,8 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
i := -e2 + int(q) + k
mul := pow5_inv_split_64[q]
vr = mul_shift_64(u64(4) * m2 , mul, i)
vp = mul_shift_64(u64(4) * m2 + u64(2) , mul, i)
vr = mul_shift_64(u64(4) * m2, mul, i)
vp = mul_shift_64(u64(4) * m2 + u64(2), mul, i)
vm = mul_shift_64(u64(4) * m2 - u64(1) - mm_shift, mul, i)
if q <= 21 {
// This should use q <= 22, but I think 21 is also safe.
@ -237,7 +238,8 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
// Same as min(e2 + (^mm & 1), pow5Factor64(mm)) >= q
// <=> e2 + (^mm & 1) >= q && pow5Factor64(mm) >= q
// <=> true && pow5Factor64(mm) >= q, since e2 >= q.
vm_is_trailing_zeros = multiple_of_power_of_five_64(mv - 1 - mm_shift, q)
vm_is_trailing_zeros = multiple_of_power_of_five_64(mv - 1 - mm_shift,
q)
} else if multiple_of_power_of_five_64(mv + 2, q) {
vp--
}
@ -250,8 +252,8 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
k := pow5_bits(i) - pow5_num_bits_64
j := int(q) - k
mul := pow5_split_64[i]
vr = mul_shift_64(u64(4) * m2 , mul, j)
vp = mul_shift_64(u64(4) * m2 + u64(2) , mul, j)
vr = mul_shift_64(u64(4) * m2, mul, j)
vp = mul_shift_64(u64(4) * m2 + u64(2), mul, j)
vm = mul_shift_64(u64(4) * m2 - u64(1) - mm_shift, mul, j)
if q <= 1 {
// {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
@ -276,9 +278,9 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
// Step 4: Find the shortest decimal representation
// in the interval of valid representations.
mut removed := 0
mut removed := 0
mut last_removed_digit := byte(0)
mut out := u64(0)
mut out := u64(0)
// On average, we remove ~2 digits.
if vm_is_trailing_zeros || vr_is_trailing_zeros {
// General case, which happens rarely (~0.7%).
@ -355,7 +357,10 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
out = vr + bool_to_u64(vr == vm || round_up)
}
return Dec64{m: out, e: e10 + removed}
return Dec64{
m: out
e: e10 + removed
}
}
//=============================================================================
@ -366,24 +371,24 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
pub fn f64_to_str(f f64, n_digit int) string {
mut u1 := Uf64{}
u1.f = f
u := unsafe {u1.u}
u := unsafe { u1.u }
neg := (u >> (mantbits64 + expbits64)) != 0
mant := u & ((u64(1) << mantbits64) - u64(1))
exp := (u >> mantbits64) & ((u64(1) << expbits64) - u64(1))
//println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}")
neg := (u >> (strconv.mantbits64 + strconv.expbits64)) != 0
mant := u & ((u64(1) << strconv.mantbits64) - u64(1))
exp := (u >> strconv.mantbits64) & ((u64(1) << strconv.expbits64) - u64(1))
// println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}")
// Exit early for easy cases.
if (exp == maxexp64) || (exp == 0 && mant == 0) {
if (exp == strconv.maxexp64) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0)
}
mut d, ok := f64_to_decimal_exact_int(mant, exp)
if !ok {
//println("to_decimal")
// println("to_decimal")
d = f64_to_decimal(mant, exp)
}
//println("${d.m} ${d.e}")
// println("${d.m} ${d.e}")
return d.get_string_64(neg, n_digit, 0)
}
@ -391,23 +396,23 @@ pub fn f64_to_str(f f64, n_digit int) string {
pub fn f64_to_str_pad(f f64, n_digit int) string {
mut u1 := Uf64{}
u1.f = f
u := unsafe {u1.u}
u := unsafe { u1.u }
neg := (u >> (mantbits64 + expbits64)) != 0
mant := u & ((u64(1) << mantbits64) - u64(1))
exp := (u >> mantbits64) & ((u64(1) << expbits64) - u64(1))
//println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}")
neg := (u >> (strconv.mantbits64 + strconv.expbits64)) != 0
mant := u & ((u64(1) << strconv.mantbits64) - u64(1))
exp := (u >> strconv.mantbits64) & ((u64(1) << strconv.expbits64) - u64(1))
// println("s:${neg} mant:${mant} exp:${exp} float:${f} byte:${u1.u:016lx}")
// Exit early for easy cases.
if (exp == maxexp64) || (exp == 0 && mant == 0) {
if (exp == strconv.maxexp64) || (exp == 0 && mant == 0) {
return get_string_special(neg, exp == 0, mant == 0)
}
mut d, ok := f64_to_decimal_exact_int(mant, exp)
if !ok {
//println("to_decimal")
// println("to_decimal")
d = f64_to_decimal(mant, exp)
}
//println("DEBUG: ${d.m} ${d.e}")
// println("DEBUG: ${d.m} ${d.e}")
return d.get_string_64(neg, n_digit, n_digit)
}

View File

@ -1,7 +1,6 @@
module strconv
/*
printf/sprintf V implementation
Copyright (c) 2020 Dario Deledda. All rights reserved.
@ -9,9 +8,7 @@ Use of this source code is governed by an MIT license
that can be found in the LICENSE file.
This file contains the printf/sprintf functions
*/
import strings
pub enum Align_text {
@ -21,11 +18,9 @@ pub enum Align_text {
}
/*
Float conversion utility
*/
const(
const (
// rounding value
dec_round = [
f64(0.5),
@ -81,19 +76,17 @@ const(
// max float 1.797693134862315708145274237317043567981e+308
/*
Single format functions
Single format functions
*/
pub struct BF_param {
pub mut:
pad_ch byte = byte(` `) // padding char
len0 int = -1 // default len for whole the number or string
len1 int = 6 // number of decimal digits, if needed
positive bool = true // mandatory: the sign of the number passed
sign_flag bool // flag for print sign as prefix in padding
allign Align_text = .right // alignment of the string
rm_tail_zero bool // remove the tail zeros from floats
pad_ch byte = byte(` `) // padding char
len0 int = -1 // default len for whole the number or string
len1 int = 6 // number of decimal digits, if needed
positive bool = true // mandatory: the sign of the number passed
sign_flag bool // flag for print sign as prefix in padding
allign Align_text = .right // alignment of the string
rm_tail_zero bool // remove the tail zeros from floats
}
pub fn format_str(s string, p BF_param) string {
@ -106,13 +99,13 @@ pub fn format_str(s string, p BF_param) string {
}
mut res := strings.new_builder(s.len + dif)
if p.allign == .right {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
res.write_string(s)
if p.allign == .left {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}

View File

@ -6,6 +6,7 @@ that can be found in the LICENSE file.
This file contains string interpolation V functions
=============================================================================*/
module strconv
import strings
// strings.Builder version of format_str
@ -19,15 +20,15 @@ pub fn format_str_sb(s string, p BF_param, mut sb strings.Builder) {
sb.write_string(s)
return
}
if p.allign == .right {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
sb.write_b(p.pad_ch)
}
}
sb.write_string(s)
if p.allign == .left {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
sb.write_b(p.pad_ch)
}
}
@ -60,10 +61,10 @@ pub fn format_dec_sb(d u64, p BF_param, mut res strings.Builder) {
}
}
// write the pad chars
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
}
if !sign_written {
// no pad char, write the sign before the number
@ -103,10 +104,14 @@ pub fn format_dec_sb(d u64, p BF_param, mut res strings.Builder) {
// calculate the digit_pairs start index
d_i = (n - (n1 * 100)) << 1
n = n1
unsafe{ buf[i] = digit_pairs.str[d_i] }
unsafe {
buf[i] = strconv.digit_pairs.str[d_i]
}
i--
d_i++
unsafe{ buf[i] = digit_pairs.str[d_i] }
unsafe {
buf[i] = strconv.digit_pairs.str[d_i]
}
i--
}
i++
@ -114,8 +119,7 @@ pub fn format_dec_sb(d u64, p BF_param, mut res strings.Builder) {
if d_i < 20 {
i++
}
unsafe{ res.write_ptr(&buf[i],n_char) }
unsafe { res.write_ptr(&buf[i], n_char) }
} else {
// we have a zero no need of more code!
res.write_b(`0`)
@ -123,19 +127,16 @@ pub fn format_dec_sb(d u64, p BF_param, mut res strings.Builder) {
//===========================================
if p.allign == .left {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
return
}
[manualfree]
[direct_array_access]
[direct_array_access; manualfree]
pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
unsafe{
unsafe {
// we add the rounding value
s := f64_to_str(f + dec_round[dec_digit], 18)
// check for +inf -inf Nan
@ -144,13 +145,13 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
}
m_sgn_flag := false
mut sgn := 1
mut b := [26]byte{}
mut d_pos := 1
mut i := 0
mut i1 := 0
mut exp := 0
mut exp_sgn := 1
mut sgn := 1
mut b := [26]byte{}
mut d_pos := 1
mut i := 0
mut i1 := 0
mut exp := 0
mut exp_sgn := 1
mut dot_res_sp := -1
@ -162,8 +163,7 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
} else if c == `+` {
sgn = 1
i++
}
else if c >= `0` && c <= `9` {
} else if c >= `0` && c <= `9` {
b[i1] = c
i1++
i++
@ -171,7 +171,7 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
if sgn > 0 {
d_pos = i
} else {
d_pos = i-1
d_pos = i - 1
}
i++
} else if c == `e` {
@ -179,7 +179,7 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
break
} else {
s.free()
return "[Float conversion error!!]"
return '[Float conversion error!!]'
}
}
b[i1] = 0
@ -200,11 +200,11 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
}
// allocate exp+32 chars for the return string
//mut res := []byte{len:exp+32,init:`0`}
mut res := []byte{len: exp+32, init: 0}
mut r_i := 0 // result string buffer index
// mut res := []byte{len:exp+32,init:`0`}
mut res := []byte{len: exp + 32, init: 0}
mut r_i := 0 // result string buffer index
//println("s:${sgn} b:${b[0]} es:${exp_sgn} exp:${exp}")
// println("s:${sgn} b:${b[0]} es:${exp_sgn} exp:${exp}")
// s no more needed
s.free()
@ -239,14 +239,14 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
r_i++
exp--
}
//println("exp: $exp $r_i $dot_res_sp")
// println("exp: $exp $r_i $dot_res_sp")
} else {
mut dot_p := true
for exp > 0 {
res[r_i] = `0`
r_i++
exp--
if dot_p {
if dot_p {
dot_res_sp = r_i
res[r_i] = `.`
r_i++
@ -266,14 +266,14 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
res.free()
return tmp_res
}
//println("r_i-d_pos: ${r_i - d_pos}")
// println("r_i-d_pos: ${r_i - d_pos}")
if dot_res_sp >= 0 {
if (r_i - dot_res_sp) > dec_digit {
r_i = dot_res_sp + dec_digit + 1
}
res[r_i] = 0
//println("result: [${tos(&res[0],r_i)}]")
// println("result: [${tos(&res[0],r_i)}]")
tmp_res := tos(res.data, r_i).clone()
res.free()
return tmp_res
@ -293,19 +293,18 @@ pub fn f64_to_str_lnd1(f f64, dec_digit int) string {
res.free()
return tmp_res
}
}
}
// strings.Builder version of format_fl
[manualfree]
pub fn format_fl(f f64, p BF_param) string {
unsafe{
mut s := ""
//mut fs := "1.2343"
mut fs := f64_to_str_lnd1(if f >= 0.0 {f} else {-f}, p.len1)
//println("Dario")
//println(fs)
unsafe {
mut s := ''
// mut fs := "1.2343"
mut fs := f64_to_str_lnd1(if f >= 0.0 { f } else { -f }, p.len1)
// println("Dario")
// println(fs)
// error!!
if fs[0] == `[` {
@ -318,7 +317,7 @@ pub fn format_fl(f f64, p BF_param) string {
fs = remove_tail_zeros(fs)
tmp.free()
}
mut res := strings.new_builder( if p.len0 > fs.len { p.len0 } else { fs.len })
mut res := strings.new_builder(if p.len0 > fs.len { p.len0 } else { fs.len })
mut sign_len_diff := 0
if p.pad_ch == `0` {
@ -338,7 +337,7 @@ pub fn format_fl(f f64, p BF_param) string {
if p.positive {
if p.sign_flag {
tmp := s
s = "+" + fs
s = '+' + fs
tmp.free()
} else {
tmp := s
@ -347,7 +346,7 @@ pub fn format_fl(f f64, p BF_param) string {
}
} else {
tmp := s
s = "-" + fs
s = '-' + fs
tmp.free()
}
}
@ -355,18 +354,17 @@ pub fn format_fl(f f64, p BF_param) string {
dif := p.len0 - s.len + sign_len_diff
if p.allign == .right {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
res.write_string(s)
if p.allign == .left {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
s.free()
fs.free()
tmp_res := res.str()
@ -377,13 +375,13 @@ pub fn format_fl(f f64, p BF_param) string {
[manualfree]
pub fn format_es(f f64, p BF_param) string {
unsafe{
mut s := ""
mut fs := f64_to_str_pad(if f> 0 {f} else {-f},p.len1)
unsafe {
mut s := ''
mut fs := f64_to_str_pad(if f > 0 { f } else { -f }, p.len1)
if p.rm_tail_zero {
fs = remove_tail_zeros(fs)
}
mut res := strings.new_builder( if p.len0 > fs.len { p.len0 } else { fs.len })
mut res := strings.new_builder(if p.len0 > fs.len { p.len0 } else { fs.len })
mut sign_len_diff := 0
if p.pad_ch == `0` {
@ -403,7 +401,7 @@ pub fn format_es(f f64, p BF_param) string {
if p.positive {
if p.sign_flag {
tmp := s
s = "+" + fs
s = '+' + fs
tmp.free()
} else {
tmp := s
@ -412,20 +410,20 @@ pub fn format_es(f f64, p BF_param) string {
}
} else {
tmp := s
s = "-" + fs
s = '-' + fs
tmp.free()
}
}
dif := p.len0 - s.len + sign_len_diff
if p.allign == .right {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
res.write_string(s)
if p.allign == .left {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
@ -439,19 +437,19 @@ pub fn format_es(f f64, p BF_param) string {
[direct_array_access]
pub fn remove_tail_zeros(s string) string {
unsafe{
unsafe {
mut buf := malloc_noscan(s.len + 1)
mut i_d := 0
mut i_s := 0
// skip spaces
for i_s < s.len && s[i_s] !in [`-`,`+`] && (s[i_s] > `9` || s[i_s] < `0`) {
for i_s < s.len && s[i_s] !in [`-`, `+`] && (s[i_s] > `9` || s[i_s] < `0`) {
buf[i_d] = s[i_s]
i_s++
i_d++
}
// sign
if i_s < s.len && s[i_s] in [`-`,`+`] {
if i_s < s.len && s[i_s] in [`-`, `+`] {
buf[i_d] = s[i_s]
i_s++
i_d++

View File

@ -1,107 +1,107 @@
import strconv
fn test_format(){
mut temp_s := ""
mut tmp_str:= ""
a0 := u32(10)
b0 := 200
c0 := byte(12)
s0 := "ciAo"
fn test_format() {
mut temp_s := ''
mut tmp_str := ''
a0 := u32(10)
b0 := 200
c0 := byte(12)
s0 := 'ciAo'
ch0 := `B`
f0 := 0.312345
f1 := 200000.0
f2 := -1234.300e6
f3 := 1234.300e-6
sc0 := "ciao: [%-08u] %d %hhd [%8s] [%08X] [%-20.4f] [%-20.4f] [%c]"
temp_s = strconv.v_sprintf(sc0 ,a0 ,b0 ,c0 ,s0, b0 ,f0, f1, ch0)
tmp_str = "ciao: [10 ] 200 12 [ ciAo] [000000C8] [0.3123 ] [200000.0000 ] [B]"
//C.printf(sc0.str,a0 ,b0 ,c0 ,s0.str ,b0 ,f0, f1, ch0)
//println("\n$temp_s")
f0 := 0.312345
f1 := 200000.0
f2 := -1234.300e6
f3 := 1234.300e-6
sc0 := 'ciao: [%-08u] %d %hhd [%8s] [%08X] [%-20.4f] [%-20.4f] [%c]'
temp_s = strconv.v_sprintf(sc0, a0, b0, c0, s0, b0, f0, f1, ch0)
tmp_str = 'ciao: [10 ] 200 12 [ ciAo] [000000C8] [0.3123 ] [200000.0000 ] [B]'
// C.printf(sc0.str,a0 ,b0 ,c0 ,s0.str ,b0 ,f0, f1, ch0)
// println("\n$temp_s")
assert tmp_str == temp_s
a := byte(12)
b := i16(13)
c := 14
d := i64(15)
sc1 := "==>%hhd %hd %d %ld"
temp_s = strconv.v_sprintf(sc1, a ,b ,c, d)
tmp_str = "==>12 13 14 15"
//C.printf(sc1.str, a ,b ,c, d)
//println("\n$temp_s")
sc1 := '==>%hhd %hd %d %ld'
temp_s = strconv.v_sprintf(sc1, a, b, c, d)
tmp_str = '==>12 13 14 15'
// C.printf(sc1.str, a ,b ,c, d)
// println("\n$temp_s")
assert tmp_str == temp_s
a1 := byte(0xff)
b1 := i16(0xffff)
c1 := u32(0xffff_ffff)
d1 := u64(-1)
sc2 := "%hhu %hu %u %lu"
temp_s = strconv.v_sprintf(sc2, a1 ,b1 ,c1, d1)
tmp_str = "255 65535 4294967295 18446744073709551615"
//C.printf(sc2.str, a1 ,b1 ,c1, d1)
//println("\n$temp_s")
assert tmp_str == temp_s
sc3 := "%hhx %hx %x %lx"
temp_s = strconv.v_sprintf(sc3, a1 ,b1 ,c1, d1)
tmp_str = "ff ffff ffffffff ffffffffffffffff"
//C.printf(sc3.str, a1 ,b1 ,c1, d1)
//println("\n$temp_s")
sc2 := '%hhu %hu %u %lu'
temp_s = strconv.v_sprintf(sc2, a1, b1, c1, d1)
tmp_str = '255 65535 4294967295 18446744073709551615'
// C.printf(sc2.str, a1 ,b1 ,c1, d1)
// println("\n$temp_s")
assert tmp_str == temp_s
sc4 := "[%-20.3e] [%20.3e] [%-020.3e] [%-020.3E] [%-020.3e] [%-020.3e]"
sc3 := '%hhx %hx %x %lx'
temp_s = strconv.v_sprintf(sc3, a1, b1, c1, d1)
tmp_str = 'ff ffff ffffffff ffffffffffffffff'
// C.printf(sc3.str, a1 ,b1 ,c1, d1)
// println("\n$temp_s")
assert tmp_str == temp_s
sc4 := '[%-20.3e] [%20.3e] [%-020.3e] [%-020.3E] [%-020.3e] [%-020.3e]'
temp_s = strconv.v_sprintf(sc4, f0, f1, f1, f1, f2, f3)
tmp_str = "[3.123e-01 ] [ 2.000e+05] [2.000e+05 ] [2.000E+05 ] [-1.234e+09 ] [1.234e-03 ]"
//C.printf(sc4.str, f0, f1, f1, f1, f2, f3)
//println("\n$temp_s")
tmp_str = '[3.123e-01 ] [ 2.000e+05] [2.000e+05 ] [2.000E+05 ] [-1.234e+09 ] [1.234e-03 ]'
// C.printf(sc4.str, f0, f1, f1, f1, f2, f3)
// println("\n$temp_s")
assert tmp_str == temp_s
sc5 := "[%.3f] [%0.3f] [%0.3F] [%0.3f] [%0.3F]"
sc5 := '[%.3f] [%0.3f] [%0.3F] [%0.3f] [%0.3F]'
temp_s = strconv.v_sprintf(sc5, f0, f1, f1, f2, f3)
tmp_str = "[0.312] [200000.000] [200000.000] [-1234300000.000] [0.001]"
//C.printf(sc5.str, f0, f1, f1, f2, f3, f3)
//println("\n$temp_s")
tmp_str = '[0.312] [200000.000] [200000.000] [-1234300000.000] [0.001]'
// C.printf(sc5.str, f0, f1, f1, f2, f3, f3)
// println("\n$temp_s")
assert tmp_str == temp_s
ml := 3
sc6 := "%.*s [%05hhX]"
temp_s = strconv.v_sprintf(sc6, ml, s0 , a)
tmp_str = "ciA [0000C]"
//C.printf(sc6.str, ml, s0.str, a)
//println("\n$temp_s")
ml := 3
sc6 := '%.*s [%05hhX]'
temp_s = strconv.v_sprintf(sc6, ml, s0, a)
tmp_str = 'ciA [0000C]'
// C.printf(sc6.str, ml, s0.str, a)
// println("\n$temp_s")
assert tmp_str == temp_s
a2 := 125
sc7 := "[%9x] [%9X] [%-9x] [%-9X] [%09x] [%09X]"
sc7 := '[%9x] [%9X] [%-9x] [%-9X] [%09x] [%09X]'
temp_s = strconv.v_sprintf(sc7, a2, a2, a2, a2, a2, a2)
tmp_str = "[ 7d] [ 7D] [7d ] [7D ] [00000007d] [00000007D]"
//C.printf(sc7.str, a2, a2, a2, a2, a2, a2)
//println("\n$temp_s")
tmp_str = '[ 7d] [ 7D] [7d ] [7D ] [00000007d] [00000007D]'
// C.printf(sc7.str, a2, a2, a2, a2, a2, a2)
// println("\n$temp_s")
assert tmp_str == temp_s
g_test := [
"[ -1e-07][ -1E-07]|",
"[ -1e-06][ -1E-06]|",
"[ -1e-05][ -1E-05]|",
"[ -0.0001][ -0.0001]|",
"[ -0.001][ -0.001]|",
"[ -0.01][ -0.01]|",
"[ -0.1][ -0.1]|",
"[ -1][ -1]|",
"[ -10][ -10]|",
"[ -100][ -100]|",
"[ -1000][ -1000]|",
"[ -10000][ -10000]|"
'[ -1e-07][ -1E-07]|',
'[ -1e-06][ -1E-06]|',
'[ -1e-05][ -1E-05]|',
'[ -0.0001][ -0.0001]|',
'[ -0.001][ -0.001]|',
'[ -0.01][ -0.01]|',
'[ -0.1][ -0.1]|',
'[ -1][ -1]|',
'[ -10][ -10]|',
'[ -100][ -100]|',
'[ -1000][ -1000]|',
'[ -10000][ -10000]|',
]
mut ft := -1e-7
mut x := 0
mut cnt:= 0
sc8 := "[%20g][%20G]|"
mut x := 0
mut cnt := 0
sc8 := '[%20g][%20G]|'
for x < 12 {
temp_s = strconv.v_sprintf(sc8, ft, ft)
//C.printf(sc8.str, ft, ft)
//println("\n$temp_s")
// C.printf(sc8.str, ft, ft)
// println("\n$temp_s")
assert temp_s == g_test[cnt]
ft = ft * 10.0
x++

View File

@ -1,7 +1,6 @@
module strconv
/*
f32/f64 ftoa functions
Copyright (c) 2019-2021 Dario Deledda. All rights reserved.
@ -17,12 +16,11 @@ Pages 270282 https://doi.org/10.1145/3192366.3192369
inspired by the Go version here:
https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea
*/
[inline]
pub fn ftoa_64(f f64) string {
return f64_to_str(f,17)
return f64_to_str(f, 17)
}
[inline]
@ -32,7 +30,7 @@ pub fn ftoa_long_64(f f64) string {
[inline]
pub fn ftoa_32(f f32) string {
return f32_to_str(f,8)
return f32_to_str(f, 8)
}
[inline]

View File

@ -6,7 +6,7 @@ const base_digits = '0123456789abcdefghijklmnopqrstuvwxyz'
// for digit values > 10, this function uses the small latin leters a-z.
[manualfree]
pub fn format_int(n i64, radix int) string {
unsafe{
unsafe {
if radix < 2 || radix > 36 {
panic('invalid radix: $radix . It should be => 2 and <= 36')
}
@ -22,11 +22,11 @@ pub fn format_int(n i64, radix int) string {
mut res := ''
for n_copy != 0 {
tmp_0 := res
tmp_1 := base_digits[n_copy % radix].ascii_str()
tmp_1 := strconv.base_digits[n_copy % radix].ascii_str()
res = tmp_1 + res
tmp_0.free()
tmp_1.free()
//res = base_digits[n_copy % radix].ascii_str() + res
// res = base_digits[n_copy % radix].ascii_str() + res
n_copy /= radix
}
return '$sign$res'
@ -37,7 +37,7 @@ pub fn format_int(n i64, radix int) string {
// for digit values > 10, this function uses the small latin leters a-z.
[manualfree]
pub fn format_uint(n u64, radix int) string {
unsafe{
unsafe {
if radix < 2 || radix > 36 {
panic('invalid radix: $radix . It should be => 2 and <= 36')
}
@ -49,11 +49,11 @@ pub fn format_uint(n u64, radix int) string {
uradix := u64(radix)
for n_copy != 0 {
tmp_0 := res
tmp_1 := base_digits[n_copy % uradix].ascii_str()
tmp_1 := strconv.base_digits[n_copy % uradix].ascii_str()
res = tmp_1 + res
tmp_0.free()
tmp_1.free()
//res = base_digits[n_copy % uradix].ascii_str() + res
// res = base_digits[n_copy % uradix].ascii_str() + res
n_copy /= uradix
}
return res

View File

@ -32,8 +32,7 @@ fn test_format_uint() {
assert strconv.format_int(255, 8) == '377'
assert strconv.format_int(255, 10) == '255'
assert strconv.format_int(255, 16) == 'ff'
assert strconv.format_uint(18446744073709551615, 2) ==
'1111111111111111111111111111111111111111111111111111111111111111'
assert strconv.format_uint(18446744073709551615, 2) == '1111111111111111111111111111111111111111111111111111111111111111'
assert strconv.format_uint(18446744073709551615, 16) == 'ffffffffffffffff'
assert strconv.parse_int('baobab', 36, 64) == 683058467
assert strconv.format_uint(683058467, 36) == 'baobab'

View File

@ -4,8 +4,8 @@ module strconv
pub struct PrepNumber {
pub mut:
negative bool // 0 if positive number, 1 if negative
exponent int // power of 10 exponent
mantissa u64 // integer mantissa
exponent int // power of 10 exponent
mantissa u64 // integer mantissa
}
// dec32 is a floating decimal type representing m * 10^e.
@ -52,4 +52,4 @@ pub union Float32u {
pub mut:
f f32
u u32
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
module strconv
/*
f32/f64 to string utilities
Copyright (c) 2019-2021 Dario Deledda. All rights reserved.
@ -17,17 +16,13 @@ Pages 270282 https://doi.org/10.1145/3192366.3192369
inspired by the Go version here:
https://github.com/cespare/ryu/tree/ba56a33f39e3bbbfa409095d0f9ae168a595feea
*/
import math.bits
//import math
// import math
/*
General Utilities
*/
fn assert1(t bool, msg string) {
if !t {
@ -61,25 +56,23 @@ fn bool_to_u64(b bool) u64 {
fn get_string_special(neg bool, expZero bool, mantZero bool) string {
if !mantZero {
return "nan"
return 'nan'
}
if !expZero {
if neg {
return "-inf"
return '-inf'
} else {
return "+inf"
return '+inf'
}
}
if neg {
return "-0e+00"
return '-0e+00'
}
return "0e+00"
return '0e+00'
}
/*
32 bit functions
32 bit functions
*/
// decimal_len_32 return the number of decimal digits of the input
[deprecated]
@ -87,26 +80,35 @@ pub fn decimal_len_32(u u32) int {
// Function precondition: u is not a 10-digit number.
// (9 digits are sufficient for round-tripping.)
// This benchmarked faster than the log2 approach used for u64.
assert1(u < 1000000000, "too big")
assert1(u < 1000000000, 'too big')
if u >= 100000000 { return 9 }
else if u >= 10000000 { return 8 }
else if u >= 1000000 { return 7 }
else if u >= 100000 { return 6 }
else if u >= 10000 { return 5 }
else if u >= 1000 { return 4 }
else if u >= 100 { return 3 }
else if u >= 10 { return 2 }
if u >= 100000000 {
return 9
} else if u >= 10000000 {
return 8
} else if u >= 1000000 {
return 7
} else if u >= 100000 {
return 6
} else if u >= 10000 {
return 5
} else if u >= 1000 {
return 4
} else if u >= 100 {
return 3
} else if u >= 10 {
return 2
}
return 1
}
fn mul_shift_32(m u32, mul u64, ishift int) u32 {
// QTODO
//assert ishift > 32
// assert ishift > 32
hi, lo := bits.mul_64(u64(m), mul)
shifted_sum := (lo >> u64(ishift)) + (hi << u64(64-ishift))
assert1(shifted_sum <= 2147483647, "shiftedSum <= math.max_u32")
shifted_sum := (lo >> u64(ishift)) + (hi << u64(64 - ishift))
assert1(shifted_sum <= 2147483647, 'shiftedSum <= math.max_u32')
return u32(shifted_sum)
}
@ -120,9 +122,9 @@ fn mul_pow5_div_pow2(m u32, i u32, j int) u32 {
fn pow5_factor_32(i_v u32) u32 {
mut v := i_v
for n := u32(0); ; n++ {
q := v/5
r := v%5
for n := u32(0); true; n++ {
q := v / 5
r := v % 5
if r != 0 {
return n
}
@ -145,8 +147,8 @@ fn multiple_of_power_of_two_32(v u32, p u32) bool {
fn log10_pow2(e int) u32 {
// The first value this approximation fails for is 2^1651
// which is just greater than 10^297.
assert1(e >= 0, "e >= 0")
assert1(e <= 1650, "e <= 1650")
assert1(e >= 0, 'e >= 0')
assert1(e <= 1650, 'e <= 1650')
return (u32(e) * 78913) >> 18
}
@ -154,8 +156,8 @@ fn log10_pow2(e int) u32 {
fn log10_pow5(e int) u32 {
// The first value this approximation fails for is 5^2621
// which is just greater than 10^1832.
assert1(e >= 0, "e >= 0")
assert1(e <= 2620, "e <= 2620")
assert1(e >= 0, 'e >= 0')
assert1(e <= 2620, 'e <= 2620')
return (u32(e) * 732923) >> 20
}
@ -164,18 +166,17 @@ fn pow5_bits(e int) int {
// This approximation works up to the point that the multiplication
// overflows at e = 3529. If the multiplication were done in 64 bits,
// it would fail at 5^4004 which is just greater than 2^9297.
assert1(e >= 0, "e >= 0")
assert1(e <= 3528, "e <= 3528")
return int( ((u32(e)*1217359)>>19) + 1)
assert1(e >= 0, 'e >= 0')
assert1(e <= 3528, 'e <= 3528')
return int(((u32(e) * 1217359) >> 19) + 1)
}
/*
64 bit functions
64 bit functions
*/
[deprecated]
// decimal_len_64 return the number of decimal digits of the input
[deprecated]
pub fn decimal_len_64(u u64) int {
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
log2 := 64 - bits.leading_zeros_64(u) - 1
@ -190,25 +191,28 @@ fn shift_right_128(v Uint128, shift int) u64 {
// (It is in the range [2, 59].)
// Check this here in case a future change requires larger shift
// values. In this case this function needs to be adjusted.
assert1(shift < 64, "shift < 64")
assert1(shift < 64, 'shift < 64')
return (v.hi << u64(64 - shift)) | (v.lo >> u32(shift))
}
fn mul_shift_64(m u64, mul Uint128, shift int) u64 {
hihi, hilo := bits.mul_64(m, mul.hi)
lohi, _ := bits.mul_64(m, mul.lo)
mut sum := Uint128{lo: lohi + hilo,hi: hihi}
lohi, _ := bits.mul_64(m, mul.lo)
mut sum := Uint128{
lo: lohi + hilo
hi: hihi
}
if sum.lo < lohi {
sum.hi++ // overflow
}
return shift_right_128(sum, shift-64)
return shift_right_128(sum, shift - 64)
}
fn pow5_factor_64(v_i u64) u32 {
mut v := v_i
for n := u32(0); ; n++ {
q := v/5
r := v%5
for n := u32(0); true; n++ {
q := v / 5
r := v % 5
if r != 0 {
return n
}
@ -226,46 +230,43 @@ fn multiple_of_power_of_two_64(v u64, p u32) bool {
}
/*
f64 to string with string format
*/
// TODO: Investigate precision issues
// f32_to_str_l return a string with the f32 converted in a string in decimal notation
[manualfree]
pub fn f32_to_str_l(f f32) string {
s := f32_to_str(f,6)
s := f32_to_str(f, 6)
res := fxx_to_str_l_parse(s)
unsafe{s.free()}
unsafe { s.free() }
return res
}
[manualfree]
pub fn f32_to_str_l_no_dot(f f32) string {
s := f32_to_str(f,6)
s := f32_to_str(f, 6)
res := fxx_to_str_l_parse_no_dot(s)
unsafe{s.free()}
unsafe { s.free() }
return res
}
[manualfree]
pub fn f64_to_str_l(f f64) string {
s := f64_to_str(f,18)
s := f64_to_str(f, 18)
res := fxx_to_str_l_parse(s)
unsafe{s.free()}
unsafe { s.free() }
return res
}
[manualfree]
pub fn f64_to_str_l_no_dot(f f64) string {
s := f64_to_str(f,18)
s := f64_to_str(f, 18)
res := fxx_to_str_l_parse_no_dot(s)
unsafe{s.free()}
unsafe { s.free() }
return res
}
// f64_to_str_l return a string with the f64 converted in a string in decimal notation
[manualfree]
pub fn fxx_to_str_l_parse(s string) string {
@ -275,13 +276,13 @@ pub fn fxx_to_str_l_parse(s string) string {
}
m_sgn_flag := false
mut sgn := 1
mut b := [26]byte{}
mut d_pos := 1
mut i := 0
mut i1 := 0
mut exp := 0
mut exp_sgn := 1
mut sgn := 1
mut b := [26]byte{}
mut d_pos := 1
mut i := 0
mut i1 := 0
mut exp := 0
mut exp_sgn := 1
// get sign and decimal parts
for c in s {
@ -291,8 +292,7 @@ pub fn fxx_to_str_l_parse(s string) string {
} else if c == `+` {
sgn = 1
i++
}
else if c >= `0` && c <= `9` {
} else if c >= `0` && c <= `9` {
b[i1] = c
i1++
i++
@ -300,14 +300,14 @@ pub fn fxx_to_str_l_parse(s string) string {
if sgn > 0 {
d_pos = i
} else {
d_pos = i-1
d_pos = i - 1
}
i++
} else if c == `e` {
i++
break
} else {
return "Float conversion error!!"
return 'Float conversion error!!'
}
}
b[i1] = 0
@ -323,16 +323,16 @@ pub fn fxx_to_str_l_parse(s string) string {
mut c := i
for c < s.len {
exp = exp * 10 + int(s[c]-`0`)
exp = exp * 10 + int(s[c] - `0`)
c++
}
// allocate exp+32 chars for the return string
mut res := []byte{len: exp+32, init: 0}
mut r_i := 0 // result string buffer index
mut res := []byte{len: exp + 32, init: 0}
mut r_i := 0 // result string buffer index
// println("s:${sgn} b:${b[0]} es:${exp_sgn} exp:${exp}")
//println("s:${sgn} b:${b[0]} es:${exp_sgn} exp:${exp}")
if sgn == 1 {
if m_sgn_flag {
res[r_i] = `+`
@ -368,7 +368,7 @@ pub fn fxx_to_str_l_parse(s string) string {
res[r_i] = `0`
r_i++
exp--
if dot_p {
if dot_p {
res[r_i] = `.`
r_i++
dot_p = false
@ -380,14 +380,14 @@ pub fn fxx_to_str_l_parse(s string) string {
i++
}
}
/*
/*
// remove the dot form the numbers like 2.
if r_i > 1 && res[r_i-1] == `.` {
r_i--
}
*/
*/
res[r_i] = 0
return unsafe { tos(res.data,r_i) }
return unsafe { tos(res.data, r_i) }
}
// f64_to_str_l return a string with the f64 converted in a string in decimal notation
@ -399,13 +399,13 @@ pub fn fxx_to_str_l_parse_no_dot(s string) string {
}
m_sgn_flag := false
mut sgn := 1
mut b := [26]byte{}
mut d_pos := 1
mut i := 0
mut i1 := 0
mut exp := 0
mut exp_sgn := 1
mut sgn := 1
mut b := [26]byte{}
mut d_pos := 1
mut i := 0
mut i1 := 0
mut exp := 0
mut exp_sgn := 1
// get sign and decimal parts
for c in s {
@ -415,8 +415,7 @@ pub fn fxx_to_str_l_parse_no_dot(s string) string {
} else if c == `+` {
sgn = 1
i++
}
else if c >= `0` && c <= `9` {
} else if c >= `0` && c <= `9` {
b[i1] = c
i1++
i++
@ -424,14 +423,14 @@ pub fn fxx_to_str_l_parse_no_dot(s string) string {
if sgn > 0 {
d_pos = i
} else {
d_pos = i-1
d_pos = i - 1
}
i++
} else if c == `e` {
i++
break
} else {
return "Float conversion error!!"
return 'Float conversion error!!'
}
}
b[i1] = 0
@ -447,16 +446,16 @@ pub fn fxx_to_str_l_parse_no_dot(s string) string {
mut c := i
for c < s.len {
exp = exp * 10 + int(s[c]-`0`)
exp = exp * 10 + int(s[c] - `0`)
c++
}
// allocate exp+32 chars for the return string
mut res := []byte{len: exp+32, init: 0}
mut r_i := 0 // result string buffer index
mut res := []byte{len: exp + 32, init: 0}
mut r_i := 0 // result string buffer index
// println("s:${sgn} b:${b[0]} es:${exp_sgn} exp:${exp}")
//println("s:${sgn} b:${b[0]} es:${exp_sgn} exp:${exp}")
if sgn == 1 {
if m_sgn_flag {
res[r_i] = `+`
@ -492,7 +491,7 @@ pub fn fxx_to_str_l_parse_no_dot(s string) string {
res[r_i] = `0`
r_i++
exp--
if dot_p {
if dot_p {
res[r_i] = `.`
r_i++
dot_p = false
@ -506,12 +505,12 @@ pub fn fxx_to_str_l_parse_no_dot(s string) string {
}
// remove the dot form the numbers like 2.
if r_i > 1 && res[r_i-1] == `.` {
if r_i > 1 && res[r_i - 1] == `.` {
r_i--
}
res[r_i] = 0
return unsafe { tos(res.data,r_i) }
return unsafe { tos(res.data, r_i) }
}
// dec_digits return the number of decimal digit of an u64
@ -538,12 +537,12 @@ pub fn dec_digits(n u64) int {
} else {
if n <= 9_999_999 { // 7
if n <= 999_999 { // 6
return 6
return 6
} else {
return 7
}
} else {
if n <= 99_999_999 { //8
if n <= 99_999_999 { // 8
return 8
} else {
if n <= 999_999_999 { // 9
@ -575,12 +574,12 @@ pub fn dec_digits(n u64) int {
} else {
if n <= 99_999_999_999_999_999 { // 7
if n <= 9_999_999_999_999_999 { // 6
return 16
return 16
} else {
return 17
}
} else {
if n <= 999_999_999_999_999_999 { //8
if n <= 999_999_999_999_999_999 { // 8
return 18
} else {
if n <= 9_999_999_999_999_999_999 { // 9
@ -590,5 +589,5 @@ pub fn dec_digits(n u64) int {
}
}
}
}
}
}
}

View File

@ -6,6 +6,7 @@ that can be found in the LICENSE file.
This file contains string interpolation V functions
=============================================================================*/
module strconv
import strings
enum Char_parse_state {
@ -15,42 +16,40 @@ enum Char_parse_state {
pad_ch
len_set_start
len_set_in
check_type
check_float
check_float_in
reset_params
}
pub fn v_printf(str string, pt ... voidptr) {
pub fn v_printf(str string, pt ...voidptr) {
print(v_sprintf(str, pt))
}
pub fn v_sprintf(str string, pt ... voidptr) string{
pub fn v_sprintf(str string, pt ...voidptr) string {
mut res := strings.new_builder(pt.len * 16)
mut i := 0 // main string index
mut p_index := 0 // parameter index
mut sign := false // sign flag
mut allign := Align_text.right
mut len0 := -1 // forced length, if -1 free length
mut len1 := -1 // decimal part for floats
def_len1 := 6 // default value for len1
mut pad_ch := byte(` `) // pad char
mut i := 0 // main string index
mut p_index := 0 // parameter index
mut sign := false // sign flag
mut allign := Align_text.right
mut len0 := -1 // forced length, if -1 free length
mut len1 := -1 // decimal part for floats
def_len1 := 6 // default value for len1
mut pad_ch := byte(` `) // pad char
// prefix chars for Length field
mut ch1 := `0` // +1 char if present else `0`
mut ch2 := `0` // +2 char if present else `0`
mut ch1 := `0` // +1 char if present else `0`
mut ch2 := `0` // +2 char if present else `0`
mut status := Char_parse_state.norm_char
for i < str.len {
if status == .reset_params {
sign = false
allign = .right
len0 = -1
len1 = -1
pad_ch = ` `
sign = false
allign = .right
len0 = -1
len1 = -1
pad_ch = ` `
status = .norm_char
ch1 = `0`
ch2 = `0`
@ -72,7 +71,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// single char, manage it here
if ch == `c` && status == .field_char {
v_sprintf_panic(p_index, pt.len)
d1 := unsafe {*(&byte(pt[p_index]))}
d1 := unsafe { *(&byte(pt[p_index])) }
res.write_b(d1)
status = .reset_params
p_index++
@ -83,8 +82,8 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// pointer, manage it here
if ch == `p` && status == .field_char {
v_sprintf_panic(p_index, pt.len)
res.write_string("0x")
res.write_string(ptr_str(unsafe {pt[p_index]}))
res.write_string('0x')
res.write_string(ptr_str(unsafe { pt[p_index] }))
status = .reset_params
p_index++
i++
@ -95,9 +94,9 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
mut fc_ch1 := `0`
mut fc_ch2 := `0`
if (i + 1) < str.len {
fc_ch1 = str[i+1]
fc_ch1 = str[i + 1]
if (i + 2) < str.len {
fc_ch2 = str[i+2]
fc_ch2 = str[i + 2]
}
}
if ch == `+` {
@ -108,13 +107,13 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
allign = .left
i++
continue
} else if ch in [`0`,` `] {
} else if ch in [`0`, ` `] {
if allign == .right {
pad_ch = ch
}
i++
continue
} else if ch == `'` {
} else if ch == `\'` {
i++
continue
} else if ch == `.` && fc_ch1 >= `1` && fc_ch1 <= `9` {
@ -125,10 +124,10 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// manage "%.*s" precision field
else if ch == `.` && fc_ch1 == `*` && fc_ch2 == `s` {
v_sprintf_panic(p_index, pt.len)
len := unsafe {*(&int(pt[p_index]))}
len := unsafe { *(&int(pt[p_index])) }
p_index++
v_sprintf_panic(p_index, pt.len)
mut s := unsafe {*(&string(pt[p_index]))}
mut s := unsafe { *(&string(pt[p_index])) }
s = s[..len]
p_index++
res.write_string(s)
@ -195,7 +194,6 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
}
if status == .check_type {
if ch == `l` {
if ch1 == `0` {
ch1 = `l`
@ -206,8 +204,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
i++
continue
}
}
else if ch == `h` {
} else if ch == `h` {
if ch1 == `0` {
ch1 = `h`
i++
@ -218,24 +215,23 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
continue
}
}
// signed integer
else if ch in [`d`,`i`] {
else if ch in [`d`, `i`] {
mut d1 := u64(0)
mut positive := true
//println("$ch1 $ch2")
// println("$ch1 $ch2")
match ch1 {
// h for 16 bit int
// hh fot 8 bit int
`h` {
if ch2 == `h` {
v_sprintf_panic(p_index, pt.len)
x := unsafe {*(&i8(pt[p_index]))}
x := unsafe { *(&i8(pt[p_index])) }
positive = if x >= 0 { true } else { false }
d1 = if positive { u64(x) } else { u64(-x) }
} else {
x := unsafe {*(&i16(pt[p_index]))}
x := unsafe { *(&i16(pt[p_index])) }
positive = if x >= 0 { true } else { false }
d1 = if positive { u64(x) } else { u64(-x) }
}
@ -258,20 +254,26 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
}
*/
v_sprintf_panic(p_index, pt.len)
x := unsafe {*(&i64(pt[p_index]))}
x := unsafe { *(&i64(pt[p_index])) }
positive = if x >= 0 { true } else { false }
d1 = if positive { u64(x) } else { u64(-x) }
}
// default int
else {
v_sprintf_panic(p_index, pt.len)
x := unsafe {*(&int(pt[p_index]))}
x := unsafe { *(&int(pt[p_index])) }
positive = if x >= 0 { true } else { false }
d1 = if positive { u64(x) } else { u64(-x) }
}
}
res.write_string(format_dec_old(d1,{pad_ch: pad_ch, len0: len0, len1: 0, positive: positive, sign_flag: sign, allign: allign}))
res.write_string(format_dec_old(d1,
pad_ch: pad_ch
len0: len0
len1: 0
positive: positive
sign_flag: sign
allign: allign
))
status = .reset_params
p_index++
i++
@ -279,7 +281,6 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
ch2 = `0`
continue
}
// unsigned integer
else if ch == `u` {
mut d1 := u64(0)
@ -290,9 +291,9 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// hh fot 8 bit unsigned int
`h` {
if ch2 == `h` {
d1 = u64(unsafe {*(&byte(pt[p_index]))})
d1 = u64(unsafe { *(&byte(pt[p_index])) })
} else {
d1 = u64(unsafe {*(&u16(pt[p_index]))})
d1 = u64(unsafe { *(&u16(pt[p_index])) })
}
}
// l u64
@ -306,34 +307,40 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
d1 = u64(*(&u64(pt[p_index])))
}
*/
d1 = u64(unsafe {*(&u64(pt[p_index]))})
d1 = u64(unsafe { *(&u64(pt[p_index])) })
}
// default int
else {
d1 = u64(unsafe {*(&u32(pt[p_index]))})
d1 = u64(unsafe { *(&u32(pt[p_index])) })
}
}
res.write_string(format_dec_old(d1,{pad_ch: pad_ch, len0: len0, len1: 0, positive: positive, sign_flag: sign, allign: allign}))
res.write_string(format_dec_old(d1,
pad_ch: pad_ch
len0: len0
len1: 0
positive: positive
sign_flag: sign
allign: allign
))
status = .reset_params
p_index++
i++
continue
}
// hex
else if ch in [`x`, `X`] {
v_sprintf_panic(p_index, pt.len)
mut s := ""
mut s := ''
match ch1 {
// h for 16 bit int
// hh fot 8 bit int
`h` {
if ch2 == `h` {
x := unsafe {*(&i8(pt[p_index]))}
x := unsafe { *(&i8(pt[p_index])) }
s = x.hex()
} else {
x := unsafe {*(&i16(pt[p_index]))}
x := unsafe { *(&i16(pt[p_index])) }
s = x.hex()
}
}
@ -350,11 +357,11 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
s = x.hex()
}
*/
x := unsafe {*(&i64(pt[p_index]))}
x := unsafe { *(&i64(pt[p_index])) }
s = x.hex()
}
else {
x := unsafe {*(&int(pt[p_index]))}
x := unsafe { *(&int(pt[p_index])) }
s = x.hex()
}
}
@ -363,7 +370,14 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
s = s.to_upper()
}
res.write_string(format_str(s,{pad_ch: pad_ch, len0: len0, len1: 0, positive: true, sign_flag: false, allign: allign}))
res.write_string(format_str(s,
pad_ch: pad_ch
len0: len0
len1: 0
positive: true
sign_flag: false
allign: allign
))
status = .reset_params
p_index++
i++
@ -373,55 +387,89 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// float and double
if ch in [`f`, `F`] {
v_sprintf_panic(p_index, pt.len)
x := unsafe {*(&f64(pt[p_index]))}
x := unsafe { *(&f64(pt[p_index])) }
positive := x >= f64(0.0)
len1 = if len1 >= 0 { len1 } else { def_len1 }
s := format_fl_old(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign})
res.write_string(if ch == `F` {s.to_upper()} else {s})
s := format_fl_old(f64(x),
pad_ch: pad_ch
len0: len0
len1: len1
positive: positive
sign_flag: sign
allign: allign
)
res.write_string(if ch == `F` { s.to_upper() } else { s })
status = .reset_params
p_index++
i++
continue
}
else if ch in [`e`, `E`] {
} else if ch in [`e`, `E`] {
v_sprintf_panic(p_index, pt.len)
x := unsafe {*(&f64(pt[p_index]))}
x := unsafe { *(&f64(pt[p_index])) }
positive := x >= f64(0.0)
len1 = if len1 >= 0 { len1 } else { def_len1 }
s := format_es_old(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign})
res.write_string(if ch == `E` {s.to_upper()} else {s})
s := format_es_old(f64(x),
pad_ch: pad_ch
len0: len0
len1: len1
positive: positive
sign_flag: sign
allign: allign
)
res.write_string(if ch == `E` { s.to_upper() } else { s })
status = .reset_params
p_index++
i++
continue
}
else if ch in [`g`, `G`] {
} else if ch in [`g`, `G`] {
v_sprintf_panic(p_index, pt.len)
x := unsafe {*(&f64(pt[p_index]))}
x := unsafe { *(&f64(pt[p_index])) }
positive := x >= f64(0.0)
mut s := ""
mut s := ''
tx := fabs(x)
if tx < 999_999.0 && tx >= 0.00001 {
//println("Here g format_fl [$tx]")
len1 = if len1 >= 0 { len1+1 } else { def_len1 }
s = format_fl_old(x, {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign, rm_tail_zero: true})
// println("Here g format_fl [$tx]")
len1 = if len1 >= 0 { len1 + 1 } else { def_len1 }
s = format_fl_old(x,
pad_ch: pad_ch
len0: len0
len1: len1
positive: positive
sign_flag: sign
allign: allign
rm_tail_zero: true
)
} else {
len1 = if len1 >= 0 { len1+1 } else { def_len1 }
s = format_es_old(x, {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign, rm_tail_zero: true})
len1 = if len1 >= 0 { len1 + 1 } else { def_len1 }
s = format_es_old(x,
pad_ch: pad_ch
len0: len0
len1: len1
positive: positive
sign_flag: sign
allign: allign
rm_tail_zero: true
)
}
res.write_string(if ch == `G` {s.to_upper()} else {s})
res.write_string(if ch == `G` { s.to_upper() } else { s })
status = .reset_params
p_index++
i++
continue
}
// string
else if ch == `s` {
v_sprintf_panic(p_index, pt.len)
s1 := unsafe{*(&string(pt[p_index]))}
s1 := unsafe { *(&string(pt[p_index])) }
pad_ch = ` `
res.write_string(format_str(s1, {pad_ch: pad_ch, len0: len0, len1: 0, positive: true, sign_flag: false, allign: allign}))
res.write_string(format_str(s1,
pad_ch: pad_ch
len0: len0
len1: 0
positive: true
sign_flag: false
allign: allign
))
status = .reset_params
p_index++
i++
@ -435,7 +483,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
}
if p_index != pt.len {
panic('${p_index} % conversion specifiers, but given ${pt.len} args')
panic('$p_index % conversion specifiers, but given $pt.len args')
}
return res.str()
@ -444,7 +492,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
[inline]
fn v_sprintf_panic(idx int, len int) {
if idx >= len {
panic('${idx+1} % conversion specifiers, but given only ${len} args')
panic('${idx + 1} % conversion specifiers, but given only $len args')
}
}
@ -458,12 +506,12 @@ fn fabs(x f64) f64 {
// strings.Builder version of format_fl
[manualfree]
pub fn format_fl_old(f f64, p BF_param) string {
unsafe{
mut s := ""
//mut fs := "1.2343"
mut fs := f64_to_str_lnd1(if f >= 0.0 {f} else {-f}, p.len1)
//println("Dario")
//println(fs)
unsafe {
mut s := ''
// mut fs := "1.2343"
mut fs := f64_to_str_lnd1(if f >= 0.0 { f } else { -f }, p.len1)
// println("Dario")
// println(fs)
// error!!
if fs[0] == `[` {
@ -476,7 +524,7 @@ pub fn format_fl_old(f f64, p BF_param) string {
fs = remove_tail_zeros_old(fs)
tmp.free()
}
mut res := strings.new_builder( if p.len0 > fs.len { p.len0 } else { fs.len })
mut res := strings.new_builder(if p.len0 > fs.len { p.len0 } else { fs.len })
mut sign_len_diff := 0
if p.pad_ch == `0` {
@ -496,7 +544,7 @@ pub fn format_fl_old(f f64, p BF_param) string {
if p.positive {
if p.sign_flag {
tmp := s
s = "+" + fs
s = '+' + fs
tmp.free()
} else {
tmp := s
@ -505,7 +553,7 @@ pub fn format_fl_old(f f64, p BF_param) string {
}
} else {
tmp := s
s = "-" + fs
s = '-' + fs
tmp.free()
}
}
@ -513,18 +561,17 @@ pub fn format_fl_old(f f64, p BF_param) string {
dif := p.len0 - s.len + sign_len_diff
if p.allign == .right {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
res.write_string(s)
if p.allign == .left {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
s.free()
fs.free()
tmp_res := res.str()
@ -535,13 +582,13 @@ pub fn format_fl_old(f f64, p BF_param) string {
[manualfree]
pub fn format_es_old(f f64, p BF_param) string {
unsafe{
mut s := ""
mut fs := f64_to_str_pad(if f> 0 {f} else {-f},p.len1)
unsafe {
mut s := ''
mut fs := f64_to_str_pad(if f > 0 { f } else { -f }, p.len1)
if p.rm_tail_zero {
fs = remove_tail_zeros_old(fs)
}
mut res := strings.new_builder( if p.len0 > fs.len { p.len0 } else { fs.len })
mut res := strings.new_builder(if p.len0 > fs.len { p.len0 } else { fs.len })
mut sign_len_diff := 0
if p.pad_ch == `0` {
@ -561,7 +608,7 @@ pub fn format_es_old(f f64, p BF_param) string {
if p.positive {
if p.sign_flag {
tmp := s
s = "+" + fs
s = '+' + fs
tmp.free()
} else {
tmp := s
@ -570,20 +617,20 @@ pub fn format_es_old(f f64, p BF_param) string {
}
} else {
tmp := s
s = "-" + fs
s = '-' + fs
tmp.free()
}
}
dif := p.len0 - s.len + sign_len_diff
if p.allign == .right {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
res.write_string(s)
if p.allign == .left {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
@ -598,16 +645,15 @@ pub fn format_es_old(f f64, p BF_param) string {
pub fn remove_tail_zeros_old(s string) string {
mut i := 0
mut last_zero_start := -1
mut dot_pos := -1
mut dot_pos := -1
mut in_decimal := false
mut prev_ch := byte(0)
for i < s.len {
ch := unsafe {s.str[i]}
ch := unsafe { s.str[i] }
if ch == `.` {
in_decimal = true
dot_pos = i
}
else if in_decimal {
} else if in_decimal {
if ch == `0` && prev_ch != `0` {
last_zero_start = i
} else if ch >= `1` && ch <= `9` {
@ -620,25 +666,25 @@ pub fn remove_tail_zeros_old(s string) string {
i++
}
mut tmp := ""
mut tmp := ''
if last_zero_start > 0 {
if last_zero_start == dot_pos+1 {
if last_zero_start == dot_pos + 1 {
tmp = s[..dot_pos] + s[i..]
}else {
} else {
tmp = s[..last_zero_start] + s[i..]
}
} else {
tmp = s
}
if unsafe {tmp.str[tmp.len-1]} == `.` {
return tmp[..tmp.len-1]
if unsafe { tmp.str[tmp.len - 1] } == `.` {
return tmp[..tmp.len - 1]
}
return tmp
}
// max int64 9223372036854775807
pub fn format_dec_old(d u64, p BF_param) string {
mut s := ""
mut s := ''
mut res := strings.new_builder(20)
mut sign_len_diff := 0
if p.pad_ch == `0` {
@ -655,26 +701,26 @@ pub fn format_dec_old(d u64, p BF_param) string {
} else {
if p.positive {
if p.sign_flag {
s = "+" + d.str()
s = '+' + d.str()
} else {
s = d.str()
}
} else {
s = "-" + d.str()
s = '-' + d.str()
}
}
dif := p.len0 - s.len + sign_len_diff
if p.allign == .right {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
res.write_string(s)
if p.allign == .left {
for i1 :=0; i1 < dif; i1++ {
for i1 := 0; i1 < dif; i1++ {
res.write_b(p.pad_ch)
}
}
return res.str()
}
}