ona/src/coral/ascii.zig
kayomn 842dbd56cf
All checks were successful
continuous-integration/drone/push Build is passing
Add runtime shader reflection support
2024-07-06 03:25:09 +01:00

196 lines
4.4 KiB
Zig

const coral = @import("./coral.zig");
const io = @import("./io.zig");
const scalars = @import("./scalars.zig");
const std = @import("std");
pub const DecimalFormat = struct {
delimiter: []const coral.Byte,
positive_prefix: enum {none, plus, space},
pub const default = DecimalFormat{
.delimiter = "",
.positive_prefix = .none,
};
pub fn parse(self: DecimalFormat, utf8: []const u8, comptime Decimal: type) ?Decimal {
if (utf8.len == 0) {
return null;
}
switch (@typeInfo(Decimal)) {
.Int => |int| {
const has_sign = switch (utf8[0]) {
'-', '+', ' ' => true,
else => false,
};
var result = @as(Decimal, 0);
for (@intFromBool(has_sign) .. utf8.len) |index| {
const radix = 10;
const code = utf8[index];
switch (code) {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9' => {
const offset_code = scalars.sub(code, '0') orelse return null;
result = scalars.mul(result, radix) orelse return null;
result = scalars.add(result, offset_code) orelse return null;
},
else => {
if (self.delimiter.len == 0 or !coral.are_equal(self.delimiter, utf8[index ..])) {
return null;
}
},
}
}
switch (int.signedness) {
.signed => {
return result * @as(Decimal, if (has_sign and utf8[0] == '-') -1 else 1);
},
.unsigned => {
if (has_sign and utf8[0] == '-') {
return null;
}
return result;
},
}
},
.Float => {
const has_sign = switch (utf8[0]) {
'-', '+', ' ' => true,
else => false,
};
// "-"
if (has_sign and utf8.len == 1) {
return null;
}
const sign_offset = @intFromBool(has_sign);
var has_decimal = utf8[sign_offset] == '.';
// "-."
if (has_decimal and (utf8.len == 2)) {
return null;
}
var result = @as(Decimal, 0);
var factor = @as(Decimal, if (has_sign and utf8[0] == '-') -1 else 1);
for (utf8[sign_offset + @intFromBool(has_decimal) .. utf8.len]) |code| {
switch (code) {
'.' => {
if (has_decimal) {
return null;
}
has_decimal = true;
},
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9' => {
if (has_decimal) {
factor /= 10.0;
}
result = ((result * 10.0) + @as(Decimal, @floatFromInt(code - '0')));
},
else => return null,
}
}
return result * factor;
},
else => @compileError("`" ++ @typeName(Decimal) ++ "` cannot be parsed from a decimal string"),
}
}
pub fn format(self: DecimalFormat, writer: io.Writer, value: anytype) io.PrintError!void {
if (value == 0) {
return io.print(writer, switch (self.positive_prefix) {
.none => "0",
.plus => "+0",
.space => " 0",
});
}
const Value = @TypeOf(value);
switch (@typeInfo(Value)) {
.Int => |int| {
const radix = 10;
var buffer = [_]u8{0} ** (1 + @max(int.bits, 1));
var buffer_start = buffer.len - 1;
{
var decomposable_value = value;
while (decomposable_value != 0) : (buffer_start -= 1) {
buffer[buffer_start] = @intCast(@mod(decomposable_value, radix) + '0');
decomposable_value = @divTrunc(decomposable_value, radix);
}
}
if (int.signedness == .unsigned and value < 0) {
buffer[buffer_start] = '-';
} else {
switch (self.positive_prefix) {
.none => buffer_start += 1,
.plus => buffer[buffer_start] = '+',
.space => buffer[buffer_start] = ' ',
}
}
return io.print(writer, buffer[buffer_start ..]);
},
.Float => |float| {
if (value < 0) {
try io.print(writer, "-");
}
const Float = @TypeOf(value);
const Int = std.meta.Int(.unsigned, float.bits);
const integer = @as(Int, @intFromFloat(value));
try self.print(writer, integer);
try io.print(writer, ".");
try self.print(writer, @as(Int, @intFromFloat((value - @as(Float, @floatFromInt(integer))) * 100)));
},
else => @compileError("`" ++ @typeName(Value) ++ "` cannot be formatted to a decimal string"),
}
}
};
pub const HexadecimalFormat = struct {
delimiter: []const u8 = "",
positive_prefix: enum {none, plus, space} = .none,
casing: enum {lower, upper} = .lower,
pub const default = HexadecimalFormat{
.delimiter = "",
.positive_prefix = .none,
.casing = .lower,
};
pub fn format(self: HexadecimalFormat, writer: io.Writer, value: anytype) io.Error!void {
// TODO: Implement.
_ = self;
_ = writer;
_ = value;
unreachable;
}
};