From 33163238e751030a58e8f12bd131e92047b0e1dc Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 3 Dec 2021 19:52:14 +0200 Subject: [PATCH] strconv: add a small performance optimisation --- vlib/builtin/string_interpolation.v | 33 +++++++++++++---------------- vlib/strconv/number_to_base.c.v | 16 +++++++++----- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/vlib/builtin/string_interpolation.v b/vlib/builtin/string_interpolation.v index b4ca6c21b9..e7ac2ba944 100644 --- a/vlib/builtin/string_interpolation.v +++ b/vlib/builtin/string_interpolation.v @@ -154,14 +154,14 @@ pub fn get_str_intp_u32_format(fmt_type StrIntpType, in_width int, in_precision // convert from struct to formated string [manualfree] -fn (data StrIntpData) get_fmt_format(mut sb strings.Builder) { +fn (data &StrIntpData) process_str_intp_data(mut sb strings.Builder) { x := data.fmt typ := StrIntpType(x & 0x1F) allign := int((x >> 5) & 0x01) - upper_case := if ((x >> 7) & 0x01) > 0 { true } else { false } + upper_case := ((x >> 7) & 0x01) > 0 sign := int((x >> 8) & 0x01) precision := int((x >> 9) & 0x7F) - tail_zeros := if ((x >> 16) & 0x01) > 0 { true } else { false } + tail_zeros := ((x >> 16) & 0x01) > 0 width := int(i16((x >> 17) & 0x3FF)) mut base := int(x >> 27) & 0xF fmt_pad_ch := byte((x >> 31) & 0xFF) @@ -187,7 +187,7 @@ fn (data StrIntpData) get_fmt_format(mut sb strings.Builder) { len0_set := if width > 0 { width } else { -1 } len1_set := if precision == 0x7F { -1 } else { precision } - sign_set := if sign == 1 { true } else { false } + sign_set := sign == 1 mut bf := strconv.BF_param{ pad_ch: pad_ch // padding char @@ -651,22 +651,19 @@ pub: } // interpolation function -[manualfree] +[direct_array_access; manualfree] pub fn str_intp(data_len int, in_data voidptr) string { mut res := strings.new_builder(256) - unsafe { - mut i := 0 - for i < data_len { - data := &StrIntpData(&byte(in_data) + (int(sizeof(StrIntpData)) * i)) - // avoid empty strings - if data.str.len != 0 { - res.write_string(data.str) - } - // skip empty data - if data.fmt != 0 { - data.get_fmt_format(mut &res) - } - i++ + input_base := &StrIntpData(in_data) + for i := 0; i < data_len; i++ { + data := unsafe { &(input_base[i]) } + // avoid empty strings + if data.str.len != 0 { + res.write_string(data.str) + } + // skip empty data + if data.fmt != 0 { + data.process_str_intp_data(mut res) } } ret := res.str() diff --git a/vlib/strconv/number_to_base.c.v b/vlib/strconv/number_to_base.c.v index 0ca7e9c915..afce53be79 100644 --- a/vlib/strconv/number_to_base.c.v +++ b/vlib/strconv/number_to_base.c.v @@ -4,7 +4,7 @@ const base_digits = '0123456789abcdefghijklmnopqrstuvwxyz' // format_int returns the string representation of the number n in base `radix` // for digit values > 10, this function uses the small latin leters a-z. -[manualfree] +[direct_array_access; manualfree] pub fn format_int(n i64, radix int) string { unsafe { if radix < 2 || radix > 36 { @@ -14,22 +14,28 @@ pub fn format_int(n i64, radix int) string { return '0' } mut n_copy := n - mut sign := '' + mut have_minus := false if n < 0 { - sign = '-' + have_minus = true n_copy = -n_copy } mut res := '' for n_copy != 0 { tmp_0 := res - tmp_1 := strconv.base_digits[n_copy % radix].ascii_str() + bdx := int(n_copy % radix) + tmp_1 := strconv.base_digits[bdx].ascii_str() res = tmp_1 + res tmp_0.free() tmp_1.free() // res = base_digits[n_copy % radix].ascii_str() + res n_copy /= radix } - return '$sign$res' + if have_minus { + final_res := '-' + res + res.free() + return final_res + } + return res } }