feature. See also
. The project being documented here (as the example) is the Zig library itself.
fmt.parseIntWithSign
fn parseIntWithSign(
comptime Result: type,
comptime Character: type,
buf: []const Character,
base: u8,
comptime sign: enum
File
Code
fn parseIntWithSign(
comptime Result: type,
comptime Character: type,
buf: []const Character,
base: u8,
comptime sign: enum { pos, neg },
) ParseIntError!Result {
if (buf.len == 0) return error.InvalidCharacter;
var buf_base = base;
var buf_start = buf;
if (base == 0) {
buf_base = 10;
if (buf.len > 2 and buf[0] == '0') {
if (math.cast(u8, buf[1])) |c| switch (std.ascii.toLower(c)) {
'b' => {
buf_base = 2;
buf_start = buf[2..];
},
'o' => {
buf_base = 8;
buf_start = buf[2..];
},
'x' => {
buf_base = 16;
buf_start = buf[2..];
},
else => {},
};
}
}
const add = switch (sign) {
.pos => math.add,
.neg => math.sub,
};
// `buf_base` from overflowing Result.
const info = @typeInfo(Result);
const Accumulate = @Int(info.int.signedness, @max(8, info.int.bits));
var accumulate: Accumulate = 0;
if (buf_start[0] == '_' or buf_start[buf_start.len - 1] == '_') return error.InvalidCharacter;
for (buf_start) |c| {
if (c == '_') continue;
const digit = try charToDigit(math.cast(u8, c) orelse return error.InvalidCharacter, buf_base);
if (accumulate != 0) {
accumulate = try math.mul(Accumulate, accumulate, math.cast(Accumulate, buf_base) orelse return error.Overflow);
} else if (sign == .neg) {
// Consider parsing "-4" as an i3.
// This should work, but positive 4 overflows i3, so we can't cast the digit to T and subtract.
accumulate = math.cast(Accumulate, -@as(i8, @intCast(digit))) orelse return error.Overflow;
continue;
}
accumulate = try add(Accumulate, accumulate, math.cast(Accumulate, digit) orelse return error.Overflow);
}
return if (Result == Accumulate)
accumulate
else
math.cast(Result, accumulate) orelse return error.Overflow;
}