aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/vlib/strconv/vprintf.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/vlib/strconv/vprintf.v')
-rw-r--r--v_windows/v/vlib/strconv/vprintf.v726
1 files changed, 726 insertions, 0 deletions
diff --git a/v_windows/v/vlib/strconv/vprintf.v b/v_windows/v/vlib/strconv/vprintf.v
new file mode 100644
index 0000000..18e37b6
--- /dev/null
+++ b/v_windows/v/vlib/strconv/vprintf.v
@@ -0,0 +1,726 @@
+/*=============================================================================
+Copyright (c) 2019-2021 Dario Deledda. All rights reserved.
+Use of this source code is governed by an MIT license
+that can be found in the LICENSE file.
+
+This file contains string interpolation V functions
+=============================================================================*/
+module strconv
+
+import strings
+
+enum Char_parse_state {
+ start
+ norm_char
+ field_char
+ 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) {
+ print(v_sprintf(str, pt))
+}
+
+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
+
+ // prefix chars for Length field
+ 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 = ` `
+ status = .norm_char
+ ch1 = `0`
+ ch2 = `0`
+ continue
+ }
+
+ ch := str[i]
+ if ch != `%` && status == .norm_char {
+ res.write_b(ch)
+ i++
+ continue
+ }
+ if ch == `%` && status == .norm_char {
+ status = .field_char
+ i++
+ continue
+ }
+
+ // single char, manage it here
+ if ch == `c` && status == .field_char {
+ v_sprintf_panic(p_index, pt.len)
+ d1 := unsafe { *(&byte(pt[p_index])) }
+ res.write_b(d1)
+ status = .reset_params
+ p_index++
+ i++
+ continue
+ }
+
+ // 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] }))
+ status = .reset_params
+ p_index++
+ i++
+ continue
+ }
+
+ if status == .field_char {
+ mut fc_ch1 := `0`
+ mut fc_ch2 := `0`
+ if (i + 1) < str.len {
+ fc_ch1 = str[i + 1]
+ if (i + 2) < str.len {
+ fc_ch2 = str[i + 2]
+ }
+ }
+ if ch == `+` {
+ sign = true
+ i++
+ continue
+ } else if ch == `-` {
+ allign = .left
+ i++
+ continue
+ } else if ch in [`0`, ` `] {
+ if allign == .right {
+ pad_ch = ch
+ }
+ i++
+ continue
+ } else if ch == `'` {
+ i++
+ continue
+ } else if ch == `.` && fc_ch1 >= `1` && fc_ch1 <= `9` {
+ status = .check_float
+ i++
+ continue
+ }
+ // 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])) }
+ p_index++
+ v_sprintf_panic(p_index, pt.len)
+ mut s := unsafe { *(&string(pt[p_index])) }
+ s = s[..len]
+ p_index++
+ res.write_string(s)
+ status = .reset_params
+ i += 3
+ continue
+ }
+ status = .len_set_start
+ continue
+ }
+
+ if status == .len_set_start {
+ if ch >= `1` && ch <= `9` {
+ len0 = int(ch - `0`)
+ status = .len_set_in
+ i++
+ continue
+ }
+ if ch == `.` {
+ status = .check_float
+ i++
+ continue
+ }
+ status = .check_type
+ continue
+ }
+
+ if status == .len_set_in {
+ if ch >= `0` && ch <= `9` {
+ len0 *= 10
+ len0 += int(ch - `0`)
+ i++
+ continue
+ }
+ if ch == `.` {
+ status = .check_float
+ i++
+ continue
+ }
+ status = .check_type
+ continue
+ }
+
+ if status == .check_float {
+ if ch >= `0` && ch <= `9` {
+ len1 = int(ch - `0`)
+ status = .check_float_in
+ i++
+ continue
+ }
+ status = .check_type
+ continue
+ }
+
+ if status == .check_float_in {
+ if ch >= `0` && ch <= `9` {
+ len1 *= 10
+ len1 += int(ch - `0`)
+ i++
+ continue
+ }
+ status = .check_type
+ continue
+ }
+
+ if status == .check_type {
+ if ch == `l` {
+ if ch1 == `0` {
+ ch1 = `l`
+ i++
+ continue
+ } else {
+ ch2 = `l`
+ i++
+ continue
+ }
+ } else if ch == `h` {
+ if ch1 == `0` {
+ ch1 = `h`
+ i++
+ continue
+ } else {
+ ch2 = `h`
+ i++
+ continue
+ }
+ }
+ // signed integer
+ else if ch in [`d`, `i`] {
+ mut d1 := u64(0)
+ mut positive := true
+
+ // 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])) }
+ positive = if x >= 0 { true } else { false }
+ d1 = if positive { u64(x) } else { u64(-x) }
+ } else {
+ x := unsafe { *(&i16(pt[p_index])) }
+ positive = if x >= 0 { true } else { false }
+ d1 = if positive { u64(x) } else { u64(-x) }
+ }
+ }
+ // l i64
+ // ll i64 for now
+ `l` {
+ // placeholder for future 128bit integer code
+ /*
+ if ch2 == `l` {
+ v_sprintf_panic(p_index, pt.len)
+ x := *(&i128(pt[p_index]))
+ positive = if x >= 0 { true } else { false }
+ d1 = if positive { u128(x) } else { u128(-x) }
+ } else {
+ v_sprintf_panic(p_index, pt.len)
+ x := *(&i64(pt[p_index]))
+ positive = if x >= 0 { true } else { false }
+ d1 = if positive { u64(x) } else { u64(-x) }
+ }
+ */
+ v_sprintf_panic(p_index, pt.len)
+ 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])) }
+ 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
+ ))
+ status = .reset_params
+ p_index++
+ i++
+ ch1 = `0`
+ ch2 = `0`
+ continue
+ }
+ // unsigned integer
+ else if ch == `u` {
+ mut d1 := u64(0)
+ positive := true
+ v_sprintf_panic(p_index, pt.len)
+ match ch1 {
+ // h for 16 bit unsigned int
+ // hh fot 8 bit unsigned int
+ `h` {
+ if ch2 == `h` {
+ d1 = u64(unsafe { *(&byte(pt[p_index])) })
+ } else {
+ d1 = u64(unsafe { *(&u16(pt[p_index])) })
+ }
+ }
+ // l u64
+ // ll u64 for now
+ `l` {
+ // placeholder for future 128bit integer code
+ /*
+ if ch2 == `l` {
+ d1 = u128(*(&u128(pt[p_index])))
+ } else {
+ d1 = u64(*(&u64(pt[p_index])))
+ }
+ */
+ d1 = u64(unsafe { *(&u64(pt[p_index])) })
+ }
+ // default int
+ else {
+ 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
+ ))
+ status = .reset_params
+ p_index++
+ i++
+ continue
+ }
+ // hex
+ else if ch in [`x`, `X`] {
+ v_sprintf_panic(p_index, pt.len)
+ mut s := ''
+ match ch1 {
+ // h for 16 bit int
+ // hh fot 8 bit int
+ `h` {
+ if ch2 == `h` {
+ x := unsafe { *(&i8(pt[p_index])) }
+ s = x.hex()
+ } else {
+ x := unsafe { *(&i16(pt[p_index])) }
+ s = x.hex()
+ }
+ }
+ // l i64
+ // ll i64 for now
+ `l` {
+ // placeholder for future 128bit integer code
+ /*
+ if ch2 == `l` {
+ x := *(&i128(pt[p_index]))
+ s = x.hex()
+ } else {
+ x := *(&i64(pt[p_index]))
+ s = x.hex()
+ }
+ */
+ x := unsafe { *(&i64(pt[p_index])) }
+ s = x.hex()
+ }
+ else {
+ x := unsafe { *(&int(pt[p_index])) }
+ s = x.hex()
+ }
+ }
+
+ if ch == `X` {
+ 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
+ ))
+ status = .reset_params
+ p_index++
+ i++
+ continue
+ }
+
+ // float and double
+ if ch in [`f`, `F`] {
+ v_sprintf_panic(p_index, pt.len)
+ 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 })
+ status = .reset_params
+ p_index++
+ i++
+ continue
+ } else if ch in [`e`, `E`] {
+ v_sprintf_panic(p_index, pt.len)
+ 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 })
+ status = .reset_params
+ p_index++
+ i++
+ continue
+ } else if ch in [`g`, `G`] {
+ v_sprintf_panic(p_index, pt.len)
+ x := unsafe { *(&f64(pt[p_index])) }
+ positive := x >= f64(0.0)
+ 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
+ )
+ } 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
+ )
+ }
+ 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])) }
+ pad_ch = ` `
+ 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++
+ continue
+ }
+ }
+
+ status = .reset_params
+ p_index++
+ i++
+ }
+
+ if p_index != pt.len {
+ panic('$p_index % conversion specifiers, but given $pt.len args')
+ }
+
+ return res.str()
+}
+
+[inline]
+fn v_sprintf_panic(idx int, len int) {
+ if idx >= len {
+ panic('${idx + 1} % conversion specifiers, but given only $len args')
+ }
+}
+
+fn fabs(x f64) f64 {
+ if x < 0.0 {
+ return -x
+ }
+ return x
+}
+
+// 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)
+
+ // error!!
+ if fs[0] == `[` {
+ s.free()
+ return fs
+ }
+
+ if p.rm_tail_zero {
+ tmp := fs
+ fs = remove_tail_zeros_old(fs)
+ tmp.free()
+ }
+ 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` {
+ if p.positive {
+ if p.sign_flag {
+ res.write_b(`+`)
+ sign_len_diff = -1
+ }
+ } else {
+ res.write_b(`-`)
+ sign_len_diff = -1
+ }
+ tmp := s
+ s = fs.clone()
+ tmp.free()
+ } else {
+ if p.positive {
+ if p.sign_flag {
+ tmp := s
+ s = '+' + fs
+ tmp.free()
+ } else {
+ tmp := s
+ s = fs.clone()
+ tmp.free()
+ }
+ } else {
+ tmp := s
+ s = '-' + fs
+ tmp.free()
+ }
+ }
+
+ dif := p.len0 - s.len + sign_len_diff
+
+ if p.allign == .right {
+ 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++ {
+ res.write_b(p.pad_ch)
+ }
+ }
+
+ s.free()
+ fs.free()
+ tmp_res := res.str()
+ res.free()
+ return tmp_res
+ }
+}
+
+[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)
+ 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 sign_len_diff := 0
+ if p.pad_ch == `0` {
+ if p.positive {
+ if p.sign_flag {
+ res.write_b(`+`)
+ sign_len_diff = -1
+ }
+ } else {
+ res.write_b(`-`)
+ sign_len_diff = -1
+ }
+ tmp := s
+ s = fs.clone()
+ tmp.free()
+ } else {
+ if p.positive {
+ if p.sign_flag {
+ tmp := s
+ s = '+' + fs
+ tmp.free()
+ } else {
+ tmp := s
+ s = fs.clone()
+ tmp.free()
+ }
+ } else {
+ tmp := s
+ s = '-' + fs
+ tmp.free()
+ }
+ }
+
+ dif := p.len0 - s.len + sign_len_diff
+ if p.allign == .right {
+ 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++ {
+ res.write_b(p.pad_ch)
+ }
+ }
+ s.free()
+ fs.free()
+ tmp_res := res.str()
+ res.free()
+ return tmp_res
+ }
+}
+
+pub fn remove_tail_zeros_old(s string) string {
+ mut i := 0
+ mut last_zero_start := -1
+ mut dot_pos := -1
+ mut in_decimal := false
+ mut prev_ch := byte(0)
+ for i < s.len {
+ ch := unsafe { s.str[i] }
+ if ch == `.` {
+ in_decimal = true
+ dot_pos = i
+ } else if in_decimal {
+ if ch == `0` && prev_ch != `0` {
+ last_zero_start = i
+ } else if ch >= `1` && ch <= `9` {
+ last_zero_start = -1
+ } else if ch == `e` {
+ break
+ }
+ }
+ prev_ch = ch
+ i++
+ }
+
+ mut tmp := ''
+ if last_zero_start > 0 {
+ if last_zero_start == dot_pos + 1 {
+ tmp = s[..dot_pos] + s[i..]
+ } else {
+ tmp = s[..last_zero_start] + s[i..]
+ }
+ } else {
+ tmp = s
+ }
+ 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 res := strings.new_builder(20)
+ mut sign_len_diff := 0
+ if p.pad_ch == `0` {
+ if p.positive {
+ if p.sign_flag {
+ res.write_b(`+`)
+ sign_len_diff = -1
+ }
+ } else {
+ res.write_b(`-`)
+ sign_len_diff = -1
+ }
+ s = d.str()
+ } else {
+ if p.positive {
+ if p.sign_flag {
+ s = '+' + d.str()
+ } else {
+ s = d.str()
+ }
+ } else {
+ s = '-' + d.str()
+ }
+ }
+ dif := p.len0 - s.len + sign_len_diff
+
+ if p.allign == .right {
+ 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++ {
+ res.write_b(p.pad_ch)
+ }
+ }
+ return res.str()
+}