strconv: format test fixes

pull/4696/head
penguindark 2020-04-26 16:26:33 +02:00 committed by GitHub
parent 2574dce174
commit d16474442a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 95 additions and 98 deletions

View File

@ -14,23 +14,23 @@ import strconv.ftoa
import strings import strings
enum Char_parse_state { enum Char_parse_state {
start, start
norm_char, norm_char
field_char, field_char
pad_ch, pad_ch
len_set_start, len_set_start
len_set_in, len_set_in
check_type, check_type
check_float, check_float
check_float_in, check_float_in
reset_params reset_params
} }
enum Align_text { enum Align_text {
right = 0, right = 0
left, left
center center
} }
@ -127,6 +127,7 @@ pub fn f64_to_str_lnd(f f64, dec_digit int) string {
} }
// allocate exp+32 chars for the return string // allocate exp+32 chars for the return string
//mut res := []byte{len:exp+32,init:`0`}
mut res := [`0`].repeat(exp+32) // TODO: Slow!! is there other possibilities to allocate this? mut res := [`0`].repeat(exp+32) // TODO: Slow!! is there other possibilities to allocate this?
mut r_i := 0 // result string buffer index mut r_i := 0 // result string buffer index
@ -205,7 +206,7 @@ struct BF_param {
pad_ch byte = ` ` // padding char pad_ch byte = ` ` // padding char
len0 int = -1 // default len for whole the number or string len0 int = -1 // default len for whole the number or string
len1 int = 6 // number of decimal digits, if needed len1 int = 6 // number of decimal digits, if needed
positive bool = true // mandatory: the sign of the number passed positive bool = true // mandatory: the sign of the number passed
sign_flag bool = false // flag for print sign as prefix in padding sign_flag bool = false // flag for print sign as prefix in padding
allign Align_text = .right // alignment of the string allign Align_text = .right // alignment of the string
rm_tail_zero bool = false // remove the tail zeros from floats rm_tail_zero bool = false // remove the tail zeros from floats
@ -219,13 +220,13 @@ pub fn format_str(s string, p BF_param) string {
mut res := strings.new_builder(s.len + dif) mut res := strings.new_builder(s.len + dif)
if p.allign == .right { if p.allign == .right {
for i1 :=0; i1 < dif; i1++ { for i1 :=0; i1 < dif; i1++ {
res.write_b(p.pad_ch) res.write_b(p.pad_ch)
} }
} }
res.write(s) res.write(s)
if p.allign == .left { if p.allign == .left {
for i1 :=0; i1 < dif; i1++ { for i1 :=0; i1 < dif; i1++ {
res.write_b(p.pad_ch) res.write_b(p.pad_ch)
} }
} }
return res.str() return res.str()
@ -258,19 +259,17 @@ pub fn format_dec(d u64, p BF_param) string {
s = "-" + d.str() s = "-" + d.str()
} }
} }
dif := p.len0 - s.len + sign_len_diff dif := p.len0 - s.len + sign_len_diff
if p.allign == .right { if p.allign == .right {
for i1 :=0; i1 < dif; i1++ { for i1 :=0; i1 < dif; i1++ {
res.write_b(p.pad_ch) res.write_b(p.pad_ch)
} }
} }
res.write(s) res.write(s)
if p.allign == .left { if p.allign == .left {
for i1 :=0; i1 < dif; i1++ { for i1 :=0; i1 < dif; i1++ {
res.write_b(p.pad_ch) res.write_b(p.pad_ch)
} }
} }
return res.str() return res.str()
@ -279,6 +278,12 @@ pub fn format_dec(d u64, p BF_param) string {
pub fn format_fl(f f64, p BF_param) string { pub fn format_fl(f f64, p BF_param) string {
mut s := "" mut s := ""
mut fs := f64_to_str_lnd(if f >= 0.0 {f} else {-f}, p.len1) mut fs := f64_to_str_lnd(if f >= 0.0 {f} else {-f}, p.len1)
// error!!
if fs[0] == `[` {
return fs
}
if p.rm_tail_zero { if p.rm_tail_zero {
fs = remove_tail_zeros(fs) fs = remove_tail_zeros(fs)
} }
@ -312,14 +317,13 @@ pub fn format_fl(f f64, p BF_param) string {
if p.allign == .right { if p.allign == .right {
for i1 :=0; i1 < dif; i1++ { for i1 :=0; i1 < dif; i1++ {
res.write_b(p.pad_ch) res.write_b(p.pad_ch)
} }
} }
res.write(s) res.write(s)
if p.allign == .left { if p.allign == .left {
for i1 :=0; i1 < dif; i1++ { for i1 :=0; i1 < dif; i1++ {
res.write_b(p.pad_ch) res.write_b(p.pad_ch)
} }
} }
@ -361,13 +365,13 @@ pub fn format_es(f f64, p BF_param) string {
dif := p.len0 - s.len + sign_len_diff dif := p.len0 - s.len + sign_len_diff
if p.allign == .right { if p.allign == .right {
for i1 :=0; i1 < dif; i1++ { for i1 :=0; i1 < dif; i1++ {
res.write_b(p.pad_ch) res.write_b(p.pad_ch)
} }
} }
res.write(s) res.write(s)
if p.allign == .left { if p.allign == .left {
for i1 :=0; i1 < dif; i1++ { for i1 :=0; i1 < dif; i1++ {
res.write_b(p.pad_ch) res.write_b(p.pad_ch)
} }
} }
return res.str() return res.str()
@ -411,7 +415,6 @@ pub fn remove_tail_zeros(s string) string {
if tmp.str[tmp.len-1] == `.` { if tmp.str[tmp.len-1] == `.` {
return tmp[..tmp.len-1] return tmp[..tmp.len-1]
} }
return tmp return tmp
} }
@ -442,7 +445,6 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
mut ch1 := `0` // +1 char if present else `0` mut ch1 := `0` // +1 char if present else `0`
mut ch2 := `0` // +2 char if present else `0` mut ch2 := `0` // +2 char if present else `0`
mut status := Char_parse_state.norm_char mut status := Char_parse_state.norm_char
for i < str.len { for i < str.len {
if status == .reset_params { if status == .reset_params {
@ -459,13 +461,11 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
} }
ch := str[i] ch := str[i]
if ch != `%` && status == .norm_char { if ch != `%` && status == .norm_char {
res.write_b(ch) res.write_b(ch)
i++ i++
continue continue
} }
if ch == `%` && status == .norm_char { if ch == `%` && status == .norm_char {
status = .field_char status = .field_char
i++ i++
@ -500,7 +500,6 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
fc_ch2 = str[i+2] fc_ch2 = str[i+2]
} }
} }
if ch == `+` { if ch == `+` {
sign = true sign = true
i++ i++
@ -531,8 +530,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
mut s := *(&string(pt[p_index])) mut s := *(&string(pt[p_index]))
s = s[..len] s = s[..len]
p_index++ p_index++
res.write(s) res.write(s)
status = .reset_params status = .reset_params
i += 3 i += 3
continue continue
@ -607,8 +605,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
i++ i++
continue continue
} }
} }
else if ch == `h` { else if ch == `h` {
if ch1 == `0` { if ch1 == `0` {
ch1 = `h` ch1 = `h`
@ -668,7 +665,6 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
} }
res.write(format_dec(d1,{positive: positive, pad_ch: pad_ch, len0: len0, sign_flag: sign, allign: allign})) res.write(format_dec(d1,{positive: positive, pad_ch: pad_ch, len0: len0, sign_flag: sign, allign: allign}))
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
@ -812,9 +808,8 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
// string // string
else if ch == `s` { else if ch == `s` {
s1 := *(&string(pt[p_index])) s1 := *(&string(pt[p_index]))
pad_ch = `0` pad_ch = ` `
res.write(format_str(s1, {pad_ch: pad_ch, len0: len0, allign: allign})) res.write(format_str(s1, {pad_ch: pad_ch, len0: len0, allign: allign}))
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
@ -825,7 +820,6 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
status = .reset_params status = .reset_params
p_index++ p_index++
i++ i++
} }
return res.str() return res.str()

View File

@ -2,107 +2,110 @@ import os
import strconv import strconv
fn test_format(){ fn test_format(){
if os.getenv('FORCE_FORMAT_TEST') != '1' {
$if !macos {
eprintln('This test is done only on macos for now.')
eprintln('LibC sprintfs implementations on other platforms have too much variation in edge cases.')
eprintln('If you still want to do it, use `FORCE_FORMAT_TEST=1 ./v -cg vlib/strconv/format_test.v`')
exit(0)
}
}
mut buf := [1024]byte
mut temp_s := "" mut temp_s := ""
mut tmp_str:= ""
a0 := u32(10) a0 := u32(10)
b0 := 200 b0 := 200
c0 := byte(12) c0 := byte(12)
s0 := "ciAo" s0 := "ciAo"
ch0 := `B` ch0 := `B`
f0 := 0.312345 f0 := 0.312345
f1 := 200000.0 f1 := 200000.0
f2 := -1234.300e6 f2 := -1234.300e6
f3 := 1234.300e-6 f3 := 1234.300e-6
sc0 := "ciao: [%-08u] %d %hhd [%08s]\nr2: [%08X] [%p] [%-20.4f] [%-20.4f] [%c]\n" sc0 := "ciao: [%-08u] %d %hhd [%8s] [%08X] [%-20.4f] [%-20.4f] [%c]"
temp_s = strconv.v_sprintf(sc0 ,a0 ,b0 ,c0 ,s0 ,b0 ,&b0 ,f0, f1, ch0) temp_s = strconv.v_sprintf(sc0 ,a0 ,b0 ,c0 ,s0, b0 ,f0, f1, ch0)
C.sprintf(buf, sc0.str,a0 ,b0 ,c0 ,s0.str ,b0 ,&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)
$if debug { //println("\n$temp_s")
eprintln('C sprintf:') assert tmp_str == temp_s
eprintln( tos2(buf) )
eprintln( tos2(buf).bytes().hex() )
eprintln('V sprintf:')
eprintln( temp_s )
eprintln( temp_s.bytes().hex() )
}
assert tos2(buf) == temp_s
a := byte(12) a := byte(12)
b := i16(13) b := i16(13)
c := 14 c := 14
d := i64(15) d := i64(15)
sc1 := "==>%hhd %hd %d %ld\n" sc1 := "==>%hhd %hd %d %ld"
temp_s = strconv.v_sprintf(sc1, a ,b ,c, d) temp_s = strconv.v_sprintf(sc1, a ,b ,c, d)
C.sprintf(buf, sc1.str, a ,b ,c, d) tmp_str = "==>12 13 14 15"
//println("$temp_s${tos2(buf)}") //C.printf(sc1.str, a ,b ,c, d)
assert tos2(buf) == temp_s //println("\n$temp_s")
assert tmp_str == temp_s
a1 := byte(0xff) a1 := byte(0xff)
b1 := i16(0xffff) b1 := i16(0xffff)
c1 := u32(0xffff_ffff) c1 := u32(0xffff_ffff)
d1 := u64(-1) d1 := u64(-1)
sc2 := "%hhu %hu %u %lu\n" sc2 := "%hhu %hu %u %lu"
temp_s = strconv.v_sprintf(sc2, a1 ,b1 ,c1, d1) temp_s = strconv.v_sprintf(sc2, a1 ,b1 ,c1, d1)
C.sprintf(buf, sc2.str, a1 ,b1 ,c1, d1) tmp_str = "255 65535 4294967295 18446744073709551615"
//println("$temp_s${tos2(buf)}") //C.printf(sc2.str, a1 ,b1 ,c1, d1)
assert tos2(buf) == temp_s //println("\n$temp_s")
assert tmp_str == temp_s
sc3 := "%hhx %hx %x %lx"
sc3 := "%hhx %hx %x %lx\n"
temp_s = strconv.v_sprintf(sc3, a1 ,b1 ,c1, d1) temp_s = strconv.v_sprintf(sc3, a1 ,b1 ,c1, d1)
C.sprintf(buf, sc3.str, a1 ,b1 ,c1, d1) tmp_str = "ff ffff ffffffff ffffffffffffffff"
//println("$temp_s${tos2(buf)}") //C.printf(sc3.str, a1 ,b1 ,c1, d1)
assert tos2(buf) == temp_s //println("\n$temp_s")
assert tmp_str == temp_s
sc4 := "[%-20.3e] [%20.3e] [%-020.3e] [%-020.3E] [%-020.3e] [%-020.3e]\n" 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) temp_s = strconv.v_sprintf(sc4, f0, f1, f1, f1, f2, f3)
C.sprintf(buf, sc4.str, 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 ]"
//println("$temp_s${tos2(buf)}") //C.printf(sc4.str, f0, f1, f1, f1, f2, f3)
assert tos2(buf) == temp_s //println("\n$temp_s")
assert tmp_str == temp_s
sc5 := "[%.3f] [%0.3f] [%0.3F] [%0.3f] [%0.3F]\n"
temp_s = strconv.v_sprintf(sc5, f0, f1, f1, f2, f3, f3)
C.sprintf(buf, sc5.str, f0, f1, f1, f2, f3, f3)
//println("$temp_s${tos2(buf)}")
assert tos2(buf) == temp_s
sc5 := "[%.3f] [%0.3f] [%0.3F] [%0.3f] [%0.3F]"
temp_s = strconv.v_sprintf(sc5, f0, f1, f1, f2, f3, 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")
assert tmp_str == temp_s
ml := 3 ml := 3
sc6 := "%.*s [%05hhX]\n" sc6 := "%.*s [%05hhX]"
temp_s = strconv.v_sprintf(sc6, ml, s0 , a) temp_s = strconv.v_sprintf(sc6, ml, s0 , a)
C.sprintf(buf, sc6.str, ml, s0.str, a) tmp_str = "ciA [0000C]"
//println("$temp_s${tos2(buf)}") //C.printf(sc6.str, ml, s0.str, a)
assert tos2(buf) == temp_s //println("\n$temp_s")
assert tmp_str == temp_s
a2 := 125 a2 := 125
sc7 := "[%9x] [%9X] [%-9x] [%-9X] [%09x] [%09X]\n" sc7 := "[%9x] [%9X] [%-9x] [%-9X] [%09x] [%09X]"
temp_s = strconv.v_sprintf(sc7, a2, a2, a2, a2, a2, a2) temp_s = strconv.v_sprintf(sc7, a2, a2, a2, a2, a2, a2)
C.sprintf(buf, sc7.str, a2, a2, a2, a2, a2, a2) tmp_str = "[ 7d] [ 7D] [7d ] [7D ] [00000007d] [00000007D]"
//println("$temp_s${tos2(buf)}") //C.printf(sc7.str, a2, a2, a2, a2, a2, a2)
assert tos2(buf) == temp_s //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]|"
]
mut ft := -1e-7 mut ft := -1e-7
mut x := 0 mut x := 0
mut cnt:= 0
sc8 := "[%20g][%20G]|" sc8 := "[%20g][%20G]|"
for x < 12 { for x < 12 {
temp_s = strconv.v_sprintf(sc8, ft, ft) temp_s = strconv.v_sprintf(sc8, ft, ft)
C.sprintf(buf,sc8.str, ft, ft) //C.printf(sc8.str, ft, ft)
//println("$temp_s ${tos2(buf)}") //println("\n$temp_s")
assert tos2(buf) == temp_s assert temp_s == g_test[cnt]
ft = ft * 10.0 ft = ft * 10.0
x++ x++
cnt++
} }
} }