From afd74ad6e66932914b0861dde6a3ac3f910c63c3 Mon Sep 17 00:00:00 2001 From: Vinicius Silva Date: Tue, 16 Jan 2024 18:58:28 -0300 Subject: [PATCH] builtin: add `is_hex()`, `is_int()`, `is_bin()`, and `is_oct()` methods to the string type (#20540) --- vlib/builtin/string.v | 143 ++++++++++++++++++++++++++++++++ vlib/builtin/string_test.v | 162 +++++++++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+) diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 818a46d83c403f..aef4c5fbc5e998 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -1786,6 +1786,149 @@ fn (s string) at_with_check(idx int) ?u8 { } } +// Check if a string is an octal value. Returns 'true' if it is, or 'false' if it is not +@[direct_array_access] +pub fn (str string) is_oct() bool { + mut i := 0 + + if str[i] == `0` { + i++ + } else if str[i] == `-` || str[i] == `+` { + i++ + + if str[i] == `0` { + i++ + } else { + return false + } + } else { + return false + } + + if str[i] == `o` { + i++ + } else { + return false + } + + if i == str.len { + return false + } + + for i < str.len { + if str[i] < `0` || str[i] > `7` { + return false + } + i++ + } + + return true +} + +// Check if a string is an binary value. Returns 'true' if it is, or 'false' if it is not +@[direct_array_access] +pub fn (str string) is_bin() bool { + mut i := 0 + + if str[i] == `0` { + i++ + } else if str[i] == `-` || str[i] == `+` { + i++ + + if str[i] == `0` { + i++ + } else { + return false + } + } else { + return false + } + + if str[i] == `b` { + i++ + } else { + return false + } + + if i == str.len { + return false + } + + for i < str.len { + if str[i] < `0` || str[i] > `1` { + return false + } + i++ + } + + return true +} + +// Check if a string is an hexadecimal value. Returns 'true' if it is, or 'false' if it is not +@[direct_array_access] +pub fn (str string) is_hex() bool { + mut i := 0 + + if str[i] == `0` { + i++ + } else if str[i] == `-` || str[i] == `+` { + i++ + + if str[i] == `0` { + i++ + } else { + return false + } + } else { + return false + } + + if str[i] == `x` { + i++ + } else { + return false + } + + if i == str.len { + return false + } + + for i < str.len { + if (str[i] < `0` || str[i] > `9`) && ((str[i] < `a` || str[i] > `f`) + && (str[i] < `A` || str[i] > `F`)) { + return false + } + i++ + } + + return true +} + +// Check if a string is an integer value. Returns 'true' if it is, or 'false' if it is not +@[direct_array_access] +pub fn (str string) is_int() bool { + mut i := 0 + + if (str[i] != `-` && str[i] != `+`) && (!str[i].is_digit()) { + return false + } else { + i++ + } + + if i == str.len && (!str[i - 1].is_digit()) { + return false + } + + for i < str.len { + if str[i] < `0` || str[i] > `9` { + return false + } + i++ + } + + return true +} + // is_space returns `true` if the byte is a white space character. // The following list is considered white space characters: ` `, `\t`, `\n`, `\v`, `\f`, `\r`, 0x85, 0xa0 // Example: assert u8(` `).is_space() == true diff --git a/vlib/builtin/string_test.v b/vlib/builtin/string_test.v index e96dbe79b10f01..6edf6cda1cafb6 100644 --- a/vlib/builtin/string_test.v +++ b/vlib/builtin/string_test.v @@ -425,6 +425,168 @@ fn test_rsplit_once() ? { assert ext3 == '' } +fn test_is_bin() { + assert '0b1'.is_bin() == true + assert '0b0'.is_bin() == true + assert '0b'.is_bin() == false + assert '-0b'.is_bin() == false + assert '-0b1'.is_bin() == true + assert '-0b0'.is_bin() == true + assert '-0b1101'.is_bin() == true + assert '-0b0101'.is_bin() == true + assert '-324'.is_bin() == false + assert '-0'.is_bin() == false + assert '0x1'.is_bin() == false + assert '0x1A'.is_bin() == false + assert '+0b1101'.is_bin() == true + assert '+0b1'.is_bin() == true + assert '-0x1'.is_bin() == false + assert '-0x1A'.is_bin() == false + assert '0x'.is_bin() == false + assert '0'.is_bin() == false + assert '0xFF'.is_bin() == false + assert '0xG'.is_bin() == false + assert '-'.is_bin() == false + assert '+'.is_bin() == false + assert '-0xFF'.is_bin() == false + assert '0.34'.is_bin() == false + assert '0o23'.is_bin() == false + assert 'vlang'.is_bin() == false +} + +fn test_is_oct() { + assert '0o0'.is_oct() == true + assert '0o1'.is_oct() == true + assert '0o2'.is_oct() == true + assert '-0o0'.is_oct() == true + assert '-0o1'.is_oct() == true + assert '-0o2'.is_oct() == true + + assert '0o04'.is_oct() == true + assert '0o16'.is_oct() == true + assert '0o23'.is_oct() == true + assert '-0o05'.is_oct() == true + assert '-0o13'.is_oct() == true + assert '-0o22'.is_oct() == true + + assert '0o8'.is_oct() == false + assert '0o9'.is_oct() == false + assert '-0o8'.is_oct() == false + assert '-0o9'.is_oct() == false + assert '0o84'.is_oct() == false + assert '0o96'.is_oct() == false + assert '-0o83'.is_oct() == false + assert '-0o2923'.is_oct() == false + assert '0b1'.is_oct() == false + assert '0b0'.is_oct() == false + assert '0b'.is_oct() == false + assert '-0b'.is_oct() == false + assert '-0b1'.is_oct() == false + assert '-0b0'.is_oct() == false + assert '-0b1101'.is_oct() == false + assert '+0o234'.is_oct() == true + assert '+0o432'.is_oct() == true + assert '-'.is_oct() == false + assert '+'.is_oct() == false + assert '-0b0101'.is_oct() == false + assert '-324'.is_oct() == false + assert '-0'.is_oct() == false + assert '0x1'.is_oct() == false + assert '0x1A'.is_oct() == false + assert '-0x1'.is_oct() == false + assert '-0x1A'.is_oct() == false + assert '0x'.is_oct() == false + assert '0'.is_oct() == false + assert '0xFF'.is_oct() == false + assert '0xG'.is_oct() == false + assert '-0xFF'.is_oct() == false + assert '0.34'.is_oct() == false + assert 'vlang'.is_oct() == false +} + +fn test_is_hex() { + assert '-324'.is_hex() == false + assert '-0'.is_hex() == false + assert '0x1'.is_hex() == true + assert '0x1A'.is_hex() == true + assert '-0x1'.is_hex() == true + assert '-0x1A'.is_hex() == true + assert '+0x1'.is_hex() == true + assert '+0x1A'.is_hex() == true + assert '0x'.is_hex() == false + assert '0'.is_hex() == false + assert '-'.is_hex() == false + assert '+'.is_hex() == false + assert '0xFF'.is_hex() == true + assert '0xG'.is_hex() == false + assert '-0xFF'.is_hex() == true + assert '0b1101'.is_hex() == false + assert '0.34'.is_hex() == false + assert '0o23'.is_hex() == false + assert 'vlang'.is_hex() == false +} + +fn test_is_int() { + assert '-324'.is_int() == true + assert '234'.is_int() == true + assert '-0'.is_int() == true + assert '-b'.is_int() == false + assert '-123456789'.is_int() == true + assert '123456789'.is_int() == true + assert '0x1'.is_int() == false + assert '0b1101'.is_int() == false + assert '0.34'.is_int() == false + assert '0o23'.is_int() == false + assert 'vlang'.is_int() == false + + assert '0o0'.is_int() == false + assert '0o1'.is_int() == false + assert '0o2'.is_int() == false + assert '-0o0'.is_int() == false + assert '-0o1'.is_int() == false + assert '-0o2'.is_int() == false + + assert '0o04'.is_int() == false + assert '0o16'.is_int() == false + assert '0o23'.is_int() == false + assert '-0o05'.is_int() == false + assert '-0o13'.is_int() == false + assert '-0o22'.is_int() == false + + assert '0o8'.is_int() == false + assert '0o9'.is_int() == false + assert '-0o8'.is_int() == false + assert '-0o9'.is_int() == false + assert '0o84'.is_int() == false + assert '0o96'.is_int() == false + assert '-0o83'.is_int() == false + assert '-0o2923'.is_int() == false + assert '0b1'.is_int() == false + assert '0b0'.is_int() == false + assert '0b'.is_int() == false + assert '-0b'.is_int() == false + assert '-0b1'.is_int() == false + assert '-0b0'.is_int() == false + assert '-0b1101'.is_int() == false + assert '-0b0101'.is_int() == false + assert '-324'.is_int() == true + assert '-0'.is_int() == true + assert '0x1'.is_int() == false + assert '0x1A'.is_int() == false + assert '-0x1'.is_int() == false + assert '-0x1A'.is_oct() == false + assert '0x'.is_int() == false + assert '0'.is_int() == true + assert '0xFF'.is_int() == false + assert '0xG'.is_int() == false + assert '-0xFF'.is_int() == false + assert '0.34'.is_int() == false + assert '-'.is_int() == false + assert '+'.is_int() == false + assert '+3'.is_int() == true + assert '+3232'.is_int() == true +} + fn test_trim_space() { a := ' a ' assert a.trim_space() == 'a'