Function parseNumberLiteral [src]

Alias for std.zig.number_literal.parseNumberLiteral

Parse Zig number literal accepted by fmt.parseInt, fmt.parseFloat and big_int.setString. Valid for any input.

Prototype

pub fn parseNumberLiteral(bytes: []const u8) Result

Parameters

bytes: []const u8

Source

pub fn parseNumberLiteral(bytes: []const u8) Result { var i: usize = 0; var base: u8 = 10; if (bytes.len >= 2 and bytes[0] == '0') switch (bytes[1]) { 'b' => { base = 2; i = 2; }, 'o' => { base = 8; i = 2; }, 'x' => { base = 16; i = 2; }, 'B', 'O', 'X' => return .{ .failure = .{ .upper_case_base = 1 } }, '.', 'e', 'E' => {}, else => return .{ .failure = .leading_zero }, }; if (bytes.len == 2 and base != 10) return .{ .failure = .digit_after_base }; var x: u64 = 0; var overflow = false; var underscore = false; var period = false; var special: u8 = 0; var exponent = false; var float = false; while (i < bytes.len) : (i += 1) { const c = bytes[i]; switch (c) { '_' => { if (i == 2 and base != 10) return .{ .failure = .{ .invalid_underscore_after_special = i } }; if (special != 0) return .{ .failure = .{ .invalid_underscore_after_special = i } }; if (underscore) return .{ .failure = .{ .repeated_underscore = i } }; underscore = true; continue; }, 'e', 'E' => if (base == 10) { float = true; if (exponent) return .{ .failure = .{ .duplicate_exponent = i } }; if (underscore) return .{ .failure = .{ .exponent_after_underscore = i } }; special = c; exponent = true; continue; }, 'p', 'P' => if (base == 16) { if (i == 2) { return .{ .failure = .{ .digit_after_base = {} } }; } float = true; if (exponent) return .{ .failure = .{ .duplicate_exponent = i } }; if (underscore) return .{ .failure = .{ .exponent_after_underscore = i } }; special = c; exponent = true; continue; }, '.' => { if (exponent) { const digit_index = i - ".e".len; if (digit_index < bytes.len) { switch (bytes[digit_index]) { '0'...'9' => return .{ .failure = .{ .period_after_exponent = i } }, else => {}, } } } float = true; if (base != 10 and base != 16) return .{ .failure = .{ .invalid_float_base = 2 } }; if (period) return .{ .failure = .duplicate_period }; period = true; if (underscore) return .{ .failure = .{ .special_after_underscore = i } }; special = c; continue; }, '+', '-' => { switch (special) { 'p', 'P' => {}, 'e', 'E' => if (base != 10) return .{ .failure = .{ .invalid_exponent_sign = i } }, else => return .{ .failure = .{ .invalid_exponent_sign = i } }, } special = c; continue; }, else => {}, } const digit = switch (c) { '0'...'9' => c - '0', 'A'...'Z' => c - 'A' + 10, 'a'...'z' => c - 'a' + 10, else => return .{ .failure = .{ .invalid_character = i } }, }; if (digit >= base) return .{ .failure = .{ .invalid_digit = .{ .i = i, .base = @as(Base, @enumFromInt(base)) } } }; if (exponent and digit >= 10) return .{ .failure = .{ .invalid_digit_exponent = i } }; underscore = false; special = 0; if (float) continue; if (x != 0) { const res = @mulWithOverflow(x, base); if (res[1] != 0) overflow = true; x = res[0]; } const res = @addWithOverflow(x, digit); if (res[1] != 0) overflow = true; x = res[0]; } if (underscore) return .{ .failure = .{ .trailing_underscore = bytes.len - 1 } }; if (special != 0) return .{ .failure = .{ .trailing_special = bytes.len - 1 } }; if (float) return .{ .float = @as(FloatBase, @enumFromInt(base)) }; if (overflow) return .{ .big_int = @as(Base, @enumFromInt(base)) }; return .{ .int = x }; }