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