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 {
6565 }
6666
6767 pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
68 const countSize = struct {
69 fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
70 size.* += bytes.len;
71 }
72 }.countSize;
73 var size: usize = 0;
74 std.fmt.format(&size, error{}, countSize, format, args) catch |err| switch (err) {};
68 const size = std.math.cast(usize, std.fmt.count(format, args)) catch |err| switch (err) {
69 error.Overflow => return error.OutOfMemory,
70 };
7571 var self = try Buffer.initSize(allocator, size);
7672 assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
7773 return self;
......@@ -154,10 +150,6 @@ pub const Buffer = struct {
154150 mem.copy(u8, self.list.toSlice(), m);
155151 }
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
161153 pub fn outStream(self: *Buffer) std.io.OutStream(*Buffer, error{OutOfMemory}, appendWrite) {
162154 return .{ .context = self };
163155 }
......@@ -216,7 +208,7 @@ test "Buffer.print" {
216208 var buf = try Buffer.init(testing.allocator, "");
217209 defer buf.deinit();
218210
219 try buf.print("Hello {} the {}", .{ 2, "world" });
211 try buf.outStream().print("Hello {} the {}", .{ 2, "world" });
220212 testing.expect(buf.eql("Hello 2 the world"));
221213}
222214
lib/std/builtin.zig+5-7
......@@ -436,19 +436,17 @@ pub const Version = struct {
436436 self: Version,
437437 comptime fmt: []const u8,
438438 options: std.fmt.FormatOptions,
439 context: var,
440 comptime Error: type,
441 comptime output: fn (@TypeOf(context), []const u8) Error!void,
442 ) Error!void {
439 out_stream: var,
440 ) !void {
443441 if (fmt.len == 0) {
444442 if (self.patch == 0) {
445443 if (self.minor == 0) {
446 return std.fmt.format(context, Error, output, "{}", .{self.major});
444 return std.fmt.format(out_stream, "{}", .{self.major});
447445 } else {
448 return std.fmt.format(context, Error, output, "{}.{}", .{ self.major, self.minor });
446 return std.fmt.format(out_stream, "{}.{}", .{ self.major, self.minor });
449447 }
450448 } 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 });
452450 }
453451 } else {
454452 @compileError("Unknown format string: '" ++ fmt ++ "'");
lib/std/fifo.zig+13-3
......@@ -293,8 +293,18 @@ pub fn LinearFifo(
293293
294294 pub usingnamespace if (T == u8)
295295 struct {
296 pub fn print(self: *Self, comptime format: []const u8, args: var) !void {
297 return std.fmt.format(self, error{OutOfMemory}, Self.write, format, args);
296 const OutStream = std.io.OutStream(*Self, Error, appendWrite);
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 };
298308 }
299309 }
300310 else
......@@ -407,7 +417,7 @@ test "LinearFifo(u8, .Dynamic)" {
407417 fifo.shrink(0);
408418
409419 {
410 try fifo.print("{}, {}!", .{ "Hello", "World" });
420 try fifo.outStream().print("{}, {}!", .{ "Hello", "World" });
411421 var result: [30]u8 = undefined;
412422 testing.expectEqualSlices(u8, "Hello, World!", result[0..fifo.read(&result)]);
413423 testing.expectEqual(@as(usize, 0), fifo.readableLength());
lib/std/fmt.zig+224-297
......@@ -69,19 +69,17 @@ fn peekIsAlign(comptime fmt: []const u8) bool {
6969///
7070/// If a formatted user type contains a function of the type
7171/// ```
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!void
72/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void
7373/// ```
7474/// with `?` being the type formatted, this function will be called instead of the default implementation.
7575/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
7676///
7777/// A user type may be a `struct`, `vector`, `union` or `enum` type.
7878pub fn format(
79 context: var,
80 comptime Errors: type,
81 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
79 out_stream: var,
8280 comptime fmt: []const u8,
8381 args: var,
84) Errors!void {
82) !void {
8583 const ArgSetType = u32;
8684 if (@typeInfo(@TypeOf(args)) != .Struct) {
8785 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
......@@ -138,7 +136,7 @@ pub fn format(
138136 .Start => switch (c) {
139137 '{' => {
140138 if (start_index < i) {
141 try output(context, fmt[start_index..i]);
139 try out_stream.writeAll(fmt[start_index..i]);
142140 }
143141
144142 start_index = i;
......@@ -150,7 +148,7 @@ pub fn format(
150148 },
151149 '}' => {
152150 if (start_index < i) {
153 try output(context, fmt[start_index..i]);
151 try out_stream.writeAll(fmt[start_index..i]);
154152 }
155153 state = .CloseBrace;
156154 },
......@@ -185,9 +183,7 @@ pub fn format(
185183 args[arg_to_print],
186184 fmt[0..0],
187185 options,
188 context,
189 Errors,
190 output,
186 out_stream,
191187 default_max_depth,
192188 );
193189
......@@ -218,9 +214,7 @@ pub fn format(
218214 args[arg_to_print],
219215 fmt[specifier_start..i],
220216 options,
221 context,
222 Errors,
223 output,
217 out_stream,
224218 default_max_depth,
225219 );
226220 state = .Start;
......@@ -265,9 +259,7 @@ pub fn format(
265259 args[arg_to_print],
266260 fmt[specifier_start..specifier_end],
267261 options,
268 context,
269 Errors,
270 output,
262 out_stream,
271263 default_max_depth,
272264 );
273265 state = .Start;
......@@ -293,9 +285,7 @@ pub fn format(
293285 args[arg_to_print],
294286 fmt[specifier_start..specifier_end],
295287 options,
296 context,
297 Errors,
298 output,
288 out_stream,
299289 default_max_depth,
300290 );
301291 state = .Start;
......@@ -316,7 +306,7 @@ pub fn format(
316306 }
317307 }
318308 if (start_index < fmt.len) {
319 try output(context, fmt[start_index..]);
309 try out_stream.writeAll(fmt[start_index..]);
320310 }
321311}
322312
......@@ -324,141 +314,131 @@ pub fn formatType(
324314 value: var,
325315 comptime fmt: []const u8,
326316 options: FormatOptions,
327 context: var,
328 comptime Errors: type,
329 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
317 out_stream: var,
330318 max_depth: usize,
331) Errors!void {
319) @TypeOf(out_stream).Error!void {
332320 if (comptime std.mem.eql(u8, fmt, "*")) {
333 try output(context, @typeName(@TypeOf(value).Child));
334 try output(context, "@");
335 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, context, Errors, output);
321 try out_stream.writeAll(@typeName(@TypeOf(value).Child));
322 try out_stream.writeAll("@");
323 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream);
336324 return;
337325 }
338326
339327 const T = @TypeOf(value);
328 if (comptime std.meta.trait.hasFn("format")(T)) {
329 return try value.format(fmt, options, out_stream);
330 }
331
340332 switch (@typeInfo(T)) {
341333 .ComptimeInt, .Int, .Float => {
342 return formatValue(value, fmt, options, context, Errors, output);
334 return formatValue(value, fmt, options, out_stream);
343335 },
344336 .Void => {
345 return output(context, "void");
337 return out_stream.writeAll("void");
346338 },
347339 .Bool => {
348 return output(context, if (value) "true" else "false");
340 return out_stream.writeAll(if (value) "true" else "false");
349341 },
350342 .Optional => {
351343 if (value) |payload| {
352 return formatType(payload, fmt, options, context, Errors, output, max_depth);
344 return formatType(payload, fmt, options, out_stream, max_depth);
353345 } else {
354 return output(context, "null");
346 return out_stream.writeAll("null");
355347 }
356348 },
357349 .ErrorUnion => {
358350 if (value) |payload| {
359 return formatType(payload, fmt, options, context, Errors, output, max_depth);
351 return formatType(payload, fmt, options, out_stream, max_depth);
360352 } else |err| {
361 return formatType(err, fmt, options, context, Errors, output, max_depth);
353 return formatType(err, fmt, options, out_stream, max_depth);
362354 }
363355 },
364356 .ErrorSet => {
365 try output(context, "error.");
366 return output(context, @errorName(value));
357 try out_stream.writeAll("error.");
358 return out_stream.writeAll(@errorName(value));
367359 },
368360 .Enum => |enumInfo| {
369 if (comptime std.meta.trait.hasFn("format")(T)) {
370 return value.format(fmt, options, context, Errors, output);
371 }
372
373 try output(context, @typeName(T));
361 try out_stream.writeAll(@typeName(T));
374362 if (enumInfo.is_exhaustive) {
375 try output(context, ".");
376 try output(context, @tagName(value));
363 try out_stream.writeAll(".");
364 try out_stream.writeAll(@tagName(value));
377365 } else {
378366 // TODO: when @tagName works on exhaustive enums print known enum strings
379 try output(context, "(");
380 try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth);
381 try output(context, ")");
367 try out_stream.writeAll("(");
368 try formatType(@enumToInt(value), fmt, options, out_stream, max_depth);
369 try out_stream.writeAll(")");
382370 }
383371 },
384372 .Union => {
385 if (comptime std.meta.trait.hasFn("format")(T)) {
386 return value.format(fmt, options, context, Errors, output);
387 }
388
389 try output(context, @typeName(T));
373 try out_stream.writeAll(@typeName(T));
390374 if (max_depth == 0) {
391 return output(context, "{ ... }");
375 return out_stream.writeAll("{ ... }");
392376 }
393377 const info = @typeInfo(T).Union;
394378 if (info.tag_type) |UnionTagType| {
395 try output(context, "{ .");
396 try output(context, @tagName(@as(UnionTagType, value)));
397 try output(context, " = ");
379 try out_stream.writeAll("{ .");
380 try out_stream.writeAll(@tagName(@as(UnionTagType, value)));
381 try out_stream.writeAll(" = ");
398382 inline for (info.fields) |u_field| {
399383 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);
401385 }
402386 }
403 try output(context, " }");
387 try out_stream.writeAll(" }");
404388 } else {
405 try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)});
389 try format(out_stream, "@{x}", .{@ptrToInt(&value)});
406390 }
407391 },
408392 .Struct => |StructT| {
409 if (comptime std.meta.trait.hasFn("format")(T)) {
410 return value.format(fmt, options, context, Errors, output);
411 }
412
413 try output(context, @typeName(T));
393 try out_stream.writeAll(@typeName(T));
414394 if (max_depth == 0) {
415 return output(context, "{ ... }");
395 return out_stream.writeAll("{ ... }");
416396 }
417 try output(context, "{");
397 try out_stream.writeAll("{");
418398 inline for (StructT.fields) |f, i| {
419399 if (i == 0) {
420 try output(context, " .");
400 try out_stream.writeAll(" .");
421401 } else {
422 try output(context, ", .");
402 try out_stream.writeAll(", .");
423403 }
424 try output(context, f.name);
425 try output(context, " = ");
426 try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1);
404 try out_stream.writeAll(f.name);
405 try out_stream.writeAll(" = ");
406 try formatType(@field(value, f.name), fmt, options, out_stream, max_depth - 1);
427407 }
428 try output(context, " }");
408 try out_stream.writeAll(" }");
429409 },
430410 .Pointer => |ptr_info| switch (ptr_info.size) {
431411 .One => switch (@typeInfo(ptr_info.child)) {
432412 .Array => |info| {
433413 if (info.child == u8) {
434 return formatText(value, fmt, options, context, Errors, output);
414 return formatText(value, fmt, options, out_stream);
435415 }
436 return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
416 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
437417 },
438418 .Enum, .Union, .Struct => {
439 return formatType(value.*, fmt, options, context, Errors, output, max_depth);
419 return formatType(value.*, fmt, options, out_stream, max_depth);
440420 },
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) }),
442422 },
443423 .Many, .C => {
444424 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);
446426 }
447427 if (ptr_info.child == u8) {
448428 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);
450430 }
451431 }
452 return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
432 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
453433 },
454434 .Slice => {
455435 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);
457437 }
458438 if (ptr_info.child == u8) {
459 return formatText(value, fmt, options, context, Errors, output);
439 return formatText(value, fmt, options, out_stream);
460440 }
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) });
462442 },
463443 },
464444 .Array => |info| {
......@@ -473,27 +453,27 @@ pub fn formatType(
473453 .sentinel = null,
474454 },
475455 });
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);
477457 },
478458 .Vector => {
479459 const len = @typeInfo(T).Vector.len;
480 try output(context, "{ ");
460 try out_stream.writeAll("{ ");
481461 var i: usize = 0;
482462 while (i < len) : (i += 1) {
483 try formatValue(value[i], fmt, options, context, Errors, output);
463 try formatValue(value[i], fmt, options, out_stream);
484464 if (i < len - 1) {
485 try output(context, ", ");
465 try out_stream.writeAll(", ");
486466 }
487467 }
488 try output(context, " }");
468 try out_stream.writeAll(" }");
489469 },
490470 .Fn => {
491 return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
471 return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
492472 },
493 .Type => return output(context, @typeName(T)),
473 .Type => return out_stream.writeAll(@typeName(T)),
494474 .EnumLiteral => {
495475 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);
497477 },
498478 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
499479 }
......@@ -503,21 +483,19 @@ fn formatValue(
503483 value: var,
504484 comptime fmt: []const u8,
505485 options: FormatOptions,
506 context: var,
507 comptime Errors: type,
508 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
509) Errors!void {
486 out_stream: var,
487) !void {
510488 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);
512490 } 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);
514492 }
515493
516494 const T = @TypeOf(value);
517495 switch (@typeInfo(T)) {
518 .Float => return formatFloatValue(value, fmt, options, context, Errors, output),
519 .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),
520 .Bool => return output(context, if (value) "true" else "false"),
496 .Float => return formatFloatValue(value, fmt, options, out_stream),
497 .Int, .ComptimeInt => return formatIntValue(value, fmt, options, out_stream),
498 .Bool => return out_stream.writeAll(if (value) "true" else "false"),
521499 else => comptime unreachable,
522500 }
523501}
......@@ -526,10 +504,8 @@ pub fn formatIntValue(
526504 value: var,
527505 comptime fmt: []const u8,
528506 options: FormatOptions,
529 context: var,
530 comptime Errors: type,
531 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
532) Errors!void {
507 out_stream: var,
508) !void {
533509 comptime var radix = 10;
534510 comptime var uppercase = false;
535511
......@@ -544,7 +520,7 @@ pub fn formatIntValue(
544520 uppercase = false;
545521 } else if (comptime std.mem.eql(u8, fmt, "c")) {
546522 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);
548524 } else {
549525 @compileError("Cannot print integer that is larger than 8 bits as a ascii");
550526 }
......@@ -561,21 +537,19 @@ pub fn formatIntValue(
561537 @compileError("Unknown format string: '" ++ fmt ++ "'");
562538 }
563539
564 return formatInt(int_value, radix, uppercase, options, context, Errors, output);
540 return formatInt(int_value, radix, uppercase, options, out_stream);
565541}
566542
567543fn formatFloatValue(
568544 value: var,
569545 comptime fmt: []const u8,
570546 options: FormatOptions,
571 context: var,
572 comptime Errors: type,
573 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
574) Errors!void {
547 out_stream: var,
548) !void {
575549 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);
577551 } else if (comptime std.mem.eql(u8, fmt, "d")) {
578 return formatFloatDecimal(value, options, context, Errors, output);
552 return formatFloatDecimal(value, options, out_stream);
579553 } else {
580554 @compileError("Unknown format string: '" ++ fmt ++ "'");
581555 }
......@@ -585,17 +559,15 @@ pub fn formatText(
585559 bytes: []const u8,
586560 comptime fmt: []const u8,
587561 options: FormatOptions,
588 context: var,
589 comptime Errors: type,
590 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
591) Errors!void {
562 out_stream: var,
563) !void {
592564 if (fmt.len == 0) {
593 return output(context, bytes);
565 return out_stream.writeAll(bytes);
594566 } else if (comptime std.mem.eql(u8, fmt, "s")) {
595 return formatBuf(bytes, options, context, Errors, output);
567 return formatBuf(bytes, options, out_stream);
596568 } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
597569 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);
599571 }
600572 return;
601573 } else {
......@@ -606,27 +578,23 @@ pub fn formatText(
606578pub fn formatAsciiChar(
607579 c: u8,
608580 options: FormatOptions,
609 context: var,
610 comptime Errors: type,
611 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
612) Errors!void {
613 return output(context, @as(*const [1]u8, &c)[0..]);
581 out_stream: var,
582) !void {
583 return out_stream.writeAll(@as(*const [1]u8, &c));
614584}
615585
616586pub fn formatBuf(
617587 buf: []const u8,
618588 options: FormatOptions,
619 context: var,
620 comptime Errors: type,
621 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
622) Errors!void {
623 try output(context, buf);
589 out_stream: var,
590) !void {
591 try out_stream.writeAll(buf);
624592
625593 const width = options.width orelse 0;
626594 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};
628596 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);
630598 }
631599}
632600
......@@ -636,40 +604,38 @@ pub fn formatBuf(
636604pub fn formatFloatScientific(
637605 value: var,
638606 options: FormatOptions,
639 context: var,
640 comptime Errors: type,
641 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
642) Errors!void {
607 out_stream: var,
608) !void {
643609 var x = @floatCast(f64, value);
644610
645611 // Errol doesn't handle these special cases.
646612 if (math.signbit(x)) {
647 try output(context, "-");
613 try out_stream.writeAll("-");
648614 x = -x;
649615 }
650616
651617 if (math.isNan(x)) {
652 return output(context, "nan");
618 return out_stream.writeAll("nan");
653619 }
654620 if (math.isPositiveInf(x)) {
655 return output(context, "inf");
621 return out_stream.writeAll("inf");
656622 }
657623 if (x == 0.0) {
658 try output(context, "0");
624 try out_stream.writeAll("0");
659625
660626 if (options.precision) |precision| {
661627 if (precision != 0) {
662 try output(context, ".");
628 try out_stream.writeAll(".");
663629 var i: usize = 0;
664630 while (i < precision) : (i += 1) {
665 try output(context, "0");
631 try out_stream.writeAll("0");
666632 }
667633 }
668634 } else {
669 try output(context, ".0");
635 try out_stream.writeAll(".0");
670636 }
671637
672 try output(context, "e+00");
638 try out_stream.writeAll("e+00");
673639 return;
674640 }
675641
......@@ -679,50 +645,50 @@ pub fn formatFloatScientific(
679645 if (options.precision) |precision| {
680646 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
684650 // {e0} case prints no `.`
685651 if (precision != 0) {
686 try output(context, ".");
652 try out_stream.writeAll(".");
687653
688654 var printed: usize = 0;
689655 if (float_decimal.digits.len > 1) {
690656 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]);
692658 printed += num_digits - 1;
693659 }
694660
695661 while (printed < precision) : (printed += 1) {
696 try output(context, "0");
662 try out_stream.writeAll("0");
697663 }
698664 }
699665 } else {
700 try output(context, float_decimal.digits[0..1]);
701 try output(context, ".");
666 try out_stream.writeAll(float_decimal.digits[0..1]);
667 try out_stream.writeAll(".");
702668 if (float_decimal.digits.len > 1) {
703669 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]);
706672 } else {
707 try output(context, "0");
673 try out_stream.writeAll("0");
708674 }
709675 }
710676
711 try output(context, "e");
677 try out_stream.writeAll("e");
712678 const exp = float_decimal.exp - 1;
713679
714680 if (exp >= 0) {
715 try output(context, "+");
681 try out_stream.writeAll("+");
716682 if (exp > -10 and exp < 10) {
717 try output(context, "0");
683 try out_stream.writeAll("0");
718684 }
719 try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
685 try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
720686 } else {
721 try output(context, "-");
687 try out_stream.writeAll("-");
722688 if (exp > -10 and exp < 10) {
723 try output(context, "0");
689 try out_stream.writeAll("0");
724690 }
725 try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);
691 try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
726692 }
727693}
728694
......@@ -731,36 +697,34 @@ pub fn formatFloatScientific(
731697pub fn formatFloatDecimal(
732698 value: var,
733699 options: FormatOptions,
734 context: var,
735 comptime Errors: type,
736 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
737) Errors!void {
700 out_stream: var,
701) !void {
738702 var x = @as(f64, value);
739703
740704 // Errol doesn't handle these special cases.
741705 if (math.signbit(x)) {
742 try output(context, "-");
706 try out_stream.writeAll("-");
743707 x = -x;
744708 }
745709
746710 if (math.isNan(x)) {
747 return output(context, "nan");
711 return out_stream.writeAll("nan");
748712 }
749713 if (math.isPositiveInf(x)) {
750 return output(context, "inf");
714 return out_stream.writeAll("inf");
751715 }
752716 if (x == 0.0) {
753 try output(context, "0");
717 try out_stream.writeAll("0");
754718
755719 if (options.precision) |precision| {
756720 if (precision != 0) {
757 try output(context, ".");
721 try out_stream.writeAll(".");
758722 var i: usize = 0;
759723 while (i < precision) : (i += 1) {
760 try output(context, "0");
724 try out_stream.writeAll("0");
761725 }
762726 } else {
763 try output(context, ".0");
727 try out_stream.writeAll(".0");
764728 }
765729 }
766730
......@@ -782,14 +746,14 @@ pub fn formatFloatDecimal(
782746
783747 if (num_digits_whole > 0) {
784748 // 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
787751 var i = num_digits_whole_no_pad;
788752 while (i < num_digits_whole) : (i += 1) {
789 try output(context, "0");
753 try out_stream.writeAll("0");
790754 }
791755 } else {
792 try output(context, "0");
756 try out_stream.writeAll("0");
793757 }
794758
795759 // {.0} special case doesn't want a trailing '.'
......@@ -797,7 +761,7 @@ pub fn formatFloatDecimal(
797761 return;
798762 }
799763
800 try output(context, ".");
764 try out_stream.writeAll(".");
801765
802766 // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.
803767 var printed: usize = 0;
......@@ -809,7 +773,7 @@ pub fn formatFloatDecimal(
809773
810774 var i: usize = 0;
811775 while (i < zeros_to_print) : (i += 1) {
812 try output(context, "0");
776 try out_stream.writeAll("0");
813777 printed += 1;
814778 }
815779
......@@ -821,14 +785,14 @@ pub fn formatFloatDecimal(
821785 // Remaining fractional portion, zero-padding if insufficient.
822786 assert(precision >= printed);
823787 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]);
825789 return;
826790 } 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..]);
828792 printed += float_decimal.digits.len - num_digits_whole_no_pad;
829793
830794 while (printed < precision) : (printed += 1) {
831 try output(context, "0");
795 try out_stream.writeAll("0");
832796 }
833797 }
834798 } else {
......@@ -840,14 +804,14 @@ pub fn formatFloatDecimal(
840804
841805 if (num_digits_whole > 0) {
842806 // 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
845809 var i = num_digits_whole_no_pad;
846810 while (i < num_digits_whole) : (i += 1) {
847 try output(context, "0");
811 try out_stream.writeAll("0");
848812 }
849813 } else {
850 try output(context, "0");
814 try out_stream.writeAll("0");
851815 }
852816
853817 // Omit `.` if no fractional portion
......@@ -855,7 +819,7 @@ pub fn formatFloatDecimal(
855819 return;
856820 }
857821
858 try output(context, ".");
822 try out_stream.writeAll(".");
859823
860824 // Zero-fill until we reach significant digits or run out of precision.
861825 if (float_decimal.exp < 0) {
......@@ -863,11 +827,11 @@ pub fn formatFloatDecimal(
863827
864828 var i: usize = 0;
865829 while (i < zero_digit_count) : (i += 1) {
866 try output(context, "0");
830 try out_stream.writeAll("0");
867831 }
868832 }
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..]);
871835 }
872836}
873837
......@@ -875,12 +839,10 @@ pub fn formatBytes(
875839 value: var,
876840 options: FormatOptions,
877841 comptime radix: usize,
878 context: var,
879 comptime Errors: type,
880 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
881) Errors!void {
842 out_stream: var,
843) !void {
882844 if (value == 0) {
883 return output(context, "0B");
845 return out_stream.writeAll("0B");
884846 }
885847
886848 const mags_si = " kMGTPEZY";
......@@ -897,10 +859,10 @@ pub fn formatBytes(
897859 else => unreachable,
898860 };
899861
900 try formatFloatDecimal(new_value, options, context, Errors, output);
862 try formatFloatDecimal(new_value, options, out_stream);
901863
902864 if (suffix == ' ') {
903 return output(context, "B");
865 return out_stream.writeAll("B");
904866 }
905867
906868 const buf = switch (radix) {
......@@ -908,7 +870,7 @@ pub fn formatBytes(
908870 1024 => &[_]u8{ suffix, 'i', 'B' },
909871 else => unreachable,
910872 };
911 return output(context, buf);
873 return out_stream.writeAll(buf);
912874}
913875
914876pub fn formatInt(
......@@ -916,10 +878,8 @@ pub fn formatInt(
916878 base: u8,
917879 uppercase: bool,
918880 options: FormatOptions,
919 context: var,
920 comptime Errors: type,
921 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
922) Errors!void {
881 out_stream: var,
882) !void {
923883 const int_value = if (@TypeOf(value) == comptime_int) blk: {
924884 const Int = math.IntFittingRange(value, value);
925885 break :blk @as(Int, value);
......@@ -927,9 +887,9 @@ pub fn formatInt(
927887 value;
928888
929889 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);
931891 } else {
932 return formatIntUnsigned(int_value, base, uppercase, options, context, Errors, output);
892 return formatIntUnsigned(int_value, base, uppercase, options, out_stream);
933893 }
934894}
935895
......@@ -938,10 +898,8 @@ fn formatIntSigned(
938898 base: u8,
939899 uppercase: bool,
940900 options: FormatOptions,
941 context: var,
942 comptime Errors: type,
943 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
944) Errors!void {
901 out_stream: var,
902) !void {
945903 const new_options = FormatOptions{
946904 .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,
947905 .precision = options.precision,
......@@ -950,15 +908,15 @@ fn formatIntSigned(
950908 const bit_count = @typeInfo(@TypeOf(value)).Int.bits;
951909 const Uint = std.meta.IntType(false, bit_count);
952910 if (value < 0) {
953 try output(context, "-");
911 try out_stream.writeAll("-");
954912 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);
956914 } 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);
958916 } else {
959 try output(context, "+");
917 try out_stream.writeAll("+");
960918 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);
962920 }
963921}
964922
......@@ -967,10 +925,8 @@ fn formatIntUnsigned(
967925 base: u8,
968926 uppercase: bool,
969927 options: FormatOptions,
970 context: var,
971 comptime Errors: type,
972 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
973) Errors!void {
928 out_stream: var,
929) !void {
974930 assert(base >= 2);
975931 var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
976932 const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
......@@ -994,34 +950,23 @@ fn formatIntUnsigned(
994950 const zero_byte: u8 = options.fill;
995951 var leftover_padding = padding - index;
996952 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..]);
998954 leftover_padding -= 1;
999955 if (leftover_padding == 0) break;
1000956 }
1001957 mem.set(u8, buf[0..index], options.fill);
1002 return output(context, &buf);
958 return out_stream.writeAll(&buf);
1003959 } else {
1004960 const padded_buf = buf[index - padding ..];
1005961 mem.set(u8, padded_buf[0..padding], options.fill);
1006 return output(context, padded_buf);
962 return out_stream.writeAll(padded_buf);
1007963 }
1008964}
1009965
1010966pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {
1011 var context = FormatIntBuf{
1012 .out_buf = out_buf,
1013 .index = 0,
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;
967 var fbs = std.io.fixedBufferStream(out_buf);
968 formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable;
969 return fbs.pos;
1025970}
1026971
1027972pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
......@@ -1121,44 +1066,36 @@ fn digitToChar(digit: u8, uppercase: bool) u8 {
11211066 };
11221067}
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
11371069pub const BufPrintError = error{
11381070 /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
1139 BufferTooSmall,
1071 NoSpaceLeft,
11401072};
11411073pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
1142 var context = BufPrintContext{ .remaining = buf };
1143 try format(&context, BufPrintError, bufPrintWrite, fmt, args);
1144 return buf[0 .. buf.len - context.remaining.len];
1074 var fbs = std.io.fixedBufferStream(buf);
1075 try format(fbs.outStream(), fmt, args);
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;
11451084}
11461085
11471086pub const AllocPrintError = error{OutOfMemory};
11481087
11491088pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
1150 var size: usize = 0;
1151 format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
1089 const size = math.cast(usize, count(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 };
11521093 const buf = try allocator.alloc(u8, size);
11531094 return bufPrint(buf, fmt, args) catch |err| switch (err) {
1154 error.BufferTooSmall => unreachable, // we just counted the size above
1095 error.NoSpaceLeft => unreachable, // we just counted the size above
11551096 };
11561097}
11571098
1158fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
1159 size.* += bytes.len;
1160}
1161
11621099pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
11631100 const result = try allocPrint(allocator, fmt ++ "\x00", args);
11641101 return result[0 .. result.len - 1 :0];
......@@ -1251,20 +1188,17 @@ test "int.padded" {
12511188test "buffer" {
12521189 {
12531190 var buf1: [32]u8 = undefined;
1254 var context = BufPrintContext{ .remaining = buf1[0..] };
1255 try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1256 var res = buf1[0 .. buf1.len - context.remaining.len];
1257 std.testing.expect(mem.eql(u8, res, "1234"));
1258
1259 context = BufPrintContext{ .remaining = buf1[0..] };
1260 try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1261 res = buf1[0 .. buf1.len - context.remaining.len];
1262 std.testing.expect(mem.eql(u8, res, "a"));
1263
1264 context = BufPrintContext{ .remaining = buf1[0..] };
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"));
1191 var fbs = std.io.fixedBufferStream(&buf1);
1192 try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
1193 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234"));
1194
1195 fbs.reset();
1196 try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
1197 std.testing.expect(mem.eql(u8, fbs.getWritten(), "a"));
1198
1199 fbs.reset();
1200 try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
1201 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100"));
12681202 }
12691203}
12701204
......@@ -1449,14 +1383,12 @@ test "custom" {
14491383 self: SelfType,
14501384 comptime fmt: []const u8,
14511385 options: FormatOptions,
1452 context: var,
1453 comptime Errors: type,
1454 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1455 ) Errors!void {
1386 out_stream: var,
1387 ) !void {
14561388 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 });
14581390 } 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 });
14601392 } else {
14611393 @compileError("Unknown format character: '" ++ fmt ++ "'");
14621394 }
......@@ -1640,10 +1572,10 @@ test "hexToBytes" {
16401572test "formatIntValue with comptime_int" {
16411573 const value: comptime_int = 123456789123456789;
16421574
1643 var buf = std.ArrayList(u8).init(std.testing.allocator);
1644 defer buf.deinit();
1645 try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);
1646 std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));
1575 var buf: [20]u8 = undefined;
1576 var fbs = std.io.fixedBufferStream(&buf);
1577 try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
1578 std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789"));
16471579}
16481580
16491581test "formatType max_depth" {
......@@ -1656,12 +1588,10 @@ test "formatType max_depth" {
16561588 self: SelfType,
16571589 comptime fmt: []const u8,
16581590 options: FormatOptions,
1659 context: var,
1660 comptime Errors: type,
1661 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1662 ) Errors!void {
1591 out_stream: var,
1592 ) !void {
16631593 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 });
16651595 } else {
16661596 @compileError("Unknown format string: '" ++ fmt ++ "'");
16671597 }
......@@ -1695,25 +1625,22 @@ test "formatType max_depth" {
16951625 inst.a = &inst;
16961626 inst.tu.ptr = &inst.tu;
16971627
1698 var buf0 = std.ArrayList(u8).init(std.testing.allocator);
1699 defer buf0.deinit();
1700 try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);
1701 std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
1702
1703 var buf1 = std.ArrayList(u8).init(std.testing.allocator);
1704 defer buf1.deinit();
1705 try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);
1706 std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
1707
1708 var buf2 = std.ArrayList(u8).init(std.testing.allocator);
1709 defer buf2.deinit();
1710 try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);
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) }"));
1712
1713 var buf3 = std.ArrayList(u8).init(std.testing.allocator);
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) }"));
1628 var buf: [1000]u8 = undefined;
1629 var fbs = std.io.fixedBufferStream(&buf);
1630 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0);
1631 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }"));
1632
1633 fbs.reset();
1634 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1);
1635 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
1636
1637 fbs.reset();
1638 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2);
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) }"));
1640
1641 fbs.reset();
1642 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3);
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) }"));
17171644}
17181645
17191646test "positional" {
lib/std/http/headers.zig+6-8
......@@ -350,15 +350,13 @@ pub const Headers = struct {
350350 self: Self,
351351 comptime fmt: []const u8,
352352 options: std.fmt.FormatOptions,
353 context: var,
354 comptime Errors: type,
355 output: fn (@TypeOf(context), []const u8) Errors!void,
356 ) Errors!void {
353 out_stream: var,
354 ) !void {
357355 for (self.toSlice()) |entry| {
358 try output(context, entry.name);
359 try output(context, ": ");
360 try output(context, entry.value);
361 try output(context, "\n");
356 try out_stream.writeAll(entry.name);
357 try out_stream.writeAll(": ");
358 try out_stream.writeAll(entry.value);
359 try out_stream.writeAll("\n");
362360 }
363361 }
364362};
lib/std/io/fixed_buffer_stream.zig+1-1
......@@ -103,7 +103,7 @@ pub fn FixedBufferStream(comptime Buffer: type) type {
103103 return self.pos;
104104 }
105105
106 pub fn getWritten(self: Self) []const u8 {
106 pub fn getWritten(self: Self) Buffer {
107107 return self.buffer[0..self.pos];
108108 }
109109
lib/std/io/out_stream.zig+1-1
......@@ -25,7 +25,7 @@ pub fn OutStream(
2525 }
2626
2727 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);
2929 }
3030
3131 pub fn writeByte(self: Self, byte: u8) Error!void {
lib/std/json.zig+72-62
......@@ -2252,45 +2252,43 @@ pub const StringifyOptions = struct {
22522252pub fn stringify(
22532253 value: var,
22542254 options: StringifyOptions,
2255 context: var,
2256 comptime Errors: type,
2257 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
2258) Errors!void {
2255 out_stream: var,
2256) !void {
22592257 const T = @TypeOf(value);
22602258 switch (@typeInfo(T)) {
22612259 .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);
22632261 },
22642262 .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);
22662264 },
22672265 .Bool => {
2268 return output(context, if (value) "true" else "false");
2266 return out_stream.writeAll(if (value) "true" else "false");
22692267 },
22702268 .Optional => {
22712269 if (value) |payload| {
2272 return try stringify(payload, options, context, Errors, output);
2270 return try stringify(payload, options, out_stream);
22732271 } else {
2274 return output(context, "null");
2272 return out_stream.writeAll("null");
22752273 }
22762274 },
22772275 .Enum => {
22782276 if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
2279 return value.jsonStringify(options, context, Errors, output);
2277 return value.jsonStringify(options, out_stream);
22802278 }
22812279
22822280 @compileError("Unable to stringify enum '" ++ @typeName(T) ++ "'");
22832281 },
22842282 .Union => {
22852283 if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
2286 return value.jsonStringify(options, context, Errors, output);
2284 return value.jsonStringify(options, out_stream);
22872285 }
22882286
22892287 const info = @typeInfo(T).Union;
22902288 if (info.tag_type) |UnionTagType| {
22912289 inline for (info.fields) |u_field| {
22922290 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);
22942292 }
22952293 }
22962294 } else {
......@@ -2299,10 +2297,10 @@ pub fn stringify(
22992297 },
23002298 .Struct => |S| {
23012299 if (comptime std.meta.trait.hasFn("jsonStringify")(T)) {
2302 return value.jsonStringify(options, context, Errors, output);
2300 return value.jsonStringify(options, out_stream);
23032301 }
23042302
2305 try output(context, "{");
2303 try out_stream.writeAll("{");
23062304 comptime var field_output = false;
23072305 inline for (S.fields) |Field, field_i| {
23082306 // don't include void fields
......@@ -2311,39 +2309,39 @@ pub fn stringify(
23112309 if (!field_output) {
23122310 field_output = true;
23132311 } else {
2314 try output(context, ",");
2312 try out_stream.writeAll(",");
23152313 }
23162314
2317 try stringify(Field.name, options, context, Errors, output);
2318 try output(context, ":");
2319 try stringify(@field(value, Field.name), options, context, Errors, output);
2315 try stringify(Field.name, options, out_stream);
2316 try out_stream.writeAll(":");
2317 try stringify(@field(value, Field.name), options, out_stream);
23202318 }
2321 try output(context, "}");
2319 try out_stream.writeAll("}");
23222320 return;
23232321 },
23242322 .Pointer => |ptr_info| switch (ptr_info.size) {
23252323 .One => {
23262324 // TODO: avoid loops?
2327 return try stringify(value.*, options, context, Errors, output);
2325 return try stringify(value.*, options, out_stream);
23282326 },
23292327 // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
23302328 .Slice => {
23312329 if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) {
2332 try output(context, "\"");
2330 try out_stream.writeAll("\"");
23332331 var i: usize = 0;
23342332 while (i < value.len) : (i += 1) {
23352333 switch (value[i]) {
23362334 // 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]),
23382336 // control characters with short escapes
2339 '\\' => try output(context, "\\\\"),
2340 '\"' => try output(context, "\\\""),
2341 '/' => try output(context, "\\/"),
2342 0x8 => try output(context, "\\b"),
2343 0xC => try output(context, "\\f"),
2344 '\n' => try output(context, "\\n"),
2345 '\r' => try output(context, "\\r"),
2346 '\t' => try output(context, "\\t"),
2337 '\\' => try out_stream.writeAll("\\\\"),
2338 '\"' => try out_stream.writeAll("\\\""),
2339 '/' => try out_stream.writeAll("\\/"),
2340 0x8 => try out_stream.writeAll("\\b"),
2341 0xC => try out_stream.writeAll("\\f"),
2342 '\n' => try out_stream.writeAll("\\n"),
2343 '\r' => try out_stream.writeAll("\\r"),
2344 '\t' => try out_stream.writeAll("\\t"),
23472345 else => {
23482346 const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable;
23492347 const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable;
......@@ -2351,40 +2349,40 @@ pub fn stringify(
23512349 // If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),
23522350 // then it may be represented as a six-character sequence: a reverse solidus, followed
23532351 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
2354 try output(context, "\\u");
2355 try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
2352 try out_stream.writeAll("\\u");
2353 try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
23562354 } else {
23572355 // To escape an extended character that is not in the Basic Multilingual Plane,
23582356 // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.
23592357 const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;
23602358 const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;
2361 try output(context, "\\u");
2362 try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
2363 try output(context, "\\u");
2364 try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, context, Errors, output);
2359 try out_stream.writeAll("\\u");
2360 try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
2361 try out_stream.writeAll("\\u");
2362 try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
23652363 }
23662364 i += ulen - 1;
23672365 },
23682366 }
23692367 }
2370 try output(context, "\"");
2368 try out_stream.writeAll("\"");
23712369 return;
23722370 }
23732371
2374 try output(context, "[");
2372 try out_stream.writeAll("[");
23752373 for (value) |x, i| {
23762374 if (i != 0) {
2377 try output(context, ",");
2375 try out_stream.writeAll(",");
23782376 }
2379 try stringify(x, options, context, Errors, output);
2377 try stringify(x, options, out_stream);
23802378 }
2381 try output(context, "]");
2379 try out_stream.writeAll("]");
23822380 return;
23832381 },
23842382 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
23852383 },
23862384 .Array => |info| {
2387 return try stringify(value[0..], options, context, Errors, output);
2385 return try stringify(value[0..], options, out_stream);
23882386 },
23892387 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
23902388 }
......@@ -2392,10 +2390,26 @@ pub fn stringify(
23922390}
23932391
23942392fn 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
23962401 expected_remaining: []const u8,
2397 fn testStringifyWrite(context: *@This(), bytes: []const u8) !void {
2398 if (context.expected_remaining.len < bytes.len) {
2402
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) {
23992413 std.debug.warn(
24002414 \\====== expected this output: =========
24012415 \\{}
......@@ -2403,12 +2417,12 @@ fn teststringify(expected: []const u8, value: var) !void {
24032417 \\{}
24042418 \\======================================
24052419 , .{
2406 context.expected_remaining,
2420 self.expected_remaining,
24072421 bytes,
24082422 });
24092423 return error.TooMuchData;
24102424 }
2411 if (!mem.eql(u8, context.expected_remaining[0..bytes.len], bytes)) {
2425 if (!mem.eql(u8, self.expected_remaining[0..bytes.len], bytes)) {
24122426 std.debug.warn(
24132427 \\====== expected this output: =========
24142428 \\{}
......@@ -2416,21 +2430,19 @@ fn teststringify(expected: []const u8, value: var) !void {
24162430 \\{}
24172431 \\======================================
24182432 , .{
2419 context.expected_remaining[0..bytes.len],
2433 self.expected_remaining[0..bytes.len],
24202434 bytes,
24212435 });
24222436 return error.DifferentData;
24232437 }
2424 context.expected_remaining = context.expected_remaining[bytes.len..];
2438 self.expected_remaining = self.expected_remaining[bytes.len..];
2439 return bytes.len;
24252440 }
24262441 };
2427 var buf: [100]u8 = undefined;
2428 var context = TestStringifyContext{ .expected_remaining = expected };
2429 try stringify(value, StringifyOptions{}, &context, error{
2430 TooMuchData,
2431 DifferentData,
2432 }, TestStringifyContext.testStringifyWrite);
2433 if (context.expected_remaining.len > 0) return error.NotEnoughData;
2442
2443 var vos = ValidationOutStream.init(expected);
2444 try stringify(value, StringifyOptions{}, vos.outStream());
2445 if (vos.expected_remaining.len > 0) return error.NotEnoughData;
24342446}
24352447
24362448test "stringify basic types" {
......@@ -2498,13 +2510,11 @@ test "stringify struct with custom stringifier" {
24982510 pub fn jsonStringify(
24992511 value: Self,
25002512 options: StringifyOptions,
2501 context: var,
2502 comptime Errors: type,
2503 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
2513 out_stream: var,
25042514 ) !void {
2505 try output(context, "[\"something special\",");
2506 try stringify(42, options, context, Errors, output);
2507 try output(context, "]");
2515 try out_stream.writeAll("[\"something special\",");
2516 try stringify(42, options, out_stream);
2517 try out_stream.writeAll("]");
25082518 }
25092519 }{ .foo = 42 });
25102520}
lib/std/math/big/int.zig+2-4
......@@ -519,16 +519,14 @@ pub const Int = struct {
519519 self: Int,
520520 comptime fmt: []const u8,
521521 options: std.fmt.FormatOptions,
522 context: var,
523 comptime FmtError: type,
524 output: fn (@TypeOf(context), []const u8) FmtError!void,
522 out_stream: var,
525523 ) FmtError!void {
526524 self.assertWritable();
527525 // TODO look at fmt and support other bases
528526 // TODO support read-only fixed integers
529527 const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
530528 defer self.allocator.?.free(str);
531 return output(context, str);
529 return out_stream.print(str);
532530 }
533531
534532 /// 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 {
269269 self: Address,
270270 comptime fmt: []const u8,
271271 options: std.fmt.FormatOptions,
272 context: var,
273 comptime Errors: type,
274 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
272 out_stream: var,
275273 ) !void {
276274 switch (self.any.family) {
277275 os.AF_INET => {
278276 const port = mem.bigToNative(u16, self.in.port);
279277 const bytes = @ptrCast(*const [4]u8, &self.in.addr);
280 try std.fmt.format(context, Errors, output, "{}.{}.{}.{}:{}", .{
278 try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
281279 bytes[0],
282280 bytes[1],
283281 bytes[2],
......@@ -288,7 +286,7 @@ pub const Address = extern union {
288286 os.AF_INET6 => {
289287 const port = mem.bigToNative(u16, self.in6.port);
290288 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:{}.{}.{}.{}]:{}", .{
292290 self.in6.addr[12],
293291 self.in6.addr[13],
294292 self.in6.addr[14],
......@@ -308,30 +306,30 @@ pub const Address = extern union {
308306 break :blk buf;
309307 },
310308 };
311 try output(context, "[");
309 try out_stream.writeAll("[");
312310 var i: usize = 0;
313311 var abbrv = false;
314312 while (i < native_endian_parts.len) : (i += 1) {
315313 if (native_endian_parts[i] == 0) {
316314 if (!abbrv) {
317 try output(context, if (i == 0) "::" else ":");
315 try out_stream.writeAll(if (i == 0) "::" else ":");
318316 abbrv = true;
319317 }
320318 continue;
321319 }
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]});
323321 if (i != native_endian_parts.len - 1) {
324 try output(context, ":");
322 try out_stream.writeAll(":");
325323 }
326324 }
327 try std.fmt.format(context, Errors, output, "]:{}", .{port});
325 try std.fmt.format(out_stream, "]:{}", .{port});
328326 },
329327 os.AF_UNIX => {
330328 if (!has_unix_sockets) {
331329 unreachable;
332330 }
333331
334 try std.fmt.format(context, Errors, output, "{}", .{&self.un.path});
332 try std.fmt.format(out_stream, "{}", .{&self.un.path});
335333 },
336334 else => unreachable,
337335 }
lib/std/os/uefi.zig+3-7
......@@ -5,8 +5,6 @@ pub const protocols = @import("uefi/protocols.zig");
55pub const Status = @import("uefi/status.zig").Status;
66pub const tables = @import("uefi/tables.zig");
77
8const fmt = @import("std").fmt;
9
108/// The EFI image's handle that is passed to its entry point.
119pub var handle: Handle = undefined;
1210
......@@ -29,13 +27,11 @@ pub const Guid = extern struct {
2927 pub fn format(
3028 self: @This(),
3129 comptime f: []const u8,
32 options: fmt.FormatOptions,
33 context: var,
34 comptime Errors: type,
35 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
30 options: std.fmt.FormatOptions,
31 out_stream: var,
3632 ) Errors!void {
3733 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}", .{
3935 self.time_low,
4036 self.time_mid,
4137 self.time_high_and_version,
lib/std/progress.zig+1-1
......@@ -190,7 +190,7 @@ pub const Progress = struct {
190190 end.* += amt;
191191 self.columns_written += amt;
192192 } else |err| switch (err) {
193 error.BufferTooSmall => {
193 error.NoSpaceLeft => {
194194 self.columns_written += self.output_buffer.len - end.*;
195195 end.* = self.output_buffer.len;
196196 },
lib/std/zig/cross_target.zig+6-6
......@@ -504,22 +504,22 @@ pub const CrossTarget = struct {
504504 if (self.os_version_min != null or self.os_version_max != null) {
505505 switch (self.getOsVersionMin()) {
506506 .none => {},
507 .semver => |v| try result.print(".{}", .{v}),
508 .windows => |v| try result.print(".{}", .{@tagName(v)}),
507 .semver => |v| try result.outStream().print(".{}", .{v}),
508 .windows => |v| try result.outStream().print(".{}", .{@tagName(v)}),
509509 }
510510 }
511511 if (self.os_version_max) |max| {
512512 switch (max) {
513513 .none => {},
514 .semver => |v| try result.print("...{}", .{v}),
515 .windows => |v| try result.print("...{}", .{@tagName(v)}),
514 .semver => |v| try result.outStream().print("...{}", .{v}),
515 .windows => |v| try result.outStream().print("...{}", .{@tagName(v)}),
516516 }
517517 }
518518
519519 if (self.glibc_version) |v| {
520 try result.print("-{}.{}", .{ @tagName(self.getAbi()), v });
520 try result.outStream().print("-{}.{}", .{ @tagName(self.getAbi()), v });
521521 } else if (self.abi) |abi| {
522 try result.print("-{}", .{@tagName(abi)});
522 try result.outStream().print("-{}", .{@tagName(abi)});
523523 }
524524
525525 return result.toOwnedSlice();
src-self-hosted/dep_tokenizer.zig+10-12
......@@ -306,12 +306,12 @@ pub const Tokenizer = struct {
306306
307307 fn errorPosition(self: *Tokenizer, position: usize, bytes: []const u8, comptime fmt: []const u8, args: var) Error {
308308 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);
310310 try buffer.append(" '");
311311 var out = makeOutput(std.Buffer.append, &buffer);
312312 try printCharValues(&out, bytes);
313313 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)});
315315 self.error_text = buffer.toSlice();
316316 return Error.InvalidInput;
317317 }
......@@ -319,10 +319,9 @@ pub const Tokenizer = struct {
319319 fn errorIllegalChar(self: *Tokenizer, position: usize, char: u8, comptime fmt: []const u8, args: var) Error {
320320 var buffer = try std.Buffer.initSize(&self.arena.allocator, 0);
321321 try buffer.append("illegal char ");
322 var out = makeOutput(std.Buffer.append, &buffer);
323 try printUnderstandableChar(&out, char);
324 std.fmt.format(&buffer, anyerror, std.Buffer.append, " at position {}", .{position}) catch {};
325 if (fmt.len != 0) std.fmt.format(&buffer, anyerror, std.Buffer.append, ": " ++ fmt, args) catch {};
322 try printUnderstandableChar(&buffer, char);
323 try buffer.outStream().print(" at position {}", .{position});
324 if (fmt.len != 0) try buffer.outStream().print(": " ++ fmt, args);
326325 self.error_text = buffer.toSlice();
327326 return Error.InvalidInput;
328327 }
......@@ -996,14 +995,13 @@ fn printCharValues(out: var, bytes: []const u8) !void {
996995 }
997996}
998997
999fn printUnderstandableChar(out: var, char: u8) !void {
998fn printUnderstandableChar(buffer: *std.Buffer, char: u8) !void {
1000999 if (!std.ascii.isPrint(char) or char == ' ') {
1001 const output = @typeInfo(@TypeOf(out)).Pointer.child.output;
1002 std.fmt.format(out.context, anyerror, output, "\\x{X:2}", .{char}) catch {};
1000 try buffer.outStream().print("\\x{X:2}", .{char});
10031001 } else {
1004 try out.write("'");
1005 try out.write(&[_]u8{printable_char_tab[char]});
1006 try out.write("'");
1002 try buffer.append("'");
1003 try buffer.appendByte(printable_char_tab[char]);
1004 try buffer.append("'");
10071005 }
10081006}
10091007
src-self-hosted/stage2.zig+3-3
......@@ -1019,7 +1019,7 @@ const Stage2Target = extern struct {
10191019 .macosx,
10201020 .netbsd,
10211021 .openbsd,
1022 => try os_builtin_str_buffer.print(
1022 => try os_builtin_str_buffer.outStream().print(
10231023 \\ .semver = .{{
10241024 \\ .min = .{{
10251025 \\ .major = {},
......@@ -1043,7 +1043,7 @@ const Stage2Target = extern struct {
10431043 target.os.version_range.semver.max.patch,
10441044 }),
10451045
1046 .linux => try os_builtin_str_buffer.print(
1046 .linux => try os_builtin_str_buffer.outStream().print(
10471047 \\ .linux = .{{
10481048 \\ .range = .{{
10491049 \\ .min = .{{
......@@ -1078,7 +1078,7 @@ const Stage2Target = extern struct {
10781078 target.os.version_range.linux.glibc.patch,
10791079 }),
10801080
1081 .windows => try os_builtin_str_buffer.print(
1081 .windows => try os_builtin_str_buffer.outStream().print(
10821082 \\ .windows = .{{
10831083 \\ .min = .{},
10841084 \\ .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
47524752}
47534753
47544754fn 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 };
47604755 const start_index = c.source_buffer.len();
47614756 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);
47644759 const end_index = c.source_buffer.len();
47654760 const token_index = c.tree.tokens.len;
47664761 const new_token = try c.tree.tokens.addOne();