mirror of
https://github.com/ziglang/zig.git
synced 2024-11-16 17:15:37 +00:00
Merge branch 'format-stream' of https://github.com/fengb/zig into fengb-format-stream
This commit is contained in:
commit
2dd920ee39
@ -65,13 +65,9 @@ pub const Buffer = struct {
|
||||
}
|
||||
|
||||
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
|
||||
const countSize = struct {
|
||||
fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
|
||||
size.* += bytes.len;
|
||||
}
|
||||
}.countSize;
|
||||
var size: usize = 0;
|
||||
std.fmt.format(&size, error{}, countSize, format, args) catch |err| switch (err) {};
|
||||
const size = std.fmt.count(format, args) catch |err| switch (err) {
|
||||
error.Overflow => return error.OutOfMemory,
|
||||
};
|
||||
var self = try Buffer.initSize(allocator, size);
|
||||
assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
|
||||
return self;
|
||||
@ -155,7 +151,7 @@ pub const Buffer = struct {
|
||||
}
|
||||
|
||||
pub fn print(self: *Buffer, comptime fmt: []const u8, args: var) !void {
|
||||
return std.fmt.format(self, error{OutOfMemory}, Buffer.append, fmt, args);
|
||||
return self.outStream().print(fmt, args);
|
||||
}
|
||||
|
||||
pub fn outStream(self: *Buffer) std.io.OutStream(*Buffer, error{OutOfMemory}, appendWrite) {
|
||||
|
@ -436,19 +436,17 @@ pub const Version = struct {
|
||||
self: Version,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
context: var,
|
||||
comptime Error: type,
|
||||
comptime output: fn (@TypeOf(context), []const u8) Error!void,
|
||||
) Error!void {
|
||||
out_stream: var,
|
||||
) !void {
|
||||
if (fmt.len == 0) {
|
||||
if (self.patch == 0) {
|
||||
if (self.minor == 0) {
|
||||
return std.fmt.format(context, Error, output, "{}", .{self.major});
|
||||
return std.fmt.format(out_stream, "{}", .{self.major});
|
||||
} else {
|
||||
return std.fmt.format(context, Error, output, "{}.{}", .{ self.major, self.minor });
|
||||
return std.fmt.format(out_stream, "{}.{}", .{ self.major, self.minor });
|
||||
}
|
||||
} else {
|
||||
return std.fmt.format(context, Error, output, "{}.{}.{}", .{ self.major, self.minor, self.patch });
|
||||
return std.fmt.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch });
|
||||
}
|
||||
} else {
|
||||
@compileError("Unknown format string: '" ++ fmt ++ "'");
|
||||
|
@ -294,7 +294,19 @@ pub fn LinearFifo(
|
||||
pub usingnamespace if (T == u8)
|
||||
struct {
|
||||
pub fn print(self: *Self, comptime format: []const u8, args: var) !void {
|
||||
return std.fmt.format(self, error{OutOfMemory}, Self.write, format, args);
|
||||
// TODO: maybe expose this stream as a method?
|
||||
const FifoStream = struct {
|
||||
const OutStream = std.io.OutStream(*Self, Error, write);
|
||||
const Error = error{OutOfMemory};
|
||||
|
||||
fn write(fifo: *Self, bytes: []const u8) Error!usize {
|
||||
try fifo.write(bytes);
|
||||
return bytes.len;
|
||||
}
|
||||
};
|
||||
|
||||
var out_stream = FifoStream.OutStream{ .context = self };
|
||||
try out_stream.print(format, args);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
509
lib/std/fmt.zig
509
lib/std/fmt.zig
File diff suppressed because it is too large
Load Diff
@ -350,15 +350,13 @@ pub const Headers = struct {
|
||||
self: Self,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@TypeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
out_stream: var,
|
||||
) !void {
|
||||
for (self.toSlice()) |entry| {
|
||||
try output(context, entry.name);
|
||||
try output(context, ": ");
|
||||
try output(context, entry.value);
|
||||
try output(context, "\n");
|
||||
try out_stream.writeAll(entry.name);
|
||||
try out_stream.writeAll(": ");
|
||||
try out_stream.writeAll(entry.value);
|
||||
try out_stream.writeAll("\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -25,7 +25,7 @@ pub fn OutStream(
|
||||
}
|
||||
|
||||
pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {
|
||||
return std.fmt.format(self, Error, writeAll, format, args);
|
||||
return std.fmt.format(self, format, args);
|
||||
}
|
||||
|
||||
pub fn writeByte(self: Self, byte: u8) Error!void {
|
||||
|
134
lib/std/json.zig
134
lib/std/json.zig
@ -2252,45 +2252,43 @@ pub const StringifyOptions = struct {
|
||||
pub fn stringify(
|
||||
value: var,
|
||||
options: StringifyOptions,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
comptime output: fn (@TypeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
out_stream: var,
|
||||
) !void {
|
||||
const T = @TypeOf(value);
|
||||
switch (@typeInfo(T)) {
|
||||
.Float, .ComptimeFloat => {
|
||||
return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, context, Errors, output);
|
||||
return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, out_stream);
|
||||
},
|
||||
.Int, .ComptimeInt => {
|
||||
return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, context, Errors, output);
|
||||
return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, out_stream);
|
||||
},
|
||||
.Bool => {
|
||||
return output(context, if (value) "true" else "false");
|
||||
return out_stream.writeAll(if (value) "true" else "false");
|
||||
},
|
||||
.Optional => {
|
||||
if (value) |payload| {
|
||||
return try stringify(payload, options, context, Errors, output);
|
||||
return try stringify(payload, options, out_stream);
|
||||
} else {
|
||||
return output(context, "null");
|
||||
return out_stream.writeAll("null");
|
||||
}
|
||||
},
|
||||
.Enum => {
|
||||
if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
|
||||
return value.jsonStringify(options, context, Errors, output);
|
||||
return value.jsonStringify(options, out_stream);
|
||||
}
|
||||
|
||||
@compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'");
|
||||
},
|
||||
.Union => {
|
||||
if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
|
||||
return value.jsonStringify(options, context, Errors, output);
|
||||
return value.jsonStringify(options, out_stream);
|
||||
}
|
||||
|
||||
const info = @typeInfo(T).Union;
|
||||
if (info.tag_type) |UnionTagType| {
|
||||
inline for (info.fields) |u_field| {
|
||||
if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
|
||||
return try stringify(@field(value, u_field.name), options, context, Errors, output);
|
||||
return try stringify(@field(value, u_field.name), options, out_stream);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -2299,10 +2297,10 @@ pub fn stringify(
|
||||
},
|
||||
.Struct => |S| {
|
||||
if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
|
||||
return value.jsonStringify(options, context, Errors, output);
|
||||
return value.jsonStringify(options, out_stream);
|
||||
}
|
||||
|
||||
try output(context, "{");
|
||||
try out_stream.writeAll("{");
|
||||
comptime var field_output = false;
|
||||
inline for (S.fields) |Field, field_i| {
|
||||
// don't include void fields
|
||||
@ -2311,39 +2309,39 @@ pub fn stringify(
|
||||
if (!field_output) {
|
||||
field_output = true;
|
||||
} else {
|
||||
try output(context, ",");
|
||||
try out_stream.writeAll(",");
|
||||
}
|
||||
|
||||
try stringify(Field.name, options, context, Errors, output);
|
||||
try output(context, ":");
|
||||
try stringify(@field(value, Field.name), options, context, Errors, output);
|
||||
try stringify(Field.name, options, out_stream);
|
||||
try out_stream.writeAll(":");
|
||||
try stringify(@field(value, Field.name), options, out_stream);
|
||||
}
|
||||
try output(context, "}");
|
||||
try out_stream.writeAll("}");
|
||||
return;
|
||||
},
|
||||
.Pointer => |ptr_info| switch (ptr_info.size) {
|
||||
.One => {
|
||||
// TODO: avoid loops?
|
||||
return try stringify(value.*, options, context, Errors, output);
|
||||
return try stringify(value.*, options, out_stream);
|
||||
},
|
||||
// TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
|
||||
.Slice => {
|
||||
if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) {
|
||||
try output(context, "\"");
|
||||
try out_stream.writeAll("\"");
|
||||
var i: usize = 0;
|
||||
while (i < value.len) : (i += 1) {
|
||||
switch (value[i]) {
|
||||
// normal ascii characters
|
||||
0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try output(context, value[i .. i + 1]),
|
||||
0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try out_stream.writeAll(value[i .. i + 1]),
|
||||
// control characters with short escapes
|
||||
'\\' => try output(context, "\\\\"),
|
||||
'\"' => try output(context, "\\\""),
|
||||
'/' => try output(context, "\\/"),
|
||||
0x8 => try output(context, "\\b"),
|
||||
0xC => try output(context, "\\f"),
|
||||
'\n' => try output(context, "\\n"),
|
||||
'\r' => try output(context, "\\r"),
|
||||
'\t' => try output(context, "\\t"),
|
||||
'\\' => try out_stream.writeAll("\\\\"),
|
||||
'\"' => try out_stream.writeAll("\\\""),
|
||||
'/' => try out_stream.writeAll("\\/"),
|
||||
0x8 => try out_stream.writeAll("\\b"),
|
||||
0xC => try out_stream.writeAll("\\f"),
|
||||
'\n' => try out_stream.writeAll("\\n"),
|
||||
'\r' => try out_stream.writeAll("\\r"),
|
||||
'\t' => try out_stream.writeAll("\\t"),
|
||||
else => {
|
||||
const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;
|
||||
const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;
|
||||
@ -2351,40 +2349,40 @@ pub fn stringify(
|
||||
// If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),
|
||||
// then it may be represented as a six-character sequence: a reverse solidus, followed
|
||||
// by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
|
||||
try output(context, "\\u");
|
||||
try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
|
||||
try out_stream.writeAll("\\u");
|
||||
try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
|
||||
} else {
|
||||
// To escape an extended character that is not in the Basic Multilingual Plane,
|
||||
// the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.
|
||||
const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;
|
||||
const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;
|
||||
try output(context, "\\u");
|
||||
try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
|
||||
try output(context, "\\u");
|
||||
try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
|
||||
try out_stream.writeAll("\\u");
|
||||
try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
|
||||
try out_stream.writeAll("\\u");
|
||||
try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
|
||||
}
|
||||
i += ulen - 1;
|
||||
},
|
||||
}
|
||||
}
|
||||
try output(context, "\"");
|
||||
try out_stream.writeAll("\"");
|
||||
return;
|
||||
}
|
||||
|
||||
try output(context, "[");
|
||||
try out_stream.writeAll("[");
|
||||
for (value) |x, i| {
|
||||
if (i != 0) {
|
||||
try output(context, ",");
|
||||
try out_stream.writeAll(",");
|
||||
}
|
||||
try stringify(x, options, context, Errors, output);
|
||||
try stringify(x, options, out_stream);
|
||||
}
|
||||
try output(context, "]");
|
||||
try out_stream.writeAll("]");
|
||||
return;
|
||||
},
|
||||
else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
|
||||
},
|
||||
.Array => |info| {
|
||||
return try stringify(value[0..], options, context, Errors, output);
|
||||
return try stringify(value[0..], options, out_stream);
|
||||
},
|
||||
else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
|
||||
}
|
||||
@ -2392,10 +2390,26 @@ pub fn stringify(
|
||||
}
|
||||
|
||||
fn teststringify(expected: []const u8, value: var) !void {
|
||||
const TestStringifyContext = struct {
|
||||
const ValidationOutStream = struct {
|
||||
const Self = @This();
|
||||
pub const OutStream = std.io.OutStream(*Self, Error, write);
|
||||
pub const Error = error{
|
||||
TooMuchData,
|
||||
DifferentData,
|
||||
};
|
||||
|
||||
expected_remaining: []const u8,
|
||||
fn testStringifyWrite(context: *@This(), bytes: []const u8) !void {
|
||||
if (context.expected_remaining.len < bytes.len) {
|
||||
|
||||
fn init(exp: []const u8) Self {
|
||||
return .{ .expected_remaining = exp };
|
||||
}
|
||||
|
||||
pub fn outStream(self: *Self) OutStream {
|
||||
return .{ .context = self };
|
||||
}
|
||||
|
||||
fn write(self: *Self, bytes: []const u8) Error!usize {
|
||||
if (self.expected_remaining.len < bytes.len) {
|
||||
std.debug.warn(
|
||||
\\====== expected this output: =========
|
||||
\\{}
|
||||
@ -2403,12 +2417,12 @@ fn teststringify(expected: []const u8, value: var) !void {
|
||||
\\{}
|
||||
\\======================================
|
||||
, .{
|
||||
context.expected_remaining,
|
||||
self.expected_remaining,
|
||||
bytes,
|
||||
});
|
||||
return error.TooMuchData;
|
||||
}
|
||||
if (!mem.eql(u8, context.expected_remaining[0..bytes.len], bytes)) {
|
||||
if (!mem.eql(u8, self.expected_remaining[0..bytes.len], bytes)) {
|
||||
std.debug.warn(
|
||||
\\====== expected this output: =========
|
||||
\\{}
|
||||
@ -2416,21 +2430,19 @@ fn teststringify(expected: []const u8, value: var) !void {
|
||||
\\{}
|
||||
\\======================================
|
||||
, .{
|
||||
context.expected_remaining[0..bytes.len],
|
||||
self.expected_remaining[0..bytes.len],
|
||||
bytes,
|
||||
});
|
||||
return error.DifferentData;
|
||||
}
|
||||
context.expected_remaining = context.expected_remaining[bytes.len..];
|
||||
self.expected_remaining = self.expected_remaining[bytes.len..];
|
||||
return bytes.len;
|
||||
}
|
||||
};
|
||||
var buf: [100]u8 = undefined;
|
||||
var context = TestStringifyContext{ .expected_remaining = expected };
|
||||
try stringify(value, StringifyOptions{}, &context, error{
|
||||
TooMuchData,
|
||||
DifferentData,
|
||||
}, TestStringifyContext.testStringifyWrite);
|
||||
if (context.expected_remaining.len > 0) return error.NotEnoughData;
|
||||
|
||||
var vos = ValidationOutStream.init(expected);
|
||||
try stringify(value, StringifyOptions{}, vos.outStream());
|
||||
if (vos.expected_remaining.len > 0) return error.NotEnoughData;
|
||||
}
|
||||
|
||||
test "stringify basic types" {
|
||||
@ -2498,13 +2510,11 @@ test "stringify struct with custom stringifier" {
|
||||
pub fn jsonStringify(
|
||||
value: Self,
|
||||
options: StringifyOptions,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
comptime output: fn (@TypeOf(context), []const u8) Errors!void,
|
||||
out_stream: var,
|
||||
) !void {
|
||||
try output(context, "[\"something special\",");
|
||||
try stringify(42, options, context, Errors, output);
|
||||
try output(context, "]");
|
||||
try out_stream.writeAll("[\"something special\",");
|
||||
try stringify(42, options, out_stream);
|
||||
try out_stream.writeAll("]");
|
||||
}
|
||||
}{ .foo = 42 });
|
||||
}
|
||||
|
@ -519,16 +519,14 @@ pub const Int = struct {
|
||||
self: Int,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
context: var,
|
||||
comptime FmtError: type,
|
||||
output: fn (@TypeOf(context), []const u8) FmtError!void,
|
||||
out_stream: var,
|
||||
) FmtError!void {
|
||||
self.assertWritable();
|
||||
// TODO look at fmt and support other bases
|
||||
// TODO support read-only fixed integers
|
||||
const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
|
||||
defer self.allocator.?.free(str);
|
||||
return output(context, str);
|
||||
return out_stream.print(str);
|
||||
}
|
||||
|
||||
/// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
|
||||
|
@ -269,15 +269,13 @@ pub const Address = extern union {
|
||||
self: Address,
|
||||
comptime fmt: []const u8,
|
||||
options: std.fmt.FormatOptions,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
comptime output: fn (@TypeOf(context), []const u8) Errors!void,
|
||||
out_stream: var,
|
||||
) !void {
|
||||
switch (self.any.family) {
|
||||
os.AF_INET => {
|
||||
const port = mem.bigToNative(u16, self.in.port);
|
||||
const bytes = @ptrCast(*const [4]u8, &self.in.addr);
|
||||
try std.fmt.format(context, Errors, output, "{}.{}.{}.{}:{}", .{
|
||||
try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
|
||||
bytes[0],
|
||||
bytes[1],
|
||||
bytes[2],
|
||||
@ -288,7 +286,7 @@ pub const Address = extern union {
|
||||
os.AF_INET6 => {
|
||||
const port = mem.bigToNative(u16, self.in6.port);
|
||||
if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
|
||||
try std.fmt.format(context, Errors, output, "[::ffff:{}.{}.{}.{}]:{}", .{
|
||||
try std.fmt.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
|
||||
self.in6.addr[12],
|
||||
self.in6.addr[13],
|
||||
self.in6.addr[14],
|
||||
@ -308,30 +306,30 @@ pub const Address = extern union {
|
||||
break :blk buf;
|
||||
},
|
||||
};
|
||||
try output(context, "[");
|
||||
try out_stream.writeAll("[");
|
||||
var i: usize = 0;
|
||||
var abbrv = false;
|
||||
while (i < native_endian_parts.len) : (i += 1) {
|
||||
if (native_endian_parts[i] == 0) {
|
||||
if (!abbrv) {
|
||||
try output(context, if (i == 0) "::" else ":");
|
||||
try out_stream.writeAll(if (i == 0) "::" else ":");
|
||||
abbrv = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
try std.fmt.format(context, Errors, output, "{x}", .{native_endian_parts[i]});
|
||||
try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});
|
||||
if (i != native_endian_parts.len - 1) {
|
||||
try output(context, ":");
|
||||
try out_stream.writeAll(":");
|
||||
}
|
||||
}
|
||||
try std.fmt.format(context, Errors, output, "]:{}", .{port});
|
||||
try std.fmt.format(out_stream, "]:{}", .{port});
|
||||
},
|
||||
os.AF_UNIX => {
|
||||
if (!has_unix_sockets) {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
try std.fmt.format(context, Errors, output, "{}", .{&self.un.path});
|
||||
try std.fmt.format(out_stream, "{}", .{&self.un.path});
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
|
@ -5,8 +5,6 @@ pub const protocols = @import("uefi/protocols.zig");
|
||||
pub const Status = @import("uefi/status.zig").Status;
|
||||
pub const tables = @import("uefi/tables.zig");
|
||||
|
||||
const fmt = @import("std").fmt;
|
||||
|
||||
/// The EFI image's handle that is passed to its entry point.
|
||||
pub var handle: Handle = undefined;
|
||||
|
||||
@ -29,13 +27,11 @@ pub const Guid = extern struct {
|
||||
pub fn format(
|
||||
self: @This(),
|
||||
comptime f: []const u8,
|
||||
options: fmt.FormatOptions,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
comptime output: fn (@TypeOf(context), []const u8) Errors!void,
|
||||
options: std.fmt.FormatOptions,
|
||||
out_stream: var,
|
||||
) Errors!void {
|
||||
if (f.len == 0) {
|
||||
return fmt.format(context, Errors, output, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
|
||||
return std.fmt.format(out_stream, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
|
||||
self.time_low,
|
||||
self.time_mid,
|
||||
self.time_high_and_version,
|
||||
|
@ -306,12 +306,12 @@ pub const Tokenizer = struct {
|
||||
|
||||
fn errorPosition(self: *Tokenizer, position: usize, bytes: []const u8, comptime fmt: []const u8, args: var) Error {
|
||||
var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
|
||||
std.fmt.format(&buffer, anyerror, std.Buffer.append, fmt, args) catch {};
|
||||
try buffer.print(fmt, args);
|
||||
try buffer.append(" '");
|
||||
var out = makeOutput(std.Buffer.append, &buffer);
|
||||
try printCharValues(&out, bytes);
|
||||
try buffer.append("'");
|
||||
std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", .{position - (bytes.len - 1)}) catch {};
|
||||
try buffer.print(" at position {}", .{position - (bytes.len - 1)});
|
||||
self.error_text = buffer.toSlice();
|
||||
return Error.InvalidInput;
|
||||
}
|
||||
@ -319,10 +319,9 @@ pub const Tokenizer = struct {
|
||||
fn errorIllegalChar(self: *Tokenizer, position: usize, char: u8, comptime fmt: []const u8, args: var) Error {
|
||||
var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
|
||||
try buffer.append("illegal char ");
|
||||
var out = makeOutput(std.Buffer.append, &buffer);
|
||||
try printUnderstandableChar(&out, char);
|
||||
std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", .{position}) catch {};
|
||||
if (fmt.len != 0) std.fmt.format(&buffer, anyerror, std.Buffer.append, ": " ++ fmt, args) catch {};
|
||||
try printUnderstandableChar(&buffer, char);
|
||||
try buffer.print(" at position {}", .{position});
|
||||
if (fmt.len != 0) try buffer.print(": " ++ fmt, args);
|
||||
self.error_text = buffer.toSlice();
|
||||
return Error.InvalidInput;
|
||||
}
|
||||
@ -996,14 +995,13 @@ fn printCharValues(out: var, bytes: []const u8) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn printUnderstandableChar(out: var, char: u8) !void {
|
||||
fn printUnderstandableChar(buffer: *std.Buffer, char: u8) !void {
|
||||
if (!std.ascii.isPrint(char) or char == ' ') {
|
||||
const output = @typeInfo(@TypeOf(out)).Pointer.child.output;
|
||||
std.fmt.format(out.context, anyerror, output, "\\x{X:2}", .{char}) catch {};
|
||||
try buffer.print("\\x{X:2}", .{char});
|
||||
} else {
|
||||
try out.write("'");
|
||||
try out.write(&[_]u8{printable_char_tab[char]});
|
||||
try out.write("'");
|
||||
try buffer.append("'");
|
||||
try buffer.appendByte(printable_char_tab[char]);
|
||||
try buffer.append("'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4752,15 +4752,10 @@ fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenInd
|
||||
}
|
||||
|
||||
fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: var) !ast.TokenIndex {
|
||||
const S = struct {
|
||||
fn callback(context: *Context, bytes: []const u8) error{OutOfMemory}!void {
|
||||
return context.source_buffer.append(bytes);
|
||||
}
|
||||
};
|
||||
const start_index = c.source_buffer.len();
|
||||
errdefer c.source_buffer.shrink(start_index);
|
||||
|
||||
try std.fmt.format(c, error{OutOfMemory}, S.callback, format, args);
|
||||
try c.source_buffer.print(format, args);
|
||||
const end_index = c.source_buffer.len();
|
||||
const token_index = c.tree.tokens.len;
|
||||
const new_token = try c.tree.tokens.addOne();
|
||||
|
Loading…
Reference in New Issue
Block a user