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" {...@@ -348,7 +348,7 @@ test "std.atomic.Queue dump" {
348 fbs.reset();348 fbs.reset();
349 try queue.dumpToStream(fbs.outStream());349 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..],
352 \\head: 0x{x}=1352 \\head: 0x{x}=1
353 \\ (null)353 \\ (null)
354 \\tail: 0x{x}=1354 \\tail: 0x{x}=1
...@@ -368,7 +368,7 @@ test "std.atomic.Queue dump" {...@@ -368,7 +368,7 @@ test "std.atomic.Queue dump" {
368 fbs.reset();368 fbs.reset();
369 try queue.dumpToStream(fbs.outStream());369 try queue.dumpToStream(fbs.outStream());
370370
371 expected = try std.fmtstream.bufPrint(expected_buffer[0..],371 expected = try std.fmt.bufPrint(expected_buffer[0..],
372 \\head: 0x{x}=1372 \\head: 0x{x}=1
373 \\ 0x{x}=2373 \\ 0x{x}=2
374 \\ (null)374 \\ (null)
lib/std/buffer.zig+2-2
...@@ -65,11 +65,11 @@ pub const Buffer = struct {...@@ -65,11 +65,11 @@ pub const Buffer = struct {
65 }65 }
6666
67 pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {67 pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: var) !Buffer {
68 const size = std.fmtstream.count(format, args) catch |err| switch (err) {68 const size = std.fmt.count(format, args) catch |err| switch (err) {
69 error.Overflow => return error.OutOfMemory,69 error.Overflow => return error.OutOfMemory,
70 };70 };
71 var self = try Buffer.initSize(allocator, size);71 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);
73 return self;73 return self;
74 }74 }
7575
lib/std/builtin.zig+7-7
...@@ -426,27 +426,27 @@ pub const Version = struct {...@@ -426,27 +426,27 @@ pub const Version = struct {
426 pub fn parse(text: []const u8) !Version {426 pub fn parse(text: []const u8) !Version {
427 var it = std.mem.separate(text, ".");427 var it = std.mem.separate(text, ".");
428 return Version{428 return Version{
429 .major = try std.fmtstream.parseInt(u32, it.next() orelse return error.InvalidVersion, 10),429 .major = try std.fmt.parseInt(u32, it.next() orelse return error.InvalidVersion, 10),
430 .minor = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10),430 .minor = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
431 .patch = try std.fmtstream.parseInt(u32, it.next() orelse "0", 10),431 .patch = try std.fmt.parseInt(u32, it.next() orelse "0", 10),
432 };432 };
433 }433 }
434434
435 pub fn format(435 pub fn format(
436 self: Version,436 self: Version,
437 comptime fmt: []const u8,437 comptime fmt: []const u8,
438 options: std.fmtstream.FormatOptions,438 options: std.fmt.FormatOptions,
439 out_stream: var,439 out_stream: var,
440 ) !void {440 ) !void {
441 if (fmt.len == 0) {441 if (fmt.len == 0) {
442 if (self.patch == 0) {442 if (self.patch == 0) {
443 if (self.minor == 0) {443 if (self.minor == 0) {
444 return std.fmtstream.format(out_stream, "{}", .{self.major});444 return std.fmt.format(out_stream, "{}", .{self.major});
445 } else {445 } else {
446 return std.fmtstream.format(out_stream, "{}.{}", .{ self.major, self.minor });446 return std.fmt.format(out_stream, "{}.{}", .{ self.major, self.minor });
447 }447 }
448 } else {448 } 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 });
450 }450 }
451 } else {451 } else {
452 @compileError("Unknown format string: '" ++ fmt ++ "'");452 @compileError("Unknown format string: '" ++ fmt ++ "'");
lib/std/fmt.zig+225-294
...@@ -69,19 +69,17 @@ fn peekIsAlign(comptime fmt: []const u8) bool {...@@ -69,19 +69,17 @@ fn peekIsAlign(comptime fmt: []const u8) bool {
69///69///
70/// If a formatted user type contains a function of the type70/// If a formatted user type contains a function of the type
71/// ```71/// ```
72/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, comptime output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void72/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void
73/// ```73/// ```
74/// with `?` being the type formatted, this function will be called instead of the default implementation.74/// with `?` being the type formatted, this function will be called instead of the default implementation.
75/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.75/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
76///76///
77/// A user type may be a `struct`, `vector`, `union` or `enum` type.77/// A user type may be a `struct`, `vector`, `union` or `enum` type.
78pub fn format(78pub fn format(
79 context: var,79 out_stream: var,
80 comptime Errors: type,
81 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
82 comptime fmt: []const u8,80 comptime fmt: []const u8,
83 args: var,81 args: var,
84) Errors!void {82) !void {
85 const ArgSetType = u32;83 const ArgSetType = u32;
86 if (@typeInfo(@TypeOf(args)) != .Struct) {84 if (@typeInfo(@TypeOf(args)) != .Struct) {
87 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));85 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
...@@ -138,7 +136,7 @@ pub fn format(...@@ -138,7 +136,7 @@ pub fn format(
138 .Start => switch (c) {136 .Start => switch (c) {
139 '{' => {137 '{' => {
140 if (start_index < i) {138 if (start_index < i) {
141 try output(context, fmt[start_index..i]);139 try out_stream.writeAll(fmt[start_index..i]);
142 }140 }
143141
144 start_index = i;142 start_index = i;
...@@ -150,7 +148,7 @@ pub fn format(...@@ -150,7 +148,7 @@ pub fn format(
150 },148 },
151 '}' => {149 '}' => {
152 if (start_index < i) {150 if (start_index < i) {
153 try output(context, fmt[start_index..i]);151 try out_stream.writeAll(fmt[start_index..i]);
154 }152 }
155 state = .CloseBrace;153 state = .CloseBrace;
156 },154 },
...@@ -185,9 +183,7 @@ pub fn format(...@@ -185,9 +183,7 @@ pub fn format(
185 args[arg_to_print],183 args[arg_to_print],
186 fmt[0..0],184 fmt[0..0],
187 options,185 options,
188 context,186 out_stream,
189 Errors,
190 output,
191 default_max_depth,187 default_max_depth,
192 );188 );
193189
...@@ -218,9 +214,7 @@ pub fn format(...@@ -218,9 +214,7 @@ pub fn format(
218 args[arg_to_print],214 args[arg_to_print],
219 fmt[specifier_start..i],215 fmt[specifier_start..i],
220 options,216 options,
221 context,217 out_stream,
222 Errors,
223 output,
224 default_max_depth,218 default_max_depth,
225 );219 );
226 state = .Start;220 state = .Start;
...@@ -265,9 +259,7 @@ pub fn format(...@@ -265,9 +259,7 @@ pub fn format(
265 args[arg_to_print],259 args[arg_to_print],
266 fmt[specifier_start..specifier_end],260 fmt[specifier_start..specifier_end],
267 options,261 options,
268 context,262 out_stream,
269 Errors,
270 output,
271 default_max_depth,263 default_max_depth,
272 );264 );
273 state = .Start;265 state = .Start;
...@@ -293,9 +285,7 @@ pub fn format(...@@ -293,9 +285,7 @@ pub fn format(
293 args[arg_to_print],285 args[arg_to_print],
294 fmt[specifier_start..specifier_end],286 fmt[specifier_start..specifier_end],
295 options,287 options,
296 context,288 out_stream,
297 Errors,
298 output,
299 default_max_depth,289 default_max_depth,
300 );290 );
301 state = .Start;291 state = .Start;
...@@ -316,7 +306,7 @@ pub fn format(...@@ -316,7 +306,7 @@ pub fn format(
316 }306 }
317 }307 }
318 if (start_index < fmt.len) {308 if (start_index < fmt.len) {
319 try output(context, fmt[start_index..]);309 try out_stream.writeAll(fmt[start_index..]);
320 }310 }
321}311}
322312
...@@ -324,141 +314,131 @@ pub fn formatType(...@@ -324,141 +314,131 @@ pub fn formatType(
324 value: var,314 value: var,
325 comptime fmt: []const u8,315 comptime fmt: []const u8,
326 options: FormatOptions,316 options: FormatOptions,
327 context: var,317 out_stream: var,
328 comptime Errors: type,
329 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
330 max_depth: usize,318 max_depth: usize,
331) Errors!void {319) @TypeOf(out_stream).Error!void {
332 if (comptime std.mem.eql(u8, fmt, "*")) {320 if (comptime std.mem.eql(u8, fmt, "*")) {
333 try output(context, @typeName(@TypeOf(value).Child));321 try out_stream.writeAll(@typeName(@TypeOf(value).Child));
334 try output(context, "@");322 try out_stream.writeAll("@");
335 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, context, Errors, output);323 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, out_stream);
336 return;324 return;
337 }325 }
338326
339 const T = @TypeOf(value);327 const T = @TypeOf(value);
328 if (comptime std.meta.trait.hasFn("format")(T)) {
329 return try value.format(fmt, options, out_stream);
330 }
331
340 switch (@typeInfo(T)) {332 switch (@typeInfo(T)) {
341 .ComptimeInt, .Int, .Float => {333 .ComptimeInt, .Int, .Float => {
342 return formatValue(value, fmt, options, context, Errors, output);334 return formatValue(value, fmt, options, out_stream);
343 },335 },
344 .Void => {336 .Void => {
345 return output(context, "void");337 return out_stream.writeAll("void");
346 },338 },
347 .Bool => {339 .Bool => {
348 return output(context, if (value) "true" else "false");340 return out_stream.writeAll(if (value) "true" else "false");
349 },341 },
350 .Optional => {342 .Optional => {
351 if (value) |payload| {343 if (value) |payload| {
352 return formatType(payload, fmt, options, context, Errors, output, max_depth);344 return formatType(payload, fmt, options, out_stream, max_depth);
353 } else {345 } else {
354 return output(context, "null");346 return out_stream.writeAll("null");
355 }347 }
356 },348 },
357 .ErrorUnion => {349 .ErrorUnion => {
358 if (value) |payload| {350 if (value) |payload| {
359 return formatType(payload, fmt, options, context, Errors, output, max_depth);351 return formatType(payload, fmt, options, out_stream, max_depth);
360 } else |err| {352 } else |err| {
361 return formatType(err, fmt, options, context, Errors, output, max_depth);353 return formatType(err, fmt, options, out_stream, max_depth);
362 }354 }
363 },355 },
364 .ErrorSet => {356 .ErrorSet => {
365 try output(context, "error.");357 try out_stream.writeAll("error.");
366 return output(context, @errorName(value));358 return out_stream.writeAll(@errorName(value));
367 },359 },
368 .Enum => |enumInfo| {360 .Enum => |enumInfo| {
369 if (comptime std.meta.trait.hasFn("format")(T)) {361 try out_stream.writeAll(@typeName(T));
370 return value.format(fmt, options, context, Errors, output);
371 }
372
373 try output(context, @typeName(T));
374 if (enumInfo.is_exhaustive) {362 if (enumInfo.is_exhaustive) {
375 try output(context, ".");363 try out_stream.writeAll(".");
376 try output(context, @tagName(value));364 try out_stream.writeAll(@tagName(value));
377 } else {365 } else {
378 // TODO: when @tagName works on exhaustive enums print known enum strings366 // TODO: when @tagName works on exhaustive enums print known enum strings
379 try output(context, "(");367 try out_stream.writeAll("(");
380 try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth);368 try formatType(@enumToInt(value), fmt, options, out_stream, max_depth);
381 try output(context, ")");369 try out_stream.writeAll(")");
382 }370 }
383 },371 },
384 .Union => {372 .Union => {
385 if (comptime std.meta.trait.hasFn("format")(T)) {373 try out_stream.writeAll(@typeName(T));
386 return value.format(fmt, options, context, Errors, output);
387 }
388
389 try output(context, @typeName(T));
390 if (max_depth == 0) {374 if (max_depth == 0) {
391 return output(context, "{ ... }");375 return out_stream.writeAll("{ ... }");
392 }376 }
393 const info = @typeInfo(T).Union;377 const info = @typeInfo(T).Union;
394 if (info.tag_type) |UnionTagType| {378 if (info.tag_type) |UnionTagType| {
395 try output(context, "{ .");379 try out_stream.writeAll("{ .");
396 try output(context, @tagName(@as(UnionTagType, value)));380 try out_stream.writeAll(@tagName(@as(UnionTagType, value)));
397 try output(context, " = ");381 try out_stream.writeAll(" = ");
398 inline for (info.fields) |u_field| {382 inline for (info.fields) |u_field| {
399 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {383 if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
400 try formatType(@field(value, u_field.name), fmt, options, context, Errors, output, max_depth - 1);384 try formatType(@field(value, u_field.name), fmt, options, out_stream, max_depth - 1);
401 }385 }
402 }386 }
403 try output(context, " }");387 try out_stream.writeAll(" }");
404 } else {388 } else {
405 try format(context, Errors, output, "@{x}", .{@ptrToInt(&value)});389 try format(out_stream, "@{x}", .{@ptrToInt(&value)});
406 }390 }
407 },391 },
408 .Struct => |StructT| {392 .Struct => |StructT| {
409 if (comptime std.meta.trait.hasFn("format")(T)) {393 try out_stream.writeAll(@typeName(T));
410 return value.format(fmt, options, context, Errors, output);
411 }
412
413 try output(context, @typeName(T));
414 if (max_depth == 0) {394 if (max_depth == 0) {
415 return output(context, "{ ... }");395 return out_stream.writeAll("{ ... }");
416 }396 }
417 try output(context, "{");397 try out_stream.writeAll("{");
418 inline for (StructT.fields) |f, i| {398 inline for (StructT.fields) |f, i| {
419 if (i == 0) {399 if (i == 0) {
420 try output(context, " .");400 try out_stream.writeAll(" .");
421 } else {401 } else {
422 try output(context, ", .");402 try out_stream.writeAll(", .");
423 }403 }
424 try output(context, f.name);404 try out_stream.writeAll(f.name);
425 try output(context, " = ");405 try out_stream.writeAll(" = ");
426 try formatType(@field(value, f.name), fmt, options, context, Errors, output, max_depth - 1);406 try formatType(@field(value, f.name), fmt, options, out_stream, max_depth - 1);
427 }407 }
428 try output(context, " }");408 try out_stream.writeAll(" }");
429 },409 },
430 .Pointer => |ptr_info| switch (ptr_info.size) {410 .Pointer => |ptr_info| switch (ptr_info.size) {
431 .One => switch (@typeInfo(ptr_info.child)) {411 .One => switch (@typeInfo(ptr_info.child)) {
432 .Array => |info| {412 .Array => |info| {
433 if (info.child == u8) {413 if (info.child == u8) {
434 return formatText(value, fmt, options, context, Errors, output);414 return formatText(value, fmt, options, out_stream);
435 }415 }
436 return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });416 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
437 },417 },
438 .Enum, .Union, .Struct => {418 .Enum, .Union, .Struct => {
439 return formatType(value.*, fmt, options, context, Errors, output, max_depth);419 return formatType(value.*, fmt, options, out_stream, max_depth);
440 },420 },
441 else => return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),421 else => return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),
442 },422 },
443 .Many, .C => {423 .Many, .C => {
444 if (ptr_info.sentinel) |sentinel| {424 if (ptr_info.sentinel) |sentinel| {
445 return formatType(mem.span(value), fmt, options, context, Errors, output, max_depth);425 return formatType(mem.span(value), fmt, options, out_stream, max_depth);
446 }426 }
447 if (ptr_info.child == u8) {427 if (ptr_info.child == u8) {
448 if (fmt.len > 0 and fmt[0] == 's') {428 if (fmt.len > 0 and fmt[0] == 's') {
449 return formatText(mem.span(value), fmt, options, context, Errors, output);429 return formatText(mem.span(value), fmt, options, out_stream);
450 }430 }
451 }431 }
452 return format(context, Errors, output, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });432 return format(out_stream, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });
453 },433 },
454 .Slice => {434 .Slice => {
455 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {435 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
456 return formatText(value, fmt, options, context, Errors, output);436 return formatText(value, fmt, options, out_stream);
457 }437 }
458 if (ptr_info.child == u8) {438 if (ptr_info.child == u8) {
459 return formatText(value, fmt, options, context, Errors, output);439 return formatText(value, fmt, options, out_stream);
460 }440 }
461 return format(context, Errors, output, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });441 return format(out_stream, "{}@{x}", .{ @typeName(ptr_info.child), @ptrToInt(value.ptr) });
462 },442 },
463 },443 },
464 .Array => |info| {444 .Array => |info| {
...@@ -473,27 +453,27 @@ pub fn formatType(...@@ -473,27 +453,27 @@ pub fn formatType(
473 .sentinel = null,453 .sentinel = null,
474 },454 },
475 });455 });
476 return formatType(@as(Slice, &value), fmt, options, context, Errors, output, max_depth);456 return formatType(@as(Slice, &value), fmt, options, out_stream, max_depth);
477 },457 },
478 .Vector => {458 .Vector => {
479 const len = @typeInfo(T).Vector.len;459 const len = @typeInfo(T).Vector.len;
480 try output(context, "{ ");460 try out_stream.writeAll("{ ");
481 var i: usize = 0;461 var i: usize = 0;
482 while (i < len) : (i += 1) {462 while (i < len) : (i += 1) {
483 try formatValue(value[i], fmt, options, context, Errors, output);463 try formatValue(value[i], fmt, options, out_stream);
484 if (i < len - 1) {464 if (i < len - 1) {
485 try output(context, ", ");465 try out_stream.writeAll(", ");
486 }466 }
487 }467 }
488 try output(context, " }");468 try out_stream.writeAll(" }");
489 },469 },
490 .Fn => {470 .Fn => {
491 return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });471 return format(out_stream, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
492 },472 },
493 .Type => return output(context, @typeName(T)),473 .Type => return out_stream.writeAll(@typeName(T)),
494 .EnumLiteral => {474 .EnumLiteral => {
495 const buffer = [_]u8{'.'} ++ @tagName(value);475 const buffer = [_]u8{'.'} ++ @tagName(value);
496 return formatType(buffer, fmt, options, context, Errors, output, max_depth);476 return formatType(buffer, fmt, options, out_stream, max_depth);
497 },477 },
498 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),478 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
499 }479 }
...@@ -503,21 +483,19 @@ fn formatValue(...@@ -503,21 +483,19 @@ fn formatValue(
503 value: var,483 value: var,
504 comptime fmt: []const u8,484 comptime fmt: []const u8,
505 options: FormatOptions,485 options: FormatOptions,
506 context: var,486 out_stream: var,
507 comptime Errors: type,487) !void {
508 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
509) Errors!void {
510 if (comptime std.mem.eql(u8, fmt, "B")) {488 if (comptime std.mem.eql(u8, fmt, "B")) {
511 return formatBytes(value, options, 1000, context, Errors, output);489 return formatBytes(value, options, 1000, out_stream);
512 } else if (comptime std.mem.eql(u8, fmt, "Bi")) {490 } else if (comptime std.mem.eql(u8, fmt, "Bi")) {
513 return formatBytes(value, options, 1024, context, Errors, output);491 return formatBytes(value, options, 1024, out_stream);
514 }492 }
515493
516 const T = @TypeOf(value);494 const T = @TypeOf(value);
517 switch (@typeInfo(T)) {495 switch (@typeInfo(T)) {
518 .Float => return formatFloatValue(value, fmt, options, context, Errors, output),496 .Float => return formatFloatValue(value, fmt, options, out_stream),
519 .Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),497 .Int, .ComptimeInt => return formatIntValue(value, fmt, options, out_stream),
520 .Bool => return output(context, if (value) "true" else "false"),498 .Bool => return out_stream.writeAll(if (value) "true" else "false"),
521 else => comptime unreachable,499 else => comptime unreachable,
522 }500 }
523}501}
...@@ -526,10 +504,8 @@ pub fn formatIntValue(...@@ -526,10 +504,8 @@ pub fn formatIntValue(
526 value: var,504 value: var,
527 comptime fmt: []const u8,505 comptime fmt: []const u8,
528 options: FormatOptions,506 options: FormatOptions,
529 context: var,507 out_stream: var,
530 comptime Errors: type,508) !void {
531 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
532) Errors!void {
533 comptime var radix = 10;509 comptime var radix = 10;
534 comptime var uppercase = false;510 comptime var uppercase = false;
535511
...@@ -544,7 +520,7 @@ pub fn formatIntValue(...@@ -544,7 +520,7 @@ pub fn formatIntValue(
544 uppercase = false;520 uppercase = false;
545 } else if (comptime std.mem.eql(u8, fmt, "c")) {521 } else if (comptime std.mem.eql(u8, fmt, "c")) {
546 if (@TypeOf(int_value).bit_count <= 8) {522 if (@TypeOf(int_value).bit_count <= 8) {
547 return formatAsciiChar(@as(u8, int_value), options, context, Errors, output);523 return formatAsciiChar(@as(u8, int_value), options, out_stream);
548 } else {524 } else {
549 @compileError("Cannot print integer that is larger than 8 bits as a ascii");525 @compileError("Cannot print integer that is larger than 8 bits as a ascii");
550 }526 }
...@@ -561,21 +537,19 @@ pub fn formatIntValue(...@@ -561,21 +537,19 @@ pub fn formatIntValue(
561 @compileError("Unknown format string: '" ++ fmt ++ "'");537 @compileError("Unknown format string: '" ++ fmt ++ "'");
562 }538 }
563539
564 return formatInt(int_value, radix, uppercase, options, context, Errors, output);540 return formatInt(int_value, radix, uppercase, options, out_stream);
565}541}
566542
567fn formatFloatValue(543fn formatFloatValue(
568 value: var,544 value: var,
569 comptime fmt: []const u8,545 comptime fmt: []const u8,
570 options: FormatOptions,546 options: FormatOptions,
571 context: var,547 out_stream: var,
572 comptime Errors: type,548) !void {
573 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
574) Errors!void {
575 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {549 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) {
576 return formatFloatScientific(value, options, context, Errors, output);550 return formatFloatScientific(value, options, out_stream);
577 } else if (comptime std.mem.eql(u8, fmt, "d")) {551 } else if (comptime std.mem.eql(u8, fmt, "d")) {
578 return formatFloatDecimal(value, options, context, Errors, output);552 return formatFloatDecimal(value, options, out_stream);
579 } else {553 } else {
580 @compileError("Unknown format string: '" ++ fmt ++ "'");554 @compileError("Unknown format string: '" ++ fmt ++ "'");
581 }555 }
...@@ -585,17 +559,15 @@ pub fn formatText(...@@ -585,17 +559,15 @@ pub fn formatText(
585 bytes: []const u8,559 bytes: []const u8,
586 comptime fmt: []const u8,560 comptime fmt: []const u8,
587 options: FormatOptions,561 options: FormatOptions,
588 context: var,562 out_stream: var,
589 comptime Errors: type,563) !void {
590 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
591) Errors!void {
592 if (fmt.len == 0) {564 if (fmt.len == 0) {
593 return output(context, bytes);565 return out_stream.writeAll(bytes);
594 } else if (comptime std.mem.eql(u8, fmt, "s")) {566 } else if (comptime std.mem.eql(u8, fmt, "s")) {
595 return formatBuf(bytes, options, context, Errors, output);567 return formatBuf(bytes, options, out_stream);
596 } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {568 } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) {
597 for (bytes) |c| {569 for (bytes) |c| {
598 try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, context, Errors, output);570 try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, out_stream);
599 }571 }
600 return;572 return;
601 } else {573 } else {
...@@ -606,27 +578,23 @@ pub fn formatText(...@@ -606,27 +578,23 @@ pub fn formatText(
606pub fn formatAsciiChar(578pub fn formatAsciiChar(
607 c: u8,579 c: u8,
608 options: FormatOptions,580 options: FormatOptions,
609 context: var,581 out_stream: var,
610 comptime Errors: type,582) !void {
611 comptime output: fn (@TypeOf(context), []const u8) Errors!void,583 return out_stream.writeAll(@as(*const [1]u8, &c)[0..]);
612) Errors!void {
613 return output(context, @as(*const [1]u8, &c)[0..]);
614}584}
615585
616pub fn formatBuf(586pub fn formatBuf(
617 buf: []const u8,587 buf: []const u8,
618 options: FormatOptions,588 options: FormatOptions,
619 context: var,589 out_stream: var,
620 comptime Errors: type,590) !void {
621 comptime output: fn (@TypeOf(context), []const u8) Errors!void,591 try out_stream.writeAll(buf);
622) Errors!void {
623 try output(context, buf);
624592
625 const width = options.width orelse 0;593 const width = options.width orelse 0;
626 var leftover_padding = if (width > buf.len) (width - buf.len) else return;594 var leftover_padding = if (width > buf.len) (width - buf.len) else return;
627 const pad_byte: u8 = options.fill;595 const pad_byte: u8 = options.fill;
628 while (leftover_padding > 0) : (leftover_padding -= 1) {596 while (leftover_padding > 0) : (leftover_padding -= 1) {
629 try output(context, @as(*const [1]u8, &pad_byte)[0..1]);597 try out_stream.writeAll(@as(*const [1]u8, &pad_byte)[0..1]);
630 }598 }
631}599}
632600
...@@ -636,40 +604,38 @@ pub fn formatBuf(...@@ -636,40 +604,38 @@ pub fn formatBuf(
636pub fn formatFloatScientific(604pub fn formatFloatScientific(
637 value: var,605 value: var,
638 options: FormatOptions,606 options: FormatOptions,
639 context: var,607 out_stream: var,
640 comptime Errors: type,608) !void {
641 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
642) Errors!void {
643 var x = @floatCast(f64, value);609 var x = @floatCast(f64, value);
644610
645 // Errol doesn't handle these special cases.611 // Errol doesn't handle these special cases.
646 if (math.signbit(x)) {612 if (math.signbit(x)) {
647 try output(context, "-");613 try out_stream.writeAll("-");
648 x = -x;614 x = -x;
649 }615 }
650616
651 if (math.isNan(x)) {617 if (math.isNan(x)) {
652 return output(context, "nan");618 return out_stream.writeAll("nan");
653 }619 }
654 if (math.isPositiveInf(x)) {620 if (math.isPositiveInf(x)) {
655 return output(context, "inf");621 return out_stream.writeAll("inf");
656 }622 }
657 if (x == 0.0) {623 if (x == 0.0) {
658 try output(context, "0");624 try out_stream.writeAll("0");
659625
660 if (options.precision) |precision| {626 if (options.precision) |precision| {
661 if (precision != 0) {627 if (precision != 0) {
662 try output(context, ".");628 try out_stream.writeAll(".");
663 var i: usize = 0;629 var i: usize = 0;
664 while (i < precision) : (i += 1) {630 while (i < precision) : (i += 1) {
665 try output(context, "0");631 try out_stream.writeAll("0");
666 }632 }
667 }633 }
668 } else {634 } else {
669 try output(context, ".0");635 try out_stream.writeAll(".0");
670 }636 }
671637
672 try output(context, "e+00");638 try out_stream.writeAll("e+00");
673 return;639 return;
674 }640 }
675641
...@@ -679,50 +645,50 @@ pub fn formatFloatScientific(...@@ -679,50 +645,50 @@ pub fn formatFloatScientific(
679 if (options.precision) |precision| {645 if (options.precision) |precision| {
680 errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);646 errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific);
681647
682 try output(context, float_decimal.digits[0..1]);648 try out_stream.writeAll(float_decimal.digits[0..1]);
683649
684 // {e0} case prints no `.`650 // {e0} case prints no `.`
685 if (precision != 0) {651 if (precision != 0) {
686 try output(context, ".");652 try out_stream.writeAll(".");
687653
688 var printed: usize = 0;654 var printed: usize = 0;
689 if (float_decimal.digits.len > 1) {655 if (float_decimal.digits.len > 1) {
690 const num_digits = math.min(float_decimal.digits.len, precision + 1);656 const num_digits = math.min(float_decimal.digits.len, precision + 1);
691 try output(context, float_decimal.digits[1..num_digits]);657 try out_stream.writeAll(float_decimal.digits[1..num_digits]);
692 printed += num_digits - 1;658 printed += num_digits - 1;
693 }659 }
694660
695 while (printed < precision) : (printed += 1) {661 while (printed < precision) : (printed += 1) {
696 try output(context, "0");662 try out_stream.writeAll("0");
697 }663 }
698 }664 }
699 } else {665 } else {
700 try output(context, float_decimal.digits[0..1]);666 try out_stream.writeAll(float_decimal.digits[0..1]);
701 try output(context, ".");667 try out_stream.writeAll(".");
702 if (float_decimal.digits.len > 1) {668 if (float_decimal.digits.len > 1) {
703 const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;669 const num_digits = if (@TypeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len;
704670
705 try output(context, float_decimal.digits[1..num_digits]);671 try out_stream.writeAll(float_decimal.digits[1..num_digits]);
706 } else {672 } else {
707 try output(context, "0");673 try out_stream.writeAll("0");
708 }674 }
709 }675 }
710676
711 try output(context, "e");677 try out_stream.writeAll("e");
712 const exp = float_decimal.exp - 1;678 const exp = float_decimal.exp - 1;
713679
714 if (exp >= 0) {680 if (exp >= 0) {
715 try output(context, "+");681 try out_stream.writeAll("+");
716 if (exp > -10 and exp < 10) {682 if (exp > -10 and exp < 10) {
717 try output(context, "0");683 try out_stream.writeAll("0");
718 }684 }
719 try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);685 try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
720 } else {686 } else {
721 try output(context, "-");687 try out_stream.writeAll("-");
722 if (exp > -10 and exp < 10) {688 if (exp > -10 and exp < 10) {
723 try output(context, "0");689 try out_stream.writeAll("0");
724 }690 }
725 try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output);691 try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, out_stream);
726 }692 }
727}693}
728694
...@@ -731,36 +697,34 @@ pub fn formatFloatScientific(...@@ -731,36 +697,34 @@ pub fn formatFloatScientific(
731pub fn formatFloatDecimal(697pub fn formatFloatDecimal(
732 value: var,698 value: var,
733 options: FormatOptions,699 options: FormatOptions,
734 context: var,700 out_stream: var,
735 comptime Errors: type,701) !void {
736 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
737) Errors!void {
738 var x = @as(f64, value);702 var x = @as(f64, value);
739703
740 // Errol doesn't handle these special cases.704 // Errol doesn't handle these special cases.
741 if (math.signbit(x)) {705 if (math.signbit(x)) {
742 try output(context, "-");706 try out_stream.writeAll("-");
743 x = -x;707 x = -x;
744 }708 }
745709
746 if (math.isNan(x)) {710 if (math.isNan(x)) {
747 return output(context, "nan");711 return out_stream.writeAll("nan");
748 }712 }
749 if (math.isPositiveInf(x)) {713 if (math.isPositiveInf(x)) {
750 return output(context, "inf");714 return out_stream.writeAll("inf");
751 }715 }
752 if (x == 0.0) {716 if (x == 0.0) {
753 try output(context, "0");717 try out_stream.writeAll("0");
754718
755 if (options.precision) |precision| {719 if (options.precision) |precision| {
756 if (precision != 0) {720 if (precision != 0) {
757 try output(context, ".");721 try out_stream.writeAll(".");
758 var i: usize = 0;722 var i: usize = 0;
759 while (i < precision) : (i += 1) {723 while (i < precision) : (i += 1) {
760 try output(context, "0");724 try out_stream.writeAll("0");
761 }725 }
762 } else {726 } else {
763 try output(context, ".0");727 try out_stream.writeAll(".0");
764 }728 }
765 }729 }
766730
...@@ -782,14 +746,14 @@ pub fn formatFloatDecimal(...@@ -782,14 +746,14 @@ pub fn formatFloatDecimal(
782746
783 if (num_digits_whole > 0) {747 if (num_digits_whole > 0) {
784 // We may have to zero pad, for instance 1e4 requires zero padding.748 // We may have to zero pad, for instance 1e4 requires zero padding.
785 try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);749 try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
786750
787 var i = num_digits_whole_no_pad;751 var i = num_digits_whole_no_pad;
788 while (i < num_digits_whole) : (i += 1) {752 while (i < num_digits_whole) : (i += 1) {
789 try output(context, "0");753 try out_stream.writeAll("0");
790 }754 }
791 } else {755 } else {
792 try output(context, "0");756 try out_stream.writeAll("0");
793 }757 }
794758
795 // {.0} special case doesn't want a trailing '.'759 // {.0} special case doesn't want a trailing '.'
...@@ -797,7 +761,7 @@ pub fn formatFloatDecimal(...@@ -797,7 +761,7 @@ pub fn formatFloatDecimal(
797 return;761 return;
798 }762 }
799763
800 try output(context, ".");764 try out_stream.writeAll(".");
801765
802 // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.766 // Keep track of fractional count printed for case where we pre-pad then post-pad with 0's.
803 var printed: usize = 0;767 var printed: usize = 0;
...@@ -809,7 +773,7 @@ pub fn formatFloatDecimal(...@@ -809,7 +773,7 @@ pub fn formatFloatDecimal(
809773
810 var i: usize = 0;774 var i: usize = 0;
811 while (i < zeros_to_print) : (i += 1) {775 while (i < zeros_to_print) : (i += 1) {
812 try output(context, "0");776 try out_stream.writeAll("0");
813 printed += 1;777 printed += 1;
814 }778 }
815779
...@@ -821,14 +785,14 @@ pub fn formatFloatDecimal(...@@ -821,14 +785,14 @@ pub fn formatFloatDecimal(
821 // Remaining fractional portion, zero-padding if insufficient.785 // Remaining fractional portion, zero-padding if insufficient.
822 assert(precision >= printed);786 assert(precision >= printed);
823 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {787 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
824 try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);788 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
825 return;789 return;
826 } else {790 } else {
827 try output(context, float_decimal.digits[num_digits_whole_no_pad..]);791 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
828 printed += float_decimal.digits.len - num_digits_whole_no_pad;792 printed += float_decimal.digits.len - num_digits_whole_no_pad;
829793
830 while (printed < precision) : (printed += 1) {794 while (printed < precision) : (printed += 1) {
831 try output(context, "0");795 try out_stream.writeAll("0");
832 }796 }
833 }797 }
834 } else {798 } else {
...@@ -840,14 +804,14 @@ pub fn formatFloatDecimal(...@@ -840,14 +804,14 @@ pub fn formatFloatDecimal(
840804
841 if (num_digits_whole > 0) {805 if (num_digits_whole > 0) {
842 // We may have to zero pad, for instance 1e4 requires zero padding.806 // We may have to zero pad, for instance 1e4 requires zero padding.
843 try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);807 try out_stream.writeAll(float_decimal.digits[0..num_digits_whole_no_pad]);
844808
845 var i = num_digits_whole_no_pad;809 var i = num_digits_whole_no_pad;
846 while (i < num_digits_whole) : (i += 1) {810 while (i < num_digits_whole) : (i += 1) {
847 try output(context, "0");811 try out_stream.writeAll("0");
848 }812 }
849 } else {813 } else {
850 try output(context, "0");814 try out_stream.writeAll("0");
851 }815 }
852816
853 // Omit `.` if no fractional portion817 // Omit `.` if no fractional portion
...@@ -855,7 +819,7 @@ pub fn formatFloatDecimal(...@@ -855,7 +819,7 @@ pub fn formatFloatDecimal(
855 return;819 return;
856 }820 }
857821
858 try output(context, ".");822 try out_stream.writeAll(".");
859823
860 // Zero-fill until we reach significant digits or run out of precision.824 // Zero-fill until we reach significant digits or run out of precision.
861 if (float_decimal.exp < 0) {825 if (float_decimal.exp < 0) {
...@@ -863,11 +827,11 @@ pub fn formatFloatDecimal(...@@ -863,11 +827,11 @@ pub fn formatFloatDecimal(
863827
864 var i: usize = 0;828 var i: usize = 0;
865 while (i < zero_digit_count) : (i += 1) {829 while (i < zero_digit_count) : (i += 1) {
866 try output(context, "0");830 try out_stream.writeAll("0");
867 }831 }
868 }832 }
869833
870 try output(context, float_decimal.digits[num_digits_whole_no_pad..]);834 try out_stream.writeAll(float_decimal.digits[num_digits_whole_no_pad..]);
871 }835 }
872}836}
873837
...@@ -875,12 +839,10 @@ pub fn formatBytes(...@@ -875,12 +839,10 @@ pub fn formatBytes(
875 value: var,839 value: var,
876 options: FormatOptions,840 options: FormatOptions,
877 comptime radix: usize,841 comptime radix: usize,
878 context: var,842 out_stream: var,
879 comptime Errors: type,843) !void {
880 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
881) Errors!void {
882 if (value == 0) {844 if (value == 0) {
883 return output(context, "0B");845 return out_stream.writeAll("0B");
884 }846 }
885847
886 const mags_si = " kMGTPEZY";848 const mags_si = " kMGTPEZY";
...@@ -897,10 +859,10 @@ pub fn formatBytes(...@@ -897,10 +859,10 @@ pub fn formatBytes(
897 else => unreachable,859 else => unreachable,
898 };860 };
899861
900 try formatFloatDecimal(new_value, options, context, Errors, output);862 try formatFloatDecimal(new_value, options, out_stream);
901863
902 if (suffix == ' ') {864 if (suffix == ' ') {
903 return output(context, "B");865 return out_stream.writeAll("B");
904 }866 }
905867
906 const buf = switch (radix) {868 const buf = switch (radix) {
...@@ -908,7 +870,7 @@ pub fn formatBytes(...@@ -908,7 +870,7 @@ pub fn formatBytes(
908 1024 => &[_]u8{ suffix, 'i', 'B' },870 1024 => &[_]u8{ suffix, 'i', 'B' },
909 else => unreachable,871 else => unreachable,
910 };872 };
911 return output(context, buf);873 return out_stream.writeAll(buf);
912}874}
913875
914pub fn formatInt(876pub fn formatInt(
...@@ -916,10 +878,8 @@ pub fn formatInt(...@@ -916,10 +878,8 @@ pub fn formatInt(
916 base: u8,878 base: u8,
917 uppercase: bool,879 uppercase: bool,
918 options: FormatOptions,880 options: FormatOptions,
919 context: var,881 out_stream: var,
920 comptime Errors: type,882) !void {
921 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
922) Errors!void {
923 const int_value = if (@TypeOf(value) == comptime_int) blk: {883 const int_value = if (@TypeOf(value) == comptime_int) blk: {
924 const Int = math.IntFittingRange(value, value);884 const Int = math.IntFittingRange(value, value);
925 break :blk @as(Int, value);885 break :blk @as(Int, value);
...@@ -927,9 +887,9 @@ pub fn formatInt(...@@ -927,9 +887,9 @@ pub fn formatInt(
927 value;887 value;
928888
929 if (@TypeOf(int_value).is_signed) {889 if (@TypeOf(int_value).is_signed) {
930 return formatIntSigned(int_value, base, uppercase, options, context, Errors, output);890 return formatIntSigned(int_value, base, uppercase, options, out_stream);
931 } else {891 } else {
932 return formatIntUnsigned(int_value, base, uppercase, options, context, Errors, output);892 return formatIntUnsigned(int_value, base, uppercase, options, out_stream);
933 }893 }
934}894}
935895
...@@ -938,10 +898,8 @@ fn formatIntSigned(...@@ -938,10 +898,8 @@ fn formatIntSigned(
938 base: u8,898 base: u8,
939 uppercase: bool,899 uppercase: bool,
940 options: FormatOptions,900 options: FormatOptions,
941 context: var,901 out_stream: var,
942 comptime Errors: type,902) !void {
943 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
944) Errors!void {
945 const new_options = FormatOptions{903 const new_options = FormatOptions{
946 .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,904 .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null,
947 .precision = options.precision,905 .precision = options.precision,
...@@ -950,15 +908,15 @@ fn formatIntSigned(...@@ -950,15 +908,15 @@ fn formatIntSigned(
950 const bit_count = @typeInfo(@TypeOf(value)).Int.bits;908 const bit_count = @typeInfo(@TypeOf(value)).Int.bits;
951 const Uint = std.meta.IntType(false, bit_count);909 const Uint = std.meta.IntType(false, bit_count);
952 if (value < 0) {910 if (value < 0) {
953 try output(context, "-");911 try out_stream.writeAll("-");
954 const new_value = math.absCast(value);912 const new_value = math.absCast(value);
955 return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);913 return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
956 } else if (options.width == null or options.width.? == 0) {914 } else if (options.width == null or options.width.? == 0) {
957 return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, context, Errors, output);915 return formatIntUnsigned(@intCast(Uint, value), base, uppercase, options, out_stream);
958 } else {916 } else {
959 try output(context, "+");917 try out_stream.writeAll("+");
960 const new_value = @intCast(Uint, value);918 const new_value = @intCast(Uint, value);
961 return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output);919 return formatIntUnsigned(new_value, base, uppercase, new_options, out_stream);
962 }920 }
963}921}
964922
...@@ -967,10 +925,8 @@ fn formatIntUnsigned(...@@ -967,10 +925,8 @@ fn formatIntUnsigned(
967 base: u8,925 base: u8,
968 uppercase: bool,926 uppercase: bool,
969 options: FormatOptions,927 options: FormatOptions,
970 context: var,928 out_stream: var,
971 comptime Errors: type,929) !void {
972 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
973) Errors!void {
974 assert(base >= 2);930 assert(base >= 2);
975 var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;931 var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;
976 const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);932 const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);
...@@ -994,34 +950,23 @@ fn formatIntUnsigned(...@@ -994,34 +950,23 @@ fn formatIntUnsigned(
994 const zero_byte: u8 = options.fill;950 const zero_byte: u8 = options.fill;
995 var leftover_padding = padding - index;951 var leftover_padding = padding - index;
996 while (true) {952 while (true) {
997 try output(context, @as(*const [1]u8, &zero_byte)[0..]);953 try out_stream.writeAll(@as(*const [1]u8, &zero_byte)[0..]);
998 leftover_padding -= 1;954 leftover_padding -= 1;
999 if (leftover_padding == 0) break;955 if (leftover_padding == 0) break;
1000 }956 }
1001 mem.set(u8, buf[0..index], options.fill);957 mem.set(u8, buf[0..index], options.fill);
1002 return output(context, &buf);958 return out_stream.writeAll(&buf);
1003 } else {959 } else {
1004 const padded_buf = buf[index - padding ..];960 const padded_buf = buf[index - padding ..];
1005 mem.set(u8, padded_buf[0..padding], options.fill);961 mem.set(u8, padded_buf[0..padding], options.fill);
1006 return output(context, padded_buf);962 return out_stream.writeAll(padded_buf);
1007 }963 }
1008}964}
1009965
1010pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {966pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {
1011 var context = FormatIntBuf{967 var fbs = std.io.fixedBufferStream(out_buf);
1012 .out_buf = out_buf,968 formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable;
1013 .index = 0,969 return fbs.pos;
1014 };
1015 formatInt(value, base, uppercase, options, &context, error{}, formatIntCallback) catch unreachable;
1016 return context.index;
1017}
1018const FormatIntBuf = struct {
1019 out_buf: []u8,
1020 index: usize,
1021};
1022fn formatIntCallback(context: *FormatIntBuf, bytes: []const u8) (error{}!void) {
1023 mem.copy(u8, context.out_buf[context.index..], bytes);
1024 context.index += bytes.len;
1025}970}
1026971
1027pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {972pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
...@@ -1121,44 +1066,40 @@ fn digitToChar(digit: u8, uppercase: bool) u8 {...@@ -1121,44 +1066,40 @@ fn digitToChar(digit: u8, uppercase: bool) u8 {
1121 };1066 };
1122}1067}
11231068
1124const BufPrintContext = struct {
1125 remaining: []u8,
1126};
1127
1128fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
1129 if (context.remaining.len < bytes.len) {
1130 mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
1131 return error.BufferTooSmall;
1132 }
1133 mem.copy(u8, context.remaining, bytes);
1134 context.remaining = context.remaining[bytes.len..];
1135}
1136
1137pub const BufPrintError = error{1069pub const BufPrintError = error{
1138 /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.1070 /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
1139 BufferTooSmall,1071 BufferTooSmall,
1140};1072};
1141pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {1073pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
1142 var context = BufPrintContext{ .remaining = buf };1074 var fbs = std.io.fixedBufferStream(buf);
1143 try format(&context, BufPrintError, bufPrintWrite, fmt, args);1075 format(fbs.outStream(), fmt, args) catch |err| switch (err) {
1144 return buf[0 .. buf.len - context.remaining.len];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);
1145}1088}
11461089
1147pub const AllocPrintError = error{OutOfMemory};1090pub const AllocPrintError = error{OutOfMemory};
11481091
1149pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {1092pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
1150 var size: usize = 0;1093 const size = count(fmt, args) catch |err| switch (err) {
1151 format(&size, error{}, countSize, 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 };
1152 const buf = try allocator.alloc(u8, size);1097 const buf = try allocator.alloc(u8, size);
1153 return bufPrint(buf, fmt, args) catch |err| switch (err) {1098 return bufPrint(buf, fmt, args) catch |err| switch (err) {
1154 error.BufferTooSmall => unreachable, // we just counted the size above1099 error.BufferTooSmall => unreachable, // we just counted the size above
1155 };1100 };
1156}1101}
11571102
1158fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
1159 size.* += bytes.len;
1160}
1161
1162pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {1103pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
1163 const result = try allocPrint(allocator, fmt ++ "\x00", args);1104 const result = try allocPrint(allocator, fmt ++ "\x00", args);
1164 return result[0 .. result.len - 1 :0];1105 return result[0 .. result.len - 1 :0];
...@@ -1251,20 +1192,17 @@ test "int.padded" {...@@ -1251,20 +1192,17 @@ test "int.padded" {
1251test "buffer" {1192test "buffer" {
1252 {1193 {
1253 var buf1: [32]u8 = undefined;1194 var buf1: [32]u8 = undefined;
1254 var context = BufPrintContext{ .remaining = buf1[0..] };1195 var fbs = std.io.fixedBufferStream(&buf1);
1255 try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1196 try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
1256 var res = buf1[0 .. buf1.len - context.remaining.len];1197 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1234"));
1257 std.testing.expect(mem.eql(u8, res, "1234"));1198
12581199 fbs.reset();
1259 context = BufPrintContext{ .remaining = buf1[0..] };1200 try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
1260 try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1201 std.testing.expect(mem.eql(u8, fbs.getWritten(), "a"));
1261 res = buf1[0 .. buf1.len - context.remaining.len];1202
1262 std.testing.expect(mem.eql(u8, res, "a"));1203 fbs.reset();
12631204 try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
1264 context = BufPrintContext{ .remaining = buf1[0..] };1205 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1100"));
1265 try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1266 res = buf1[0 .. buf1.len - context.remaining.len];
1267 std.testing.expect(mem.eql(u8, res, "1100"));
1268 }1206 }
1269}1207}
12701208
...@@ -1449,14 +1387,12 @@ test "custom" {...@@ -1449,14 +1387,12 @@ test "custom" {
1449 self: SelfType,1387 self: SelfType,
1450 comptime fmt: []const u8,1388 comptime fmt: []const u8,
1451 options: FormatOptions,1389 options: FormatOptions,
1452 context: var,1390 out_stream: var,
1453 comptime Errors: type,1391 ) !void {
1454 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1455 ) Errors!void {
1456 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {1392 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 });
1458 } else if (comptime std.mem.eql(u8, fmt, "d")) {1394 } 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 });
1460 } else {1396 } else {
1461 @compileError("Unknown format character: '" ++ fmt ++ "'");1397 @compileError("Unknown format character: '" ++ fmt ++ "'");
1462 }1398 }
...@@ -1640,10 +1576,10 @@ test "hexToBytes" {...@@ -1640,10 +1576,10 @@ test "hexToBytes" {
1640test "formatIntValue with comptime_int" {1576test "formatIntValue with comptime_int" {
1641 const value: comptime_int = 123456789123456789;1577 const value: comptime_int = 123456789123456789;
16421578
1643 var buf = std.ArrayList(u8).init(std.testing.allocator);1579 var buf: [20]u8 = undefined;
1644 defer buf.deinit();1580 var fbs = std.io.fixedBufferStream(&buf);
1645 try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);1581 try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
1646 std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));1582 std.testing.expect(mem.eql(u8, fbs.getWritten(), "123456789123456789"));
1647}1583}
16481584
1649test "formatType max_depth" {1585test "formatType max_depth" {
...@@ -1656,12 +1592,10 @@ test "formatType max_depth" {...@@ -1656,12 +1592,10 @@ test "formatType max_depth" {
1656 self: SelfType,1592 self: SelfType,
1657 comptime fmt: []const u8,1593 comptime fmt: []const u8,
1658 options: FormatOptions,1594 options: FormatOptions,
1659 context: var,1595 out_stream: var,
1660 comptime Errors: type,1596 ) !void {
1661 comptime output: fn (@TypeOf(context), []const u8) Errors!void,
1662 ) Errors!void {
1663 if (fmt.len == 0) {1597 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 });
1665 } else {1599 } else {
1666 @compileError("Unknown format string: '" ++ fmt ++ "'");1600 @compileError("Unknown format string: '" ++ fmt ++ "'");
1667 }1601 }
...@@ -1695,25 +1629,22 @@ test "formatType max_depth" {...@@ -1695,25 +1629,22 @@ test "formatType max_depth" {
1695 inst.a = &inst;1629 inst.a = &inst;
1696 inst.tu.ptr = &inst.tu;1630 inst.tu.ptr = &inst.tu;
16971631
1698 var buf0 = std.ArrayList(u8).init(std.testing.allocator);1632 var buf: [1000]u8 = undefined;
1699 defer buf0.deinit();1633 var fbs = std.io.fixedBufferStream(&buf);
1700 try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);1634 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 0);
1701 std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));1635 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }"));
17021636
1703 var buf1 = std.ArrayList(u8).init(std.testing.allocator);1637 fbs.reset();
1704 defer buf1.deinit();1638 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 1);
1705 try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);1639 std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
1706 std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));1640
17071641 fbs.reset();
1708 var buf2 = std.ArrayList(u8).init(std.testing.allocator);1642 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 2);
1709 defer buf2.deinit();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) }"));
1710 try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);1644
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) }"));1645 fbs.reset();
17121646 try formatType(inst, "", FormatOptions{}, fbs.outStream(), 3);
1713 var buf3 = std.ArrayList(u8).init(std.testing.allocator);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) }"));
1714 defer buf3.deinit();
1715 try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3);
1716 std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
1717}1648}
17181649
1719test "positional" {1650test "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 {...@@ -349,7 +349,7 @@ pub const Headers = struct {
349 pub fn format(349 pub fn format(
350 self: Self,350 self: Self,
351 comptime fmt: []const u8,351 comptime fmt: []const u8,
352 options: std.fmtstream.FormatOptions,352 options: std.fmt.FormatOptions,
353 out_stream: var,353 out_stream: var,
354 ) !void {354 ) !void {
355 for (self.toSlice()) |entry| {355 for (self.toSlice()) |entry| {
...@@ -591,5 +591,5 @@ test "Headers.format" {...@@ -591,5 +591,5 @@ test "Headers.format" {
591 \\foo: bar591 \\foo: bar
592 \\cookie: somevalue592 \\cookie: somevalue
593 \\593 \\
594 , try std.fmtstream.bufPrint(buf[0..], "{}", .{h}));594 , try std.fmt.bufPrint(buf[0..], "{}", .{h}));
595}595}
lib/std/io/out_stream.zig+1-1
...@@ -25,7 +25,7 @@ pub fn OutStream(...@@ -25,7 +25,7 @@ pub fn OutStream(
25 }25 }
2626
27 pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {27 pub fn print(self: Self, comptime format: []const u8, args: var) Error!void {
28 return std.fmtstream.format(self, format, args);28 return std.fmt.format(self, format, args);
29 }29 }
3030
31 pub fn writeByte(self: Self, byte: u8) Error!void {31 pub fn writeByte(self: Self, byte: u8) Error!void {
lib/std/json.zig+5-5
...@@ -2257,10 +2257,10 @@ pub fn stringify(...@@ -2257,10 +2257,10 @@ pub fn stringify(
2257 const T = @TypeOf(value);2257 const T = @TypeOf(value);
2258 switch (@typeInfo(T)) {2258 switch (@typeInfo(T)) {
2259 .Float, .ComptimeFloat => {2259 .Float, .ComptimeFloat => {
2260 return std.fmtstream.formatFloatScientific(value, std.fmtstream.FormatOptions{}, out_stream);2260 return std.fmt.formatFloatScientific(value, std.fmt.FormatOptions{}, out_stream);
2261 },2261 },
2262 .Int, .ComptimeInt => {2262 .Int, .ComptimeInt => {
2263 return std.fmtstream.formatIntValue(value, "", std.fmtstream.FormatOptions{}, out_stream);2263 return std.fmt.formatIntValue(value, "", std.fmt.FormatOptions{}, out_stream);
2264 },2264 },
2265 .Bool => {2265 .Bool => {
2266 return out_stream.writeAll(if (value) "true" else "false");2266 return out_stream.writeAll(if (value) "true" else "false");
...@@ -2350,16 +2350,16 @@ pub fn stringify(...@@ -2350,16 +2350,16 @@ pub fn stringify(
2350 // then it may be represented as a six-character sequence: a reverse solidus, followed2350 // then it may be represented as a six-character sequence: a reverse solidus, followed
2351 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.2351 // by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point.
2352 try out_stream.writeAll("\\u");2352 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);
2354 } else {2354 } else {
2355 // To escape an extended character that is not in the Basic Multilingual Plane,2355 // To escape an extended character that is not in the Basic Multilingual Plane,
2356 // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.2356 // the character is represented as a 12-character sequence, encoding the UTF-16 surrogate pair.
2357 const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;2357 const high = @intCast(u16, (codepoint - 0x10000) >> 10) + 0xD800;
2358 const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;2358 const low = @intCast(u16, codepoint & 0x3FF) + 0xDC00;
2359 try out_stream.writeAll("\\u");2359 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);
2361 try out_stream.writeAll("\\u");2361 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);
2363 }2363 }
2364 i += ulen - 1;2364 i += ulen - 1;
2365 },2365 },
lib/std/math/big/int.zig+1-1
...@@ -518,7 +518,7 @@ pub const Int = struct {...@@ -518,7 +518,7 @@ pub const Int = struct {
518 pub fn format(518 pub fn format(
519 self: Int,519 self: Int,
520 comptime fmt: []const u8,520 comptime fmt: []const u8,
521 options: std.fmtstream.FormatOptions,521 options: std.fmt.FormatOptions,
522 out_stream: var,522 out_stream: var,
523 ) FmtError!void {523 ) FmtError!void {
524 self.assertWritable();524 self.assertWritable();
lib/std/net.zig+7-7
...@@ -268,14 +268,14 @@ pub const Address = extern union {...@@ -268,14 +268,14 @@ pub const Address = extern union {
268 pub fn format(268 pub fn format(
269 self: Address,269 self: Address,
270 comptime fmt: []const u8,270 comptime fmt: []const u8,
271 options: std.fmtstream.FormatOptions,271 options: std.fmt.FormatOptions,
272 out_stream: var,272 out_stream: var,
273 ) !void {273 ) !void {
274 switch (self.any.family) {274 switch (self.any.family) {
275 os.AF_INET => {275 os.AF_INET => {
276 const port = mem.bigToNative(u16, self.in.port);276 const port = mem.bigToNative(u16, self.in.port);
277 const bytes = @ptrCast(*const [4]u8, &self.in.addr);277 const bytes = @ptrCast(*const [4]u8, &self.in.addr);
278 try std.fmtstream.format(out_stream, "{}.{}.{}.{}:{}", .{278 try std.fmt.format(out_stream, "{}.{}.{}.{}:{}", .{
279 bytes[0],279 bytes[0],
280 bytes[1],280 bytes[1],
281 bytes[2],281 bytes[2],
...@@ -286,7 +286,7 @@ pub const Address = extern union {...@@ -286,7 +286,7 @@ pub const Address = extern union {
286 os.AF_INET6 => {286 os.AF_INET6 => {
287 const port = mem.bigToNative(u16, self.in6.port);287 const port = mem.bigToNative(u16, self.in6.port);
288 if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {288 if (mem.eql(u8, self.in6.addr[0..12], &[_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) {
289 try std.fmtstream.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{289 try std.fmt.format(out_stream, "[::ffff:{}.{}.{}.{}]:{}", .{
290 self.in6.addr[12],290 self.in6.addr[12],
291 self.in6.addr[13],291 self.in6.addr[13],
292 self.in6.addr[14],292 self.in6.addr[14],
...@@ -317,19 +317,19 @@ pub const Address = extern union {...@@ -317,19 +317,19 @@ pub const Address = extern union {
317 }317 }
318 continue;318 continue;
319 }319 }
320 try std.fmtstream.format(out_stream, "{x}", .{native_endian_parts[i]});320 try std.fmt.format(out_stream, "{x}", .{native_endian_parts[i]});
321 if (i != native_endian_parts.len - 1) {321 if (i != native_endian_parts.len - 1) {
322 try out_stream.writeAll(":");322 try out_stream.writeAll(":");
323 }323 }
324 }324 }
325 try std.fmtstream.format(out_stream, "]:{}", .{port});325 try std.fmt.format(out_stream, "]:{}", .{port});
326 },326 },
327 os.AF_UNIX => {327 os.AF_UNIX => {
328 if (!has_unix_sockets) {328 if (!has_unix_sockets) {
329 unreachable;329 unreachable;
330 }330 }
331331
332 try std.fmtstream.format(out_stream, "{}", .{&self.un.path});332 try std.fmt.format(out_stream, "{}", .{&self.un.path});
333 },333 },
334 else => unreachable,334 else => unreachable,
335 }335 }
...@@ -438,7 +438,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*...@@ -438,7 +438,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
438 const name_c = try std.cstr.addNullByte(allocator, name);438 const name_c = try std.cstr.addNullByte(allocator, name);
439 defer allocator.free(name_c);439 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});
442 defer allocator.free(port_c);442 defer allocator.free(port_c);
443443
444 const hints = os.addrinfo{444 const hints = os.addrinfo{
lib/std/net/test.zig+2-2
...@@ -29,7 +29,7 @@ test "parse and render IPv6 addresses" {...@@ -29,7 +29,7 @@ test "parse and render IPv6 addresses" {
29 };29 };
30 for (ips) |ip, i| {30 for (ips) |ip, i| {
31 var addr = net.Address.parseIp6(ip, 0) catch unreachable;31 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;
33 std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));33 std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3]));
34 }34 }
3535
...@@ -51,7 +51,7 @@ test "parse and render IPv4 addresses" {...@@ -51,7 +51,7 @@ test "parse and render IPv4 addresses" {
51 "127.0.0.1",51 "127.0.0.1",
52 }) |ip| {52 }) |ip| {
53 var addr = net.Address.parseIp4(ip, 0) catch unreachable;53 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;
55 std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));55 std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2]));
56 }56 }
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...@@ -3049,7 +3049,7 @@ pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP
3049 defer close(fd);3049 defer close(fd);
30503050
3051 var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined;3051 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
3054 return readlinkC(@ptrCast([*:0]const u8, proc_path.ptr), out_buffer);3054 return readlinkC(@ptrCast([*:0]const u8, proc_path.ptr), out_buffer);
3055 }3055 }
lib/std/os/uefi.zig+2-2
...@@ -27,11 +27,11 @@ pub const Guid = extern struct {...@@ -27,11 +27,11 @@ pub const Guid = extern struct {
27 pub fn format(27 pub fn format(
28 self: @This(),28 self: @This(),
29 comptime f: []const u8,29 comptime f: []const u8,
30 options: std.fmtstream.FormatOptions,30 options: std.fmt.FormatOptions,
31 out_stream: var,31 out_stream: var,
32 ) Errors!void {32 ) Errors!void {
33 if (f.len == 0) {33 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}", .{
35 self.time_low,35 self.time_low,
36 self.time_mid,36 self.time_mid,
37 self.time_high_and_version,37 self.time_high_and_version,
lib/std/progress.zig+3-3
...@@ -130,11 +130,11 @@ pub const Progress = struct {...@@ -130,11 +130,11 @@ pub const Progress = struct {
130 var end: usize = 0;130 var end: usize = 0;
131 if (self.columns_written > 0) {131 if (self.columns_written > 0) {
132 // restore cursor position132 // 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;
134 self.columns_written = 0;134 self.columns_written = 0;
135135
136 // clear rest of line136 // 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;
138 }138 }
139139
140 if (!self.done) {140 if (!self.done) {
...@@ -185,7 +185,7 @@ pub const Progress = struct {...@@ -185,7 +185,7 @@ pub const Progress = struct {
185 }185 }
186186
187 fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: var) void {187 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| {
189 const amt = written.len;189 const amt = written.len;
190 end.* += amt;190 end.* += amt;
191 self.columns_written += amt;191 self.columns_written += amt;
lib/std/special/build_runner.zig+3-3
...@@ -2,7 +2,7 @@ const root = @import("@build");...@@ -2,7 +2,7 @@ const root = @import("@build");
2const std = @import("std");2const std = @import("std");
3const builtin = @import("builtin");3const builtin = @import("builtin");
4const io = std.io;4const io = std.io;
5const fmtstream = std.fmtstream;5const fmt = std.fmt;
6const Builder = std.build.Builder;6const Builder = std.build.Builder;
7const mem = std.mem;7const mem = std.mem;
8const process = std.process;8const process = std.process;
...@@ -153,7 +153,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {...@@ -153,7 +153,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
153 const allocator = builder.allocator;153 const allocator = builder.allocator;
154 for (builder.top_level_steps.toSliceConst()) |top_level_step| {154 for (builder.top_level_steps.toSliceConst()) |top_level_step| {
155 const name = if (&top_level_step.step == builder.default_step)155 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})
157 else157 else
158 top_level_step.step.name;158 top_level_step.step.name;
159 try out_stream.print(" {s:22} {}\n", .{ name, top_level_step.description });159 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 {...@@ -175,7 +175,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
175 try out_stream.print(" (none)\n", .{});175 try out_stream.print(" (none)\n", .{});
176 } else {176 } else {
177 for (builder.available_options_list.toSliceConst()) |option| {177 for (builder.available_options_list.toSliceConst()) |option| {
178 const name = try fmtstream.allocPrint(allocator, " -D{}=[{}]", .{178 const name = try fmt.allocPrint(allocator, " -D{}=[{}]", .{
179 option.name,179 option.name,
180 Builder.typeIdName(option.type_id),180 Builder.typeIdName(option.type_id),
181 });181 });
lib/std/std.zig-1
...@@ -38,7 +38,6 @@ pub const elf = @import("elf.zig");...@@ -38,7 +38,6 @@ pub const elf = @import("elf.zig");
38pub const event = @import("event.zig");38pub const event = @import("event.zig");
39pub const fifo = @import("fifo.zig");39pub const fifo = @import("fifo.zig");
40pub const fmt = @import("fmt.zig");40pub const fmt = @import("fmt.zig");
41pub const fmtstream = @import("fmtstream.zig");
42pub const fs = @import("fs.zig");41pub const fs = @import("fs.zig");
43pub const hash = @import("hash.zig");42pub const hash = @import("hash.zig");
44pub const hash_map = @import("hash_map.zig");43pub const hash_map = @import("hash_map.zig");
lib/std/target.zig+2-2
...@@ -972,7 +972,7 @@ pub const Target = struct {...@@ -972,7 +972,7 @@ pub const Target = struct {
972 }972 }
973973
974 pub fn linuxTripleSimple(allocator: *mem.Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![:0]u8 {974 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) });
976 }976 }
977977
978 pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 {978 pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![:0]u8 {
...@@ -1158,7 +1158,7 @@ pub const Target = struct {...@@ -1158,7 +1158,7 @@ pub const Target = struct {
1158 var result: DynamicLinker = .{};1158 var result: DynamicLinker = .{};
1159 const S = struct {1159 const S = struct {
1160 fn print(r: *DynamicLinker, comptime fmt: []const u8, args: var) DynamicLinker {1160 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);
1162 return r.*;1162 return r.*;
1163 }1163 }
1164 fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {1164 fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {
lib/std/zig/cross_target.zig+1-1
...@@ -573,7 +573,7 @@ pub const CrossTarget = struct {...@@ -573,7 +573,7 @@ pub const CrossTarget = struct {
573 .Dynamic => "",573 .Dynamic => "",
574 };574 };
575575
576 return std.fmtstream.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix });576 return std.fmt.allocPrint0(allocator, "{}-{}{}", .{ arch, os, static_suffix });
577 }577 }
578578
579 pub const Executor = union(enum) {579 pub const Executor = union(enum) {
lib/std/zig/system.zig+3-3
...@@ -130,7 +130,7 @@ pub const NativePaths = struct {...@@ -130,7 +130,7 @@ pub const NativePaths = struct {
130 }130 }
131131
132 pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {132 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);
134 errdefer self.include_dirs.allocator.free(item);134 errdefer self.include_dirs.allocator.free(item);
135 try self.include_dirs.append(item);135 try self.include_dirs.append(item);
136 }136 }
...@@ -140,7 +140,7 @@ pub const NativePaths = struct {...@@ -140,7 +140,7 @@ pub const NativePaths = struct {
140 }140 }
141141
142 pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {142 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);
144 errdefer self.lib_dirs.allocator.free(item);144 errdefer self.lib_dirs.allocator.free(item);
145 try self.lib_dirs.append(item);145 try self.lib_dirs.append(item);
146 }146 }
...@@ -150,7 +150,7 @@ pub const NativePaths = struct {...@@ -150,7 +150,7 @@ pub const NativePaths = struct {
150 }150 }
151151
152 pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {152 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);
154 errdefer self.warnings.allocator.free(item);154 errdefer self.warnings.allocator.free(item);
155 try self.warnings.append(item);155 try self.warnings.append(item);
156 }156 }
src-self-hosted/compilation.zig+3-3
...@@ -1051,7 +1051,7 @@ pub const Compilation = struct {...@@ -1051,7 +1051,7 @@ pub const Compilation = struct {
1051 }1051 }
10521052
1053 fn addCompileError(self: *Compilation, tree_scope: *Scope.AstTree, span: Span, comptime fmt: []const u8, args: var) !void {1053 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);
1055 errdefer self.gpa().free(text);1055 errdefer self.gpa().free(text);
10561056
1057 const msg = try Msg.createFromScope(self, tree_scope, span, text);1057 const msg = try Msg.createFromScope(self, tree_scope, span, text);
...@@ -1061,7 +1061,7 @@ pub const Compilation = struct {...@@ -1061,7 +1061,7 @@ pub const Compilation = struct {
1061 }1061 }
10621062
1063 fn addCompileErrorCli(self: *Compilation, realpath: []const u8, comptime fmt: []const u8, args: var) !void {1063 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);
1065 errdefer self.gpa().free(text);1065 errdefer self.gpa().free(text);
10661066
1067 const msg = try Msg.createFromCli(self, realpath, text);1067 const msg = try Msg.createFromCli(self, realpath, text);
...@@ -1154,7 +1154,7 @@ pub const Compilation = struct {...@@ -1154,7 +1154,7 @@ pub const Compilation = struct {
1154 const tmp_dir = try self.getTmpDir();1154 const tmp_dir = try self.getTmpDir();
1155 const file_prefix = self.getRandomFileName();1155 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 });
1158 defer self.gpa().free(file_name);1158 defer self.gpa().free(file_name);
11591159
1160 const full_path = try fs.path.join(self.gpa(), &[_][]const u8{ tmp_dir, file_name[0..] });1160 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 {...@@ -893,7 +893,7 @@ fn printSection(out: var, label: []const u8, bytes: []const u8) !void {
893893
894fn printLabel(out: var, label: []const u8, bytes: []const u8) !void {894fn printLabel(out: var, label: []const u8, bytes: []const u8) !void {
895 var buf: [80]u8 = undefined;895 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 });
897 try out.write(text);897 try out.write(text);
898 var i: usize = text.len;898 var i: usize = text.len;
899 const end = 79;899 const end = 79;
...@@ -979,13 +979,13 @@ fn hexDump16(out: var, offset: usize, bytes: []const u8) !void {...@@ -979,13 +979,13 @@ fn hexDump16(out: var, offset: usize, bytes: []const u8) !void {
979979
980fn printDecValue(out: var, value: u64, width: u8) !void {980fn printDecValue(out: var, value: u64, width: u8) !void {
981 var buffer: [20]u8 = undefined;981 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);
983 try out.write(buffer[0..len]);983 try out.write(buffer[0..len]);
984}984}
985985
986fn printHexValue(out: var, value: u64, width: u8) !void {986fn printHexValue(out: var, value: u64, width: u8) !void {
987 var buffer: [16]u8 = undefined;987 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);
989 try out.write(buffer[0..len]);989 try out.write(buffer[0..len]);
990}990}
991991
src-self-hosted/libc_installation.zig+1-1
...@@ -543,7 +543,7 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {...@@ -543,7 +543,7 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
543 const allocator = args.allocator;543 const allocator = args.allocator;
544544
545 const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;545 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});
547 defer allocator.free(arg1);547 defer allocator.free(arg1);
548 const argv = [_][]const u8{ cc_exe, arg1 };548 const argv = [_][]const u8{ cc_exe, arg1 };
549549
src-self-hosted/link.zig+10-10
...@@ -296,13 +296,13 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -296,13 +296,13 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
296296
297 const is_library = ctx.comp.kind == .Lib;297 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()});
300 try ctx.args.append(@ptrCast([*:0]const u8, out_arg.ptr));300 try ctx.args.append(@ptrCast([*:0]const u8, out_arg.ptr));
301301
302 if (ctx.comp.haveLibC()) {302 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));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.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_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.fmtstream.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.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));
306 }306 }
307307
308 if (ctx.link_in_crt) {308 if (ctx.link_in_crt) {
...@@ -310,20 +310,20 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -310,20 +310,20 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
310 const d_str = if (ctx.comp.build_mode == .Debug) "d" else "";310 const d_str = if (ctx.comp.build_mode == .Debug) "d" else "";
311311
312 if (ctx.comp.is_static) {312 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});
314 try ctx.args.append(@ptrCast([*:0]const u8, cmt_lib_name.ptr));314 try ctx.args.append(@ptrCast([*:0]const u8, cmt_lib_name.ptr));
315 } else {315 } 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});
317 try ctx.args.append(@ptrCast([*:0]const u8, msvcrt_lib_name.ptr));317 try ctx.args.append(@ptrCast([*:0]const u8, msvcrt_lib_name.ptr));
318 }318 }
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", .{
321 lib_str,321 lib_str,
322 d_str,322 d_str,
323 });323 });
324 try ctx.args.append(@ptrCast([*:0]const u8, vcruntime_lib_name.ptr));324 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 });
327 try ctx.args.append(@ptrCast([*:0]const u8, crt_lib_name.ptr));327 try ctx.args.append(@ptrCast([*:0]const u8, crt_lib_name.ptr));
328328
329 // Visual C++ 2015 Conformance Changes329 // Visual C++ 2015 Conformance Changes
...@@ -383,7 +383,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -383,7 +383,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
383 .IPhoneOS => try ctx.args.append("-iphoneos_version_min"),383 .IPhoneOS => try ctx.args.append("-iphoneos_version_min"),
384 .IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),384 .IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),
385 }385 }
386 const ver_str = try std.fmtstream.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{386 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", .{
387 platform.major,387 platform.major,
388 platform.minor,388 platform.minor,
389 platform.micro,389 platform.micro,
...@@ -445,7 +445,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -445,7 +445,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
445 try ctx.args.append("-lSystem");445 try ctx.args.append("-lSystem");
446 } else {446 } else {
447 if (mem.indexOfScalar(u8, lib.name, '/') == null) {447 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});
449 try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));449 try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
450 } else {450 } else {
451 const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);451 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(...@@ -138,7 +138,7 @@ pub fn cmdTargets(
138 for (available_glibcs) |glibc| {138 for (available_glibcs) |glibc| {
139 try jws.arrayElem();139 try jws.arrayElem();
140140
141 const tmp = try std.fmtstream.allocPrint(allocator, "{}", .{glibc});141 const tmp = try std.fmt.allocPrint(allocator, "{}", .{glibc});
142 defer allocator.free(tmp);142 defer allocator.free(tmp);
143 try jws.emitString(tmp);143 try jws.emitString(tmp);
144 }144 }
src-self-hosted/test.zig+3-3
...@@ -81,7 +81,7 @@ pub const TestContext = struct {...@@ -81,7 +81,7 @@ pub const TestContext = struct {
81 msg: []const u8,81 msg: []const u8,
82 ) !void {82 ) !void {
83 var file_index_buf: [20]u8 = undefined;83 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()});
85 const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });85 const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
8686
87 if (std.fs.path.dirname(file1_path)) |dirname| {87 if (std.fs.path.dirname(file1_path)) |dirname| {
...@@ -114,10 +114,10 @@ pub const TestContext = struct {...@@ -114,10 +114,10 @@ pub const TestContext = struct {
114 expected_output: []const u8,114 expected_output: []const u8,
115 ) !void {115 ) !void {
116 var file_index_buf: [20]u8 = undefined;116 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()});
118 const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });118 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() });
121 if (std.fs.path.dirname(file1_path)) |dirname| {121 if (std.fs.path.dirname(file1_path)) |dirname| {
122 try std.fs.cwd().makePath(dirname);122 try std.fs.cwd().makePath(dirname);
123 }123 }
src-self-hosted/translate_c.zig+22-22
...@@ -89,7 +89,7 @@ const Scope = struct {...@@ -89,7 +89,7 @@ const Scope = struct {
89 var proposed_name = name;89 var proposed_name = name;
90 while (scope.contains(proposed_name)) {90 while (scope.contains(proposed_name)) {
91 scope.mangle_count += 1;91 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 });
93 }93 }
94 try scope.variables.push(.{ .name = name, .alias = proposed_name });94 try scope.variables.push(.{ .name = name, .alias = proposed_name });
95 return proposed_name;95 return proposed_name;
...@@ -246,7 +246,7 @@ pub const Context = struct {...@@ -246,7 +246,7 @@ pub const Context = struct {
246246
247 const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc);247 const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc);
248 const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc);248 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 });
250 }250 }
251};251};
252252
...@@ -516,7 +516,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -516,7 +516,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
516516
517 const arg_name = blk: {517 const arg_name = blk: {
518 const param_prefix = if (is_const) "" else "arg_";518 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 });
520 break :blk try block_scope.makeMangledName(c, bare_arg_name);520 break :blk try block_scope.makeMangledName(c, bare_arg_name);
521 };521 };
522522
...@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
560560
561 // TODO https://github.com/ziglang/zig/issues/3756561 // TODO https://github.com/ziglang/zig/issues/3756
562 // TODO https://github.com/ziglang/zig/issues/1802562 // 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;
564 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);564 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
565565
566 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);566 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
...@@ -620,7 +620,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -620,7 +620,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
620 _ = try appendToken(rp.c, .LParen, "(");620 _ = try appendToken(rp.c, .LParen, "(");
621 const expr = try transCreateNodeStringLiteral(621 const expr = try transCreateNodeStringLiteral(
622 rp.c,622 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]}),
624 );624 );
625 _ = try appendToken(rp.c, .RParen, ")");625 _ = try appendToken(rp.c, .RParen, ")");
626626
...@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l...@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l
677677
678 // TODO https://github.com/ziglang/zig/issues/3756678 // TODO https://github.com/ziglang/zig/issues/3756
679 // TODO https://github.com/ziglang/zig/issues/1802679 // 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
682 if (mem.eql(u8, checked_name, "uint8_t"))682 if (mem.eql(u8, checked_name, "uint8_t"))
683 return transTypeDefAsBuiltin(c, typedef_decl, "u8")683 return transTypeDefAsBuiltin(c, typedef_decl, "u8")
...@@ -738,7 +738,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -738,7 +738,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
738 // Record declarations such as `struct {...} x` have no name but they're not738 // Record declarations such as `struct {...} x` have no name but they're not
739 // anonymous hence here isAnonymousStructOrUnion is not needed739 // anonymous hence here isAnonymousStructOrUnion is not needed
740 if (bare_name.len == 0) {740 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()});
742 is_unnamed = true;742 is_unnamed = true;
743 }743 }
744744
...@@ -755,7 +755,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -755,7 +755,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
755 return null;755 return null;
756 }756 }
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 });
759 _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);759 _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
760760
761 const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);761 const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
...@@ -812,7 +812,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -812,7 +812,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
812 var is_anon = false;812 var is_anon = false;
813 var raw_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, field_decl)));813 var raw_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, field_decl)));
814 if (ZigClangFieldDecl_isAnonymousStructOrUnion(field_decl)) {814 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()});
816 is_anon = true;816 is_anon = true;
817 }817 }
818 const field_name = try appendIdentifier(c, raw_name);818 const field_name = try appendIdentifier(c, raw_name);
...@@ -882,11 +882,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No...@@ -882,11 +882,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No
882 var bare_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, enum_decl)));882 var bare_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, enum_decl)));
883 var is_unnamed = false;883 var is_unnamed = false;
884 if (bare_name.len == 0) {884 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()});
886 is_unnamed = true;886 is_unnamed = true;
887 }887 }
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});
890 _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);890 _ = try c.decl_table.put(@ptrToInt(ZigClangEnumDecl_getCanonicalDecl(enum_decl)), name);
891 const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);891 const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
892 node.eq_token = try appendToken(c, .Equal, "=");892 node.eq_token = try appendToken(c, .Equal, "=");
...@@ -1754,9 +1754,9 @@ fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {...@@ -1754,9 +1754,9 @@ fn escapeChar(c: u8, char_buf: *[4]u8) []const u8 {
1754 // Handle the remaining escapes Zig doesn't support by turning them1754 // Handle the remaining escapes Zig doesn't support by turning them
1755 // into their respective hex representation1755 // into their respective hex representation
1756 if (std.ascii.isCntrl(c))1756 if (std.ascii.isCntrl(c))
1757 return std.fmtstream.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable1757 return std.fmt.bufPrint(char_buf[0..], "\\x{x:0<2}", .{c}) catch unreachable
1758 else1758 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;
1760 },1760 },
1761 };1761 };
1762}1762}
...@@ -2436,7 +2436,7 @@ fn transCase(...@@ -2436,7 +2436,7 @@ fn transCase(
2436) TransError!*ast.Node {2436) TransError!*ast.Node {
2437 const block_scope = scope.findBlockScope(rp.c) catch unreachable;2437 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
2438 const switch_scope = scope.getSwitch();2438 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)});
2440 _ = try appendToken(rp.c, .Semicolon, ";");2440 _ = try appendToken(rp.c, .Semicolon, ";");
24412441
2442 const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {2442 const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {
...@@ -4607,7 +4607,7 @@ fn finishTransFnProto(...@@ -4607,7 +4607,7 @@ fn finishTransFnProto(
4607 _ = try appendToken(rp.c, .LParen, "(");4607 _ = try appendToken(rp.c, .LParen, "(");
4608 const expr = try transCreateNodeStringLiteral(4608 const expr = try transCreateNodeStringLiteral(
4609 rp.c,4609 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]}),
4611 );4611 );
4612 _ = try appendToken(rp.c, .RParen, ")");4612 _ = try appendToken(rp.c, .RParen, ")");
46134613
...@@ -4866,7 +4866,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {...@@ -4866,7 +4866,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
4866 const name = try c.str(raw_name);4866 const name = try c.str(raw_name);
4867 // TODO https://github.com/ziglang/zig/issues/37564867 // TODO https://github.com/ziglang/zig/issues/3756
4868 // TODO https://github.com/ziglang/zig/issues/18024868 // 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;
4870 if (scope.containsNow(mangled_name)) {4870 if (scope.containsNow(mangled_name)) {
4871 continue;4871 continue;
4872 }4872 }
...@@ -5151,11 +5151,11 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl...@@ -5151,11 +5151,11 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl
5151 switch (lit_bytes[1]) {5151 switch (lit_bytes[1]) {
5152 '0'...'7' => {5152 '0'...'7' => {
5153 // Octal5153 // 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});
5155 },5155 },
5156 'X' => {5156 'X' => {
5157 // Hexadecimal with capital X, valid in C but not in Zig5157 // 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..]});
5159 },5159 },
5160 else => {},5160 else => {},
5161 }5161 }
...@@ -5186,7 +5186,7 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl...@@ -5186,7 +5186,7 @@ fn parseCNumLit(c: *Context, tok: *CToken, source: []const u8, source_loc: ZigCl
5186 return &cast_node.base;5186 return &cast_node.base;
5187 } else if (tok.id == .FloatLiteral) {5187 } else if (tok.id == .FloatLiteral) {
5188 if (lit_bytes[0] == '.')5188 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});
5190 if (tok.id.FloatLiteral == .None) {5190 if (tok.id.FloatLiteral == .None) {
5191 return transCreateNodeFloat(c, lit_bytes);5191 return transCreateNodeFloat(c, lit_bytes);
5192 }5192 }
...@@ -5319,7 +5319,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const...@@ -5319,7 +5319,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
5319 num += c - 'A' + 10;5319 num += c - 'A' + 10;
5320 },5320 },
5321 else => {5321 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 });
5323 num = 0;5323 num = 0;
5324 if (c == '\\')5324 if (c == '\\')
5325 state = .Escape5325 state = .Escape
...@@ -5345,7 +5345,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const...@@ -5345,7 +5345,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
5345 };5345 };
5346 num += c - '0';5346 num += c - '0';
5347 } else {5347 } 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 });
5349 num = 0;5349 num = 0;
5350 count = 0;5350 count = 0;
5351 if (c == '\\')5351 if (c == '\\')
...@@ -5359,7 +5359,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const...@@ -5359,7 +5359,7 @@ fn zigifyEscapeSequences(ctx: *Context, source_bytes: []const u8, name: []const
5359 }5359 }
5360 }5360 }
5361 if (state == .Hex or state == .Octal)5361 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 });
5363 return bytes[0..i];5363 return bytes[0..i];
5364}5364}
53655365
src-self-hosted/type.zig+4-4
...@@ -581,7 +581,7 @@ pub const Type = struct {...@@ -581,7 +581,7 @@ pub const Type = struct {
581 errdefer comp.gpa().destroy(self);581 errdefer comp.gpa().destroy(self);
582582
583 const u_or_i = "ui"[@boolToInt(key.is_signed)];583 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 });
585 errdefer comp.gpa().free(name);585 errdefer comp.gpa().free(name);
586586
587 self.base.init(comp, .Int, name);587 self.base.init(comp, .Int, name);
...@@ -764,13 +764,13 @@ pub const Type = struct {...@@ -764,13 +764,13 @@ pub const Type = struct {
764 .Non => "",764 .Non => "",
765 };765 };
766 const name = switch (self.key.alignment) {766 const name = switch (self.key.alignment) {
767 .Abi => try std.fmtstream.allocPrint(comp.gpa(), "{}{}{}{}", .{767 .Abi => try std.fmt.allocPrint(comp.gpa(), "{}{}{}{}", .{
768 size_str,768 size_str,
769 mut_str,769 mut_str,
770 vol_str,770 vol_str,
771 self.key.child_type.name,771 self.key.child_type.name,
772 }),772 }),
773 .Override => |alignment| try std.fmtstream.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{773 .Override => |alignment| try std.fmt.allocPrint(comp.gpa(), "{}align<{}> {}{}{}", .{
774 size_str,774 size_str,
775 alignment,775 alignment,
776 mut_str,776 mut_str,
...@@ -845,7 +845,7 @@ pub const Type = struct {...@@ -845,7 +845,7 @@ pub const Type = struct {
845 };845 };
846 errdefer comp.gpa().destroy(self);846 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 });
849 errdefer comp.gpa().free(name);849 errdefer comp.gpa().free(name);
850850
851 self.base.init(comp, .Array, name);851 self.base.init(comp, .Array, name);
test/src/compare_output.zig+4-4
...@@ -4,7 +4,7 @@ const std = @import("std");...@@ -4,7 +4,7 @@ const std = @import("std");
4const builtin = std.builtin;4const builtin = std.builtin;
5const build = std.build;5const build = std.build;
6const ArrayList = std.ArrayList;6const ArrayList = std.ArrayList;
7const fmtstream = std.fmtstream;7const fmt = std.fmt;
8const mem = std.mem;8const mem = std.mem;
9const fs = std.fs;9const fs = std.fs;
10const warn = std.debug.warn;10const warn = std.debug.warn;
...@@ -97,7 +97,7 @@ pub const CompareOutputContext = struct {...@@ -97,7 +97,7 @@ pub const CompareOutputContext = struct {
9797
98 switch (case.special) {98 switch (case.special) {
99 Special.Asm => {99 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 {}", .{
101 case.name,101 case.name,
102 }) catch unreachable;102 }) catch unreachable;
103 if (self.test_filter) |filter| {103 if (self.test_filter) |filter| {
...@@ -116,7 +116,7 @@ pub const CompareOutputContext = struct {...@@ -116,7 +116,7 @@ pub const CompareOutputContext = struct {
116 },116 },
117 Special.None => {117 Special.None => {
118 for (self.modes) |mode| {118 for (self.modes) |mode| {
119 const annotated_case_name = fmtstream.allocPrint(self.b.allocator, "{} {} ({})", .{119 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", .{
120 "compare-output",120 "compare-output",
121 case.name,121 case.name,
122 @tagName(mode),122 @tagName(mode),
...@@ -141,7 +141,7 @@ pub const CompareOutputContext = struct {...@@ -141,7 +141,7 @@ pub const CompareOutputContext = struct {
141 }141 }
142 },142 },
143 Special.RuntimeSafety => {143 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;
145 if (self.test_filter) |filter| {145 if (self.test_filter) |filter| {
146 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;146 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
147 }147 }
test/src/run_translated_c.zig+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3const std = @import("std");3const std = @import("std");
4const build = std.build;4const build = std.build;
5const ArrayList = std.ArrayList;5const ArrayList = std.ArrayList;
6const fmtstream = std.fmtstream;6const fmt = std.fmt;
7const mem = std.mem;7const mem = std.mem;
8const fs = std.fs;8const fs = std.fs;
9const warn = std.debug.warn;9const warn = std.debug.warn;
...@@ -76,7 +76,7 @@ pub const RunTranslatedCContext = struct {...@@ -76,7 +76,7 @@ pub const RunTranslatedCContext = struct {
76 pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {76 pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
77 const b = self.b;77 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;
80 if (self.test_filter) |filter| {80 if (self.test_filter) |filter| {
81 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;81 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
82 }82 }
test/src/translate_c.zig+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3const std = @import("std");3const std = @import("std");
4const build = std.build;4const build = std.build;
5const ArrayList = std.ArrayList;5const ArrayList = std.ArrayList;
6const fmtstream = std.fmtstream;6const fmt = std.fmt;
7const mem = std.mem;7const mem = std.mem;
8const fs = std.fs;8const fs = std.fs;
9const warn = std.debug.warn;9const warn = std.debug.warn;
...@@ -99,7 +99,7 @@ pub const TranslateCContext = struct {...@@ -99,7 +99,7 @@ pub const TranslateCContext = struct {
99 const b = self.b;99 const b = self.b;
100100
101 const translate_c_cmd = "translate-c";101 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;
103 if (self.test_filter) |filter| {103 if (self.test_filter) |filter| {
104 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;104 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
105 }105 }
test/stage1/behavior/enum_with_members.zig+3-3
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const expect = @import("std").testing.expect;1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;2const mem = @import("std").mem;
3const fmtstream = @import("std").fmtstream;3const fmt = @import("std").fmt;
44
5const ET = union(enum) {5const ET = union(enum) {
6 SINT: i32,6 SINT: i32,
...@@ -8,8 +8,8 @@ const ET = union(enum) {...@@ -8,8 +8,8 @@ const ET = union(enum) {
88
9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
10 return switch (a.*) {10 return switch (a.*) {
11 ET.SINT => |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| fmtstream.formatIntBuf(buf, x, 10, false, fmtstream.FormatOptions{}),12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, fmt.FormatOptions{}),
13 };13 };
14 }14 }
15};15};
test/tests.zig+5-5
...@@ -8,7 +8,7 @@ const Buffer = std.Buffer;...@@ -8,7 +8,7 @@ const Buffer = std.Buffer;
8const io = std.io;8const io = std.io;
9const fs = std.fs;9const fs = std.fs;
10const mem = std.mem;10const mem = std.mem;
11const fmtstream = std.fmtstream;11const fmt = std.fmt;
12const ArrayList = std.ArrayList;12const ArrayList = std.ArrayList;
13const Mode = builtin.Mode;13const Mode = builtin.Mode;
14const LibExeObjStep = build.LibExeObjStep;14const LibExeObjStep = build.LibExeObjStep;
...@@ -484,7 +484,7 @@ pub const StackTracesContext = struct {...@@ -484,7 +484,7 @@ pub const StackTracesContext = struct {
484 const expect_for_mode = expect[@enumToInt(mode)];484 const expect_for_mode = expect[@enumToInt(mode)];
485 if (expect_for_mode.len == 0) continue;485 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, "{} {} ({})", .{
488 "stack-trace",488 "stack-trace",
489 name,489 name,
490 @tagName(mode),490 @tagName(mode),
...@@ -943,7 +943,7 @@ pub const CompileErrorContext = struct {...@@ -943,7 +943,7 @@ pub const CompileErrorContext = struct {
943 pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {943 pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
944 const b = self.b;944 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 {}", .{
947 case.name,947 case.name,
948 }) catch unreachable;948 }) catch unreachable;
949 if (self.test_filter) |filter| {949 if (self.test_filter) |filter| {
...@@ -1009,7 +1009,7 @@ pub const StandaloneContext = struct {...@@ -1009,7 +1009,7 @@ pub const StandaloneContext = struct {
1009 const b = self.b;1009 const b = self.b;
10101010
1011 for (self.modes) |mode| {1011 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 {} ({})", .{
1013 root_src,1013 root_src,
1014 @tagName(mode),1014 @tagName(mode),
1015 }) catch unreachable;1015 }) catch unreachable;
...@@ -1152,7 +1152,7 @@ pub const GenHContext = struct {...@@ -1152,7 +1152,7 @@ pub const GenHContext = struct {
1152 const b = self.b;1152 const b = self.b;
11531153
1154 const mode = builtin.Mode.Debug;1154 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;
1156 if (self.test_filter) |filter| {1156 if (self.test_filter) |filter| {
1157 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;1157 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
1158 }1158 }
tools/process_headers.zig+2-2
...@@ -299,7 +299,7 @@ pub fn main() !void {...@@ -299,7 +299,7 @@ pub fn main() !void {
299 std.debug.warn("unrecognized C ABI: {}\n", .{abi_name});299 std.debug.warn("unrecognized C ABI: {}\n", .{abi_name});
300 usageAndExit(args[0]);300 usageAndExit(args[0]);
301 };301 };
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
304 // TODO compiler crashed when I wrote this the canonical way304 // TODO compiler crashed when I wrote this the canonical way
305 var libc_targets: []const LibCTarget = undefined;305 var libc_targets: []const LibCTarget = undefined;
...@@ -440,7 +440,7 @@ pub fn main() !void {...@@ -440,7 +440,7 @@ pub fn main() !void {
440 .specific => |a| @tagName(a),440 .specific => |a| @tagName(a),
441 else => @tagName(dest_target.arch),441 else => @tagName(dest_target.arch),
442 };442 };
443 const out_subpath = try std.fmtstream.allocPrint(allocator, "{}-{}-{}", .{443 const out_subpath = try std.fmt.allocPrint(allocator, "{}-{}-{}", .{
444 arch_name,444 arch_name,
445 @tagName(dest_target.os),445 @tagName(dest_target.os),
446 @tagName(dest_target.abi),446 @tagName(dest_target.abi),
tools/update_glibc.zig+2-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const fs = std.fs;2const fs = std.fs;
3const fmtstream = std.fmtstream;3const fmt = std.fmt;
4const assert = std.debug.assert;4const assert = std.debug.assert;
55
6// Example abilist path:6// Example abilist path:
...@@ -154,7 +154,7 @@ pub fn main() !void {...@@ -154,7 +154,7 @@ pub fn main() !void {
154 const fn_set = &target_funcs_gop.kv.value.list;154 const fn_set = &target_funcs_gop.kv.value.list;
155155
156 for (lib_names) |lib_name, lib_name_index| {156 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});
158 const abi_list_filename = blk: {158 const abi_list_filename = blk: {
159 if (abi_list.targets[0].abi == .gnuabi64 and std.mem.eql(u8, lib_name, "c")) {159 if (abi_list.targets[0].abi == .gnuabi64 and std.mem.eql(u8, lib_name, "c")) {
160 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename });160 break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename });