File: stoi.ha

package info (click to toggle)
hare 0.26.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 7,352 kB
  • sloc: asm: 1,374; makefile: 123; sh: 117; lisp: 101
file content (86 lines) | stat: -rw-r--r-- 3,136 bytes parent folder | download | duplicates (3)
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);
};