| 1 | const std = @import("std"); |
| 2 | const maxInt = std.math.maxInt; |
| 3 | |
| 4 | pub fn parseU64(buf: []const u8, radix: u8) !u64 { |
| 5 | var x: u64 = 0; |
| 6 | |
| 7 | for (buf) |c| { |
| 8 | const digit = charToDigit(c); |
| 9 | |
| 10 | if (digit >= radix) { |
| 11 | return error.InvalidChar; |
| 12 | } |
| 13 | |
| 14 | // x *= radix |
| 15 | var ov = @mulWithOverflow(x, radix); |
| 16 | if (ov[1] != 0) return error.OverFlow; |
| 17 | |
| 18 | // x += digit |
| 19 | ov = @addWithOverflow(ov[0], digit); |
| 20 | if (ov[1] != 0) return error.OverFlow; |
| 21 | x = ov[0]; |
| 22 | } |
| 23 | |
| 24 | return x; |
| 25 | } |
| 26 | |
| 27 | fn charToDigit(c: u8) u8 { |
| 28 | return switch (c) { |
| 29 | '0'...'9' => c - '0', |
| 30 | 'A'...'Z' => c - 'A' + 10, |
| 31 | 'a'...'z' => c - 'a' + 10, |
| 32 | else => maxInt(u8), |
| 33 | }; |
| 34 | } |
| 35 | |
| 36 | test "parse u64" { |
| 37 | const result = try parseU64("1234", 10); |
| 38 | try std.testing.expectEqual(1234, result); |
| 39 | } |
| 40 | |
| 41 | // test |