Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

parsePartialNumberBase

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);

    // parse initial digits before dot
    var mantissa: MantissaT = 0;
    tryParseDigits(MantissaT, stream, &mantissa, info.base);
    const int_end = stream.offsetTrue();
    var n_digits = @as(isize, @intCast(stream.offsetTrue()));

    // handle dot with the following digits
    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));
    }

    // adjust required shift to offset mantissa for base-16 (2^4)
    if (info.base == 16) {
        exponent *= 4;
    }

    if (n_digits == 0) {
        return null;
    }

    // handle scientific format
    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; // length must be complete parsed length
    n.* += len;

    if (stream.underscore_count > 0 and !validUnderscores(stream.slice, info.base)) {
        return null;
    }

    // common case with not many digits
    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(); // re-parse from beginning
    while (stream.firstIs("0._")) {
        // '0' = '.' + 2
        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) {
        // at this point we have more than max_mantissa_digits significant digits, let's try again
        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)) {
                // big int
                break :blk @as(i64, @intCast(int_end)) - @as(i64, @intCast(stream.offsetTrue()));
            } else {
                // the next byte must be present and be '.'
                // 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;
        }
        // add back the explicit part
        exponent += exp_number;
    }

    return Number(T){
        .exponent = exponent,
        .mantissa = mantissa,
        .negative = negative,
        .many_digits = many_digits,
        .hex = info.base == 16,
    };
}