1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
// SPDX-License-Identifier: MPL-2.0
// (c) Hare authors <https://harelang.org>
use types;
// Converts a string to an i64. Returns [[invalid]] if the string is empty or
// contains invalid characters. Returns [[overflow]] if the number is too large
// to be represented by an i64.
export fn stoi64(s: str, base: base = base::DEC) (i64 | invalid | overflow) = {
let (sign, u) = parseint(s, base)?;
// Two's complement: I64_MIN = -I64_MAX - 1
let max = if (sign) types::I64_MAX: u64 + 1 else types::I64_MAX: u64;
if (u > max) {
return overflow;
};
return u: i64 * (if (sign) -1 else 1);
};
fn stoiminmax(
s: str,
base: base,
min: i64,
max: i64,
) (i64 | invalid | overflow) = {
const n = stoi64(s, base)?;
if (n < min || n > max) {
return overflow;
};
return n;
};
// Converts a string to an i32. Returns [[invalid]] if the string is empty or
// contains invalid characters. Returns [[overflow]] if the number is too large
// to be represented by an i32.
export fn stoi32(s: str, base: base = base::DEC) (i32 | invalid | overflow) =
stoiminmax(s, base, types::I32_MIN, types::I32_MAX)?: i32;
// Converts a string to an i16. Returns [[invalid]] if the string is empty or
// contains invalid characters. Returns [[overflow]] if the number is too large
// to be represented by an i16.
export fn stoi16(s: str, base: base = base::DEC) (i16 | invalid | overflow) =
stoiminmax(s, base, types::I16_MIN, types::I16_MAX)?: i16;
// Converts a string to an i8. Returns [[invalid]] if the string is empty or
// contains invalid characters. Returns [[overflow]] if the number is too large
// to be represented by an i8.
export fn stoi8(s: str, base: base = base::DEC) (i8 | invalid | overflow) =
stoiminmax(s, base, types::I8_MIN, types::I8_MAX)?: i8;
// Converts a string to an int. Returns [[invalid]] if the string is empty or
// contains invalid characters. Returns [[overflow]] if the number is too large
// to be represented by an int.
export fn stoi(s: str, base: base = base::DEC) (int | invalid | overflow) =
stoiminmax(s, base, types::INT_MIN, types::INT_MAX)?: int;
@test fn stoi() void = {
assert(stoi64("") as invalid == 0);
assert(stoi64("abc") as invalid == 0);
assert(stoi64("1a") as invalid == 1);
assert(stoi64("+") as invalid == 1);
assert(stoi64("-+") as invalid == 1);
assert(stoi64("-z") as invalid == 1);
assert(stoi64("9223372036854775808") is overflow);
assert(stoi64("-9223372036854775809") is overflow);
assert(stoi64("0") as i64 == 0);
assert(stoi64("1") as i64 == 1);
assert(stoi64("+1") as i64 == 1);
assert(stoi64("-1") as i64 == -1);
assert(stoi64("9223372036854775807") as i64 == types::I64_MAX);
assert(stoi64("-9223372036854775808") as i64 == types::I64_MIN);
assert(stoi32("2147483648") is overflow);
assert(stoi32("-2147483649") is overflow);
assert(stoi32("2147483647") as i32 == 2147483647);
assert(stoi32("-2147483648") as i32 == -2147483648);
};
@test fn stoi_bases() void = {
assert(stoi64("-7f", 16) as i64 == -0x7f);
assert(stoi64("7F", 16) as i64 == 0x7f);
assert(stoi64("37", 8) as i64 == 0o37);
assert(stoi64("-110101", 2) as i64 == -0b110101);
};
|