authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-13 12:07:06-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-13 12:07:06-04:00
log3eff77bfb52accbc16eb831753ff4917fc2b4873
tree49fbf58b5b43ebaffc71eabb7aaa1eb4197044f4
parenta9297f22671dff800821ff940395411f2adb8582
parent4905102901e7d798860f8346faeae505a7268968
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'fengb-format-stream'


16 files changed, 361 insertions(+), 441 deletions(-)

lib/std/buffer.zig+4-12
...@@ -65,13 +65,9 @@ pub const Buffer = struct {...@@ -65,13 +65,9 @@ pub const Buffer = struct {
65 }65 }
6666
67 pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {67 pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
68 const countSize = struct {68 const size = std.math.cast(usize, std.fmt.count(format, args)) catch |err| switch (err) {
69 fn countSize(size: *usize, bytes: []const u8) (error{}!void) {69 error.Overflow => return error.OutOfMemory,
70 size.* += bytes.len;70 };
71 }
72 }.countSize;
73 var size: usize = 0;
74 std.fmt.format(&size, error{}, countSize, format, args) catch |err| switch (err) {};
75 var self = try Buffer.initSize(allocator, size);71 var self = try Buffer.initSize(allocator, size);
76 assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);72 assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
77 return self;73 return self;
...@@ -154,10 +150,6 @@ pub const Buffer = struct {...@@ -154,10 +150,6 @@ pub const Buffer = struct {
154 mem.copy(u8, self.list.toSlice(), m);150 mem.copy(u8, self.list.toSlice(), m);
155 }151 }
156152
157 pub fn print(self: *Buffer, comptime fmt: []const u8, args: var) !void {
158 return std.fmt.format(self, error{OutOfMemory}, Buffer.append, fmt, args);
159 }
160
161 pub fn outStream(self: *Buffer) std.io.OutStream(*Buffer, error{OutOfMemory}, appendWrite) {153 pub fn outStream(self: *Buffer) std.io.OutStream(*Buffer, error{OutOfMemory}, appendWrite) {
162 return .{ .context = self };154 return .{ .context = self };
163 }155 }
...@@ -216,7 +208,7 @@ test "Buffer.print" {...@@ -216,7 +208,7 @@ test "Buffer.print" {
216 var buf = try Buffer.init(testing.allocator, "");208 var buf = try Buffer.init(testing.allocator, "");
217 defer buf.deinit();209 defer buf.deinit();
218210
219 try buf.print("Hello {} the {}", .{ 2, "world" });211 try buf.outStream().print("Hello {} the {}", .{ 2, "world" });
220 testing.expect(buf.eql("Hello 2 the world"));212 testing.expect(buf.eql("Hello 2 the world"));
221}213}
222214
lib/std/builtin.zig+5-7
...@@ -436,19 +436,17 @@ pub const Version = struct {...@@ -436,19 +436,17 @@ pub const Version = struct {
436 self: Version,436 self: Version,
437 comptime fmt: []const u8,437 comptime fmt: []const u8,
438 options: std.fmt.FormatOptions,438 options: std.fmt.FormatOptions,
439 context: var,439 out_stream: var,
440 comptime Error: type,440 ) !void {
441 comptime output: fn (@TypeOf(context), []const u8) Error!void,
442 ) Error!void {
443 if (fmt.len == 0) {441 if (fmt.len == 0) {
444 if (self.patch == 0) {442 if (self.patch == 0) {
445 if (self.minor == 0) {443 if (self.minor == 0) {
446 return std.fmt.format(context, Error, output, "{}", .{self.major});444 return std.fmt.format(out_stream, "{}", .{self.major});
447 } else {445 } else {
448 return std.fmt.format(context, Error, output, "{}.{}", .{ self.major, self.minor });446 return std.fmt.format(out_stream, "{}.{}", .{ self.major, self.minor });
449 }447 }
450 } else {448 } else {
451 return std.fmt.format(context, Error, output, "{}.{}.{}", .{ self.major, self.minor, self.patch });449 return std.fmt.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch });
452 }450 }
453 } else {451 } else {
454 @compileError("Unknown format string: '" ++ fmt ++ "'");452 @compileError("Unknown format string: '" ++ fmt ++ "'");
lib/std/fifo.zig+13-3
...@@ -293,8 +293,18 @@ pub fn LinearFifo(...@@ -293,8 +293,18 @@ pub fn LinearFifo(
293293
294 pub usingnamespace if (T == u8)294 pub usingnamespace if (T == u8)
295 struct {295 struct {
296 pub fn print(self: *Self, comptime format: []const u8, args: var) !void {296 const OutStream = std.io.OutStream(*Self, Error, appendWrite);
297 return std.fmt.format(self, error{OutOfMemory}, Self.write, format, args);297 const Error = error{OutOfMemory};
298
299 /// Same as `write` except it returns the number of bytes written, which is always the same
300 /// as `bytes.len`. The purpose of this function existing is to match `std.io.OutStream` API.
301 pub fn appendWrite(fifo: *Self, bytes: []const u8) Error!usize {
302 try fifo.write(bytes);
303 return bytes.len;
304 }
305
306 pub fn outStream(self: *Self) OutStream {
307 return .{ .context = self };
298 }308 }
299 }309 }
300 else310 else
...@@ -407,7 +417,7 @@ test "LinearFifo(u8, .Dynamic)" {...@@ -407,7 +417,7 @@ test "LinearFifo(u8, .Dynamic)" {
407 fifo.shrink(0);417 fifo.shrink(0);
408418
409 {419 {
410 try fifo.print("{}, {}!", .{ "Hello", "World" });420 try fifo.outStream().print("{}, {}!", .{ "Hello", "World" });
411 var result: [30]u8 = undefined;421 var result: [30]u8 = undefined;
412 testing.expectEqualSlices(u8, "Hello, World!", result[0..fifo.read(&result)]);422 testing.expectEqualSlices(u8, "Hello, World!", result[0..fifo.read(&result)]);
413 testing.expectEqual(@as(usize, 0), fifo.readableLength());423 testing.expectEqual(@as(usize, 0), fifo.readableLength());
lib/std/fmt.zig+224-297
...@@ -69,19 +69,17 @@ fn peekIsAlign(comptime fmt: []const u8) bool {...@@ -69,19 +69,17 @@ fn peekIsAlign(comptime fmt: []const u8) bool {
69///69///
70/// If a formatted user type contains a function of the type70/// If a formatted user type contains a function of the type
71/// ```71/// ```
72/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, comptime output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void72/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void
73/// ```73/// ```
74/// with `?` being the type formatted, this function will be called instead of the default implementation.74/// with `?` being the type formatted, this function will be called instead of the default implementation.
75/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.75/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
76///76///
77/// A user type may be a `struct`, `vector`, `union` or `enum` type.77/// A user type may be a `struct`, `vector`, `union` or `enum` type.
78pub fn format(78pub fn format(
79 context: var,79 out_stream: var,
80 comptime Errors: type,
81 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
82 comptime fmt: []const u8,80 comptime fmt: []const u8,
83 args: var,81 args: var,
84) Errors!void {82) !void {
85 const ArgSetType = u32;83 const ArgSetType = u32;
86 if (@typeInfo(@TypeOf(args)) != .Struct) {84 if (@typeInfo(@TypeOf(args)) != .Struct) {
87 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));85 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
...@@ -138,7 +136,7 @@ pub fn format(...@@ -138,7 +136,7 @@ pub fn format(
138 .Start => switch (c) {136 .Start => switch (c) {
139 '{' => {137 '{' => {
140 if (start_index < i) {138 if (start_index < i) {
141 try output(context, fmt[start_index..i]);139 try out_stream.writeAll(fmt[start_index..i]);
142 }140 }
143141
144 start_index = i;142 start_index = i;
...@@ -150,7 +148,7 @@ pub fn format(...@@ -150,7 +148,7 @@ pub fn format(
150 },148 },
151 '}' => {149 '}' => {
152 if (start_index < i) {150 if (start_index < i) {
153 try output(context, fmt[start_index..i]);151 try out_stream.writeAll(fmt[start_index..i]);
154 }152 }
155 state = .CloseBrace;153 state = .CloseBrace;
156 },154 },
...@@ -185,9 +183,7 @@ pub fn format(...@@ -185,9 +183,7 @@ pub fn format(
185 args[arg_to_print],183 args[arg_to_print],
186 fmt[0..0],184 fmt[0..0],
187 options,185 options,
188 context,186 out_stream,
189 Errors,
190 output,
191 default_max_depth,187 default_max_depth,
192 );188 );
193189
...@@ -218,9 +214,7 @@ pub fn format(...@@ -218,9 +214,7 @@ pub fn format(
218 args[arg_to_print],214 args[arg_to_print],
219 fmt[specifier_start..i],215 fmt[specifier_start..i],
220 options,216 options,
221 context,217 out_stream,
222 Errors,
223 output,
224 default_max_depth,218 default_max_depth,
225 );219 );
226 state = .Start;220 state = .Start;
...@@ -265,9 +259,7 @@ pub fn format(...@@ -265,9 +259,7 @@ pub fn format(
265 args[arg_to_print],259 args[arg_to_print],
266 fmt[specifier_start..specifier_end],260 fmt[specifier_start..specifier_end],
267 options,261 options,
268 context,262 out_stream,
269 Errors,
270 output,
271 default_max_depth,263 default_max_depth,
272 );264 );
273 state = .Start;265 state = .Start;
...@@ -293,9 +285,7 @@ pub fn format(...@@ -293,9 +285,7 @@ pub fn format(
293 args[arg_to_print],285 args[arg_to_print],
294 fmt[specifier_start..specifier_end],286 fmt[specifier_start..specifier_end],
295 options,287 options,
296 context,288 out_stream,
297 Errors,
298 output,
299 default_max_depth,289 default_max_depth,
300 );290 );
301 state = .Start;291 state = .Start;
...@@ -316,7 +306,7 @@ pub fn format(...@@ -316,7 +306,7 @@ pub fn format(
316 }306 }
317 }307 }
318 if (start_index < fmt.len) {308 if (start_index < fmt.len) {
319 try output(context, fmt[start_index..]);309 try out_stream.writeAll(fmt[start_index..]);
320 }310 }
321}311}
322312
...@@ -324,141 +314,131 @@ pub fn formatType(...@@ -324,141 +314,131 @@ pub fn formatType(
324 value: var,314 value: var,
325 comptime fmt: []const u8,315 comptime fmt: []const u8,
326 options: FormatOptions,316 options: FormatOptions,
327 context: var,317 out_stream: var,
328 comptime Errors: type,
329 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
330 max_depth: usize,318 max_depth: usize,
331) Errors!void {319) @TypeOf(out_stream).Error!void {
332 if (comptime std.mem.eql(u8, fmt, "*")) {320 if (comptime std.mem.eql(u8, fmt, "*")) {
333 try output(context, @typeName(@TypeOf(value).Child));321 try out_stream.writeAll(@typeName(@TypeOf(value).Child));
334 try output(context, "@");322 try out_stream.writeAll("@");
335 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, context, Errors, output);323 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream);
336 return;324 return;
337 }325 }
338326
339 const T = @TypeOf(value);327 const T = @TypeOf(value);
328 if (comptime std.meta.trait.hasFn("format")(T)) {
329 return try value.format(fmt, options, out_stream);
330 }
331
340 switch (@typeInfo(T)) {332 switch (@typeInfo(T)) {
341 .ComptimeInt, .Int, .Float => {333 .ComptimeInt, .Int, .Float => {
342 return formatValue(value, fmt, options, context, Errors, output);334 return formatValue(value, fmt, options, out_stream);
343 },335 },
344 .Void => {336 .Void => {
345 return output(context, "void");337 return out_stream.writeAll("void");
346 },338 },
347 .Bool => {339 .Bool => {
348 return output(context, if (value) "true" else "false");340 return out_stream.writeAll(if (value) "true" else "false");
349 },341 },
350 .Optional => {342 .Optional => {
351 if (value) |payload| {343 if (value) |payload| {
352 return formatType(payload, fmt, options, context, Errors, output, max_depth);344 return formatType(payload, fmt, options, out_stream, max_depth);
353 } else {345 } else {
354 return output(context, "null");346 return out_stream.writeAll("null");
355 }347 }
356 },348 },
357 .ErrorUnion => {349 .ErrorUnion => {
358 if (value) |payload| {350 if (value) |payload| {
359 return formatType(payload, fmt, options, context, Errors, output, max_depth);351 return formatType(payload, fmt, options, out_stream, max_depth);
360 } else |err| {352 } else |err| {
361 return formatType(err, fmt, options, context, Errors, output, max_depth);353 return formatType(err, fmt, options, out_stream, max_depth);
362 }354 }
363 },355 },
364 .ErrorSet => {356 .ErrorSet => {
365 try output(context, "error.");357 try out_stream.writeAll("error.");
366 return output(context, @errorName(value));358 return out_stream.writeAll(@errorName(value));
367 },359 },
368 .Enum => |enumInfo| {360 .Enum => |enumInfo| {
369 if (comptime std.meta.trait.hasFn("format")(T)) {361 try out_stream.writeAll(@typeName(T));
370 return value.format(fmt, options, context, Errors, output);
371 }
372
373 try output(context, @typeName(T));
374 if (enumInfo.is_exhaustive) {362 if (enumInfo.is_exhaustive) {
375 try output(context, ".");363 try out_stream.writeAll(".");
376 try output(context, @tagName(value));364 try out_stream.writeAll(@tagName(value));
377 } else {365 } else {
378 // TODO: when @tagName works on exhaustive enums print known enum strings366 // TODO: when @tagName works on exhaustive enums print known enum strings
379 try output(context, "(");367 try out_stream.writeAll("(");
380 try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth);368 try formatType(@enumToInt(value), fmt, options, out_stream, max_depth);
381 try output(context, ")");369 try out_stream.writeAll(")");
382 }370 }
383 },371 },
384 .Union => {372 .Union => {
385 if (comptime std.meta.trait.hasFn("format")(T)) {373 try out_stream.writeAll(@typeName(T));
386 return value.format(fmt, options, context, Errors, output);
387 }
388
389 try output(context, @typeName(T));
390 if (max_depth == 0) {374 if (max_depth == 0) {
391 return output(context, "{ ... }");375 return out_stream.writeAll("{ ... }");
392 }376 }
393 const info = @typeInfo(T).Union;377 const info = @typeInfo(T).Union;
394 if (info.tag_type) |UnionTagType| {378 if (info.tag_type) |UnionTagType| {
395 try output(context, "{ .");379 try out_stream.writeAll("{ .");
396 try output(context, @tagName(@as(UnionTagType, value)));380 try out_stream.writeAll(@tagName(@as(UnionTagType, value)));
397 try output(context, " = ");381 try out_stream.writeAll(" = ");
398 inline for (info.fields) |u_field| {382 inline for (info.fields) |u_field| {
399 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {383 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
400 try formatType(@field(value, u_field.name), fmt, options, context, Errors, output, max_depth - 1);384 try formatType(@field(value, u_field.name), fmt, options, out_stream, max_depth - 1);
401 }385 }
402 }386 }
403 try output(context, " }");387 try out_stream.writeAll(" }");
404 } else {388 } else {
405 try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)});389 try format(out_stream, "@{x}", .{@ptrToInt(&value)});
406 }390 }
407 },391 },
408 .Struct => |StructT| {392 .Struct => |StructT| {
409 if (comptime std.meta.trait.hasFn("format")(T)) {393 try out_stream.writeAll(@typeName(T));
410 return value.format(fmt, options, context, Errors, output);
411 }
412
413 try output(context, @typeName(T));
414 if (max_depth == 0) {394 if (max_depth == 0) {
415 return output(context, "{ ... }");395 return out_stream.writeAll("{ ... }");
416 }396 }
417 try output(context, "{");397 try out_stream.writeAll("{");
418 inline for (StructT.fields) |f, i| {398 inline for (StructT.fields) |f, i| {
419 if (i == 0) {399 if (i == 0) {
420 try output(context, " .");400 try out_stream.writeAll(" .");
421 } else {401 } else {
422 try output(context, ", .");402 try out_stream.writeAll(", .");
423 }403 }
424 try output(context, f.name);404 try out_stream.writeAll(f.name);
425 try output(context, " = ");405 try out_stream.writeAll(" = ");
426 try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1);406 try formatType(@field(value, f.name), fmt, options, out_stream, max_depth - 1);
427 }407 }
428 try output(context, " }");408 try out_stream.writeAll(" }");
429 },409 },
430 .Pointer => |ptr_info| switch (ptr_info.size) {410 .Pointer => |ptr_info| switch (ptr_info.size) {
431 .One => switch (@typeInfo(ptr_info.child)) {411 .One => switch (@typeInfo(ptr_info.child)) {
432 .Array => |info| {412 .Array => |info| {
433 if (info.child == u8) {413 if (info.child == u8) {
434 return formatText(value, fmt, options, context, Errors, output);414 return formatText(value, fmt, options, out_stream);
435 }415 }
436 return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });416 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
437 },417 },
438 .Enum, .Union, .Struct => {418 .Enum, .Union, .Struct => {
439 return formatType(value.*, fmt, options, context, Errors, output, max_depth);419 return formatType(value.*, fmt, options, out_stream, max_depth);
440 },420 },
441 else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),421 else => return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
442 },422 },
443 .Many, .C => {423 .Many, .C => {
444 if (ptr_info.sentinel) |sentinel| {424 if (ptr_info.sentinel) |sentinel| {
445 return formatType(mem.span(value), fmt, options, context, Errors, output, max_depth);425 return formatType(mem.span(value), fmt, options, out_stream, max_depth);
446 }426 }
447 if (ptr_info.child == u8) {427 if (ptr_info.child == u8) {
448 if (fmt.len > 0 and fmt[0] == 's') {428 if (fmt.len > 0 and fmt[0] == 's') {
449 return formatText(mem.span(value), fmt, options, context, Errors, output);429 return formatText(mem.span(value), fmt, options, out_stream);
450 }430 }
451 }431 }
452 return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });432 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
453 },433 },
454 .Slice => {434 .Slice => {
455 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {435 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
456 return formatText(value, fmt, options, context, Errors, output);436 return formatText(value, fmt, options, out_stream);
457 }437 }
458 if (ptr_info.child == u8) {438 if (ptr_info.child == u8) {
459 return formatText(value, fmt, options, context, Errors, output);439 return formatText(value, fmt, options, out_stream);
460 }440 }
461 return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });441 return format(out_stream, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
462 },442 },
463 },443 },
464 .Array => |info| {444 .Array => |info| {
...@@ -473,27 +453,27 @@ pub fn formatType(...@@ -473,27 +453,27 @@ pub fn formatType(
473 .sentinel = null,453 .sentinel = null,
474 },454 },
475 });455 });
476 return formatType(@as(Slice, &value), fmt, options, context, Errors, output, max_depth);456 return formatType(@as(Slice, &value), fmt, options, out_stream, max_depth);
477 },457 },
478 .Vector => {458 .Vector => {
479 const len = @typeInfo(T).Vector.len;459 const len = @typeInfo(T).Vector.len;
480 try output(context, "{ ");460 try out_stream.writeAll("{ ");
481 var i: usize = 0;461 var i: usize = 0;
482 while (i < len) : (i += 1) {462 while (i < len) : (i += 1) {
483 try formatValue(value[i], fmt, options, context, Errors, output);463 try formatValue(value[i], fmt, options, out_stream);
484 if (i < len - 1) {464 if (i < len - 1) {
485 try output(context, ", ");465 try out_stream.writeAll(", ");
486 }466 }
487 }467 }
488 try output(context, " }");468 try out_stream.writeAll(" }");
489 },469 },
490 .Fn => {470 .Fn => {
491 return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });471 return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
492 },472 },
493 .Type => return output(context, @typeName(T)),473 .Type => return out_stream.writeAll(@typeName(T)),
494 .EnumLiteral => {474 .EnumLiteral => {
495 const buffer = [_]u8{'.'} ++ @tagName(value);475 const buffer = [_]u8{'.'} ++ @tagName(value);
496 return formatType(buffer, fmt, options, context, Errors, output, max_depth);476 return formatType(buffer, fmt, options, out_stream, max_depth);
497 },477 },
498 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),478 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
499 }479 }
...@@ -503,21 +483,19 @@ fn formatValue(...@@ -503,21 +483,19 @@ fn formatValue(
503 value: var,483 value: var,
504 comptime fmt: []const u8,484 comptime fmt: []const u8,
505 options: FormatOptions,485 options: FormatOptions,
506 context: var,486 out_stream: var,
507 comptime Errors: type,487) !void {
508 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
509) Errors!void {
510 if (comptime std.mem.eql(u8, fmt, "B")) {488 if (comptime std.mem.eql(u8, fmt, "B")) {
511 return formatBytes(value, options, 1000, context, Errors, output);489 return formatBytes(value, options, 1000, out_stream);
512 } else if (comptime std.mem.eql(u8, fmt, "Bi")) {490 } else if (comptime std.mem.eql(u8, fmt, "Bi")) {
513 return formatBytes(value, options, 1024, context, Errors, output);491 return formatBytes(value, options, 1024, out_stream);
514 }492 }
515493
516 const T = @TypeOf(value);494 const T = @TypeOf(value);
517 switch (@typeInfo(T)) {495 switch (@typeInfo(T)) {
518 .Float => return formatFloatValue(value, fmt, options, context, Errors, output),496 .Float => return formatFloatValue(value, fmt, options, out_stream),
519 .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),497 .Int, .ComptimeInt => return formatIntValue(value, fmt, options, out_stream),
520 .Bool => return output(context, if (value) "true" else "false"),498 .Bool => return out_stream.writeAll(if (value) "true" else "false"),
521 else => comptime unreachable,499 else => comptime unreachable,
522 }500 }
523}501}
...@@ -526,10 +504,8 @@ pub fn formatIntValue(...@@ -526,10 +504,8 @@ pub fn formatIntValue(
526 value: var,504 value: var,
527 comptime fmt: []const u8,505 comptime fmt: []const u8,
528 options: FormatOptions,506 options: FormatOptions,
529 context: var,507 out_stream: var,
530 comptime Errors: type,508) !void {
531 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
532) Errors!void {
533 comptime var radix = 10;509 comptime var radix = 10;
534 comptime var uppercase = false;510 comptime var uppercase = false;
535511
...@@ -544,7 +520,7 @@ pub fn formatIntValue(...@@ -544,7 +520,7 @@ pub fn formatIntValue(
544 uppercase = false;520 uppercase = false;
545 } else if (comptime std.mem.eql(u8, fmt, "c")) {521 } else if (comptime std.mem.eql(u8, fmt, "c")) {
546 if (@TypeOf(int_value).bit_count <= 8) {522 if (@TypeOf(int_value).bit_count <= 8) {
547 return formatAsciiChar(@as(u8, int_value), options, context, Errors, output);523 return formatAsciiChar(@as(u8, int_value), options, out_stream);
548 } else {524 } else {
549 @compileError("Cannot print integer that is larger than 8 bits as a ascii");525 @compileError("Cannot print integer that is larger than 8 bits as a ascii");
550 }526 }
...@@ -561,21 +537,19 @@ pub fn formatIntValue(...@@ -561,21 +537,19 @@ pub fn formatIntValue(
561 @compileError("Unknown format string: '" ++ fmt ++ "'");537 @compileError("Unknown format string: '" ++ fmt ++ "'");
562 }538 }
563539
564 return formatInt(int_value, radix, uppercase, options, context, Errors, output);540 return formatInt(int_value, radix, uppercase, options, out_stream);
565}541}
566542
567fn formatFloatValue(543fn formatFloatValue(
568 value: var,544 value: var,
569 comptime fmt: []const u8,545 comptime fmt: []const u8,
570 options: FormatOptions,546 options: FormatOptions,
571 context: var,547 out_stream: var,
572 comptime Errors: type,548) !void {
573 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
574) Errors!void {
575 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {549 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
576 return formatFloatScientific(value, options, context, Errors, output);550 return formatFloatScientific(value, options, out_stream);
577 } else if (comptime std.mem.eql(u8, fmt, "d")) {551 } else if (comptime std.mem.eql(u8, fmt, "d")) {
578 return formatFloatDecimal(value, options, context, Errors, output);552 return formatFloatDecimal(value, options, out_stream);
579 } else {553 } else {
580 @compileError("Unknown format string: '" ++ fmt ++ "'");554 @compileError("Unknown format string: '" ++ fmt ++ "'");
581 }555 }
...@@ -585,17 +559,15 @@ pub fn formatText(...@@ -585,17 +559,15 @@ pub fn formatText(
585 bytes: []const u8,559 bytes: []const u8,
586 comptime fmt: []const u8,560 comptime fmt: []const u8,
587 options: FormatOptions,561 options: FormatOptions,
588 context: var,562 out_stream: var,
589 comptime Errors: type,563) !void {
590 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
591) Errors!void {
592 if (fmt.len == 0) {564 if (fmt.len == 0) {
593 return output(context, bytes);565 return out_stream.writeAll(bytes);
594 } else if (comptime std.mem.eql(u8, fmt, "s")) {566 } else if (comptime std.mem.eql(u8, fmt, "s")) {
595 return formatBuf(bytes, options, context, Errors, output);567 return formatBuf(bytes, options, out_stream);
596 } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {568 } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
597 for (bytes) |c| {569 for (bytes) |c| {
598 try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, context, Errors, output);570 try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, out_stream);
599 }571 }
600 return;572 return;
601 } else {573 } else {
...@@ -606,27 +578,23 @@ pub fn formatText(...@@ -606,27 +578,23 @@ pub fn formatText(
606pub fn formatAsciiChar(578pub fn formatAsciiChar(
607 c: u8,579 c: u8,
608 options: FormatOptions,580 options: FormatOptions,
609 context: var,581 out_stream: var,
610 comptime Errors: type,582) !void {
611 comptime output: fn (@TypeOf(context), []const u8) Errors!void,583 return out_stream.writeAll(@as(*const [1]u8, &c));
612) Errors!void {
613 return output(context, @as(*const [1]u8, &c)[0..]);
614}584}
615585
616pub fn formatBuf(586pub fn formatBuf(
617 buf: []const u8,587 buf: []const u8,
618 options: FormatOptions,588 options: FormatOptions,
619 context: var,589 out_stream: var,
620 comptime Errors: type,590) !void {
621 comptime output: fn (@TypeOf(context), []const u8) Errors!void,591 try out_stream.writeAll(buf);
622) Errors!void {
623 try output(context, buf);
624592
625 const width = options.width orelse 0;593 const width = options.width orelse 0;
626 var leftover_padding = if (width > buf.len) (width - buf.len) else return;594 var leftover_padding = if (width > buf.len) (width - buf.len) else return;
627 const pad_byte: u8 = options.fill;595 const pad_byte = [1]u8{options.fill};
628 while (leftover_padding > 0) : (leftover_padding -= 1) {596 while (leftover_padding > 0) : (leftover_padding -= 1) {
629 try output(context, @as(*const [1]u8, &pad_byte)[0..1]);597 try out_stream.writeAll(&pad_byte);
630 }598 }
631}599}
632600
...@@ -636,40 +604,38 @@ pub fn formatBuf(...@@ -636,40 +604,38 @@ pub fn formatBuf(
636pub fn formatFloatScientific(604pub fn formatFloatScientific(
637 value: var,605 value: var,
638 options: FormatOptions,606 options: FormatOptions,
639 context: var,607 out_stream: var,
640 comptime Errors: type,608) !void {
641 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
642) Errors!void {
643 var x = @floatCast(f64, value);609 var x = @floatCast(f64, value);
644610
645 // Errol doesn't handle these special cases.611 // Errol doesn't handle these special cases.
646 if (math.signbit(x)) {612 if (math.signbit(x)) {
647 try output(context, "-");613 try out_stream.writeAll("-");
648 x = -x;614 x = -x;
649 }615 }
650616
651 if (math.isNan(x)) {617 if (math.isNan(x)) {
652 return output(context, "nan");618 return out_stream.writeAll("nan");
653 }619 }
654 if (math.isPositiveInf(x)) {620 if (math.isPositiveInf(x)) {
655 return output(context, "inf");621 return out_stream.writeAll("inf");
656 }622 }
657 if (x == 0.0) {623 if (x == 0.0) {
658 try output(context, "0");624 try out_stream.writeAll("0");
659625
660 if (options.precision) |precision| {626 if (options.precision) |precision| {
661 if (precision != 0) {627 if (precision != 0) {
662 try output(context, ".");628 try out_stream.writeAll(".");
663 var i: usize = 0;629 var i: usize = 0;
664 while (i < precision) : (i += 1) {630 while (i < precision) : (i += 1) {
665 try output(context, "0");631 try out_stream.writeAll("0");
666 }632 }
667 }633 }
668 } else {634 } else {
669 try output(context, ".0");635 try out_stream.writeAll(".0");
670 }636 }
671637
672 try output(context, "e+00");638 try out_stream.writeAll("e+00");
673 return;639 return;
674 }640 }
675641
...@@ -679,50 +645,50 @@ pub fn formatFloatScientific(...@@ -679,50 +645,50 @@ pub fn formatFloatScientific(
679 if (options.precision) |precision| {645 if (options.precision) |precision| {
680 errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);646 errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);
681647
682 try output(context, float_decimal.digits[0..1]);648 try out_stream.writeAll(float_decimal.digits[0..1]);
683649
684 // {e0} case prints no `.`650 // {e0} case prints no `.`
685 if (precision != 0) {651 if (precision != 0) {
686 try output(context, ".");652 try out_stream.writeAll(".");
687653
688 var printed: usize = 0;654 var printed: usize = 0;
689 if (float_decimal.digits.len > 1) {655 if (float_decimal.digits.len > 1) {
690 const num_digits = math.min(float_decimal.digits.len, precision + 1);656 const num_digits = math.min(float_decimal.digits.len, precision + 1);
691 try output(context, float_decimal.digits[1..num_digits]);657 try out_stream.writeAll(float_decimal.digits[1..num_digits]);
692 printed += num_digits - 1;658 printed += num_digits - 1;
693 }659 }
694660
695 while (printed < precision) : (printed += 1) {661 while (printed < precision) : (printed += 1) {
696 try output(context, "0");662 try out_stream.writeAll("0");
697 }663 }
698 }664 }
699 } else {665 } else {
700 try output(context, float_decimal.digits[0..1]);666 try out_stream.writeAll(float_decimal.digits[0..1]);
701 try output(context, ".");667 try out_stream.writeAll(".");
702 if (float_decimal.digits.len > 1) {668 if (float_decimal.digits.len > 1) {
703 const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;669 const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
704670
705 try output(context, float_decimal.digits[1..num_digits]);671 try out_stream.writeAll(float_decimal.digits[1..num_digits]);
706 } else {672 } else {
707 try output(context, "0");673 try out_stream.writeAll("0");
708 }674 }
709 }675 }
710676
711 try output(context, "e");677 try out_stream.writeAll("e");
712 const exp = float_decimal.exp - 1;678 const exp = float_decimal.exp - 1;
713679
714 if (exp >= 0) {680 if (exp >= 0) {
715 try output(context, "+");681 try out_stream.writeAll("+");
716 if (exp > -10 and exp < 10) {682 if (exp > -10 and exp < 10) {
717 try output(context, "0");683 try out_stream.writeAll("0");
718 }684 }
719 try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);685 try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
720 } else {686 } else {
721 try output(context, "-");687 try out_stream.writeAll("-");
722 if (exp > -10 and exp < 10) {688 if (exp > -10 and exp < 10) {
723 try output(context, "0");689 try out_stream.writeAll("0");
724 }690 }
725 try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);691 try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
726 }692 }
727}693}
728694
...@@ -731,36 +697,34 @@ pub fn formatFloatScientific(...@@ -731,36 +697,34 @@ pub fn formatFloatScientific(
731pub fn formatFloatDecimal(697pub fn formatFloatDecimal(
732 value: var,698 value: var,
733 options: FormatOptions,699 options: FormatOptions,
734 context: var,700 out_stream: var,
735 comptime Errors: type,701) !void {
736 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
737) Errors!void {
738 var x = @as(f64, value);702 var x = @as(f64, value);
739703
740 // Errol doesn't handle these special cases.704 // Errol doesn't handle these special cases.
741 if (math.signbit(x)) {705 if (math.signbit(x)) {
742 try output(context, "-");706 try out_stream.writeAll("-");
743 x = -x;707 x = -x;
744 }708 }
745709
746 if (math.isNan(x)) {710 if (math.isNan(x)) {
747 return output(context, "nan");711 return out_stream.writeAll("nan");
748 }712 }
749 if (math.isPositiveInf(x)) {713 if (math.isPositiveInf(x)) {
750 return output(context, "inf");714 return out_stream.writeAll("inf");
751 }715 }
752 if (x == 0.0) {716 if (x == 0.0) {
753 try output(context, "0");717 try out_stream.writeAll("0");
754718
755 if (options.precision) |precision| {719 if (options.precision) |precision| {
756 if (precision != 0) {720 if (precision != 0) {
757 try output(context, ".");721 try out_stream.writeAll(".");
758 var i: usize = 0;722 var i: usize = 0;
759 while (i < precision) : (i += 1) {723 while (i < precision) : (i += 1) {
760 try output(context, "0");724 try out_stream.writeAll("0");
761 }725 }
762 } else {726 } else {
763 try output(context, ".0");727 try out_stream.writeAll(".0");
764 }728 }
765 }729 }
766730
...@@ -782,14 +746,14 @@ pub fn formatFloatDecimal(...@@ -782,14 +746,14 @@ pub fn formatFloatDecimal(
782746
783 if (num_digits_whole > 0) {747 if (num_digits_whole > 0) {
784 // We may have to zero pad, for instance 1e4 requires zero padding.748 // We may have to zero pad, for instance 1e4 requires zero padding.
785 try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);749 try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
786750
787 var i = num_digits_whole_no_pad;751 var i = num_digits_whole_no_pad;
788 while (i < num_digits_whole) : (i += 1) {752 while (i < num_digits_whole) : (i += 1) {
789 try output(context, "0");753 try out_stream.writeAll("0");
790 }754 }
791 } else {755 } else {
792 try output(context, "0");756 try out_stream.writeAll("0");
793 }757 }
794758
795 // {.0} special case doesn't want a trailing '.'759 // {.0} special case doesn't want a trailing '.'
...@@ -797,7 +761,7 @@ pub fn formatFloatDecimal(...@@ -797,7 +761,7 @@ pub fn formatFloatDecimal(
797 return;761 return;
798 }762 }
799763
800 try output(context, ".");764 try out_stream.writeAll(".");
801765
802 // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.766 // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.
803 var printed: usize = 0;767 var printed: usize = 0;
...@@ -809,7 +773,7 @@ pub fn formatFloatDecimal(...@@ -809,7 +773,7 @@ pub fn formatFloatDecimal(
809773
810 var i: usize = 0;774 var i: usize = 0;
811 while (i < zeros_to_print) : (i += 1) {775 while (i < zeros_to_print) : (i += 1) {
812 try output(context, "0");776 try out_stream.writeAll("0");
813 printed += 1;777 printed += 1;
814 }778 }
815779
...@@ -821,14 +785,14 @@ pub fn formatFloatDecimal(...@@ -821,14 +785,14 @@ pub fn formatFloatDecimal(
821 // Remaining fractional portion, zero-padding if insufficient.785 // Remaining fractional portion, zero-padding if insufficient.
822 assert(precision >= printed);786 assert(precision >= printed);
823 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {787 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
824 try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);788 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
825 return;789 return;
826 } else {790 } else {
827 try output(context, float_decimal.digits[num_digits_whole_no_pad..]);791 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
828 printed += float_decimal.digits.len - num_digits_whole_no_pad;792 printed += float_decimal.digits.len - num_digits_whole_no_pad;
829793
830 while (printed < precision) : (printed += 1) {794 while (printed < precision) : (printed += 1) {
831 try output(context, "0");795 try out_stream.writeAll("0");
832 }796 }
833 }797 }
834 } else {798 } else {
...@@ -840,14 +804,14 @@ pub fn formatFloatDecimal(...@@ -840,14 +804,14 @@ pub fn formatFloatDecimal(
840804
841 if (num_digits_whole > 0) {805 if (num_digits_whole > 0) {
842 // We may have to zero pad, for instance 1e4 requires zero padding.806 // We may have to zero pad, for instance 1e4 requires zero padding.
843 try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);807 try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
844808
845 var i = num_digits_whole_no_pad;809 var i = num_digits_whole_no_pad;
846 while (i < num_digits_whole) : (i += 1) {810 while (i < num_digits_whole) : (i += 1) {
847 try output(context, "0");811 try out_stream.writeAll("0");
848 }812 }
849 } else {813 } else {
850 try output(context, "0");814 try out_stream.writeAll("0");
851 }815 }
852816
853 // Omit `.` if no fractional portion817 // Omit `.` if no fractional portion
...@@ -855,7 +819,7 @@ pub fn formatFloatDecimal(...@@ -855,7 +819,7 @@ pub fn formatFloatDecimal(
855 return;819 return;
856 }820 }
857821
858 try output(context, ".");822 try out_stream.writeAll(".");
859823
860 // Zero-fill until we reach significant digits or run out of precision.824 // Zero-fill until we reach significant digits or run out of precision.
861 if (float_decimal.exp < 0) {825 if (float_decimal.exp < 0) {
...@@ -863,11 +827,11 @@ pub fn formatFloatDecimal(...@@ -863,11 +827,11 @@ pub fn formatFloatDecimal(
863827
864 var i: usize = 0;828 var i: usize = 0;
865 while (i < zero_digit_count) : (i += 1) {829 while (i < zero_digit_count) : (i += 1) {
866 try output(context, "0");830 try out_stream.writeAll("0");
867 }831 }
868 }832 }
869833
870 try output(context, float_decimal.digits[num_digits_whole_no_pad..]);834 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
871 }835 }
872}836}
873837
...@@ -875,12 +839,10 @@ pub fn formatBytes(...@@ -875,12 +839,10 @@ pub fn formatBytes(
875 value: var,839 value: var,
876 options: FormatOptions,840 options: FormatOptions,
877 comptime radix: usize,841 comptime radix: usize,
878 context: var,842 out_stream: var,
879 comptime Errors: type,843) !void {
880 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
881) Errors!void {
882 if (value == 0) {844 if (value == 0) {
883 return output(context, "0B");845 return out_stream.writeAll("0B");
884 }846 }
885847
886 const mags_si = " kMGTPEZY";848 const mags_si = " kMGTPEZY";
...@@ -897,10 +859,10 @@ pub fn formatBytes(...@@ -897,10 +859,10 @@ pub fn formatBytes(
897 else => unreachable,859 else => unreachable,
898 };860 };
899861
900 try formatFloatDecimal(new_value, options, context, Errors, output);862 try formatFloatDecimal(new_value, options, out_stream);
901863
902 if (suffix == ' ') {864 if (suffix == ' ') {
903 return output(context, "B");865 return out_stream.writeAll("B");
904 }866 }
905867
906 const buf = switch (radix) {868 const buf = switch (radix) {
...@@ -908,7 +870,7 @@ pub fn formatBytes(...@@ -908,7 +870,7 @@ pub fn formatBytes(
908 1024 => &[_]u8{ suffix, 'i', 'B' },870 1024 => &[_]u8{ suffix, 'i', 'B' },
909 else => unreachable,871 else => unreachable,
910 };872 };
911 return output(context, buf);873 return out_stream.writeAll(buf);
912}874}
913875
914pub fn formatInt(876pub fn formatInt(
...@@ -916,10 +878,8 @@ pub fn formatInt(...@@ -916,10 +878,8 @@ pub fn formatInt(
916 base: u8,878 base: u8,
917 uppercase: bool,879 uppercase: bool,
918 options: FormatOptions,880 options: FormatOptions,
919 context: var,881 out_stream: var,
920 comptime Errors: type,882) !void {
921 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
922) Errors!void {
923 const int_value = if (@TypeOf(value) == comptime_int) blk: {883 const int_value = if (@TypeOf(value) == comptime_int) blk: {
924 const Int = math.IntFittingRange(value, value);884 const Int = math.IntFittingRange(value, value);
925 break :blk @as(Int, value);885 break :blk @as(Int, value);
...@@ -927,9 +887,9 @@ pub fn formatInt(...@@ -927,9 +887,9 @@ pub fn formatInt(
927 value;887 value;
928888
929 if (@TypeOf(int_value).is_signed) {889 if (@TypeOf(int_value).is_signed) {
930 return formatIntSigned(int_value, base, uppercase, options, context, Errors, output);890 return formatIntSigned(int_value, base, uppercase, options, out_stream);
931 } else {891 } else {
932 return formatIntUnsigned(int_value, base, uppercase, options, context, Errors, output);892 return formatIntUnsigned(int_value, base, uppercase, options, out_stream);
933 }893 }
934}894}
935895
...@@ -938,10 +898,8 @@ fn formatIntSigned(...@@ -938,10 +898,8 @@ fn formatIntSigned(
938 base: u8,898 base: u8,
939 uppercase: bool,899 uppercase: bool,
940 options: FormatOptions,900 options: FormatOptions,
941 context: var,901 out_stream: var,
942 comptime Errors: type,902) !void {
943 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
944) Errors!void {
945 const new_options = FormatOptions{903 const new_options = FormatOptions{
946 .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,904 .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,
947 .precision = options.precision,905 .precision = options.precision,
...@@ -950,15 +908,15 @@ fn formatIntSigned(...@@ -950,15 +908,15 @@ fn formatIntSigned(
950 const bit_count = @typeInfo(@TypeOf(value)).Int.bits;908 const bit_count = @typeInfo(@TypeOf(value)).Int.bits;
951 const Uint = std.meta.IntType(false, bit_count);909 const Uint = std.meta.IntType(false, bit_count);
952 if (value < 0) {910 if (value < 0) {
953 try output(context, "-");911 try out_stream.writeAll("-");
954 const new_value = math.absCast(value);912 const new_value = math.absCast(value);
955 return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);913 return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
956 } else if (options.width == null or options.width.? == 0) {914 } else if (options.width == null or options.width.? == 0) {
957 return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, context, Errors, output);915 return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, out_stream);
958 } else {916 } else {
959 try output(context, "+");917 try out_stream.writeAll("+");
960 const new_value = @intCast(Uint, value);918 const new_value = @intCast(Uint, value);
961 return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);919 return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
962 }920 }
963}921}
964922
...@@ -967,10 +925,8 @@ fn formatIntUnsigned(...@@ -967,10 +925,8 @@ fn formatIntUnsigned(
967 base: u8,925 base: u8,
968 uppercase: bool,926 uppercase: bool,
969 options: FormatOptions,927 options: FormatOptions,
970 context: var,928 out_stream: var,
971 comptime Errors: type,929) !void {
972 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
973) Errors!void {
974 assert(base >= 2);930 assert(base >= 2);
975 var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;931 var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
976 const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);932 const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
...@@ -994,34 +950,23 @@ fn formatIntUnsigned(...@@ -994,34 +950,23 @@ fn formatIntUnsigned(
994 const zero_byte: u8 = options.fill;950 const zero_byte: u8 = options.fill;
995 var leftover_padding = padding - index;951 var leftover_padding = padding - index;
996 while (true) {952 while (true) {
997 try output(context, @as(*const [1]u8, &zero_byte)[0..]);953 try out_stream.writeAll(@as(*const [1]u8, &zero_byte)[0..]);
998 leftover_padding -= 1;954 leftover_padding -= 1;
999 if (leftover_padding == 0) break;955 if (leftover_padding == 0) break;
1000 }956 }
1001 mem.set(u8, buf[0..index], options.fill);957 mem.set(u8, buf[0..index], options.fill);
1002 return output(context, &buf);958 return out_stream.writeAll(&buf);
1003 } else {959 } else {
1004 const padded_buf = buf[index - padding ..];960 const padded_buf = buf[index - padding ..];
1005 mem.set(u8, padded_buf[0..padding], options.fill);961 mem.set(u8, padded_buf[0..padding], options.fill);
1006 return output(context, padded_buf);962 return out_stream.writeAll(padded_buf);
1007 }963 }
1008}964}
1009965
1010pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {966pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {
1011 var context = FormatIntBuf{967 var fbs = std.io.fixedBufferStream(out_buf);
1012 .out_buf = out_buf,968 formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable;
1013 .index = 0,969 return fbs.pos;
1014 };
1015 formatInt(value, base, uppercase, options, &context, error{}, formatIntCallback) catch unreachable;
1016 return context.index;
1017}
1018const FormatIntBuf = struct {
1019 out_buf: []u8,
1020 index: usize,
1021};
1022fn formatIntCallback(context: *FormatIntBuf, bytes: []const u8) (error{}!void) {
1023 mem.copy(u8, context.out_buf[context.index..], bytes);
1024 context.index += bytes.len;
1025}970}
1026971
1027pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {972pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
...@@ -1121,44 +1066,36 @@ fn digitToChar(digit: u8, uppercase: bool) u8 {...@@ -1121,44 +1066,36 @@ fn digitToChar(digit: u8, uppercase: bool) u8 {
1121 };1066 };
1122}1067}
11231068
1124const BufPrintContext = struct {
1125 remaining: []u8,
1126};
1127
1128fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
1129 if (context.remaining.len < bytes.len) {
1130 mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
1131 return error.BufferTooSmall;
1132 }
1133 mem.copy(u8, context.remaining, bytes);
1134 context.remaining = context.remaining[bytes.len..];
1135}
1136
1137pub const BufPrintError = error{1069pub const BufPrintError = error{
1138 /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.1070 /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
1139 BufferTooSmall,1071 NoSpaceLeft,
1140};1072};
1141pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {1073pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
1142 var context = BufPrintContext{ .remaining = buf };1074 var fbs = std.io.fixedBufferStream(buf);
1143 try format(&context, BufPrintError, bufPrintWrite, fmt, args);1075 try format(fbs.outStream(), fmt, args);
1144 return buf[0 .. buf.len - context.remaining.len];1076 return fbs.getWritten();
1077}
1078
1079// Count the characters needed for format. Useful for preallocating memory
1080pub fn count(comptime fmt: []const u8, args: var) u64 {
1081 var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
1082 format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {};
1083 return counting_stream.bytes_written;
1145}1084}
11461085
1147pub const AllocPrintError = error{OutOfMemory};1086pub const AllocPrintError = error{OutOfMemory};
11481087
1149pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {1088pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
1150 var size: usize = 0;1089 const size = math.cast(usize, count(fmt, args)) catch |err| switch (err) {
1151 format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};1090 // Output too long. Can't possibly allocate enough memory to display it.
1091 error.Overflow => return error.OutOfMemory,
1092 };
1152 const buf = try allocator.alloc(u8, size);1093 const buf = try allocator.alloc(u8, size);
1153 return bufPrint(buf, fmt, args) catch |err| switch (err) {1094 return bufPrint(buf, fmt, args) catch |err| switch (err) {
1154 error.BufferTooSmall => unreachable, // we just counted the size above1095 error.NoSpaceLeft => unreachable, // we just counted the size above
1155 };1096 };
1156}1097}
11571098
1158fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
1159 size.* += bytes.len;
1160}
1161
1162pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {1099pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
1163 const result = try allocPrint(allocator, fmt ++ "\x00", args);1100 const result = try allocPrint(allocator, fmt ++ "\x00", args);
1164 return result[0 .. result.len - 1 :0];1101 return result[0 .. result.len - 1 :0];
...@@ -1251,20 +1188,17 @@ test "int.padded" {...@@ -1251,20 +1188,17 @@ test "int.padded" {
1251test "buffer" {1188test "buffer" {
1252 {1189 {
1253 var buf1: [32]u8 = undefined;1190 var buf1: [32]u8 = undefined;
1254 var context = BufPrintContext{ .remaining = buf1[0..] };1191 var fbs = std.io.fixedBufferStream(&buf1);
1255 try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1192 try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
1256 var res = buf1[0 .. buf1.len - context.remaining.len];1193 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234"));
1257 std.testing.expect(mem.eql(u8, res, "1234"));1194
12581195 fbs.reset();
1259 context = BufPrintContext{ .remaining = buf1[0..] };1196 try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
1260 try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1197 std.testing.expect(mem.eql(u8, fbs.getWritten(), "a"));
1261 res = buf1[0 .. buf1.len - context.remaining.len];1198
1262 std.testing.expect(mem.eql(u8, res, "a"));1199 fbs.reset();
12631200 try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
1264 context = BufPrintContext{ .remaining = buf1[0..] };1201 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100"));
1265 try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1266 res = buf1[0 .. buf1.len - context.remaining.len];
1267 std.testing.expect(mem.eql(u8, res, "1100"));
1268 }1202 }
1269}1203}
12701204
...@@ -1449,14 +1383,12 @@ test "custom" {...@@ -1449,14 +1383,12 @@ test "custom" {
1449 self: SelfType,1383 self: SelfType,
1450 comptime fmt: []const u8,1384 comptime fmt: []const u8,
1451 options: FormatOptions,1385 options: FormatOptions,
1452 context: var,1386 out_stream: var,
1453 comptime Errors: type,1387 ) !void {
1454 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1455 ) Errors!void {
1456 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {1388 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
1457 return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });1389 return std.fmt.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
1458 } else if (comptime std.mem.eql(u8, fmt, "d")) {1390 } else if (comptime std.mem.eql(u8, fmt, "d")) {
1459 return std.fmt.format(context, Errors, output, "{d:.3}x{d:.3}", .{ self.x, self.y });1391 return std.fmt.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
1460 } else {1392 } else {
1461 @compileError("Unknown format character: '" ++ fmt ++ "'");1393 @compileError("Unknown format character: '" ++ fmt ++ "'");
1462 }1394 }
...@@ -1640,10 +1572,10 @@ test "hexToBytes" {...@@ -1640,10 +1572,10 @@ test "hexToBytes" {
1640test "formatIntValue with comptime_int" {1572test "formatIntValue with comptime_int" {
1641 const value: comptime_int = 123456789123456789;1573 const value: comptime_int = 123456789123456789;
16421574
1643 var buf = std.ArrayList(u8).init(std.testing.allocator);1575 var buf: [20]u8 = undefined;
1644 defer buf.deinit();1576 var fbs = std.io.fixedBufferStream(&buf);
1645 try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);1577 try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
1646 std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));1578 std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789"));
1647}1579}
16481580
1649test "formatType max_depth" {1581test "formatType max_depth" {
...@@ -1656,12 +1588,10 @@ test "formatType max_depth" {...@@ -1656,12 +1588,10 @@ test "formatType max_depth" {
1656 self: SelfType,1588 self: SelfType,
1657 comptime fmt: []const u8,1589 comptime fmt: []const u8,
1658 options: FormatOptions,1590 options: FormatOptions,
1659 context: var,1591 out_stream: var,
1660 comptime Errors: type,1592 ) !void {
1661 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1662 ) Errors!void {
1663 if (fmt.len == 0) {1593 if (fmt.len == 0) {
1664 return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });1594 return std.fmt.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
1665 } else {1595 } else {
1666 @compileError("Unknown format string: '" ++ fmt ++ "'");1596 @compileError("Unknown format string: '" ++ fmt ++ "'");
1667 }1597 }
...@@ -1695,25 +1625,22 @@ test "formatType max_depth" {...@@ -1695,25 +1625,22 @@ test "formatType max_depth" {
1695 inst.a = &inst;1625 inst.a = &inst;
1696 inst.tu.ptr = &inst.tu;1626 inst.tu.ptr = &inst.tu;
16971627
1698 var buf0 = std.ArrayList(u8).init(std.testing.allocator);1628 var buf: [1000]u8 = undefined;
1699 defer buf0.deinit();1629 var fbs = std.io.fixedBufferStream(&buf);
1700 try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);1630 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0);
1701 std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));1631 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }"));
17021632
1703 var buf1 = std.ArrayList(u8).init(std.testing.allocator);1633 fbs.reset();
1704 defer buf1.deinit();1634 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1);
1705 try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);1635 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
1706 std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));1636
17071637 fbs.reset();
1708 var buf2 = std.ArrayList(u8).init(std.testing.allocator);1638 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2);
1709 defer buf2.deinit();1639 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
1710 try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);1640
1711 std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));1641 fbs.reset();
17121642 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3);
1713 var buf3 = std.ArrayList(u8).init(std.testing.allocator);1643 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
1714 defer buf3.deinit();
1715 try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3);
1716 std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
1717}1644}
17181645
1719test "positional" {1646test "positional" {
lib/std/http/headers.zig+6-8
...@@ -350,15 +350,13 @@ pub const Headers = struct {...@@ -350,15 +350,13 @@ pub const Headers = struct {
350 self: Self,350 self: Self,
351 comptime fmt: []const u8,351 comptime fmt: []const u8,
352 options: std.fmt.FormatOptions,352 options: std.fmt.FormatOptions,
353 context: var,353 out_stream: var,
354 comptime Errors: type,354 ) !void {
355 output: fn (@TypeOf(context), []const u8) Errors!void,
356 ) Errors!void {
357 for (self.toSlice()) |entry| {355 for (self.toSlice()) |entry| {
358 try output(context, entry.name);356 try out_stream.writeAll(entry.name);
359 try output(context, ": ");357 try out_stream.writeAll(": ");
360 try output(context, entry.value);358 try out_stream.writeAll(entry.value);
361 try output(context, "\n");359 try out_stream.writeAll("\n");
362 }360 }
363 }361 }
364};362};
lib/std/io/fixed_buffer_stream.zig+1-1
...@@ -103,7 +103,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {...@@ -103,7 +103,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
103 return self.pos;103 return self.pos;
104 }104 }
105105
106 pub fn getWritten(self: Self) []const u8 {106 pub fn getWritten(self: Self) Buffer {
107 return self.buffer[0..self.pos];107 return self.buffer[0..self.pos];
108 }108 }
109109
lib/std/io/out_stream.zig+1-1
...@@ -25,7 +25,7 @@ pub fn OutStream(...@@ -25,7 +25,7 @@ pub fn OutStream(
25 }25 }
2626
27 pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {27 pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {
28 return std.fmt.format(self, Error, writeAll, format, args);28 return std.fmt.format(self, format, args);
29 }29 }
3030
31 pub fn writeByte(self: Self, byte: u8) Error!void {31 pub fn writeByte(self: Self, byte: u8) Error!void {
lib/std/json.zig+72-62
...@@ -2252,45 +2252,43 @@ pub const StringifyOptions = struct {...@@ -2252,45 +2252,43 @@ pub const StringifyOptions = struct {
2252pub fn stringify(2252pub fn stringify(
2253 value: var,2253 value: var,
2254 options: StringifyOptions,2254 options: StringifyOptions,
2255 context: var,2255 out_stream: var,
2256 comptime Errors: type,2256) !void {
2257 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
2258) Errors!void {
2259 const T = @TypeOf(value);2257 const T = @TypeOf(value);
2260 switch (@typeInfo(T)) {2258 switch (@typeInfo(T)) {
2261 .Float, .ComptimeFloat => {2259 .Float, .ComptimeFloat => {
2262 return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, context, Errors, output);2260 return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, out_stream);
2263 },2261 },
2264 .Int, .ComptimeInt => {2262 .Int, .ComptimeInt => {
2265 return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, context, Errors, output);2263 return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, out_stream);
2266 },2264 },
2267 .Bool => {2265 .Bool => {
2268 return output(context, if (value) "true" else "false");2266 return out_stream.writeAll(if (value) "true" else "false");
2269 },2267 },
2270 .Optional => {2268 .Optional => {
2271 if (value) |payload| {2269 if (value) |payload| {
2272 return try stringify(payload, options, context, Errors, output);2270 return try stringify(payload, options, out_stream);
2273 } else {2271 } else {
2274 return output(context, "null");2272 return out_stream.writeAll("null");
2275 }2273 }
2276 },2274 },
2277 .Enum => {2275 .Enum => {
2278 if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {2276 if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
2279 return value.jsonStringify(options, context, Errors, output);2277 return value.jsonStringify(options, out_stream);
2280 }2278 }
22812279
2282 @compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'");2280 @compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'");
2283 },2281 },
2284 .Union => {2282 .Union => {
2285 if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {2283 if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
2286 return value.jsonStringify(options, context, Errors, output);2284 return value.jsonStringify(options, out_stream);
2287 }2285 }
22882286
2289 const info = @typeInfo(T).Union;2287 const info = @typeInfo(T).Union;
2290 if (info.tag_type) |UnionTagType| {2288 if (info.tag_type) |UnionTagType| {
2291 inline for (info.fields) |u_field| {2289 inline for (info.fields) |u_field| {
2292 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {2290 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
2293 return try stringify(@field(value, u_field.name), options, context, Errors, output);2291 return try stringify(@field(value, u_field.name), options, out_stream);
2294 }2292 }
2295 }2293 }
2296 } else {2294 } else {
...@@ -2299,10 +2297,10 @@ pub fn stringify(...@@ -2299,10 +2297,10 @@ pub fn stringify(
2299 },2297 },
2300 .Struct => |S| {2298 .Struct => |S| {
2301 if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {2299 if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
2302 return value.jsonStringify(options, context, Errors, output);2300 return value.jsonStringify(options, out_stream);
2303 }2301 }
23042302
2305 try output(context, "{");2303 try out_stream.writeAll("{");
2306 comptime var field_output = false;2304 comptime var field_output = false;
2307 inline for (S.fields) |Field, field_i| {2305 inline for (S.fields) |Field, field_i| {
2308 // don't include void fields2306 // don't include void fields
...@@ -2311,39 +2309,39 @@ pub fn stringify(...@@ -2311,39 +2309,39 @@ pub fn stringify(
2311 if (!field_output) {2309 if (!field_output) {
2312 field_output = true;2310 field_output = true;
2313 } else {2311 } else {
2314 try output(context, ",");2312 try out_stream.writeAll(",");
2315 }2313 }
23162314
2317 try stringify(Field.name, options, context, Errors, output);2315 try stringify(Field.name, options, out_stream);
2318 try output(context, ":");2316 try out_stream.writeAll(":");
2319 try stringify(@field(value, Field.name), options, context, Errors, output);2317 try stringify(@field(value, Field.name), options, out_stream);
2320 }2318 }
2321 try output(context, "}");2319 try out_stream.writeAll("}");
2322 return;2320 return;
2323 },2321 },
2324 .Pointer => |ptr_info| switch (ptr_info.size) {2322 .Pointer => |ptr_info| switch (ptr_info.size) {
2325 .One => {2323 .One => {
2326 // TODO: avoid loops?2324 // TODO: avoid loops?
2327 return try stringify(value.*, options, context, Errors, output);2325 return try stringify(value.*, options, out_stream);
2328 },2326 },
2329 // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)2327 // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
2330 .Slice => {2328 .Slice => {
2331 if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) {2329 if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) {
2332 try output(context, "\"");2330 try out_stream.writeAll("\"");
2333 var i: usize = 0;2331 var i: usize = 0;
2334 while (i < value.len) : (i += 1) {2332 while (i < value.len) : (i += 1) {
2335 switch (value[i]) {2333 switch (value[i]) {
2336 // normal ascii characters2334 // normal ascii characters
2337 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try output(context, value[i .. i + 1]),2335 0x20...0x21, 0x23...0x2E, 0x30...0x5B, 0x5D...0x7F => try out_stream.writeAll(value[i .. i + 1]),
2338 // control characters with short escapes2336 // control characters with short escapes
2339 '\\' => try output(context, "\\\\"),2337 '\\' => try out_stream.writeAll("\\\\"),
2340 '\"' => try output(context, "\\\""),2338 '\"' => try out_stream.writeAll("\\\""),
2341 '/' => try output(context, "\\/"),2339 '/' => try out_stream.writeAll("\\/"),
2342 0x8 => try output(context, "\\b"),2340 0x8 => try out_stream.writeAll("\\b"),
2343 0xC => try output(context, "\\f"),2341 0xC => try out_stream.writeAll("\\f"),
2344 '\n' => try output(context, "\\n"),2342 '\n' => try out_stream.writeAll("\\n"),
2345 '\r' => try output(context, "\\r"),2343 '\r' => try out_stream.writeAll("\\r"),
2346 '\t' => try output(context, "\\t"),2344 '\t' => try out_stream.writeAll("\\t"),
2347 else => {2345 else => {
2348 const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;2346 const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;
2349 const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;2347 const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;
...@@ -2351,40 +2349,40 @@ pub fn stringify(...@@ -2351,40 +2349,40 @@ pub fn stringify(
2351 // If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),2349 // If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),
2352 // then it may be represented as a six-character sequence: a reverse solidus, followed2350 // then it may be represented as a six-character sequence: a reverse solidus, followed
2353 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.2351 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
2354 try output(context, "\\u");2352 try out_stream.writeAll("\\u");
2355 try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);2353 try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
2356 } else {2354 } else {
2357 // To escape an extended character that is not in the Basic Multilingual Plane,2355 // To escape an extended character that is not in the Basic Multilingual Plane,
2358 // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.2356 // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.
2359 const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;2357 const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;
2360 const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;2358 const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;
2361 try output(context, "\\u");2359 try out_stream.writeAll("\\u");
2362 try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);2360 try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
2363 try output(context, "\\u");2361 try out_stream.writeAll("\\u");
2364 try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);2362 try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
2365 }2363 }
2366 i += ulen - 1;2364 i += ulen - 1;
2367 },2365 },
2368 }2366 }
2369 }2367 }
2370 try output(context, "\"");2368 try out_stream.writeAll("\"");
2371 return;2369 return;
2372 }2370 }
23732371
2374 try output(context, "[");2372 try out_stream.writeAll("[");
2375 for (value) |x, i| {2373 for (value) |x, i| {
2376 if (i != 0) {2374 if (i != 0) {
2377 try output(context, ",");2375 try out_stream.writeAll(",");
2378 }2376 }
2379 try stringify(x, options, context, Errors, output);2377 try stringify(x, options, out_stream);
2380 }2378 }
2381 try output(context, "]");2379 try out_stream.writeAll("]");
2382 return;2380 return;
2383 },2381 },
2384 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),2382 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
2385 },2383 },
2386 .Array => |info| {2384 .Array => |info| {
2387 return try stringify(value[0..], options, context, Errors, output);2385 return try stringify(value[0..], options, out_stream);
2388 },2386 },
2389 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),2387 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
2390 }2388 }
...@@ -2392,10 +2390,26 @@ pub fn stringify(...@@ -2392,10 +2390,26 @@ pub fn stringify(
2392}2390}
23932391
2394fn teststringify(expected: []const u8, value: var) !void {2392fn teststringify(expected: []const u8, value: var) !void {
2395 const TestStringifyContext = struct {2393 const ValidationOutStream = struct {
2394 const Self = @This();
2395 pub const OutStream = std.io.OutStream(*Self, Error, write);
2396 pub const Error = error{
2397 TooMuchData,
2398 DifferentData,
2399 };
2400
2396 expected_remaining: []const u8,2401 expected_remaining: []const u8,
2397 fn testStringifyWrite(context: *@This(), bytes: []const u8) !void {2402
2398 if (context.expected_remaining.len < bytes.len) {2403 fn init(exp: []const u8) Self {
2404 return .{ .expected_remaining = exp };
2405 }
2406
2407 pub fn outStream(self: *Self) OutStream {
2408 return .{ .context = self };
2409 }
2410
2411 fn write(self: *Self, bytes: []const u8) Error!usize {
2412 if (self.expected_remaining.len < bytes.len) {
2399 std.debug.warn(2413 std.debug.warn(
2400 \\====== expected this output: =========2414 \\====== expected this output: =========
2401 \\{}2415 \\{}
...@@ -2403,12 +2417,12 @@ fn teststringify(expected: []const u8, value: var) !void {...@@ -2403,12 +2417,12 @@ fn teststringify(expected: []const u8, value: var) !void {
2403 \\{}2417 \\{}
2404 \\======================================2418 \\======================================
2405 , .{2419 , .{
2406 context.expected_remaining,2420 self.expected_remaining,
2407 bytes,2421 bytes,
2408 });2422 });
2409 return error.TooMuchData;2423 return error.TooMuchData;
2410 }2424 }
2411 if (!mem.eql(u8, context.expected_remaining[0..bytes.len], bytes)) {2425 if (!mem.eql(u8, self.expected_remaining[0..bytes.len], bytes)) {
2412 std.debug.warn(2426 std.debug.warn(
2413 \\====== expected this output: =========2427 \\====== expected this output: =========
2414 \\{}2428 \\{}
...@@ -2416,21 +2430,19 @@ fn teststringify(expected: []const u8, value: var) !void {...@@ -2416,21 +2430,19 @@ fn teststringify(expected: []const u8, value: var) !void {
2416 \\{}2430 \\{}
2417 \\======================================2431 \\======================================
2418 , .{2432 , .{
2419 context.expected_remaining[0..bytes.len],2433 self.expected_remaining[0..bytes.len],
2420 bytes,2434 bytes,
2421 });2435 });
2422 return error.DifferentData;2436 return error.DifferentData;
2423 }2437 }
2424 context.expected_remaining = context.expected_remaining[bytes.len..];2438 self.expected_remaining = self.expected_remaining[bytes.len..];
2439 return bytes.len;
2425 }2440 }
2426 };2441 };
2427 var buf: [100]u8 = undefined;2442
2428 var context = TestStringifyContext{ .expected_remaining = expected };2443 var vos = ValidationOutStream.init(expected);
2429 try stringify(value, StringifyOptions{}, &context, error{2444 try stringify(value, StringifyOptions{}, vos.outStream());
2430 TooMuchData,2445 if (vos.expected_remaining.len > 0) return error.NotEnoughData;
2431 DifferentData,
2432 }, TestStringifyContext.testStringifyWrite);
2433 if (context.expected_remaining.len > 0) return error.NotEnoughData;
2434}2446}
24352447
2436test "stringify basic types" {2448test "stringify basic types" {
...@@ -2498,13 +2510,11 @@ test "stringify struct with custom stringifier" {...@@ -2498,13 +2510,11 @@ test "stringify struct with custom stringifier" {
2498 pub fn jsonStringify(2510 pub fn jsonStringify(
2499 value: Self,2511 value: Self,
2500 options: StringifyOptions,2512 options: StringifyOptions,
2501 context: var,2513 out_stream: var,
2502 comptime Errors: type,
2503 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
2504 ) !void {2514 ) !void {
2505 try output(context, "[\"something special\",");2515 try out_stream.writeAll("[\"something special\",");
2506 try stringify(42, options, context, Errors, output);2516 try stringify(42, options, out_stream);
2507 try output(context, "]");2517 try out_stream.writeAll("]");
2508 }2518 }
2509 }{ .foo = 42 });2519 }{ .foo = 42 });
2510}2520}
lib/std/math/big/int.zig+2-4
...@@ -519,16 +519,14 @@ pub const Int = struct {...@@ -519,16 +519,14 @@ pub const Int = struct {
519 self: Int,519 self: Int,
520 comptime fmt: []const u8,520 comptime fmt: []const u8,
521 options: std.fmt.FormatOptions,521 options: std.fmt.FormatOptions,
522 context: var,522 out_stream: var,
523 comptime FmtError: type,
524 output: fn (@TypeOf(context), []const u8) FmtError!void,
525 ) FmtError!void {523 ) FmtError!void {
526 self.assertWritable();524 self.assertWritable();
527 // TODO look at fmt and support other bases525 // TODO look at fmt and support other bases
528 // TODO support read-only fixed integers526 // TODO support read-only fixed integers
529 const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");527 const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
530 defer self.allocator.?.free(str);528 defer self.allocator.?.free(str);
531 return output(context, str);529 return out_stream.print(str);
532 }530 }
533531
534 /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.532 /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
lib/std/net.zig+9-11
...@@ -269,15 +269,13 @@ pub const Address = extern union {...@@ -269,15 +269,13 @@ pub const Address = extern union {
269 self: Address,269 self: Address,
270 comptime fmt: []const u8,270 comptime fmt: []const u8,
271 options: std.fmt.FormatOptions,271 options: std.fmt.FormatOptions,
272 context: var,272 out_stream: var,
273 comptime Errors: type,
274 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
275 ) !void {273 ) !void {
276 switch (self.any.family) {274 switch (self.any.family) {
277 os.AF_INET => {275 os.AF_INET => {
278 const port = mem.bigToNative(u16, self.in.port);276 const port = mem.bigToNative(u16, self.in.port);
279 const bytes = @ptrCast(*const [4]u8, &self.in.addr);277 const bytes = @ptrCast(*const [4]u8, &self.in.addr);
280 try std.fmt.format(context, Errors, output, "{}.{}.{}.{}:{}", .{278 try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
281 bytes[0],279 bytes[0],
282 bytes[1],280 bytes[1],
283 bytes[2],281 bytes[2],
...@@ -288,7 +286,7 @@ pub const Address = extern union {...@@ -288,7 +286,7 @@ pub const Address = extern union {
288 os.AF_INET6 => {286 os.AF_INET6 => {
289 const port = mem.bigToNative(u16, self.in6.port);287 const port = mem.bigToNative(u16, self.in6.port);
290 if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {288 if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
291 try std.fmt.format(context, Errors, output, "[::ffff:{}.{}.{}.{}]:{}", .{289 try std.fmt.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
292 self.in6.addr[12],290 self.in6.addr[12],
293 self.in6.addr[13],291 self.in6.addr[13],
294 self.in6.addr[14],292 self.in6.addr[14],
...@@ -308,30 +306,30 @@ pub const Address = extern union {...@@ -308,30 +306,30 @@ pub const Address = extern union {
308 break :blk buf;306 break :blk buf;
309 },307 },
310 };308 };
311 try output(context, "[");309 try out_stream.writeAll("[");
312 var i: usize = 0;310 var i: usize = 0;
313 var abbrv = false;311 var abbrv = false;
314 while (i < native_endian_parts.len) : (i += 1) {312 while (i < native_endian_parts.len) : (i += 1) {
315 if (native_endian_parts[i] == 0) {313 if (native_endian_parts[i] == 0) {
316 if (!abbrv) {314 if (!abbrv) {
317 try output(context, if (i == 0) "::" else ":");315 try out_stream.writeAll(if (i == 0) "::" else ":");
318 abbrv = true;316 abbrv = true;
319 }317 }
320 continue;318 continue;
321 }319 }
322 try std.fmt.format(context, Errors, output, "{x}", .{native_endian_parts[i]});320 try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});
323 if (i != native_endian_parts.len - 1) {321 if (i != native_endian_parts.len - 1) {
324 try output(context, ":");322 try out_stream.writeAll(":");
325 }323 }
326 }324 }
327 try std.fmt.format(context, Errors, output, "]:{}", .{port});325 try std.fmt.format(out_stream, "]:{}", .{port});
328 },326 },
329 os.AF_UNIX => {327 os.AF_UNIX => {
330 if (!has_unix_sockets) {328 if (!has_unix_sockets) {
331 unreachable;329 unreachable;
332 }330 }
333331
334 try std.fmt.format(context, Errors, output, "{}", .{&self.un.path});332 try std.fmt.format(out_stream, "{}", .{&self.un.path});
335 },333 },
336 else => unreachable,334 else => unreachable,
337 }335 }
lib/std/os/uefi.zig+3-7
...@@ -5,8 +5,6 @@ pub const protocols = @import("uefi/protocols.zig");...@@ -5,8 +5,6 @@ pub const protocols = @import("uefi/protocols.zig");
5pub const Status = @import("uefi/status.zig").Status;5pub const Status = @import("uefi/status.zig").Status;
6pub const tables = @import("uefi/tables.zig");6pub const tables = @import("uefi/tables.zig");
77
8const fmt = @import("std").fmt;
9
10/// The EFI image's handle that is passed to its entry point.8/// The EFI image's handle that is passed to its entry point.
11pub var handle: Handle = undefined;9pub var handle: Handle = undefined;
1210
...@@ -29,13 +27,11 @@ pub const Guid = extern struct {...@@ -29,13 +27,11 @@ pub const Guid = extern struct {
29 pub fn format(27 pub fn format(
30 self: @This(),28 self: @This(),
31 comptime f: []const u8,29 comptime f: []const u8,
32 options: fmt.FormatOptions,30 options: std.fmt.FormatOptions,
33 context: var,31 out_stream: var,
34 comptime Errors: type,
35 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
36 ) Errors!void {32 ) Errors!void {
37 if (f.len == 0) {33 if (f.len == 0) {
38 return fmt.format(context, Errors, output, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{34 return std.fmt.format(out_stream, "{x:0>8}-{x:0>4}-{x:0>4}-{x:0>2}{x:0>2}-{x:0>12}", .{
39 self.time_low,35 self.time_low,
40 self.time_mid,36 self.time_mid,
41 self.time_high_and_version,37 self.time_high_and_version,
lib/std/progress.zig+1-1
...@@ -190,7 +190,7 @@ pub const Progress = struct {...@@ -190,7 +190,7 @@ pub const Progress = struct {
190 end.* += amt;190 end.* += amt;
191 self.columns_written += amt;191 self.columns_written += amt;
192 } else |err| switch (err) {192 } else |err| switch (err) {
193 error.BufferTooSmall => {193 error.NoSpaceLeft => {
194 self.columns_written += self.output_buffer.len - end.*;194 self.columns_written += self.output_buffer.len - end.*;
195 end.* = self.output_buffer.len;195 end.* = self.output_buffer.len;
196 },196 },
lib/std/zig/cross_target.zig+6-6
...@@ -504,22 +504,22 @@ pub const CrossTarget = struct {...@@ -504,22 +504,22 @@ pub const CrossTarget = struct {
504 if (self.os_version_min != null or self.os_version_max != null) {504 if (self.os_version_min != null or self.os_version_max != null) {
505 switch (self.getOsVersionMin()) {505 switch (self.getOsVersionMin()) {
506 .none => {},506 .none => {},
507 .semver => |v| try result.print(".{}", .{v}),507 .semver => |v| try result.outStream().print(".{}", .{v}),
508 .windows => |v| try result.print(".{}", .{@tagName(v)}),508 .windows => |v| try result.outStream().print(".{}", .{@tagName(v)}),
509 }509 }
510 }510 }
511 if (self.os_version_max) |max| {511 if (self.os_version_max) |max| {
512 switch (max) {512 switch (max) {
513 .none => {},513 .none => {},
514 .semver => |v| try result.print("...{}", .{v}),514 .semver => |v| try result.outStream().print("...{}", .{v}),
515 .windows => |v| try result.print("...{}", .{@tagName(v)}),515 .windows => |v| try result.outStream().print("...{}", .{@tagName(v)}),
516 }516 }
517 }517 }
518518
519 if (self.glibc_version) |v| {519 if (self.glibc_version) |v| {
520 try result.print("-{}.{}", .{ @tagName(self.getAbi()), v });520 try result.outStream().print("-{}.{}", .{ @tagName(self.getAbi()), v });
521 } else if (self.abi) |abi| {521 } else if (self.abi) |abi| {
522 try result.print("-{}", .{@tagName(abi)});522 try result.outStream().print("-{}", .{@tagName(abi)});
523 }523 }
524524
525 return result.toOwnedSlice();525 return result.toOwnedSlice();
src-self-hosted/dep_tokenizer.zig+10-12
...@@ -306,12 +306,12 @@ pub const Tokenizer = struct {...@@ -306,12 +306,12 @@ pub const Tokenizer = struct {
306306
307 fn errorPosition(self: *Tokenizer, position: usize, bytes: []const u8, comptime fmt: []const u8, args: var) Error {307 fn errorPosition(self: *Tokenizer, position: usize, bytes: []const u8, comptime fmt: []const u8, args: var) Error {
308 var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);308 var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
309 std.fmt.format(&buffer, anyerror, std.Buffer.append, fmt, args) catch {};309 try buffer.outStream().print(fmt, args);
310 try buffer.append(" '");310 try buffer.append(" '");
311 var out = makeOutput(std.Buffer.append, &buffer);311 var out = makeOutput(std.Buffer.append, &buffer);
312 try printCharValues(&out, bytes);312 try printCharValues(&out, bytes);
313 try buffer.append("'");313 try buffer.append("'");
314 std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", .{position - (bytes.len - 1)}) catch {};314 try buffer.outStream().print(" at position {}", .{position - (bytes.len - 1)});
315 self.error_text = buffer.toSlice();315 self.error_text = buffer.toSlice();
316 return Error.InvalidInput;316 return Error.InvalidInput;
317 }317 }
...@@ -319,10 +319,9 @@ pub const Tokenizer = struct {...@@ -319,10 +319,9 @@ pub const Tokenizer = struct {
319 fn errorIllegalChar(self: *Tokenizer, position: usize, char: u8, comptime fmt: []const u8, args: var) Error {319 fn errorIllegalChar(self: *Tokenizer, position: usize, char: u8, comptime fmt: []const u8, args: var) Error {
320 var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);320 var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
321 try buffer.append("illegal char ");321 try buffer.append("illegal char ");
322 var out = makeOutput(std.Buffer.append, &buffer);322 try printUnderstandableChar(&buffer, char);
323 try printUnderstandableChar(&out, char);323 try buffer.outStream().print(" at position {}", .{position});
324 std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", .{position}) catch {};324 if (fmt.len != 0) try buffer.outStream().print(": " ++ fmt, args);
325 if (fmt.len != 0) std.fmt.format(&buffer, anyerror, std.Buffer.append, ": " ++ fmt, args) catch {};
326 self.error_text = buffer.toSlice();325 self.error_text = buffer.toSlice();
327 return Error.InvalidInput;326 return Error.InvalidInput;
328 }327 }
...@@ -996,14 +995,13 @@ fn printCharValues(out: var, bytes: []const u8) !void {...@@ -996,14 +995,13 @@ fn printCharValues(out: var, bytes: []const u8) !void {
996 }995 }
997}996}
998997
999fn printUnderstandableChar(out: var, char: u8) !void {998fn printUnderstandableChar(buffer: *std.Buffer, char: u8) !void {
1000 if (!std.ascii.isPrint(char) or char == ' ') {999 if (!std.ascii.isPrint(char) or char == ' ') {
1001 const output = @typeInfo(@TypeOf(out)).Pointer.child.output;1000 try buffer.outStream().print("\\x{X:2}", .{char});
1002 std.fmt.format(out.context, anyerror, output, "\\x{X:2}", .{char}) catch {};
1003 } else {1001 } else {
1004 try out.write("'");1002 try buffer.append("'");
1005 try out.write(&[_]u8{printable_char_tab[char]});1003 try buffer.appendByte(printable_char_tab[char]);
1006 try out.write("'");1004 try buffer.append("'");
1007 }1005 }
1008}1006}
10091007
src-self-hosted/stage2.zig+3-3
...@@ -1019,7 +1019,7 @@ const Stage2Target = extern struct {...@@ -1019,7 +1019,7 @@ const Stage2Target = extern struct {
1019 .macosx,1019 .macosx,
1020 .netbsd,1020 .netbsd,
1021 .openbsd,1021 .openbsd,
1022 => try os_builtin_str_buffer.print(1022 => try os_builtin_str_buffer.outStream().print(
1023 \\ .semver = .{{1023 \\ .semver = .{{
1024 \\ .min = .{{1024 \\ .min = .{{
1025 \\ .major = {},1025 \\ .major = {},
...@@ -1043,7 +1043,7 @@ const Stage2Target = extern struct {...@@ -1043,7 +1043,7 @@ const Stage2Target = extern struct {
1043 target.os.version_range.semver.max.patch,1043 target.os.version_range.semver.max.patch,
1044 }),1044 }),
10451045
1046 .linux => try os_builtin_str_buffer.print(1046 .linux => try os_builtin_str_buffer.outStream().print(
1047 \\ .linux = .{{1047 \\ .linux = .{{
1048 \\ .range = .{{1048 \\ .range = .{{
1049 \\ .min = .{{1049 \\ .min = .{{
...@@ -1078,7 +1078,7 @@ const Stage2Target = extern struct {...@@ -1078,7 +1078,7 @@ const Stage2Target = extern struct {
1078 target.os.version_range.linux.glibc.patch,1078 target.os.version_range.linux.glibc.patch,
1079 }),1079 }),
10801080
1081 .windows => try os_builtin_str_buffer.print(1081 .windows => try os_builtin_str_buffer.outStream().print(
1082 \\ .windows = .{{1082 \\ .windows = .{{
1083 \\ .min = .{},1083 \\ .min = .{},
1084 \\ .max = .{},1084 \\ .max = .{},
src-self-hosted/translate_c.zig+1-6
...@@ -4752,15 +4752,10 @@ fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenInd...@@ -4752,15 +4752,10 @@ fn appendToken(c: *Context, token_id: Token.Id, bytes: []const u8) !ast.TokenInd
4752}4752}
47534753
4754fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: var) !ast.TokenIndex {4754fn appendTokenFmt(c: *Context, token_id: Token.Id, comptime format: []const u8, args: var) !ast.TokenIndex {
4755 const S = struct {
4756 fn callback(context: *Context, bytes: []const u8) error{OutOfMemory}!void {
4757 return context.source_buffer.append(bytes);
4758 }
4759 };
4760 const start_index = c.source_buffer.len();4755 const start_index = c.source_buffer.len();
4761 errdefer c.source_buffer.shrink(start_index);4756 errdefer c.source_buffer.shrink(start_index);
47624757
4763 try std.fmt.format(c, error{OutOfMemory}, S.callback, format, args);4758 try c.source_buffer.outStream().print(format, args);
4764 const end_index = c.source_buffer.len();4759 const end_index = c.source_buffer.len();
4765 const token_index = c.tree.tokens.len;4760 const token_index = c.tree.tokens.len;
4766 const new_token = try c.tree.tokens.addOne();4761 const new_token = try c.tree.tokens.addOne();