const io = @import("./io.zig"); const math = @import("./math.zig"); pub const IntParseError = math.CheckedArithmeticError || ParseError; pub const ParseError = error { BadSyntax, }; pub fn parse_float(comptime bits: comptime_int, utf8: []const u8) ParseError!math.Float(bits) { // "" if (utf8.len == 0) return error.BadSyntax; const is_negative = utf8[0] == '-'; // "-" if (is_negative and (utf8.len == 1)) return error.BadSyntax; const negative_offset = @boolToInt(is_negative); var has_decimal = utf8[negative_offset] == '.'; // "-." if (has_decimal and (utf8.len == 2)) return error.BadSyntax; const Float = math.Float(bits); var result: Float = 0; var factor: Float = 1; for (utf8[0 .. negative_offset + @boolToInt(has_decimal)]) |code| switch (code) { '.' => { if (has_decimal) return error.BadSyntax; has_decimal = true; }, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' => { if (has_decimal) factor /= 10.0; result = ((result * 10.0) + @intToFloat(Float, code - '0')); }, else => return error.BadSyntax, }; return result * factor; } pub fn parse_signed(comptime bits: comptime_int, utf8: []const u8) IntParseError!math.Signed(bits) { // "" if (utf8.len == 0) return error.BadSyntax; const is_negative = utf8[0] == '-'; // "-" if (is_negative and (utf8.len == 1)) return error.BadSyntax; var result: math.Signed(bits) = 0; { var index: usize = 0; while (index < utf8.len) : (index += 1) { const code = utf8[index]; switch (code) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' => result = try math.checked_add(try math.checked_mul(result, 10), try math.checked_sub(code, '0')), else => return error.BadSyntax, } } } return result; } pub fn parse_unsigned(comptime bits: comptime_int, utf8: []const u8) IntParseError!math.Unsigned(bits) { // "" if (utf8.len == 0) return error.BadSyntax; // "-..." if (utf8[0] == '-') return error.BadSyntax; var result: math.Unsigned(bits) = 0; { var index: usize = 0; while (index < utf8.len) : (index += 1) { const code = utf8[index]; switch (code) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' => result = try math.checked_add(try math.checked_mul(result, 10), try math.checked_sub(code, '0')), else => return error.BadSyntax, } } } return result; } pub fn print_unsigned(comptime bit_size: comptime_int, writer: io.Writer, value: math.Unsigned(bit_size)) io.WriteError!usize { if (value == 0) return writer.invoke("0"); var buffer = [_]u8{0} ** 39; var buffer_count: usize = 0; var split_value = value; while (split_value != 0) : (buffer_count += 1) { const radix = 10; buffer[buffer_count] = @intCast(u8, (split_value % radix) + '0'); split_value = (split_value / radix); } { const half_buffer_count = buffer_count / 2; var index: usize = 0; while (index < half_buffer_count) : (index += 1) { io.swap(u8, &buffer[index], &buffer[buffer_count - index - 1]); } } return writer.invoke(buffer[0 .. buffer_count]); }