ona/source/coral/utf8.zig

102 lines
2.3 KiB
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.Unsigned(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.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 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;
}