85 lines
2.3 KiB
Zig
85 lines
2.3 KiB
Zig
|
const io = @import("./io.zig");
|
||
|
const math = @import("./math.zig");
|
||
|
|
||
|
///
|
||
|
/// [PrintError.WriteFailure] occurs when the underlying [io.Writer] implementation failed to write
|
||
|
/// the entirety of a the requested print operation.
|
||
|
///
|
||
|
pub const PrintError = error {
|
||
|
WriteFailure,
|
||
|
};
|
||
|
|
||
|
///
|
||
|
/// Number formatting modes supported by [printInt].
|
||
|
///
|
||
|
pub const Radix = enum {
|
||
|
binary,
|
||
|
tinary,
|
||
|
quaternary,
|
||
|
quinary,
|
||
|
senary,
|
||
|
septenary,
|
||
|
octal,
|
||
|
nonary,
|
||
|
decimal,
|
||
|
undecimal,
|
||
|
duodecimal,
|
||
|
tridecimal,
|
||
|
tetradecimal,
|
||
|
pentadecimal,
|
||
|
hexadecimal,
|
||
|
};
|
||
|
|
||
|
///
|
||
|
/// Writes `value` as a ASCII / UTF-8 encoded integer to `writer`, returning `true` if the full
|
||
|
/// sequence was successfully written, otherwise `false`.
|
||
|
///
|
||
|
/// The `radix` argument identifies which base system to format `value` as.
|
||
|
///
|
||
|
pub fn printInt(writer: io.Writer, radix: Radix, value: anytype) PrintError!void {
|
||
|
const Int = @TypeOf(value);
|
||
|
|
||
|
switch (@typeInfo(Int)) {
|
||
|
.Int => |int_info| {
|
||
|
if (value == 0) return writer.apply("0");
|
||
|
|
||
|
const base = @enumToInt(radix);
|
||
|
const is_signed = (int_info.signedness == .signed);
|
||
|
|
||
|
var buffer = [_]u8{0} ** (math.ceil(math.log(math.
|
||
|
maxInt(Int), base)) + @boolToInt(is_signed));
|
||
|
|
||
|
var buffer_count: usize = 0;
|
||
|
var n1 = value;
|
||
|
|
||
|
if (is_signed and (value < 0)) {
|
||
|
// Negative value.
|
||
|
n1 = -value;
|
||
|
buffer[0] = '-';
|
||
|
buffer_count += 1;
|
||
|
}
|
||
|
|
||
|
while (n1 != 0) {
|
||
|
buffer[buffer_count] = @intCast(u8, (n1 % base) + '0');
|
||
|
n1 = (n1 / base);
|
||
|
buffer_count += 1;
|
||
|
}
|
||
|
|
||
|
for (buffer[0 .. (buffer_count / 2)]) |_, i|
|
||
|
io.swap(u8, &buffer[i], &buffer[buffer_count - i - 1]);
|
||
|
|
||
|
if (writer.call(buffer[0 .. buffer_count]) != buffer_count) return error.WriteFailure;
|
||
|
},
|
||
|
|
||
|
// Cast comptime int into known-size integer and try again.
|
||
|
.ComptimeInt => return printInt(writer, radix,
|
||
|
@intCast(math.IntFittingRange(value, value), value)),
|
||
|
|
||
|
else => @compileError("`value` must be of type int or comptime_int"),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
test "Print 64-bit signed integer" {
|
||
|
// TODO: implement.
|
||
|
}
|