authorgravatar for benjamin.feng@glassdoor.comBenjamin Feng <benjamin.feng@glassdoor.com> 2020-03-06 16:59:21-06:00
committergravatar for benjamin.feng@glassdoor.comBenjamin Feng <benjamin.feng@glassdoor.com> 2020-03-12 10:41:09-05:00
log4aae55b4ccf44fa3c2c2a81a6a34f3c898dece30
treea4116c5259e3f39df939008f23ac66f65ce61194
parented7f30e1cd0c00c82c511ad826fe8d8b60b2f57f

Replace fmt with new fmtstream


34 files changed, 336 insertions(+), 2091 deletions(-)

lib/std/atomic/queue.zig+2-2
......@@ -348,7 +348,7 @@ test "std.atomic.Queue dump" {
348348 fbs.reset();
349349 try queue.dumpToStream(fbs.outStream());
350350
351 var expected = try std.fmtstream.bufPrint(expected_buffer[0..],
351 var expected = try std.fmt.bufPrint(expected_buffer[0..],
352352 \\head: 0x{x}=1
353353 \\ (null)
354354 \\tail: 0x{x}=1
......@@ -368,7 +368,7 @@ test "std.atomic.Queue dump" {
368368 fbs.reset();
369369 try queue.dumpToStream(fbs.outStream());
370370
371 expected = try std.fmtstream.bufPrint(expected_buffer[0..],
371 expected = try std.fmt.bufPrint(expected_buffer[0..],
372372 \\head: 0x{x}=1
373373 \\ 0x{x}=2
374374 \\ (null)
lib/std/buffer.zig+2-2
......@@ -65,11 +65,11 @@ pub const Buffer = struct {
6565 }
6666
6767 pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
68 const size = std.fmtstream.count(format, args) catch |err| switch (err) {
68 const size = std.fmt.count(format, args) catch |err| switch (err) {
6969 error.Overflow => return error.OutOfMemory,
7070 };
7171 var self = try Buffer.initSize(allocator, size);
72 assert((std.fmtstream.bufPrint(self.list.items, format, args) catch unreachable).len == size);
72 assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
7373 return self;
7474 }
7575
lib/std/builtin.zig+7-7
......@@ -426,27 +426,27 @@ pub const Version = struct {
426426 pub fn parse(text: []const u8) !Version {
427427 var it = std.mem.separate(text, ".");
428428 return Version{
429 .major = try std.fmtstream.parseInt(u32, it.next() orelse return error.InvalidVersion, 10),
430 .minor = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10),
431 .patch = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10),
429 .major = try std.fmt.parseInt(u32, it.next() orelse return error.InvalidVersion, 10),
430 .minor = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
431 .patch = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
432432 };
433433 }
434434
435435 pub fn format(
436436 self: Version,
437437 comptime fmt: []const u8,
438 options: std.fmtstream.FormatOptions,
438 options: std.fmt.FormatOptions,
439439 out_stream: var,
440440 ) !void {
441441 if (fmt.len == 0) {
442442 if (self.patch == 0) {
443443 if (self.minor == 0) {
444 return std.fmtstream.format(out_stream, "{}", .{self.major});
444 return std.fmt.format(out_stream, "{}", .{self.major});
445445 } else {
446 return std.fmtstream.format(out_stream, "{}.{}", .{ self.major, self.minor });
446 return std.fmt.format(out_stream, "{}.{}", .{ self.major, self.minor });
447447 }
448448 } else {
449 return std.fmtstream.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch });
449 return std.fmt.format(out_stream, "{}.{}.{}", .{ self.major, self.minor, self.patch });
450450 }
451451 } else {
452452 @compileError("Unknown format string: '" ++ fmt ++ "'");
lib/std/fmt.zig+225-294
......@@ -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)[0..]);
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;
627595 const pad_byte: 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(@as(*const [1]u8, &pad_byte)[0..1]);
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,40 @@ 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.
11391071 BufferTooSmall,
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 format(fbs.outStream(), fmt, args) catch |err| switch (err) {
1076 error.NoSpaceLeft => return error.BufferTooSmall,
1077 };
1078 //TODO: should we change one of these return signatures?
1079 //return fbs.getWritten();
1080 return buf[0..fbs.pos];
1081}
1082
1083// Count the characters needed for format. Useful for preallocating memory
1084pub fn count(comptime fmt: []const u8, args: var) !usize {
1085 var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
1086 format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {};
1087 return std.math.cast(usize, counting_stream.bytes_written);
11451088}
11461089
11471090pub const AllocPrintError = error{OutOfMemory};
11481091
11491092pub 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) {};
1093 const size = count(fmt, args) catch |err| switch (err) {
1094 // Output too long. Can't possibly allocate enough memory to display it.
1095 error.Overflow => return error.OutOfMemory,
1096 };
11521097 const buf = try allocator.alloc(u8, size);
11531098 return bufPrint(buf, fmt, args) catch |err| switch (err) {
11541099 error.BufferTooSmall => unreachable, // we just counted the size above
11551100 };
11561101}
11571102
1158fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
1159 size.* += bytes.len;
1160}
1161
11621103pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
11631104 const result = try allocPrint(allocator, fmt ++ "\x00", args);
11641105 return result[0 .. result.len - 1 :0];
......@@ -1251,20 +1192,17 @@ test "int.padded" {
12511192test "buffer" {
12521193 {
12531194 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"));
1195 var fbs = std.io.fixedBufferStream(&buf1);
1196 try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
1197 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234"));
1198
1199 fbs.reset();
1200 try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
1201 std.testing.expect(mem.eql(u8, fbs.getWritten(), "a"));
1202
1203 fbs.reset();
1204 try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
1205 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100"));
12681206 }
12691207}
12701208
......@@ -1449,14 +1387,12 @@ test "custom" {
14491387 self: SelfType,
14501388 comptime fmt: []const u8,
14511389 options: FormatOptions,
1452 context: var,
1453 comptime Errors: type,
1454 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1455 ) Errors!void {
1390 out_stream: var,
1391 ) !void {
14561392 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 });
1393 return std.fmt.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
14581394 } 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 });
1395 return std.fmt.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
14601396 } else {
14611397 @compileError("Unknown format character: '" ++ fmt ++ "'");
14621398 }
......@@ -1640,10 +1576,10 @@ test "hexToBytes" {
16401576test "formatIntValue with comptime_int" {
16411577 const value: comptime_int = 123456789123456789;
16421578
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"));
1579 var buf: [20]u8 = undefined;
1580 var fbs = std.io.fixedBufferStream(&buf);
1581 try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
1582 std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789"));
16471583}
16481584
16491585test "formatType max_depth" {
......@@ -1656,12 +1592,10 @@ test "formatType max_depth" {
16561592 self: SelfType,
16571593 comptime fmt: []const u8,
16581594 options: FormatOptions,
1659 context: var,
1660 comptime Errors: type,
1661 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1662 ) Errors!void {
1595 out_stream: var,
1596 ) !void {
16631597 if (fmt.len == 0) {
1664 return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y });
1598 return std.fmt.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
16651599 } else {
16661600 @compileError("Unknown format string: '" ++ fmt ++ "'");
16671601 }
......@@ -1695,25 +1629,22 @@ test "formatType max_depth" {
16951629 inst.a = &inst;
16961630 inst.tu.ptr = &inst.tu;
16971631
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) }"));
1632 var buf: [1000]u8 = undefined;
1633 var fbs = std.io.fixedBufferStream(&buf);
1634 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0);
1635 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }"));
1636
1637 fbs.reset();
1638 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1);
1639 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
1640
1641 fbs.reset();
1642 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2);
1643 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) }"));
1644
1645 fbs.reset();
1646 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3);
1647 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) }"));
17171648}
17181649
17191650test "positional" {
lib/std/fmtstream.zig deleted-1685
......@@ -1,1685 +0,0 @@
1const std = @import("std.zig");
2const math = std.math;
3const assert = std.debug.assert;
4const mem = std.mem;
5const builtin = @import("builtin");
6const errol = @import("fmt/errol.zig");
7const lossyCast = std.math.lossyCast;
8
9pub const default_max_depth = 3;
10
11pub const Alignment = enum {
12 Left,
13 Center,
14 Right,
15};
16
17pub const FormatOptions = struct {
18 precision: ?usize = null,
19 width: ?usize = null,
20 alignment: ?Alignment = null,
21 fill: u8 = ' ',
22};
23
24fn peekIsAlign(comptime fmt: []const u8) bool {
25 // Should only be called during a state transition to the format segment.
26 comptime assert(fmt[0] == ':');
27
28 inline for (([_]u8{ 1, 2 })[0..]) |i| {
29 if (fmt.len > i and (fmt[i] == '<' or fmt[i] == '^' or fmt[i] == '>')) {
30 return true;
31 }
32 }
33 return false;
34}
35
36/// Renders fmt string with args, calling output with slices of bytes.
37/// If `output` returns an error, the error is returned from `format` and
38/// `output` is not called again.
39///
40/// The format string must be comptime known and may contain placeholders following
41/// this format:
42/// `{[position][specifier]:[fill][alignment][width].[precision]}`
43///
44/// Each word between `[` and `]` is a parameter you have to replace with something:
45///
46/// - *position* is the index of the argument that should be inserted
47/// - *specifier* is a type-dependent formatting option that determines how a type should formatted (see below)
48/// - *fill* is a single character which is used to pad the formatted text
49/// - *alignment* is one of the three characters `<`, `^` or `>`. they define if the text is *left*, *center*, or *right* aligned
50/// - *width* is the total width of the field in characters
51/// - *precision* specifies how many decimals a formatted number should have
52///
53/// Note that most of the parameters are optional and may be omitted. Also you can leave out separators like `:` and `.` when
54/// all parameters after the separator are omitted.
55/// Only exception is the *fill* parameter. If *fill* is required, one has to specify *alignment* as well, as otherwise
56/// the digits after `:` is interpreted as *width*, not *fill*.
57///
58/// The *specifier* has several options for types:
59/// - `x` and `X`:
60/// - format the non-numeric value as a string of bytes in hexadecimal notation ("binary dump") in either lower case or upper case
61/// - output numeric value in hexadecimal notation
62/// - `s`: print a pointer-to-many as a c-string, use zero-termination
63/// - `B` and `Bi`: output a memory size in either metric (1000) or power-of-two (1024) based notation. works for both float and integer values.
64/// - `e`: output floating point value in scientific notation
65/// - `d`: output numeric value in decimal notation
66/// - `b`: output integer value in binary notation
67/// - `c`: output integer as an ASCII character. Integer type must have 8 bits at max.
68/// - `*`: output the address of the value instead of the value itself.
69///
70/// If a formatted user type contains a function of the type
71/// ```
72/// fn format(value: ?, comptime fmt: []const u8, options: std.fmtstream.FormatOptions, out_stream: var) !void
73/// ```
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.
76///
77/// A user type may be a `struct`, `vector`, `union` or `enum` type.
78pub fn format(
79 out_stream: var,
80 comptime fmt: []const u8,
81 args: var,
82) !void {
83 const ArgSetType = u32;
84 if (@typeInfo(@TypeOf(args)) != .Struct) {
85 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
86 }
87 if (args.len > ArgSetType.bit_count) {
88 @compileError("32 arguments max are supported per format call");
89 }
90
91 const State = enum {
92 Start,
93 Positional,
94 CloseBrace,
95 Specifier,
96 FormatFillAndAlign,
97 FormatWidth,
98 FormatPrecision,
99 };
100
101 comptime var start_index = 0;
102 comptime var state = State.Start;
103 comptime var maybe_pos_arg: ?comptime_int = null;
104 comptime var specifier_start = 0;
105 comptime var specifier_end = 0;
106 comptime var options = FormatOptions{};
107 comptime var arg_state: struct {
108 next_arg: usize = 0,
109 used_args: ArgSetType = 0,
110 args_len: usize = args.len,
111
112 fn hasUnusedArgs(comptime self: *@This()) bool {
113 return (@popCount(ArgSetType, self.used_args) != self.args_len);
114 }
115
116 fn nextArg(comptime self: *@This(), comptime pos_arg: ?comptime_int) comptime_int {
117 const next_idx = pos_arg orelse blk: {
118 const arg = self.next_arg;
119 self.next_arg += 1;
120 break :blk arg;
121 };
122
123 if (next_idx >= self.args_len) {
124 @compileError("Too few arguments");
125 }
126
127 // Mark this argument as used
128 self.used_args |= 1 << next_idx;
129
130 return next_idx;
131 }
132 } = .{};
133
134 inline for (fmt) |c, i| {
135 switch (state) {
136 .Start => switch (c) {
137 '{' => {
138 if (start_index < i) {
139 try out_stream.writeAll(fmt[start_index..i]);
140 }
141
142 start_index = i;
143 specifier_start = i + 1;
144 specifier_end = i + 1;
145 maybe_pos_arg = null;
146 state = .Positional;
147 options = FormatOptions{};
148 },
149 '}' => {
150 if (start_index < i) {
151 try out_stream.writeAll(fmt[start_index..i]);
152 }
153 state = .CloseBrace;
154 },
155 else => {},
156 },
157 .Positional => switch (c) {
158 '{' => {
159 state = .Start;
160 start_index = i;
161 },
162 ':' => {
163 state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth;
164 specifier_end = i;
165 },
166 '0'...'9' => {
167 if (maybe_pos_arg == null) {
168 maybe_pos_arg = 0;
169 }
170
171 maybe_pos_arg.? *= 10;
172 maybe_pos_arg.? += c - '0';
173 specifier_start = i + 1;
174
175 if (maybe_pos_arg.? >= args.len) {
176 @compileError("Positional value refers to non-existent argument");
177 }
178 },
179 '}' => {
180 const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
181
182 try formatType(
183 args[arg_to_print],
184 fmt[0..0],
185 options,
186 out_stream,
187 default_max_depth,
188 );
189
190 state = .Start;
191 start_index = i + 1;
192 },
193 else => {
194 state = .Specifier;
195 specifier_start = i;
196 },
197 },
198 .CloseBrace => switch (c) {
199 '}' => {
200 state = .Start;
201 start_index = i;
202 },
203 else => @compileError("Single '}' encountered in format string"),
204 },
205 .Specifier => switch (c) {
206 ':' => {
207 specifier_end = i;
208 state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth;
209 },
210 '}' => {
211 const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
212
213 try formatType(
214 args[arg_to_print],
215 fmt[specifier_start..i],
216 options,
217 out_stream,
218 default_max_depth,
219 );
220 state = .Start;
221 start_index = i + 1;
222 },
223 else => {},
224 },
225 // Only entered if the format string contains a fill/align segment.
226 .FormatFillAndAlign => switch (c) {
227 '<' => {
228 options.alignment = Alignment.Left;
229 state = .FormatWidth;
230 },
231 '^' => {
232 options.alignment = Alignment.Center;
233 state = .FormatWidth;
234 },
235 '>' => {
236 options.alignment = Alignment.Right;
237 state = .FormatWidth;
238 },
239 else => {
240 options.fill = c;
241 },
242 },
243 .FormatWidth => switch (c) {
244 '0'...'9' => {
245 if (options.width == null) {
246 options.width = 0;
247 }
248
249 options.width.? *= 10;
250 options.width.? += c - '0';
251 },
252 '.' => {
253 state = .FormatPrecision;
254 },
255 '}' => {
256 const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
257
258 try formatType(
259 args[arg_to_print],
260 fmt[specifier_start..specifier_end],
261 options,
262 out_stream,
263 default_max_depth,
264 );
265 state = .Start;
266 start_index = i + 1;
267 },
268 else => {
269 @compileError("Unexpected character in width value: " ++ [_]u8{c});
270 },
271 },
272 .FormatPrecision => switch (c) {
273 '0'...'9' => {
274 if (options.precision == null) {
275 options.precision = 0;
276 }
277
278 options.precision.? *= 10;
279 options.precision.? += c - '0';
280 },
281 '}' => {
282 const arg_to_print = comptime arg_state.nextArg(maybe_pos_arg);
283
284 try formatType(
285 args[arg_to_print],
286 fmt[specifier_start..specifier_end],
287 options,
288 out_stream,
289 default_max_depth,
290 );
291 state = .Start;
292 start_index = i + 1;
293 },
294 else => {
295 @compileError("Unexpected character in precision value: " ++ [_]u8{c});
296 },
297 },
298 }
299 }
300 comptime {
301 if (comptime arg_state.hasUnusedArgs()) {
302 @compileError("Unused arguments");
303 }
304 if (state != State.Start) {
305 @compileError("Incomplete format string: " ++ fmt);
306 }
307 }
308 if (start_index < fmt.len) {
309 try out_stream.writeAll(fmt[start_index..]);
310 }
311}
312
313pub fn formatType(
314 value: var,
315 comptime fmt: []const u8,
316 options: FormatOptions,
317 out_stream: var,
318 max_depth: usize,
319) @TypeOf(out_stream).Error!void {
320 if (comptime std.mem.eql(u8, fmt, "*")) {
321 try out_stream.writeAll(@typeName(@TypeOf(value).Child));
322 try out_stream.writeAll("@");
323 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream);
324 return;
325 }
326
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
332 switch (@typeInfo(T)) {
333 .ComptimeInt, .Int, .Float => {
334 return formatValue(value, fmt, options, out_stream);
335 },
336 .Void => {
337 return out_stream.writeAll("void");
338 },
339 .Bool => {
340 return out_stream.writeAll(if (value) "true" else "false");
341 },
342 .Optional => {
343 if (value) |payload| {
344 return formatType(payload, fmt, options, out_stream, max_depth);
345 } else {
346 return out_stream.writeAll("null");
347 }
348 },
349 .ErrorUnion => {
350 if (value) |payload| {
351 return formatType(payload, fmt, options, out_stream, max_depth);
352 } else |err| {
353 return formatType(err, fmt, options, out_stream, max_depth);
354 }
355 },
356 .ErrorSet => {
357 try out_stream.writeAll("error.");
358 return out_stream.writeAll(@errorName(value));
359 },
360 .Enum => |enumInfo| {
361 try out_stream.writeAll(@typeName(T));
362 if (enumInfo.is_exhaustive) {
363 try out_stream.writeAll(".");
364 try out_stream.writeAll(@tagName(value));
365 } else {
366 // TODO: when @tagName works on exhaustive enums print known enum strings
367 try out_stream.writeAll("(");
368 try formatType(@enumToInt(value), fmt, options, out_stream, max_depth);
369 try out_stream.writeAll(")");
370 }
371 },
372 .Union => {
373 try out_stream.writeAll(@typeName(T));
374 if (max_depth == 0) {
375 return out_stream.writeAll("{ ... }");
376 }
377 const info = @typeInfo(T).Union;
378 if (info.tag_type) |UnionTagType| {
379 try out_stream.writeAll("{ .");
380 try out_stream.writeAll(@tagName(@as(UnionTagType, value)));
381 try out_stream.writeAll(" = ");
382 inline for (info.fields) |u_field| {
383 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
384 try formatType(@field(value, u_field.name), fmt, options, out_stream, max_depth - 1);
385 }
386 }
387 try out_stream.writeAll(" }");
388 } else {
389 try format(out_stream, "@{x}", .{@ptrToInt(&value)});
390 }
391 },
392 .Struct => |StructT| {
393 try out_stream.writeAll(@typeName(T));
394 if (max_depth == 0) {
395 return out_stream.writeAll("{ ... }");
396 }
397 try out_stream.writeAll("{");
398 inline for (StructT.fields) |f, i| {
399 if (i == 0) {
400 try out_stream.writeAll(" .");
401 } else {
402 try out_stream.writeAll(", .");
403 }
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);
407 }
408 try out_stream.writeAll(" }");
409 },
410 .Pointer => |ptr_info| switch (ptr_info.size) {
411 .One => switch (@typeInfo(ptr_info.child)) {
412 .Array => |info| {
413 if (info.child == u8) {
414 return formatText(value, fmt, options, out_stream);
415 }
416 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
417 },
418 .Enum, .Union, .Struct => {
419 return formatType(value.*, fmt, options, out_stream, max_depth);
420 },
421 else => return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
422 },
423 .Many, .C => {
424 if (ptr_info.sentinel) |sentinel| {
425 return formatType(mem.span(value), fmt, options, out_stream, max_depth);
426 }
427 if (ptr_info.child == u8) {
428 if (fmt.len > 0 and fmt[0] == 's') {
429 return formatText(mem.span(value), fmt, options, out_stream);
430 }
431 }
432 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
433 },
434 .Slice => {
435 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
436 return formatText(value, fmt, options, out_stream);
437 }
438 if (ptr_info.child == u8) {
439 return formatText(value, fmt, options, out_stream);
440 }
441 return format(out_stream, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
442 },
443 },
444 .Array => |info| {
445 const Slice = @Type(builtin.TypeInfo{
446 .Pointer = .{
447 .size = .Slice,
448 .is_const = true,
449 .is_volatile = false,
450 .is_allowzero = false,
451 .alignment = @alignOf(info.child),
452 .child = info.child,
453 .sentinel = null,
454 },
455 });
456 return formatType(@as(Slice, &value), fmt, options, out_stream, max_depth);
457 },
458 .Vector => {
459 const len = @typeInfo(T).Vector.len;
460 try out_stream.writeAll("{ ");
461 var i: usize = 0;
462 while (i < len) : (i += 1) {
463 try formatValue(value[i], fmt, options, out_stream);
464 if (i < len - 1) {
465 try out_stream.writeAll(", ");
466 }
467 }
468 try out_stream.writeAll(" }");
469 },
470 .Fn => {
471 return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
472 },
473 .Type => return out_stream.writeAll(@typeName(T)),
474 .EnumLiteral => {
475 const buffer = [_]u8{'.'} ++ @tagName(value);
476 return formatType(buffer, fmt, options, out_stream, max_depth);
477 },
478 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
479 }
480}
481
482fn formatValue(
483 value: var,
484 comptime fmt: []const u8,
485 options: FormatOptions,
486 out_stream: var,
487) !void {
488 if (comptime std.mem.eql(u8, fmt, "B")) {
489 return formatBytes(value, options, 1000, out_stream);
490 } else if (comptime std.mem.eql(u8, fmt, "Bi")) {
491 return formatBytes(value, options, 1024, out_stream);
492 }
493
494 const T = @TypeOf(value);
495 switch (@typeInfo(T)) {
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"),
499 else => comptime unreachable,
500 }
501}
502
503pub fn formatIntValue(
504 value: var,
505 comptime fmt: []const u8,
506 options: FormatOptions,
507 out_stream: var,
508) !void {
509 comptime var radix = 10;
510 comptime var uppercase = false;
511
512 const int_value = if (@TypeOf(value) == comptime_int) blk: {
513 const Int = math.IntFittingRange(value, value);
514 break :blk @as(Int, value);
515 } else
516 value;
517
518 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "d")) {
519 radix = 10;
520 uppercase = false;
521 } else if (comptime std.mem.eql(u8, fmt, "c")) {
522 if (@TypeOf(int_value).bit_count <= 8) {
523 return formatAsciiChar(@as(u8, int_value), options, out_stream);
524 } else {
525 @compileError("Cannot print integer that is larger than 8 bits as a ascii");
526 }
527 } else if (comptime std.mem.eql(u8, fmt, "b")) {
528 radix = 2;
529 uppercase = false;
530 } else if (comptime std.mem.eql(u8, fmt, "x")) {
531 radix = 16;
532 uppercase = false;
533 } else if (comptime std.mem.eql(u8, fmt, "X")) {
534 radix = 16;
535 uppercase = true;
536 } else {
537 @compileError("Unknown format string: '" ++ fmt ++ "'");
538 }
539
540 return formatInt(int_value, radix, uppercase, options, out_stream);
541}
542
543fn formatFloatValue(
544 value: var,
545 comptime fmt: []const u8,
546 options: FormatOptions,
547 out_stream: var,
548) !void {
549 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
550 return formatFloatScientific(value, options, out_stream);
551 } else if (comptime std.mem.eql(u8, fmt, "d")) {
552 return formatFloatDecimal(value, options, out_stream);
553 } else {
554 @compileError("Unknown format string: '" ++ fmt ++ "'");
555 }
556}
557
558pub fn formatText(
559 bytes: []const u8,
560 comptime fmt: []const u8,
561 options: FormatOptions,
562 out_stream: var,
563) !void {
564 if (fmt.len == 0) {
565 return out_stream.writeAll(bytes);
566 } else if (comptime std.mem.eql(u8, fmt, "s")) {
567 return formatBuf(bytes, options, out_stream);
568 } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
569 for (bytes) |c| {
570 try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, out_stream);
571 }
572 return;
573 } else {
574 @compileError("Unknown format string: '" ++ fmt ++ "'");
575 }
576}
577
578pub fn formatAsciiChar(
579 c: u8,
580 options: FormatOptions,
581 out_stream: var,
582) !void {
583 return out_stream.writeAll(@as(*const [1]u8, &c)[0..]);
584}
585
586pub fn formatBuf(
587 buf: []const u8,
588 options: FormatOptions,
589 out_stream: var,
590) !void {
591 try out_stream.writeAll(buf);
592
593 const width = options.width orelse 0;
594 var leftover_padding = if (width > buf.len) (width - buf.len) else return;
595 const pad_byte: u8 = options.fill;
596 while (leftover_padding > 0) : (leftover_padding -= 1) {
597 try out_stream.writeAll(@as(*const [1]u8, &pad_byte)[0..1]);
598 }
599}
600
601// Print a float in scientific notation to the specified precision. Null uses full precision.
602// It should be the case that every full precision, printed value can be re-parsed back to the
603// same type unambiguously.
604pub fn formatFloatScientific(
605 value: var,
606 options: FormatOptions,
607 out_stream: var,
608) !void {
609 var x = @floatCast(f64, value);
610
611 // Errol doesn't handle these special cases.
612 if (math.signbit(x)) {
613 try out_stream.writeAll("-");
614 x = -x;
615 }
616
617 if (math.isNan(x)) {
618 return out_stream.writeAll("nan");
619 }
620 if (math.isPositiveInf(x)) {
621 return out_stream.writeAll("inf");
622 }
623 if (x == 0.0) {
624 try out_stream.writeAll("0");
625
626 if (options.precision) |precision| {
627 if (precision != 0) {
628 try out_stream.writeAll(".");
629 var i: usize = 0;
630 while (i < precision) : (i += 1) {
631 try out_stream.writeAll("0");
632 }
633 }
634 } else {
635 try out_stream.writeAll(".0");
636 }
637
638 try out_stream.writeAll("e+00");
639 return;
640 }
641
642 var buffer: [32]u8 = undefined;
643 var float_decimal = errol.errol3(x, buffer[0..]);
644
645 if (options.precision) |precision| {
646 errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);
647
648 try out_stream.writeAll(float_decimal.digits[0..1]);
649
650 // {e0} case prints no `.`
651 if (precision != 0) {
652 try out_stream.writeAll(".");
653
654 var printed: usize = 0;
655 if (float_decimal.digits.len > 1) {
656 const num_digits = math.min(float_decimal.digits.len, precision + 1);
657 try out_stream.writeAll(float_decimal.digits[1..num_digits]);
658 printed += num_digits - 1;
659 }
660
661 while (printed < precision) : (printed += 1) {
662 try out_stream.writeAll("0");
663 }
664 }
665 } else {
666 try out_stream.writeAll(float_decimal.digits[0..1]);
667 try out_stream.writeAll(".");
668 if (float_decimal.digits.len > 1) {
669 const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
670
671 try out_stream.writeAll(float_decimal.digits[1..num_digits]);
672 } else {
673 try out_stream.writeAll("0");
674 }
675 }
676
677 try out_stream.writeAll("e");
678 const exp = float_decimal.exp - 1;
679
680 if (exp >= 0) {
681 try out_stream.writeAll("+");
682 if (exp > -10 and exp < 10) {
683 try out_stream.writeAll("0");
684 }
685 try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
686 } else {
687 try out_stream.writeAll("-");
688 if (exp > -10 and exp < 10) {
689 try out_stream.writeAll("0");
690 }
691 try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
692 }
693}
694
695// Print a float of the format x.yyyyy where the number of y is specified by the precision argument.
696// By default floats are printed at full precision (no rounding).
697pub fn formatFloatDecimal(
698 value: var,
699 options: FormatOptions,
700 out_stream: var,
701) !void {
702 var x = @as(f64, value);
703
704 // Errol doesn't handle these special cases.
705 if (math.signbit(x)) {
706 try out_stream.writeAll("-");
707 x = -x;
708 }
709
710 if (math.isNan(x)) {
711 return out_stream.writeAll("nan");
712 }
713 if (math.isPositiveInf(x)) {
714 return out_stream.writeAll("inf");
715 }
716 if (x == 0.0) {
717 try out_stream.writeAll("0");
718
719 if (options.precision) |precision| {
720 if (precision != 0) {
721 try out_stream.writeAll(".");
722 var i: usize = 0;
723 while (i < precision) : (i += 1) {
724 try out_stream.writeAll("0");
725 }
726 } else {
727 try out_stream.writeAll(".0");
728 }
729 }
730
731 return;
732 }
733
734 // non-special case, use errol3
735 var buffer: [32]u8 = undefined;
736 var float_decimal = errol.errol3(x, buffer[0..]);
737
738 if (options.precision) |precision| {
739 errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Decimal);
740
741 // exp < 0 means the leading is always 0 as errol result is normalized.
742 var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
743
744 // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
745 var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
746
747 if (num_digits_whole > 0) {
748 // We may have to zero pad, for instance 1e4 requires zero padding.
749 try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
750
751 var i = num_digits_whole_no_pad;
752 while (i < num_digits_whole) : (i += 1) {
753 try out_stream.writeAll("0");
754 }
755 } else {
756 try out_stream.writeAll("0");
757 }
758
759 // {.0} special case doesn't want a trailing '.'
760 if (precision == 0) {
761 return;
762 }
763
764 try out_stream.writeAll(".");
765
766 // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.
767 var printed: usize = 0;
768
769 // Zero-fill until we reach significant digits or run out of precision.
770 if (float_decimal.exp <= 0) {
771 const zero_digit_count = @intCast(usize, -float_decimal.exp);
772 const zeros_to_print = math.min(zero_digit_count, precision);
773
774 var i: usize = 0;
775 while (i < zeros_to_print) : (i += 1) {
776 try out_stream.writeAll("0");
777 printed += 1;
778 }
779
780 if (printed >= precision) {
781 return;
782 }
783 }
784
785 // Remaining fractional portion, zero-padding if insufficient.
786 assert(precision >= printed);
787 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
788 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
789 return;
790 } else {
791 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
792 printed += float_decimal.digits.len - num_digits_whole_no_pad;
793
794 while (printed < precision) : (printed += 1) {
795 try out_stream.writeAll("0");
796 }
797 }
798 } else {
799 // exp < 0 means the leading is always 0 as errol result is normalized.
800 var num_digits_whole = if (float_decimal.exp > 0) @intCast(usize, float_decimal.exp) else 0;
801
802 // the actual slice into the buffer, we may need to zero-pad between num_digits_whole and this.
803 var num_digits_whole_no_pad = math.min(num_digits_whole, float_decimal.digits.len);
804
805 if (num_digits_whole > 0) {
806 // We may have to zero pad, for instance 1e4 requires zero padding.
807 try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
808
809 var i = num_digits_whole_no_pad;
810 while (i < num_digits_whole) : (i += 1) {
811 try out_stream.writeAll("0");
812 }
813 } else {
814 try out_stream.writeAll("0");
815 }
816
817 // Omit `.` if no fractional portion
818 if (float_decimal.exp >= 0 and num_digits_whole_no_pad == float_decimal.digits.len) {
819 return;
820 }
821
822 try out_stream.writeAll(".");
823
824 // Zero-fill until we reach significant digits or run out of precision.
825 if (float_decimal.exp < 0) {
826 const zero_digit_count = @intCast(usize, -float_decimal.exp);
827
828 var i: usize = 0;
829 while (i < zero_digit_count) : (i += 1) {
830 try out_stream.writeAll("0");
831 }
832 }
833
834 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
835 }
836}
837
838pub fn formatBytes(
839 value: var,
840 options: FormatOptions,
841 comptime radix: usize,
842 out_stream: var,
843) !void {
844 if (value == 0) {
845 return out_stream.writeAll("0B");
846 }
847
848 const mags_si = " kMGTPEZY";
849 const mags_iec = " KMGTPEZY";
850 const magnitude = switch (radix) {
851 1000 => math.min(math.log2(value) / comptime math.log2(1000), mags_si.len - 1),
852 1024 => math.min(math.log2(value) / 10, mags_iec.len - 1),
853 else => unreachable,
854 };
855 const new_value = lossyCast(f64, value) / math.pow(f64, lossyCast(f64, radix), lossyCast(f64, magnitude));
856 const suffix = switch (radix) {
857 1000 => mags_si[magnitude],
858 1024 => mags_iec[magnitude],
859 else => unreachable,
860 };
861
862 try formatFloatDecimal(new_value, options, out_stream);
863
864 if (suffix == ' ') {
865 return out_stream.writeAll("B");
866 }
867
868 const buf = switch (radix) {
869 1000 => &[_]u8{ suffix, 'B' },
870 1024 => &[_]u8{ suffix, 'i', 'B' },
871 else => unreachable,
872 };
873 return out_stream.writeAll(buf);
874}
875
876pub fn formatInt(
877 value: var,
878 base: u8,
879 uppercase: bool,
880 options: FormatOptions,
881 out_stream: var,
882) !void {
883 const int_value = if (@TypeOf(value) == comptime_int) blk: {
884 const Int = math.IntFittingRange(value, value);
885 break :blk @as(Int, value);
886 } else
887 value;
888
889 if (@TypeOf(int_value).is_signed) {
890 return formatIntSigned(int_value, base, uppercase, options, out_stream);
891 } else {
892 return formatIntUnsigned(int_value, base, uppercase, options, out_stream);
893 }
894}
895
896fn formatIntSigned(
897 value: var,
898 base: u8,
899 uppercase: bool,
900 options: FormatOptions,
901 out_stream: var,
902) !void {
903 const new_options = FormatOptions{
904 .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,
905 .precision = options.precision,
906 .fill = options.fill,
907 };
908 const bit_count = @typeInfo(@TypeOf(value)).Int.bits;
909 const Uint = std.meta.IntType(false, bit_count);
910 if (value < 0) {
911 try out_stream.writeAll("-");
912 const new_value = math.absCast(value);
913 return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
914 } else if (options.width == null or options.width.? == 0) {
915 return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, out_stream);
916 } else {
917 try out_stream.writeAll("+");
918 const new_value = @intCast(Uint, value);
919 return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
920 }
921}
922
923fn formatIntUnsigned(
924 value: var,
925 base: u8,
926 uppercase: bool,
927 options: FormatOptions,
928 out_stream: var,
929) !void {
930 assert(base >= 2);
931 var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
932 const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
933 const MinInt = std.meta.IntType(@TypeOf(value).is_signed, min_int_bits);
934 var a: MinInt = value;
935 var index: usize = buf.len;
936
937 while (true) {
938 const digit = a % base;
939 index -= 1;
940 buf[index] = digitToChar(@intCast(u8, digit), uppercase);
941 a /= base;
942 if (a == 0) break;
943 }
944
945 const digits_buf = buf[index..];
946 const width = options.width orelse 0;
947 const padding = if (width > digits_buf.len) (width - digits_buf.len) else 0;
948
949 if (padding > index) {
950 const zero_byte: u8 = options.fill;
951 var leftover_padding = padding - index;
952 while (true) {
953 try out_stream.writeAll(@as(*const [1]u8, &zero_byte)[0..]);
954 leftover_padding -= 1;
955 if (leftover_padding == 0) break;
956 }
957 mem.set(u8, buf[0..index], options.fill);
958 return out_stream.writeAll(&buf);
959 } else {
960 const padded_buf = buf[index - padding ..];
961 mem.set(u8, padded_buf[0..padding], options.fill);
962 return out_stream.writeAll(padded_buf);
963 }
964}
965
966pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {
967 var fbs = std.io.fixedBufferStream(out_buf);
968 formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable;
969 return fbs.pos;
970}
971
972pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
973 if (!T.is_signed) return parseUnsigned(T, buf, radix);
974 if (buf.len == 0) return @as(T, 0);
975 if (buf[0] == '-') {
976 return math.negate(try parseUnsigned(T, buf[1..], radix));
977 } else if (buf[0] == '+') {
978 return parseUnsigned(T, buf[1..], radix);
979 } else {
980 return parseUnsigned(T, buf, radix);
981 }
982}
983
984test "parseInt" {
985 std.testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
986 std.testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
987 std.testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
988 std.testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
989 std.testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
990 std.testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
991 std.testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
992}
993
994pub const ParseUnsignedError = error{
995 /// The result cannot fit in the type specified
996 Overflow,
997
998 /// The input had a byte that was not a digit
999 InvalidCharacter,
1000};
1001
1002pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsignedError!T {
1003 var x: T = 0;
1004
1005 for (buf) |c| {
1006 const digit = try charToDigit(c, radix);
1007
1008 if (x != 0) x = try math.mul(T, x, try math.cast(T, radix));
1009 x = try math.add(T, x, try math.cast(T, digit));
1010 }
1011
1012 return x;
1013}
1014
1015test "parseUnsigned" {
1016 std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
1017 std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
1018 std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
1019
1020 std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
1021 std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
1022
1023 std.testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
1024
1025 std.testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
1026 std.testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
1027
1028 std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
1029 std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
1030
1031 std.testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
1032
1033 // these numbers should fit even though the radix itself doesn't fit in the destination type
1034 std.testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
1035 std.testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
1036 std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
1037 std.testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
1038 std.testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
1039 std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
1040}
1041
1042pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
1043
1044test "parseFloat" {
1045 _ = @import("fmt/parse_float.zig");
1046}
1047
1048pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
1049 const value = switch (c) {
1050 '0'...'9' => c - '0',
1051 'A'...'Z' => c - 'A' + 10,
1052 'a'...'z' => c - 'a' + 10,
1053 else => return error.InvalidCharacter,
1054 };
1055
1056 if (value >= radix) return error.InvalidCharacter;
1057
1058 return value;
1059}
1060
1061fn digitToChar(digit: u8, uppercase: bool) u8 {
1062 return switch (digit) {
1063 0...9 => digit + '0',
1064 10...35 => digit + ((if (uppercase) @as(u8, 'A') else @as(u8, 'a')) - 10),
1065 else => unreachable,
1066 };
1067}
1068
1069pub const BufPrintError = error{
1070 /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
1071 BufferTooSmall,
1072};
1073pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
1074 var fbs = std.io.fixedBufferStream(buf);
1075 format(fbs.outStream(), fmt, args) catch |err| switch (err) {
1076 error.NoSpaceLeft => return error.BufferTooSmall,
1077 };
1078 //TODO: should we change one of these return signatures?
1079 //return fbs.getWritten();
1080 return buf[0..fbs.pos];
1081}
1082
1083// Count the characters needed for format. Useful for preallocating memory
1084pub fn count(comptime fmt: []const u8, args: var) !usize {
1085 var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
1086 format(counting_stream.outStream(), fmt, args) catch |err| switch (err) {};
1087 return std.math.cast(usize, counting_stream.bytes_written);
1088}
1089
1090pub const AllocPrintError = error{OutOfMemory};
1091
1092pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
1093 const size = count(fmt, args) catch |err| switch (err) {
1094 // Output too long. Can't possibly allocate enough memory to display it.
1095 error.Overflow => return error.OutOfMemory,
1096 };
1097 const buf = try allocator.alloc(u8, size);
1098 return bufPrint(buf, fmt, args) catch |err| switch (err) {
1099 error.BufferTooSmall => unreachable, // we just counted the size above
1100 };
1101}
1102
1103pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
1104 const result = try allocPrint(allocator, fmt ++ "\x00", args);
1105 return result[0 .. result.len - 1 :0];
1106}
1107
1108test "bufPrintInt" {
1109 var buffer: [100]u8 = undefined;
1110 const buf = buffer[0..];
1111
1112 std.testing.expectEqualSlices(u8, "-1", bufPrintIntToSlice(buf, @as(i1, -1), 10, false, FormatOptions{}));
1113
1114 std.testing.expectEqualSlices(u8, "-101111000110000101001110", bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{}));
1115 std.testing.expectEqualSlices(u8, "-12345678", bufPrintIntToSlice(buf, @as(i32, -12345678), 10, false, FormatOptions{}));
1116 std.testing.expectEqualSlices(u8, "-bc614e", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, false, FormatOptions{}));
1117 std.testing.expectEqualSlices(u8, "-BC614E", bufPrintIntToSlice(buf, @as(i32, -12345678), 16, true, FormatOptions{}));
1118
1119 std.testing.expectEqualSlices(u8, "12345678", bufPrintIntToSlice(buf, @as(u32, 12345678), 10, true, FormatOptions{}));
1120
1121 std.testing.expectEqualSlices(u8, " 666", bufPrintIntToSlice(buf, @as(u32, 666), 10, false, FormatOptions{ .width = 6 }));
1122 std.testing.expectEqualSlices(u8, " 1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 6 }));
1123 std.testing.expectEqualSlices(u8, "1234", bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 1 }));
1124
1125 std.testing.expectEqualSlices(u8, "+42", bufPrintIntToSlice(buf, @as(i32, 42), 10, false, FormatOptions{ .width = 3 }));
1126 std.testing.expectEqualSlices(u8, "-42", bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 }));
1127}
1128
1129fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 {
1130 return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
1131}
1132
1133test "parse u64 digit too big" {
1134 _ = parseUnsigned(u64, "123a", 10) catch |err| {
1135 if (err == error.InvalidCharacter) return;
1136 unreachable;
1137 };
1138 unreachable;
1139}
1140
1141test "parse unsigned comptime" {
1142 comptime {
1143 std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
1144 }
1145}
1146
1147test "optional" {
1148 {
1149 const value: ?i32 = 1234;
1150 try testFmt("optional: 1234\n", "optional: {}\n", .{value});
1151 }
1152 {
1153 const value: ?i32 = null;
1154 try testFmt("optional: null\n", "optional: {}\n", .{value});
1155 }
1156}
1157
1158test "error" {
1159 {
1160 const value: anyerror!i32 = 1234;
1161 try testFmt("error union: 1234\n", "error union: {}\n", .{value});
1162 }
1163 {
1164 const value: anyerror!i32 = error.InvalidChar;
1165 try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
1166 }
1167}
1168
1169test "int.small" {
1170 {
1171 const value: u3 = 0b101;
1172 try testFmt("u3: 5\n", "u3: {}\n", .{value});
1173 }
1174}
1175
1176test "int.specifier" {
1177 {
1178 const value: u8 = 'a';
1179 try testFmt("u8: a\n", "u8: {c}\n", .{value});
1180 }
1181 {
1182 const value: u8 = 0b1100;
1183 try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
1184 }
1185}
1186
1187test "int.padded" {
1188 try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
1189 try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
1190}
1191
1192test "buffer" {
1193 {
1194 var buf1: [32]u8 = undefined;
1195 var fbs = std.io.fixedBufferStream(&buf1);
1196 try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
1197 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234"));
1198
1199 fbs.reset();
1200 try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
1201 std.testing.expect(mem.eql(u8, fbs.getWritten(), "a"));
1202
1203 fbs.reset();
1204 try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
1205 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100"));
1206 }
1207}
1208
1209test "array" {
1210 {
1211 const value: [3]u8 = "abc".*;
1212 try testFmt("array: abc\n", "array: {}\n", .{value});
1213 try testFmt("array: abc\n", "array: {}\n", .{&value});
1214
1215 var buf: [100]u8 = undefined;
1216 try testFmt(
1217 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
1218 "array: {*}\n",
1219 .{&value},
1220 );
1221 }
1222}
1223
1224test "slice" {
1225 {
1226 const value: []const u8 = "abc";
1227 try testFmt("slice: abc\n", "slice: {}\n", .{value});
1228 }
1229 {
1230 const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
1231 try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
1232 }
1233
1234 try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
1235 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
1236}
1237
1238test "pointer" {
1239 {
1240 const value = @intToPtr(*align(1) i32, 0xdeadbeef);
1241 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
1242 try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
1243 }
1244 {
1245 const value = @intToPtr(fn () void, 0xdeadbeef);
1246 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
1247 }
1248 {
1249 const value = @intToPtr(fn () void, 0xdeadbeef);
1250 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
1251 }
1252}
1253
1254test "cstr" {
1255 try testFmt(
1256 "cstr: Test C\n",
1257 "cstr: {s}\n",
1258 .{@ptrCast([*c]const u8, "Test C")},
1259 );
1260 try testFmt(
1261 "cstr: Test C \n",
1262 "cstr: {s:10}\n",
1263 .{@ptrCast([*c]const u8, "Test C")},
1264 );
1265}
1266
1267test "filesize" {
1268 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
1269 try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
1270}
1271
1272test "struct" {
1273 {
1274 const Struct = struct {
1275 field: u8,
1276 };
1277 const value = Struct{ .field = 42 };
1278 try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
1279 try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
1280 }
1281 {
1282 const Struct = struct {
1283 a: u0,
1284 b: u1,
1285 };
1286 const value = Struct{ .a = 0, .b = 1 };
1287 try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
1288 }
1289}
1290
1291test "enum" {
1292 const Enum = enum {
1293 One,
1294 Two,
1295 };
1296 const value = Enum.Two;
1297 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
1298 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
1299}
1300
1301test "non-exhaustive enum" {
1302 const Enum = enum(u16) {
1303 One = 0x000f,
1304 Two = 0xbeef,
1305 _,
1306 };
1307 try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
1308 try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
1309 try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
1310 try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
1311 try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
1312 try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
1313}
1314
1315test "float.scientific" {
1316 try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
1317 try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
1318 try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
1319 try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
1320}
1321
1322test "float.scientific.precision" {
1323 try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
1324 try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
1325 try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
1326 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
1327 // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
1328 try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
1329}
1330
1331test "float.special" {
1332 try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
1333 // negative nan is not defined by IEE 754,
1334 // and ARM thus normalizes it to positive nan
1335 if (builtin.arch != builtin.Arch.arm) {
1336 try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
1337 }
1338 try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
1339 try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
1340}
1341
1342test "float.decimal" {
1343 try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
1344 try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
1345 try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
1346 try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
1347 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
1348 // -11.12339... is rounded back up to -11.1234
1349 try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
1350 try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
1351 try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
1352 try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
1353 try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
1354 try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
1355 try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
1356 try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
1357 try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
1358 try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
1359}
1360
1361test "float.libc.sanity" {
1362 try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
1363 try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
1364 try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
1365 try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
1366 try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
1367
1368 // libc differences
1369 //
1370 // This is 0.015625 exactly according to gdb. We thus round down,
1371 // however glibc rounds up for some reason. This occurs for all
1372 // floats of the form x.yyyy25 on a precision point.
1373 try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
1374 // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
1375 // also rounds to 630 so I'm inclined to believe libc is not
1376 // optimal here.
1377 try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
1378}
1379
1380test "custom" {
1381 const Vec2 = struct {
1382 const SelfType = @This();
1383 x: f32,
1384 y: f32,
1385
1386 pub fn format(
1387 self: SelfType,
1388 comptime fmt: []const u8,
1389 options: FormatOptions,
1390 out_stream: var,
1391 ) !void {
1392 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
1393 return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
1394 } else if (comptime std.mem.eql(u8, fmt, "d")) {
1395 return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
1396 } else {
1397 @compileError("Unknown format character: '" ++ fmt ++ "'");
1398 }
1399 }
1400 };
1401
1402 var buf1: [32]u8 = undefined;
1403 var value = Vec2{
1404 .x = 10.2,
1405 .y = 2.22,
1406 };
1407 try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
1408 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
1409
1410 // same thing but not passing a pointer
1411 try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
1412 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
1413}
1414
1415test "struct" {
1416 const S = struct {
1417 a: u32,
1418 b: anyerror,
1419 };
1420
1421 const inst = S{
1422 .a = 456,
1423 .b = error.Unused,
1424 };
1425
1426 try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
1427}
1428
1429test "union" {
1430 const TU = union(enum) {
1431 float: f32,
1432 int: u32,
1433 };
1434
1435 const UU = union {
1436 float: f32,
1437 int: u32,
1438 };
1439
1440 const EU = extern union {
1441 float: f32,
1442 int: u32,
1443 };
1444
1445 const tu_inst = TU{ .int = 123 };
1446 const uu_inst = UU{ .int = 456 };
1447 const eu_inst = EU{ .float = 321.123 };
1448
1449 try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
1450
1451 var buf: [100]u8 = undefined;
1452 const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
1453 std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
1454
1455 const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
1456 std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
1457}
1458
1459test "enum" {
1460 const E = enum {
1461 One,
1462 Two,
1463 Three,
1464 };
1465
1466 const inst = E.Two;
1467
1468 try testFmt("E.Two", "{}", .{inst});
1469}
1470
1471test "struct.self-referential" {
1472 const S = struct {
1473 const SelfType = @This();
1474 a: ?*SelfType,
1475 };
1476
1477 var inst = S{
1478 .a = null,
1479 };
1480 inst.a = &inst;
1481
1482 try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
1483}
1484
1485test "struct.zero-size" {
1486 const A = struct {
1487 fn foo() void {}
1488 };
1489 const B = struct {
1490 a: A,
1491 c: i32,
1492 };
1493
1494 const a = A{};
1495 const b = B{ .a = a, .c = 0 };
1496
1497 try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
1498}
1499
1500test "bytes.hex" {
1501 const some_bytes = "\xCA\xFE\xBA\xBE";
1502 try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
1503 try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
1504 //Test Slices
1505 try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
1506 try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
1507 const bytes_with_zeros = "\x00\x0E\xBA\xBE";
1508 try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
1509}
1510
1511fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void {
1512 var buf: [100]u8 = undefined;
1513 const result = try bufPrint(buf[0..], template, args);
1514 if (mem.eql(u8, result, expected)) return;
1515
1516 std.debug.warn("\n====== expected this output: =========\n", .{});
1517 std.debug.warn("{}", .{expected});
1518 std.debug.warn("\n======== instead found this: =========\n", .{});
1519 std.debug.warn("{}", .{result});
1520 std.debug.warn("\n======================================\n", .{});
1521 return error.TestFailed;
1522}
1523
1524pub fn trim(buf: []const u8) []const u8 {
1525 var start: usize = 0;
1526 while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
1527
1528 var end: usize = buf.len;
1529 while (true) {
1530 if (end > start) {
1531 const new_end = end - 1;
1532 if (isWhiteSpace(buf[new_end])) {
1533 end = new_end;
1534 continue;
1535 }
1536 }
1537 break;
1538 }
1539 return buf[start..end];
1540}
1541
1542test "trim" {
1543 std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
1544 std.testing.expect(mem.eql(u8, "", trim(" ")));
1545 std.testing.expect(mem.eql(u8, "", trim("")));
1546 std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
1547 std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
1548}
1549
1550pub fn isWhiteSpace(byte: u8) bool {
1551 return switch (byte) {
1552 ' ', '\t', '\n', '\r' => true,
1553 else => false,
1554 };
1555}
1556
1557pub fn hexToBytes(out: []u8, input: []const u8) !void {
1558 if (out.len * 2 < input.len)
1559 return error.InvalidLength;
1560
1561 var in_i: usize = 0;
1562 while (in_i != input.len) : (in_i += 2) {
1563 const hi = try charToDigit(input[in_i], 16);
1564 const lo = try charToDigit(input[in_i + 1], 16);
1565 out[in_i / 2] = (hi << 4) | lo;
1566 }
1567}
1568
1569test "hexToBytes" {
1570 const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
1571 var pb: [32]u8 = undefined;
1572 try hexToBytes(pb[0..], test_hex_str);
1573 try testFmt(test_hex_str, "{X}", .{pb});
1574}
1575
1576test "formatIntValue with comptime_int" {
1577 const value: comptime_int = 123456789123456789;
1578
1579 var buf: [20]u8 = undefined;
1580 var fbs = std.io.fixedBufferStream(&buf);
1581 try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
1582 std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789"));
1583}
1584
1585test "formatType max_depth" {
1586 const Vec2 = struct {
1587 const SelfType = @This();
1588 x: f32,
1589 y: f32,
1590
1591 pub fn format(
1592 self: SelfType,
1593 comptime fmt: []const u8,
1594 options: FormatOptions,
1595 out_stream: var,
1596 ) !void {
1597 if (fmt.len == 0) {
1598 return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
1599 } else {
1600 @compileError("Unknown format string: '" ++ fmt ++ "'");
1601 }
1602 }
1603 };
1604 const E = enum {
1605 One,
1606 Two,
1607 Three,
1608 };
1609 const TU = union(enum) {
1610 const SelfType = @This();
1611 float: f32,
1612 int: u32,
1613 ptr: ?*SelfType,
1614 };
1615 const S = struct {
1616 const SelfType = @This();
1617 a: ?*SelfType,
1618 tu: TU,
1619 e: E,
1620 vec: Vec2,
1621 };
1622
1623 var inst = S{
1624 .a = null,
1625 .tu = TU{ .ptr = null },
1626 .e = E.Two,
1627 .vec = Vec2{ .x = 10.2, .y = 2.22 },
1628 };
1629 inst.a = &inst;
1630 inst.tu.ptr = &inst.tu;
1631
1632 var buf: [1000]u8 = undefined;
1633 var fbs = std.io.fixedBufferStream(&buf);
1634 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0);
1635 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }"));
1636
1637 fbs.reset();
1638 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1);
1639 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
1640
1641 fbs.reset();
1642 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2);
1643 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) }"));
1644
1645 fbs.reset();
1646 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3);
1647 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) }"));
1648}
1649
1650test "positional" {
1651 try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
1652 try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
1653 try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
1654 try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
1655 try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
1656}
1657
1658test "positional with specifier" {
1659 try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
1660}
1661
1662test "positional/alignment/width/precision" {
1663 try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
1664}
1665
1666test "vector" {
1667 // https://github.com/ziglang/zig/issues/3317
1668 if (builtin.arch == .mipsel) return error.SkipZigTest;
1669
1670 const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
1671 const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
1672 const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
1673
1674 try testFmt("{ true, false, true, false }", "{}", .{vbool});
1675 try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
1676 try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
1677 try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
1678 try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
1679 try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
1680 try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
1681}
1682
1683test "enum-literal" {
1684 try testFmt(".hello_world", "{}", .{.hello_world});
1685}
lib/std/http/headers.zig+2-2
......@@ -349,7 +349,7 @@ pub const Headers = struct {
349349 pub fn format(
350350 self: Self,
351351 comptime fmt: []const u8,
352 options: std.fmtstream.FormatOptions,
352 options: std.fmt.FormatOptions,
353353 out_stream: var,
354354 ) !void {
355355 for (self.toSlice()) |entry| {
......@@ -591,5 +591,5 @@ test "Headers.format" {
591591 \\foo: bar
592592 \\cookie: somevalue
593593 \\
594 , try std.fmtstream.bufPrint(buf[0..], "{}", .{h}));
594 , try std.fmt.bufPrint(buf[0..], "{}", .{h}));
595595}
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.fmtstream.format(self, 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+5-5
......@@ -2257,10 +2257,10 @@ pub fn stringify(
22572257 const T = @TypeOf(value);
22582258 switch (@typeInfo(T)) {
22592259 .Float, .ComptimeFloat => {
2260 return std.fmtstream.formatFloatScientific(value, std.fmtstream.FormatOptions{}, out_stream);
2260 return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, out_stream);
22612261 },
22622262 .Int, .ComptimeInt => {
2263 return std.fmtstream.formatIntValue(value, "", std.fmtstream.FormatOptions{}, out_stream);
2263 return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, out_stream);
22642264 },
22652265 .Bool => {
22662266 return out_stream.writeAll(if (value) "true" else "false");
......@@ -2350,16 +2350,16 @@ pub fn stringify(
23502350 // then it may be represented as a six-character sequence: a reverse solidus, followed
23512351 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
23522352 try out_stream.writeAll("\\u");
2353 try std.fmtstream.formatIntValue(codepoint, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
2353 try std.fmt.formatIntValue(codepoint, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
23542354 } else {
23552355 // To escape an extended character that is not in the Basic Multilingual Plane,
23562356 // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.
23572357 const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;
23582358 const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;
23592359 try out_stream.writeAll("\\u");
2360 try std.fmtstream.formatIntValue(high, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
2360 try std.fmt.formatIntValue(high, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
23612361 try out_stream.writeAll("\\u");
2362 try std.fmtstream.formatIntValue(low, "x", std.fmtstream.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
2362 try std.fmt.formatIntValue(low, "x", std.fmt.FormatOptions{ .width = 4, .fill = '0' }, out_stream);
23632363 }
23642364 i += ulen - 1;
23652365 },
lib/std/math/big/int.zig+1-1
......@@ -518,7 +518,7 @@ pub const Int = struct {
518518 pub fn format(
519519 self: Int,
520520 comptime fmt: []const u8,
521 options: std.fmtstream.FormatOptions,
521 options: std.fmt.FormatOptions,
522522 out_stream: var,
523523 ) FmtError!void {
524524 self.assertWritable();
lib/std/net.zig+7-7
......@@ -268,14 +268,14 @@ pub const Address = extern union {
268268 pub fn format(
269269 self: Address,
270270 comptime fmt: []const u8,
271 options: std.fmtstream.FormatOptions,
271 options: std.fmt.FormatOptions,
272272 out_stream: var,
273273 ) !void {
274274 switch (self.any.family) {
275275 os.AF_INET => {
276276 const port = mem.bigToNative(u16, self.in.port);
277277 const bytes = @ptrCast(*const [4]u8, &self.in.addr);
278 try std.fmtstream.format(out_stream, "{}.{}.{}.{}:{}", .{
278 try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
279279 bytes[0],
280280 bytes[1],
281281 bytes[2],
......@@ -286,7 +286,7 @@ pub const Address = extern union {
286286 os.AF_INET6 => {
287287 const port = mem.bigToNative(u16, self.in6.port);
288288 if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
289 try std.fmtstream.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
289 try std.fmt.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
290290 self.in6.addr[12],
291291 self.in6.addr[13],
292292 self.in6.addr[14],
......@@ -317,19 +317,19 @@ pub const Address = extern union {
317317 }
318318 continue;
319319 }
320 try std.fmtstream.format(out_stream, "{x}", .{native_endian_parts[i]});
320 try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});
321321 if (i != native_endian_parts.len - 1) {
322322 try out_stream.writeAll(":");
323323 }
324324 }
325 try std.fmtstream.format(out_stream, "]:{}", .{port});
325 try std.fmt.format(out_stream, "]:{}", .{port});
326326 },
327327 os.AF_UNIX => {
328328 if (!has_unix_sockets) {
329329 unreachable;
330330 }
331331
332 try std.fmtstream.format(out_stream, "{}", .{&self.un.path});
332 try std.fmt.format(out_stream, "{}", .{&self.un.path});
333333 },
334334 else => unreachable,
335335 }
......@@ -438,7 +438,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
438438 const name_c = try std.cstr.addNullByte(allocator, name);
439439 defer allocator.free(name_c);
440440
441 const port_c = try std.fmtstream.allocPrint(allocator, "{}\x00", .{port});
441 const port_c = try std.fmt.allocPrint(allocator, "{}\x00", .{port});
442442 defer allocator.free(port_c);
443443
444444 const hints = os.addrinfo{
lib/std/net/test.zig+2-2
......@@ -29,7 +29,7 @@ test "parse and render IPv6 addresses" {
2929 };
3030 for (ips) |ip, i| {
3131 var addr = net.Address.parseIp6(ip, 0) catch unreachable;
32 var newIp = std.fmtstream.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
32 var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
3333 std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
3434 }
3535
......@@ -51,7 +51,7 @@ test "parse and render IPv4 addresses" {
5151 "127.0.0.1",
5252 }) |ip| {
5353 var addr = net.Address.parseIp4(ip, 0) catch unreachable;
54 var newIp = std.fmtstream.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
54 var newIp = std.fmt.bufPrint(buffer[0..], "{}", .{addr}) catch unreachable;
5555 std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
5656 }
5757
lib/std/os.zig+1-1
......@@ -3049,7 +3049,7 @@ pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP
30493049 defer close(fd);
30503050
30513051 var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined;
3052 const proc_path = std.fmtstream.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", .{fd}) catch unreachable;
3052 const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", .{fd}) catch unreachable;
30533053
30543054 return readlinkC(@ptrCast([*:0]const u8, proc_path.ptr), out_buffer);
30553055 }
lib/std/os/uefi.zig+2-2
......@@ -27,11 +27,11 @@ pub const Guid = extern struct {
2727 pub fn format(
2828 self: @This(),
2929 comptime f: []const u8,
30 options: std.fmtstream.FormatOptions,
30 options: std.fmt.FormatOptions,
3131 out_stream: var,
3232 ) Errors!void {
3333 if (f.len == 0) {
34 return std.fmtstream.format(out_stream, "{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}", .{
3535 self.time_low,
3636 self.time_mid,
3737 self.time_high_and_version,
lib/std/progress.zig+3-3
......@@ -130,11 +130,11 @@ pub const Progress = struct {
130130 var end: usize = 0;
131131 if (self.columns_written > 0) {
132132 // restore cursor position
133 end += (std.fmtstream.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len;
133 end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", .{self.columns_written}) catch unreachable).len;
134134 self.columns_written = 0;
135135
136136 // clear rest of line
137 end += (std.fmtstream.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
137 end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
138138 }
139139
140140 if (!self.done) {
......@@ -185,7 +185,7 @@ pub const Progress = struct {
185185 }
186186
187187 fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: var) void {
188 if (std.fmtstream.bufPrint(self.output_buffer[end.*..], format, args)) |written| {
188 if (std.fmt.bufPrint(self.output_buffer[end.*..], format, args)) |written| {
189189 const amt = written.len;
190190 end.* += amt;
191191 self.columns_written += amt;
lib/std/special/build_runner.zig+3-3
......@@ -2,7 +2,7 @@ const root = @import("@build");
22const std = @import("std");
33const builtin = @import("builtin");
44const io = std.io;
5const fmtstream = std.fmtstream;
5const fmt = std.fmt;
66const Builder = std.build.Builder;
77const mem = std.mem;
88const process = std.process;
......@@ -153,7 +153,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
153153 const allocator = builder.allocator;
154154 for (builder.top_level_steps.toSliceConst()) |top_level_step| {
155155 const name = if (&top_level_step.step == builder.default_step)
156 try fmtstream.allocPrint(allocator, "{} (default)", .{top_level_step.step.name})
156 try fmt.allocPrint(allocator, "{} (default)", .{top_level_step.step.name})
157157 else
158158 top_level_step.step.name;
159159 try out_stream.print(" {s:22} {}\n", .{ name, top_level_step.description });
......@@ -175,7 +175,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
175175 try out_stream.print(" (none)\n", .{});
176176 } else {
177177 for (builder.available_options_list.toSliceConst()) |option| {
178 const name = try fmtstream.allocPrint(allocator, " -D{}=[{}]", .{
178 const name = try fmt.allocPrint(allocator, " -D{}=[{}]", .{
179179 option.name,
180180 Builder.typeIdName(option.type_id),
181181 });
lib/std/std.zig-1
......@@ -38,7 +38,6 @@ pub const elf = @import("elf.zig");
3838pub const event = @import("event.zig");
3939pub const fifo = @import("fifo.zig");
4040pub const fmt = @import("fmt.zig");
41pub const fmtstream = @import("fmtstream.zig");
4241pub const fs = @import("fs.zig");
4342pub const hash = @import("hash.zig");
4443pub const hash_map = @import("hash_map.zig");
lib/std/target.zig+2-2
......@@ -972,7 +972,7 @@ pub const Target = struct {
972972 }
973973
974974 pub fn linuxTripleSimple(allocator: *mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![:0]u8 {
975 return std.fmtstream.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
975 return std.fmt.allocPrint0(allocator, "{}-{}-{}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
976976 }
977977
978978 pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 {
......@@ -1158,7 +1158,7 @@ pub const Target = struct {
11581158 var result: DynamicLinker = .{};
11591159 const S = struct {
11601160 fn print(r: *DynamicLinker, comptime fmt: []const u8, args: var) DynamicLinker {
1161 r.max_byte = @intCast(u8, (std.fmtstream.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1);
1161 r.max_byte = @intCast(u8, (std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1);
11621162 return r.*;
11631163 }
11641164 fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {
lib/std/zig/cross_target.zig+1-1
......@@ -573,7 +573,7 @@ pub const CrossTarget = struct {
573573 .Dynamic => "",
574574 };
575575
576 return std.fmtstream.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix });
576 return std.fmt.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix });
577577 }
578578
579579 pub const Executor = union(enum) {
lib/std/zig/system.zig+3-3
......@@ -130,7 +130,7 @@ pub const NativePaths = struct {
130130 }
131131
132132 pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
133 const item = try std.fmtstream.allocPrint0(self.include_dirs.allocator, fmt, args);
133 const item = try std.fmt.allocPrint0(self.include_dirs.allocator, fmt, args);
134134 errdefer self.include_dirs.allocator.free(item);
135135 try self.include_dirs.append(item);
136136 }
......@@ -140,7 +140,7 @@ pub const NativePaths = struct {
140140 }
141141
142142 pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
143 const item = try std.fmtstream.allocPrint0(self.lib_dirs.allocator, fmt, args);
143 const item = try std.fmt.allocPrint0(self.lib_dirs.allocator, fmt, args);
144144 errdefer self.lib_dirs.allocator.free(item);
145145 try self.lib_dirs.append(item);
146146 }
......@@ -150,7 +150,7 @@ pub const NativePaths = struct {
150150 }
151151
152152 pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
153 const item = try std.fmtstream.allocPrint0(self.warnings.allocator, fmt, args);
153 const item = try std.fmt.allocPrint0(self.warnings.allocator, fmt, args);
154154 errdefer self.warnings.allocator.free(item);
155155 try self.warnings.append(item);
156156 }
src-self-hosted/compilation.zig+3-3
......@@ -1051,7 +1051,7 @@ pub const Compilation = struct {
10511051 }
10521052
10531053 fn addCompileError(self: *Compilation, tree_scope: *Scope.AstTree, span: Span, comptime fmt: []const u8, args: var) !void {
1054 const text = try std.fmtstream.allocPrint(self.gpa(), fmt, args);
1054 const text = try std.fmt.allocPrint(self.gpa(), fmt, args);
10551055 errdefer self.gpa().free(text);
10561056
10571057 const msg = try Msg.createFromScope(self, tree_scope, span, text);
......@@ -1061,7 +1061,7 @@ pub const Compilation = struct {
10611061 }
10621062
10631063 fn addCompileErrorCli(self: *Compilation, realpath: []const u8, comptime fmt: []const u8, args: var) !void {
1064 const text = try std.fmtstream.allocPrint(self.gpa(), fmt, args);
1064 const text = try std.fmt.allocPrint(self.gpa(), fmt, args);
10651065 errdefer self.gpa().free(text);
10661066
10671067 const msg = try Msg.createFromCli(self, realpath, text);
......@@ -1154,7 +1154,7 @@ pub const Compilation = struct {
11541154 const tmp_dir = try self.getTmpDir();
11551155 const file_prefix = self.getRandomFileName();
11561156
1157 const file_name = try std.fmtstream.allocPrint(self.gpa(), "{}{}", .{ file_prefix[0..], suffix });
1157 const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", .{ file_prefix[0..], suffix });
11581158 defer self.gpa().free(file_name);
11591159
11601160 const full_path = try fs.path.join(self.gpa(), &[_][]const u8{ tmp_dir, file_name[0..] });
src-self-hosted/dep_tokenizer.zig+3-3
......@@ -893,7 +893,7 @@ fn printSection(out: var, label: []const u8, bytes: []const u8) !void {
893893
894894fn printLabel(out: var, label: []const u8, bytes: []const u8) !void {
895895 var buf: [80]u8 = undefined;
896 var text = try std.fmtstream.bufPrint(buf[0..], "{} {} bytes ", .{ label, bytes.len });
896 var text = try std.fmt.bufPrint(buf[0..], "{} {} bytes ", .{ label, bytes.len });
897897 try out.write(text);
898898 var i: usize = text.len;
899899 const end = 79;
......@@ -979,13 +979,13 @@ fn hexDump16(out: var, offset: usize, bytes: []const u8) !void {
979979
980980fn printDecValue(out: var, value: u64, width: u8) !void {
981981 var buffer: [20]u8 = undefined;
982 const len = std.fmtstream.formatIntBuf(buffer[0..], value, 10, false, width);
982 const len = std.fmt.formatIntBuf(buffer[0..], value, 10, false, width);
983983 try out.write(buffer[0..len]);
984984}
985985
986986fn printHexValue(out: var, value: u64, width: u8) !void {
987987 var buffer: [16]u8 = undefined;
988 const len = std.fmtstream.formatIntBuf(buffer[0..], value, 16, false, width);
988 const len = std.fmt.formatIntBuf(buffer[0..], value, 16, false, width);
989989 try out.write(buffer[0..len]);
990990}
991991
src-self-hosted/libc_installation.zig+1-1
......@@ -543,7 +543,7 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
543543 const allocator = args.allocator;
544544
545545 const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
546 const arg1 = try std.fmtstream.allocPrint(allocator, "-print-file-name={}", .{args.search_basename});
546 const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{args.search_basename});
547547 defer allocator.free(arg1);
548548 const argv = [_][]const u8{ cc_exe, arg1 };
549549
src-self-hosted/link.zig+10-10
......@@ -296,13 +296,13 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
296296
297297 const is_library = ctx.comp.kind == .Lib;
298298
299 const out_arg = try std.fmtstream.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()});
299 const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()});
300300 try ctx.args.append(@ptrCast([*:0]const u8, out_arg.ptr));
301301
302302 if (ctx.comp.haveLibC()) {
303 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));
304 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));
305 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr));
303 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));
304 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));
305 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr));
306306 }
307307
308308 if (ctx.link_in_crt) {
......@@ -310,20 +310,20 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
310310 const d_str = if (ctx.comp.build_mode == .Debug) "d" else "";
311311
312312 if (ctx.comp.is_static) {
313 const cmt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", .{d_str});
313 const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", .{d_str});
314314 try ctx.args.append(@ptrCast([*:0]const u8, cmt_lib_name.ptr));
315315 } else {
316 const msvcrt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", .{d_str});
316 const msvcrt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", .{d_str});
317317 try ctx.args.append(@ptrCast([*:0]const u8, msvcrt_lib_name.ptr));
318318 }
319319
320 const vcruntime_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", .{
320 const vcruntime_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", .{
321321 lib_str,
322322 d_str,
323323 });
324324 try ctx.args.append(@ptrCast([*:0]const u8, vcruntime_lib_name.ptr));
325325
326 const crt_lib_name = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", .{ lib_str, d_str });
326 const crt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", .{ lib_str, d_str });
327327 try ctx.args.append(@ptrCast([*:0]const u8, crt_lib_name.ptr));
328328
329329 // Visual C++ 2015 Conformance Changes
......@@ -383,7 +383,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
383383 .IPhoneOS => try ctx.args.append("-iphoneos_version_min"),
384384 .IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),
385385 }
386 const ver_str = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{
386 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{
387387 platform.major,
388388 platform.minor,
389389 platform.micro,
......@@ -445,7 +445,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
445445 try ctx.args.append("-lSystem");
446446 } else {
447447 if (mem.indexOfScalar(u8, lib.name, '/') == null) {
448 const arg = try std.fmtstream.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
448 const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
449449 try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
450450 } else {
451451 const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
src-self-hosted/print_targets.zig+1-1
......@@ -138,7 +138,7 @@ pub fn cmdTargets(
138138 for (available_glibcs) |glibc| {
139139 try jws.arrayElem();
140140
141 const tmp = try std.fmtstream.allocPrint(allocator, "{}", .{glibc});
141 const tmp = try std.fmt.allocPrint(allocator, "{}", .{glibc});
142142 defer allocator.free(tmp);
143143 try jws.emitString(tmp);
144144 }
src-self-hosted/test.zig+3-3
......@@ -81,7 +81,7 @@ pub const TestContext = struct {
8181 msg: []const u8,
8282 ) !void {
8383 var file_index_buf: [20]u8 = undefined;
84 const file_index = try std.fmtstream.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
84 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
8585 const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
8686
8787 if (std.fs.path.dirname(file1_path)) |dirname| {
......@@ -114,10 +114,10 @@ pub const TestContext = struct {
114114 expected_output: []const u8,
115115 ) !void {
116116 var file_index_buf: [20]u8 = undefined;
117 const file_index = try std.fmtstream.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
117 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", .{self.file_index.incr()});
118118 const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
119119
120 const output_file = try std.fmtstream.allocPrint(allocator, "{}-out{}", .{ file1_path, (Target{ .Native = {} }).exeFileExt() });
120 const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", .{ file1_path, (Target{ .Native = {} }).exeFileExt() });
121121 if (std.fs.path.dirname(file1_path)) |dirname| {
122122 try std.fs.cwd().makePath(dirname);
123123 }
src-self-hosted/translate_c.zig+22-22
......@@ -89,7 +89,7 @@ const Scope = struct {
8989 var proposed_name = name;
9090 while (scope.contains(proposed_name)) {
9191 scope.mangle_count += 1;
92 proposed_name = try std.fmtstream.allocPrint(c.a(), "{}_{}", .{ name, scope.mangle_count });
92 proposed_name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, scope.mangle_count });
9393 }
9494 try scope.variables.push(.{ .name = name, .alias = proposed_name });
9595 return proposed_name;
......@@ -246,7 +246,7 @@ pub const Context = struct {
246246
247247 const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc);
248248 const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc);
249 return std.fmtstream.allocPrint(c.a(), "{}:{}:{}", .{ filename, line, column });
249 return std.fmt.allocPrint(c.a(), "{}:{}:{}", .{ filename, line, column });
250250 }
251251};
252252
......@@ -516,7 +516,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
516516
517517 const arg_name = blk: {
518518 const param_prefix = if (is_const) "" else "arg_";
519 const bare_arg_name = try std.fmtstream.allocPrint(c.a(), "{}{}", .{ param_prefix, mangled_param_name });
519 const bare_arg_name = try std.fmt.allocPrint(c.a(), "{}{}", .{ param_prefix, mangled_param_name });
520520 break :blk try block_scope.makeMangledName(c, bare_arg_name);
521521 };
522522
......@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
560560
561561 // TODO https://github.com/ziglang/zig/issues/3756
562562 // TODO https://github.com/ziglang/zig/issues/1802
563 const checked_name = if (isZigPrimitiveType(var_name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name;
563 const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ var_name, c.getMangle() }) else var_name;
564564 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
565565
566566 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
......@@ -620,7 +620,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
620620 _ = try appendToken(rp.c, .LParen, "(");
621621 const expr = try transCreateNodeStringLiteral(
622622 rp.c,
623 try std.fmtstream.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
623 try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
624624 );
625625 _ = try appendToken(rp.c, .RParen, ")");
626626
......@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l
677677
678678 // TODO https://github.com/ziglang/zig/issues/3756
679679 // TODO https://github.com/ziglang/zig/issues/1802
680 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name;
680 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name;
681681
682682 if (mem.eql(u8, checked_name, "uint8_t"))
683683 return transTypeDefAsBuiltin(c, typedef_decl, "u8")
......@@ -738,7 +738,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
738738 // Record declarations such as `struct {...} x` have no name but they're not
739739 // anonymous hence here isAnonymousStructOrUnion is not needed
740740 if (bare_name.len == 0) {
741 bare_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
741 bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
742742 is_unnamed = true;
743743 }
744744
......@@ -755,7 +755,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
755755 return null;
756756 }
757757
758 const name = try std.fmtstream.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
758 const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
759759 _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
760760
761761 const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
......@@ -812,7 +812,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
812812 var is_anon = false;
813813 var raw_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, field_decl)));
814814 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {
815 raw_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
815 raw_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
816816 is_anon = true;
817817 }
818818 const field_name = try appendIdentifier(c, raw_name);
......@@ -882,11 +882,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No
882882 var bare_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, enum_decl)));
883883 var is_unnamed = false;
884884 if (bare_name.len == 0) {
885 bare_name = try std.fmtstream.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
885 bare_name = try std.fmt.allocPrint(c.a(), "unnamed_{}", .{c.getMangle()});
886886 is_unnamed = true;
887887 }
888888
889 const name = try std.fmtstream.allocPrint(c.a(), "enum_{}", .{bare_name});
889 const name = try std.fmt.allocPrint(c.a(), "enum_{}", .{bare_name});
890890 _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
891891 const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
892892 node.eq_token = try appendToken(c, .Equal, "=");
......@@ -1754,9 +1754,9 @@ fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
17541754 // Handle the remaining escapes Zig doesn't support by turning them
17551755 // into their respective hex representation
17561756 if (std.ascii.isCntrl(c))
1757 return std.fmtstream.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable
1757 return std.fmt.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable
17581758 else
1759 return std.fmtstream.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
1759 return std.fmt.bufPrint(char_buf[0..], "{c}", .{c}) catch unreachable;
17601760 },
17611761 };
17621762}
......@@ -2436,7 +2436,7 @@ fn transCase(
24362436) TransError!*ast.Node {
24372437 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
24382438 const switch_scope = scope.getSwitch();
2439 const label = try std.fmtstream.allocPrint(rp.c.a(), "__case_{}", .{switch_scope.cases.len - @boolToInt(switch_scope.has_default)});
2439 const label = try std.fmt.allocPrint(rp.c.a(), "__case_{}", .{switch_scope.cases.len - @boolToInt(switch_scope.has_default)});
24402440 _ = try appendToken(rp.c, .Semicolon, ";");
24412441
24422442 const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {
......@@ -4607,7 +4607,7 @@ fn finishTransFnProto(
46074607 _ = try appendToken(rp.c, .LParen, "(");
46084608 const expr = try transCreateNodeStringLiteral(
46094609 rp.c,
4610 try std.fmtstream.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
4610 try std.fmt.allocPrint(rp.c.a(), "\"{}\"", .{str_ptr[0..str_len]}),
46114611 );
46124612 _ = try appendToken(rp.c, .RParen, ")");
46134613
......@@ -4866,7 +4866,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
48664866 const name = try c.str(raw_name);
48674867 // TODO https://github.com/ziglang/zig/issues/3756
48684868 // TODO https://github.com/ziglang/zig/issues/1802
4869 const mangled_name = if (isZigPrimitiveType(name)) try std.fmtstream.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name;
4869 const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }) else name;
48704870 if (scope.containsNow(mangled_name)) {
48714871 continue;
48724872 }
......@@ -5151,11 +5151,11 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl
51515151 switch (lit_bytes[1]) {
51525152 '0'...'7' => {
51535153 // Octal
5154 lit_bytes = try std.fmtstream.allocPrint(c.a(), "0o{}", .{lit_bytes});
5154 lit_bytes = try std.fmt.allocPrint(c.a(), "0o{}", .{lit_bytes});
51555155 },
51565156 'X' => {
51575157 // Hexadecimal with capital X, valid in C but not in Zig
5158 lit_bytes = try std.fmtstream.allocPrint(c.a(), "0x{}", .{lit_bytes[2..]});
5158 lit_bytes = try std.fmt.allocPrint(c.a(), "0x{}", .{lit_bytes[2..]});
51595159 },
51605160 else => {},
51615161 }
......@@ -5186,7 +5186,7 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl
51865186 return &cast_node.base;
51875187 } else if (tok.id == .FloatLiteral) {
51885188 if (lit_bytes[0] == '.')
5189 lit_bytes = try std.fmtstream.allocPrint(c.a(), "0{}", .{lit_bytes});
5189 lit_bytes = try std.fmt.allocPrint(c.a(), "0{}", .{lit_bytes});
51905190 if (tok.id.FloatLiteral == .None) {
51915191 return transCreateNodeFloat(c, lit_bytes);
51925192 }
......@@ -5319,7 +5319,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
53195319 num += c - 'A' + 10;
53205320 },
53215321 else => {
5322 i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 });
5322 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
53235323 num = 0;
53245324 if (c == '\\')
53255325 state = .Escape
......@@ -5345,7 +5345,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
53455345 };
53465346 num += c - '0';
53475347 } else {
5348 i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 });
5348 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
53495349 num = 0;
53505350 count = 0;
53515351 if (c == '\\')
......@@ -5359,7 +5359,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
53595359 }
53605360 }
53615361 if (state == .Hex or state == .Octal)
5362 i += std.fmtstream.formatIntBuf(bytes[i..], num, 16, false, std.fmtstream.FormatOptions{ .fill = '0', .width = 2 });
5362 i += std.fmt.formatIntBuf(bytes[i..], num, 16, false, std.fmt.FormatOptions{ .fill = '0', .width = 2 });
53635363 return bytes[0..i];
53645364}
53655365
src-self-hosted/type.zig+4-4
......@@ -581,7 +581,7 @@ pub const Type = struct {
581581 errdefer comp.gpa().destroy(self);
582582
583583 const u_or_i = "ui"[@boolToInt(key.is_signed)];
584 const name = try std.fmtstream.allocPrint(comp.gpa(), "{c}{}", .{ u_or_i, key.bit_count });
584 const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", .{ u_or_i, key.bit_count });
585585 errdefer comp.gpa().free(name);
586586
587587 self.base.init(comp, .Int, name);
......@@ -764,13 +764,13 @@ pub const Type = struct {
764764 .Non => "",
765765 };
766766 const name = switch (self.key.alignment) {
767 .Abi => try std.fmtstream.allocPrint(comp.gpa(), "{}{}{}{}", .{
767 .Abi => try std.fmt.allocPrint(comp.gpa(), "{}{}{}{}", .{
768768 size_str,
769769 mut_str,
770770 vol_str,
771771 self.key.child_type.name,
772772 }),
773 .Override => |alignment| try std.fmtstream.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{
773 .Override => |alignment| try std.fmt.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{
774774 size_str,
775775 alignment,
776776 mut_str,
......@@ -845,7 +845,7 @@ pub const Type = struct {
845845 };
846846 errdefer comp.gpa().destroy(self);
847847
848 const name = try std.fmtstream.allocPrint(comp.gpa(), "[{}]{}", .{ key.len, key.elem_type.name });
848 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", .{ key.len, key.elem_type.name });
849849 errdefer comp.gpa().free(name);
850850
851851 self.base.init(comp, .Array, name);
test/src/compare_output.zig+4-4
......@@ -4,7 +4,7 @@ const std = @import("std");
44const builtin = std.builtin;
55const build = std.build;
66const ArrayList = std.ArrayList;
7const fmtstream = std.fmtstream;
7const fmt = std.fmt;
88const mem = std.mem;
99const fs = std.fs;
1010const warn = std.debug.warn;
......@@ -97,7 +97,7 @@ pub const CompareOutputContext = struct {
9797
9898 switch (case.special) {
9999 Special.Asm => {
100 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "assemble-and-link {}", .{
100 const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", .{
101101 case.name,
102102 }) catch unreachable;
103103 if (self.test_filter) |filter| {
......@@ -116,7 +116,7 @@ pub const CompareOutputContext = struct {
116116 },
117117 Special.None => {
118118 for (self.modes) |mode| {
119 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {} ({})", .{
119 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", .{
120120 "compare-output",
121121 case.name,
122122 @tagName(mode),
......@@ -141,7 +141,7 @@ pub const CompareOutputContext = struct {
141141 }
142142 },
143143 Special.RuntimeSafety => {
144 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "safety {}", .{case.name}) catch unreachable;
144 const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", .{case.name}) catch unreachable;
145145 if (self.test_filter) |filter| {
146146 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
147147 }
test/src/run_translated_c.zig+2-2
......@@ -3,7 +3,7 @@
33const std = @import("std");
44const build = std.build;
55const ArrayList = std.ArrayList;
6const fmtstream = std.fmtstream;
6const fmt = std.fmt;
77const mem = std.mem;
88const fs = std.fs;
99const warn = std.debug.warn;
......@@ -76,7 +76,7 @@ pub const RunTranslatedCContext = struct {
7676 pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
7777 const b = self.b;
7878
79 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "run-translated-c {}", .{case.name}) catch unreachable;
79 const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {}", .{case.name}) catch unreachable;
8080 if (self.test_filter) |filter| {
8181 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
8282 }
test/src/translate_c.zig+2-2
......@@ -3,7 +3,7 @@
33const std = @import("std");
44const build = std.build;
55const ArrayList = std.ArrayList;
6const fmtstream = std.fmtstream;
6const fmt = std.fmt;
77const mem = std.mem;
88const fs = std.fs;
99const warn = std.debug.warn;
......@@ -99,7 +99,7 @@ pub const TranslateCContext = struct {
9999 const b = self.b;
100100
101101 const translate_c_cmd = "translate-c";
102 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable;
102 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable;
103103 if (self.test_filter) |filter| {
104104 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
105105 }
test/stage1/behavior/enum_with_members.zig+3-3
......@@ -1,6 +1,6 @@
11const expect = @import("std").testing.expect;
22const mem = @import("std").mem;
3const fmtstream = @import("std").fmtstream;
3const fmt = @import("std").fmt;
44
55const ET = union(enum) {
66 SINT: i32,
......@@ -8,8 +8,8 @@ const ET = union(enum) {
88
99 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
1010 return switch (a.*) {
11 ET.SINT => |x| fmtstream.formatIntBuf(buf, x, 10, false, fmtstream.FormatOptions{}),
12 ET.UINT => |x| fmtstream.formatIntBuf(buf, x, 10, false, fmtstream.FormatOptions{}),
11 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
1313 };
1414 }
1515};
test/tests.zig+5-5
......@@ -8,7 +8,7 @@ const Buffer = std.Buffer;
88const io = std.io;
99const fs = std.fs;
1010const mem = std.mem;
11const fmtstream = std.fmtstream;
11const fmt = std.fmt;
1212const ArrayList = std.ArrayList;
1313const Mode = builtin.Mode;
1414const LibExeObjStep = build.LibExeObjStep;
......@@ -484,7 +484,7 @@ pub const StackTracesContext = struct {
484484 const expect_for_mode = expect[@enumToInt(mode)];
485485 if (expect_for_mode.len == 0) continue;
486486
487 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {} ({})", .{
487 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", .{
488488 "stack-trace",
489489 name,
490490 @tagName(mode),
......@@ -943,7 +943,7 @@ pub const CompileErrorContext = struct {
943943 pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
944944 const b = self.b;
945945
946 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "compile-error {}", .{
946 const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {}", .{
947947 case.name,
948948 }) catch unreachable;
949949 if (self.test_filter) |filter| {
......@@ -1009,7 +1009,7 @@ pub const StandaloneContext = struct {
10091009 const b = self.b;
10101010
10111011 for (self.modes) |mode| {
1012 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "build {} ({})", .{
1012 const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", .{
10131013 root_src,
10141014 @tagName(mode),
10151015 }) catch unreachable;
......@@ -1152,7 +1152,7 @@ pub const GenHContext = struct {
11521152 const b = self.b;
11531153
11541154 const mode = builtin.Mode.Debug;
1155 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "gen-h {} ({})", .{ case.name, @tagName(mode) }) catch unreachable;
1155 const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", .{ case.name, @tagName(mode) }) catch unreachable;
11561156 if (self.test_filter) |filter| {
11571157 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
11581158 }
tools/process_headers.zig+2-2
......@@ -299,7 +299,7 @@ pub fn main() !void {
299299 std.debug.warn("unrecognized C ABI: {}\n", .{abi_name});
300300 usageAndExit(args[0]);
301301 };
302 const generic_name = try std.fmtstream.allocPrint(allocator, "generic-{}", .{abi_name});
302 const generic_name = try std.fmt.allocPrint(allocator, "generic-{}", .{abi_name});
303303
304304 // TODO compiler crashed when I wrote this the canonical way
305305 var libc_targets: []const LibCTarget = undefined;
......@@ -440,7 +440,7 @@ pub fn main() !void {
440440 .specific => |a| @tagName(a),
441441 else => @tagName(dest_target.arch),
442442 };
443 const out_subpath = try std.fmtstream.allocPrint(allocator, "{}-{}-{}", .{
443 const out_subpath = try std.fmt.allocPrint(allocator, "{}-{}-{}", .{
444444 arch_name,
445445 @tagName(dest_target.os),
446446 @tagName(dest_target.abi),
tools/update_glibc.zig+2-2
......@@ -1,6 +1,6 @@
11const std = @import("std");
22const fs = std.fs;
3const fmtstream = std.fmtstream;
3const fmt = std.fmt;
44const assert = std.debug.assert;
55
66// Example abilist path:
......@@ -154,7 +154,7 @@ pub fn main() !void {
154154 const fn_set = &target_funcs_gop.kv.value.list;
155155
156156 for (lib_names) |lib_name, lib_name_index| {
157 const basename = try fmtstream.allocPrint(allocator, "lib{}.abilist", .{lib_name});
157 const basename = try fmt.allocPrint(allocator, "lib{}.abilist", .{lib_name});
158158 const abi_list_filename = blk: {
159159 if (abi_list.targets[0].abi == .gnuabi64 and std.mem.eql(u8, lib_name, "c")) {
160160 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename });