mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-25 12:24:57 +00:00
Add i128 and u128 parsers to strconv
This commit is contained in:
@@ -300,6 +300,229 @@ parse_uint :: proc(s: string, base := 0) -> (value: uint, ok: bool) {
|
||||
}
|
||||
|
||||
|
||||
// Parses an integer value from a string, in the given base, without a prefix.
|
||||
//
|
||||
// Returns ok=false if no numeric value of the appropriate base could be found,
|
||||
// or if the input string contained more than just the number.
|
||||
//
|
||||
// ```
|
||||
// n, ok := strconv.parse_i128_of_base("-1234eeee", 10);
|
||||
// assert(n == -1234 && ok);
|
||||
// ```
|
||||
parse_i128_of_base :: proc(str: string, base: int) -> (value: i128, ok: bool) {
|
||||
assert(base <= 16, "base must be 1-16")
|
||||
|
||||
s := str
|
||||
if s == "" {
|
||||
return
|
||||
}
|
||||
|
||||
neg := false
|
||||
if len(s) > 1 {
|
||||
switch s[0] {
|
||||
case '-':
|
||||
neg = true
|
||||
s = s[1:]
|
||||
case '+':
|
||||
s = s[1:]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
i := 0
|
||||
for r in s {
|
||||
if r == '_' {
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
v := i128(_digit_value(r))
|
||||
if v >= i128(base) {
|
||||
break
|
||||
}
|
||||
value *= i128(base)
|
||||
value += v
|
||||
i += 1
|
||||
}
|
||||
s = s[i:]
|
||||
|
||||
if neg {
|
||||
value = -value
|
||||
}
|
||||
ok = len(s) == 0
|
||||
return
|
||||
}
|
||||
|
||||
// Parses a integer value from a string, in base 10, unless there's a prefix.
|
||||
//
|
||||
// Returns ok=false if a valid integer could not be found,
|
||||
// or if the input string contained more than just the number.
|
||||
//
|
||||
// ```
|
||||
// n, ok := strconv.parse_i128_maybe_prefixed("1234");
|
||||
// assert(n == 1234 && ok);
|
||||
//
|
||||
// n, ok = strconv.parse_i128_maybe_prefixed("0xeeee");
|
||||
// assert(n == 0xeeee && ok);
|
||||
// ```
|
||||
parse_i128_maybe_prefixed :: proc(str: string) -> (value: i128, ok: bool) {
|
||||
s := str
|
||||
if s == "" {
|
||||
return
|
||||
}
|
||||
|
||||
neg := false
|
||||
if len(s) > 1 {
|
||||
switch s[0] {
|
||||
case '-':
|
||||
neg = true
|
||||
s = s[1:]
|
||||
case '+':
|
||||
s = s[1:]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
base: i128 = 10
|
||||
if len(s) > 2 && s[0] == '0' {
|
||||
switch s[1] {
|
||||
case 'b': base = 2; s = s[2:]
|
||||
case 'o': base = 8; s = s[2:]
|
||||
case 'd': base = 10; s = s[2:]
|
||||
case 'z': base = 12; s = s[2:]
|
||||
case 'x': base = 16; s = s[2:]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
i := 0
|
||||
for r in s {
|
||||
if r == '_' {
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
v := i128(_digit_value(r))
|
||||
if v >= base {
|
||||
break
|
||||
}
|
||||
value *= base
|
||||
value += v
|
||||
i += 1
|
||||
}
|
||||
s = s[i:]
|
||||
|
||||
if neg {
|
||||
value = -value
|
||||
}
|
||||
ok = len(s) == 0
|
||||
return
|
||||
}
|
||||
|
||||
parse_i128 :: proc{parse_i128_maybe_prefixed, parse_i128_of_base}
|
||||
|
||||
// Parses an unsigned integer value from a string, in the given base, and
|
||||
// without a prefix.
|
||||
//
|
||||
// Returns ok=false if no numeric value of the appropriate base could be found,
|
||||
// or if the input string contained more than just the number.
|
||||
//
|
||||
// ```
|
||||
// n, ok := strconv.parse_u128_of_base("1234eeee", 10);
|
||||
// assert(n == 1234 && ok);
|
||||
//
|
||||
// n, ok = strconv.parse_u128_of_base("5678eeee", 16);
|
||||
// assert(n == 0x5678eeee && ok);
|
||||
// ```
|
||||
parse_u128_of_base :: proc(str: string, base: int) -> (value: u128, ok: bool) {
|
||||
assert(base <= 16, "base must be 1-16")
|
||||
s := str
|
||||
if s == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if len(s) > 1 && s[0] == '+' {
|
||||
s = s[1:]
|
||||
}
|
||||
|
||||
i := 0
|
||||
for r in s {
|
||||
if r == '_' {
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
v := u128(_digit_value(r))
|
||||
if v >= u128(base) {
|
||||
break
|
||||
}
|
||||
value *= u128(base)
|
||||
value += v
|
||||
i += 1
|
||||
}
|
||||
s = s[i:]
|
||||
|
||||
ok = len(s) == 0
|
||||
return
|
||||
}
|
||||
|
||||
// Parses an unsigned integer value from a string in base 10, unless there's a prefix.
|
||||
//
|
||||
// Returns ok=false if a valid integer could not be found, if the value was negative,
|
||||
// or if the input string contained more than just the number.
|
||||
//
|
||||
// ```
|
||||
// n, ok := strconv.parse_u128_maybe_prefixed("1234");
|
||||
// assert(n == 1234 && ok);
|
||||
//
|
||||
// n, ok = strconv.parse_u128_maybe_prefixed("0xeeee");
|
||||
// assert(n == 0xeeee && ok);
|
||||
// ```
|
||||
parse_u128_maybe_prefixed :: proc(str: string) -> (value: u128, ok: bool) {
|
||||
s := str
|
||||
if s == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if len(s) > 1 && s[0] == '+' {
|
||||
s = s[1:]
|
||||
}
|
||||
|
||||
|
||||
base := u128(10)
|
||||
if len(s) > 2 && s[0] == '0' {
|
||||
switch s[1] {
|
||||
case 'b': base = 2; s = s[2:]
|
||||
case 'o': base = 8; s = s[2:]
|
||||
case 'd': base = 10; s = s[2:]
|
||||
case 'z': base = 12; s = s[2:]
|
||||
case 'x': base = 16; s = s[2:]
|
||||
}
|
||||
}
|
||||
|
||||
i := 0
|
||||
for r in s {
|
||||
if r == '_' {
|
||||
i += 1
|
||||
continue
|
||||
}
|
||||
v := u128(_digit_value(r))
|
||||
if v >= base {
|
||||
break
|
||||
}
|
||||
value *= base
|
||||
value += v
|
||||
i += 1
|
||||
}
|
||||
s = s[i:]
|
||||
|
||||
ok = len(s) == 0
|
||||
return
|
||||
}
|
||||
|
||||
parse_u128 :: proc{parse_u128_maybe_prefixed, parse_u128_of_base}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Parses a 32-bit floating point number from a string.
|
||||
//
|
||||
// Returns ok=false if a base 10 float could not be found,
|
||||
|
||||
Reference in New Issue
Block a user