From 7fd1b169f38fb5791ce3c6c675649b864dd4bcb6 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Tue, 6 Feb 2024 23:53:02 +0800 Subject: [PATCH] builtin: add a string.u8_array() method (#20736) --- vlib/builtin/string.v | 53 ++++++++++++++++++++++++++++++++++++++ vlib/builtin/string_test.v | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 24c388ec11df42..e0ccfa33b86a36 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -613,6 +613,59 @@ pub fn (s string) u8() u8 { return u8(strconv.common_parse_uint(s, 0, 8, false, false) or { 0 }) } +// u8_array returns the value of the hex/bin string as u8 array. +// hex string example: `'0x11223344ee'.u8_array() == [u8(0x11),0x22,0x33,0x44,0xee]`. +// bin string example: `'0b1101_1101'.u8_array() == [u8(0xdd)]`. +// underscore in the string will be stripped. +pub fn (s string) u8_array() []u8 { + // strip underscore in the string + mut tmps := s.replace('_', '') + if tmps.len == 0 { + return []u8{} + } + tmps = tmps.to_lower() + if tmps.starts_with('0x') { + tmps = tmps[2..] + if tmps.len == 0 { + return []u8{} + } + // make sure every digit is valid hex digit + if !tmps.contains_only('0123456789abcdef') { + return []u8{} + } + // make sure tmps has even hex digits + if tmps.len % 2 == 1 { + tmps = '0' + tmps + } + + mut ret := []u8{len: tmps.len / 2} + for i in 0 .. ret.len { + ret[i] = u8(tmps[2 * i..2 * i + 2].parse_uint(16, 8) or { 0 }) + } + return ret + } else if tmps.starts_with('0b') { + tmps = tmps[2..] + if tmps.len == 0 { + return []u8{} + } + // make sure every digit is valid binary digit + if !tmps.contains_only('01') { + return []u8{} + } + // make sure tmps has multiple of 8 binary digits + if tmps.len % 8 != 0 { + tmps = '0'.repeat(8 - tmps.len % 8) + tmps + } + + mut ret := []u8{len: tmps.len / 8} + for i in 0 .. ret.len { + ret[i] = u8(tmps[8 * i..8 * i + 8].parse_uint(2, 8) or { 0 }) + } + return ret + } + return []u8{} +} + // u16 returns the value of the string as u16 `'1'.u16() == u16(1)`. @[inline] pub fn (s string) u16() u16 { diff --git a/vlib/builtin/string_test.v b/vlib/builtin/string_test.v index 4fee869f6c045e..4b5792bf5e6b71 100644 --- a/vlib/builtin/string_test.v +++ b/vlib/builtin/string_test.v @@ -811,6 +811,52 @@ fn test_to_num() { assert big.i64() == 93993993939322 } +fn test_to_u8_array() { + // empty string + assert ''.u8_array() == [] + assert '0x'.u8_array() == [] + assert '0X'.u8_array() == [] + assert '0b'.u8_array() == [] + assert '0B'.u8_array() == [] + // invalid digit + assert '-123'.u8_array() == [] + assert '1_2xt'.u8_array() == [] + assert 'd1_2xt'.u8_array() == [] + + // --------------------------------- + // hex test + // invalid hex digit + assert '0X-123'.u8_array() == [] + assert '0O12'.u8_array() == [] + // odd number of digits + assert '0x1'.u8_array() == [u8(0x01)] + assert '0x123'.u8_array() == [u8(0x01), 0x23] + assert '0x1_23'.u8_array() == [u8(0x01), 0x23] + + // long digits + long_u8 := [u8(0x00), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, + 0xdd, 0xee, 0xff] + assert '0x00112233445566778899aabbccddeeff'.u8_array() == long_u8 + assert '0x00_112_2334455667788_99aabbccddeeff'.u8_array() == long_u8 + assert '0x00112233445566778899AABBCCDDEEFF'.u8_array() == long_u8 + assert '0x001_12233445566778899A_ABBCCDDEEFF'.u8_array() == long_u8 + + // --------------------------------- + // bin test + // invalid bin digit + assert '0b-123'.u8_array() == [] + assert '0B12'.u8_array() == [] + // not enough length + assert '0b0'.u8_array() == [u8(0x00)] + assert '0b1'.u8_array() == [u8(0x01)] + assert '0b101'.u8_array() == [u8(0x05)] + assert '0b0101'.u8_array() == [u8(0x05)] + // long digits + assert '0b0101_0101'.u8_array() == [u8(0x55)] + assert '0b0101010110101010'.u8_array() == [u8(0x55), 0xaa] + assert '0b0101010110101010_0101010110101010'.u8_array() == [u8(0x55), 0xaa, 0x55, 0xaa] +} + fn test_inter_format_string() { float_num := 1.52345 float_num_string := '-${float_num:.3f}-'