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.

stringToInteger

stdlib.stringToInteger
fn stringToInteger(comptime T: type, noalias buf: [*:0]const u8, noalias maybe_end: ?*[*:0]const u8, base: c_int) T

File

lib/c/stdlib.zig:133

Code

fn stringToInteger(comptime T: type, noalias buf: [*:0]const u8, noalias maybe_end: ?*[*:0]const u8, base: c_int) T {
    comptime assert(std.math.isPowerOfTwo(@bitSizeOf(T)));

    if (base < 0 or base == 1 or base > 36) {
        if (maybe_end) |end| {
            end.* = buf;
        }

        std.c._errno().* = @backingInt(std.c.E.INVAL);
        return 0;
    }

    var current = buf;
    while (std.ascii.isWhitespace(current[0])) : (current += 1) {}

    const negative: bool = switch (current[0]) {
        '-' => blk: {
            current += 1;
            break :blk true;
        },
        '+' => blk: {
            current += 1;
            break :blk false;
        },
        else => false,
    };

    // The prefix is allowed iff base == 0 or base == base of the prefix
    const real_base: u6, const digits = blk: {
        if (current[0] == '0') {
            if ((base == 0 or base == 16) and std.ascii.toLower(current[1]) == 'x' and std.ascii.isHex(current[2])) {
                break :blk .{ 16, current[2..] };
            } else if (base == 0) {
                break :blk .{ 8, current };
            } else {
                break :blk .{
                    switch (base) {
                        0 => 10,
                        else => @intCast(base),
                    },
                    current,
                };
            }
        } else {
            const real_base: u6 = switch (base) {
                0 => 10,
                else => @intCast(base),
            };

            _ = std.fmt.charToDigit(current[0], real_base) catch {
                // No digits to parse. Setting errno to .INVAL is optional in this case.
                if (maybe_end) |end| {
                    end.* = buf;
                }
                return 0;
            };
            break :blk .{ real_base, current };
        }
    };

    if (@typeInfo(T).int.signedness == .unsigned) {
        const result = parseDigitsWithSignGenericCharacter(T, u8, digits, maybe_end, real_base, .pos) catch {
            std.c._errno().* = @backingInt(std.c.E.RANGE);
            return std.math.maxInt(T);
        };

        return if (negative) -%result else result;
    }

    if (negative) return parseDigitsWithSignGenericCharacter(T, u8, digits, maybe_end, real_base, .neg) catch blk: {
        std.c._errno().* = @backingInt(std.c.E.RANGE);
        break :blk std.math.minInt(T);
    };

    return parseDigitsWithSignGenericCharacter(T, u8, digits, maybe_end, real_base, .pos) catch blk: {
        std.c._errno().* = @backingInt(std.c.E.RANGE);
        break :blk std.math.maxInt(T);
    };
}