feature. See also
. The project being documented here (as the example) is the Zig library itself.
parse.parsePartialNumberBase
fn parsePartialNumberBase(comptime T: type, stream: *FloatStream, negative: bool, n: *usize, comptime info: ParseInfo) ?Number(T)
File
Code
fn parsePartialNumberBase(comptime T: type, stream: *FloatStream, negative: bool, n: *usize, comptime info: ParseInfo) ?Number(T) {
std.debug.assert(info.base == 10 or info.base == 16);
const MantissaT = common.mantissaType(T);
var mantissa: MantissaT = 0;
tryParseDigits(MantissaT, stream, &mantissa, info.base);
const int_end = stream.offsetTrue();
var n_digits = @as(isize, @intCast(stream.offsetTrue()));
var exponent: i64 = 0;
if (stream.firstIs(".")) {
stream.advance(1);
const marker = stream.offsetTrue();
tryParseDigits(MantissaT, stream, &mantissa, info.base);
const n_after_dot = stream.offsetTrue() - marker;
exponent = -@as(i64, @intCast(n_after_dot));
n_digits += @as(isize, @intCast(n_after_dot));
}
if (info.base == 16) {
exponent *= 4;
}
if (n_digits == 0) {
return null;
}
var exp_number: i64 = 0;
if (stream.firstIsLower(&.{info.exp_char_lower})) {
stream.advance(1);
exp_number = parseScientific(stream) orelse return null;
exponent += exp_number;
}
const len = stream.offset;
n.* += len;
if (stream.underscore_count > 0 and !validUnderscores(stream.slice, info.base)) {
return null;
}
if (n_digits <= info.max_mantissa_digits) {
return Number(T){
.exponent = exponent,
.mantissa = mantissa,
.negative = negative,
.many_digits = false,
.hex = info.base == 16,
};
}
n_digits -= info.max_mantissa_digits;
var many_digits = false;
stream.reset();
while (stream.firstIs("0._")) {
const next = stream.firstUnchecked();
if (next != '_') {
n_digits -= @as(isize, @intCast(next -| ('0' - 1)));
} else {
stream.underscore_count += 1;
}
stream.advance(1);
}
if (n_digits > 0) {
many_digits = true;
mantissa = 0;
stream.reset();
tryParseNDigits(MantissaT, stream, &mantissa, info.base, info.max_mantissa_digits);
exponent = blk: {
if (mantissa >= min_n_digit_int(MantissaT, info.max_mantissa_digits)) {
break :blk @as(i64, @intCast(int_end)) - @as(i64, @intCast(stream.offsetTrue()));
} else {
// We know this is true because we had more than 19
// digits previously, so we overflowed a 64-bit integer,
// but parsing only the integral digits produced less
// than 19 digits. That means we must have a decimal
// point, and at least 1 fractional digit.
stream.advance(1);
const marker = stream.offsetTrue();
tryParseNDigits(MantissaT, stream, &mantissa, info.base, info.max_mantissa_digits);
break :blk @as(i64, @intCast(marker)) - @as(i64, @intCast(stream.offsetTrue()));
}
};
if (info.base == 16) {
exponent *= 4;
}
exponent += exp_number;
}
return Number(T){
.exponent = exponent,
.mantissa = mantissa,
.negative = negative,
.many_digits = many_digits,
.hex = info.base == 16,
};
}