| ... | @@ -69,7 +69,6 @@ pub fn format( | ... | @@ -69,7 +69,6 @@ pub fn format( |
| 69 | FormatFillAndAlign, | 69 | FormatFillAndAlign, |
| 70 | FormatWidth, | 70 | FormatWidth, |
| 71 | FormatPrecision, | 71 | FormatPrecision, |
| 72 | Pointer, | | |
| 73 | }; | 72 | }; |
| 74 | | 73 | |
| 75 | comptime var start_index = 0; | 74 | comptime var start_index = 0; |
| ... | @@ -109,9 +108,6 @@ pub fn format( | ... | @@ -109,9 +108,6 @@ pub fn format( |
| 109 | state = .Start; | 108 | state = .Start; |
| 110 | start_index = i; | 109 | start_index = i; |
| 111 | }, | 110 | }, |
| 112 | '*' => { | | |
| 113 | state = .Pointer; | | |
| 114 | }, | | |
| 115 | ':' => { | 111 | ':' => { |
| 116 | state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth; | 112 | state = if (comptime peekIsAlign(fmt[i..])) State.FormatFillAndAlign else State.FormatWidth; |
| 117 | specifier_end = i; | 113 | specifier_end = i; |
| ... | @@ -256,19 +252,6 @@ pub fn format( | ... | @@ -256,19 +252,6 @@ pub fn format( |
| 256 | @compileError("Unexpected character in precision value: " ++ [_]u8{c}); | 252 | @compileError("Unexpected character in precision value: " ++ [_]u8{c}); |
| 257 | }, | 253 | }, |
| 258 | }, | 254 | }, |
| 259 | .Pointer => switch (c) { | | |
| 260 | '}' => { | | |
| 261 | const arg_to_print = comptime nextArg(&used_pos_args, maybe_pos_arg, &next_arg); | | |
| 262 | | | |
| 263 | try output(context, @typeName(@typeOf(args[arg_to_print]).Child)); | | |
| 264 | try output(context, "@"); | | |
| 265 | try formatInt(@ptrToInt(args[arg_to_print]), 16, false, 0, context, Errors, output); | | |
| 266 | | | |
| 267 | state = .Start; | | |
| 268 | start_index = i + 1; | | |
| 269 | }, | | |
| 270 | else => @compileError("Unexpected format character after '*'"), | | |
| 271 | }, | | |
| 272 | } | 255 | } |
| 273 | } | 256 | } |
| 274 | comptime { | 257 | comptime { |
| ... | @@ -293,12 +276,19 @@ pub fn format( | ... | @@ -293,12 +276,19 @@ pub fn format( |
| 293 | pub fn formatType( | 276 | pub fn formatType( |
| 294 | value: var, | 277 | value: var, |
| 295 | comptime fmt: []const u8, | 278 | comptime fmt: []const u8, |
| 296 | comptime options: FormatOptions, | 279 | options: FormatOptions, |
| 297 | context: var, | 280 | context: var, |
| 298 | comptime Errors: type, | 281 | comptime Errors: type, |
| 299 | output: fn (@typeOf(context), []const u8) Errors!void, | 282 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 300 | max_depth: usize, | 283 | max_depth: usize, |
| 301 | ) Errors!void { | 284 | ) Errors!void { |
| | 285 | if (comptime std.mem.eql(u8, fmt, "*")) { |
| | 286 | try output(context, @typeName(@typeOf(value).Child)); |
| | 287 | try output(context, "@"); |
| | 288 | try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, context, Errors, output); |
| | 289 | return; |
| | 290 | } |
| | 291 | |
| 302 | const T = @typeOf(value); | 292 | const T = @typeOf(value); |
| 303 | switch (@typeInfo(T)) { | 293 | switch (@typeInfo(T)) { |
| 304 | .ComptimeInt, .Int, .Float => { | 294 | .ComptimeInt, .Int, .Float => { |
| ... | @@ -438,15 +428,15 @@ pub fn formatType( | ... | @@ -438,15 +428,15 @@ pub fn formatType( |
| 438 | fn formatValue( | 428 | fn formatValue( |
| 439 | value: var, | 429 | value: var, |
| 440 | comptime fmt: []const u8, | 430 | comptime fmt: []const u8, |
| 441 | comptime options: FormatOptions, | 431 | options: FormatOptions, |
| 442 | context: var, | 432 | context: var, |
| 443 | comptime Errors: type, | 433 | comptime Errors: type, |
| 444 | output: fn (@typeOf(context), []const u8) Errors!void, | 434 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 445 | ) Errors!void { | 435 | ) Errors!void { |
| 446 | if (comptime std.mem.eql(u8, fmt, "B")) { | 436 | if (comptime std.mem.eql(u8, fmt, "B")) { |
| 447 | return formatBytes(value, options.width, 1000, context, Errors, output); | 437 | return formatBytes(value, options, 1000, context, Errors, output); |
| 448 | } else if (comptime std.mem.eql(u8, fmt, "Bi")) { | 438 | } else if (comptime std.mem.eql(u8, fmt, "Bi")) { |
| 449 | return formatBytes(value, options.width, 1024, context, Errors, output); | 439 | return formatBytes(value, options, 1024, context, Errors, output); |
| 450 | } | 440 | } |
| 451 | | 441 | |
| 452 | const T = @typeOf(value); | 442 | const T = @typeOf(value); |
| ... | @@ -460,7 +450,7 @@ fn formatValue( | ... | @@ -460,7 +450,7 @@ fn formatValue( |
| 460 | pub fn formatIntValue( | 450 | pub fn formatIntValue( |
| 461 | value: var, | 451 | value: var, |
| 462 | comptime fmt: []const u8, | 452 | comptime fmt: []const u8, |
| 463 | comptime options: FormatOptions, | 453 | options: FormatOptions, |
| 464 | context: var, | 454 | context: var, |
| 465 | comptime Errors: type, | 455 | comptime Errors: type, |
| 466 | output: fn (@typeOf(context), []const u8) Errors!void, | 456 | output: fn (@typeOf(context), []const u8) Errors!void, |
| ... | @@ -479,7 +469,7 @@ pub fn formatIntValue( | ... | @@ -479,7 +469,7 @@ pub fn formatIntValue( |
| 479 | uppercase = false; | 469 | uppercase = false; |
| 480 | } else if (comptime std.mem.eql(u8, fmt, "c")) { | 470 | } else if (comptime std.mem.eql(u8, fmt, "c")) { |
| 481 | if (@typeOf(int_value).bit_count <= 8) { | 471 | if (@typeOf(int_value).bit_count <= 8) { |
| 482 | return formatAsciiChar(u8(int_value), context, Errors, output); | 472 | return formatAsciiChar(u8(int_value), options, context, Errors, output); |
| 483 | } else { | 473 | } else { |
| 484 | @compileError("Cannot print integer that is larger than 8 bits as a ascii"); | 474 | @compileError("Cannot print integer that is larger than 8 bits as a ascii"); |
| 485 | } | 475 | } |
| ... | @@ -496,21 +486,21 @@ pub fn formatIntValue( | ... | @@ -496,21 +486,21 @@ pub fn formatIntValue( |
| 496 | @compileError("Unknown format string: '" ++ fmt ++ "'"); | 486 | @compileError("Unknown format string: '" ++ fmt ++ "'"); |
| 497 | } | 487 | } |
| 498 | | 488 | |
| 499 | return formatInt(int_value, radix, uppercase, options.width orelse 0, context, Errors, output); | 489 | return formatInt(int_value, radix, uppercase, options, context, Errors, output); |
| 500 | } | 490 | } |
| 501 | | 491 | |
| 502 | fn formatFloatValue( | 492 | fn formatFloatValue( |
| 503 | value: var, | 493 | value: var, |
| 504 | comptime fmt: []const u8, | 494 | comptime fmt: []const u8, |
| 505 | comptime options: FormatOptions, | 495 | options: FormatOptions, |
| 506 | context: var, | 496 | context: var, |
| 507 | comptime Errors: type, | 497 | comptime Errors: type, |
| 508 | output: fn (@typeOf(context), []const u8) Errors!void, | 498 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 509 | ) Errors!void { | 499 | ) Errors!void { |
| 510 | if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) { | 500 | if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) { |
| 511 | return formatFloatScientific(value, options.precision, context, Errors, output); | 501 | return formatFloatScientific(value, options, context, Errors, output); |
| 512 | } else if (comptime std.mem.eql(u8, fmt, "d")) { | 502 | } else if (comptime std.mem.eql(u8, fmt, "d")) { |
| 513 | return formatFloatDecimal(value, options.precision, context, Errors, output); | 503 | return formatFloatDecimal(value, options, context, Errors, output); |
| 514 | } else { | 504 | } else { |
| 515 | @compileError("Unknown format string: '" ++ fmt ++ "'"); | 505 | @compileError("Unknown format string: '" ++ fmt ++ "'"); |
| 516 | } | 506 | } |
| ... | @@ -519,7 +509,7 @@ fn formatFloatValue( | ... | @@ -519,7 +509,7 @@ fn formatFloatValue( |
| 519 | pub fn formatText( | 509 | pub fn formatText( |
| 520 | bytes: []const u8, | 510 | bytes: []const u8, |
| 521 | comptime fmt: []const u8, | 511 | comptime fmt: []const u8, |
| 522 | comptime options: FormatOptions, | 512 | options: FormatOptions, |
| 523 | context: var, | 513 | context: var, |
| 524 | comptime Errors: type, | 514 | comptime Errors: type, |
| 525 | output: fn (@typeOf(context), []const u8) Errors!void, | 515 | output: fn (@typeOf(context), []const u8) Errors!void, |
| ... | @@ -527,11 +517,10 @@ pub fn formatText( | ... | @@ -527,11 +517,10 @@ pub fn formatText( |
| 527 | if (fmt.len == 0) { | 517 | if (fmt.len == 0) { |
| 528 | return output(context, bytes); | 518 | return output(context, bytes); |
| 529 | } else if (comptime std.mem.eql(u8, fmt, "s")) { | 519 | } else if (comptime std.mem.eql(u8, fmt, "s")) { |
| 530 | if (options.width) |w| return formatBuf(bytes, w, context, Errors, output); | 520 | return formatBuf(bytes, options, context, Errors, output); |
| 531 | return formatBuf(bytes, 0, context, Errors, output); | | |
| 532 | } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) { | 521 | } else if (comptime (std.mem.eql(u8, fmt, "x") or std.mem.eql(u8, fmt, "X"))) { |
| 533 | for (bytes) |c| { | 522 | for (bytes) |c| { |
| 534 | try formatInt(c, 16, fmt[0] == 'X', 2, context, Errors, output); | 523 | try formatInt(c, 16, fmt[0] == 'X', FormatOptions{ .width = 2, .fill = '0' }, context, Errors, output); |
| 535 | } | 524 | } |
| 536 | return; | 525 | return; |
| 537 | } else { | 526 | } else { |
| ... | @@ -541,6 +530,7 @@ pub fn formatText( | ... | @@ -541,6 +530,7 @@ pub fn formatText( |
| 541 | | 530 | |
| 542 | pub fn formatAsciiChar( | 531 | pub fn formatAsciiChar( |
| 543 | c: u8, | 532 | c: u8, |
| | 533 | options: FormatOptions, |
| 544 | context: var, | 534 | context: var, |
| 545 | comptime Errors: type, | 535 | comptime Errors: type, |
| 546 | output: fn (@typeOf(context), []const u8) Errors!void, | 536 | output: fn (@typeOf(context), []const u8) Errors!void, |
| ... | @@ -550,15 +540,16 @@ pub fn formatAsciiChar( | ... | @@ -550,15 +540,16 @@ pub fn formatAsciiChar( |
| 550 | | 540 | |
| 551 | pub fn formatBuf( | 541 | pub fn formatBuf( |
| 552 | buf: []const u8, | 542 | buf: []const u8, |
| 553 | width: usize, | 543 | options: FormatOptions, |
| 554 | context: var, | 544 | context: var, |
| 555 | comptime Errors: type, | 545 | comptime Errors: type, |
| 556 | output: fn (@typeOf(context), []const u8) Errors!void, | 546 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 557 | ) Errors!void { | 547 | ) Errors!void { |
| 558 | try output(context, buf); | 548 | try output(context, buf); |
| 559 | | 549 | |
| | 550 | const width = options.width orelse 0; |
| 560 | var leftover_padding = if (width > buf.len) (width - buf.len) else return; | 551 | var leftover_padding = if (width > buf.len) (width - buf.len) else return; |
| 561 | const pad_byte: u8 = ' '; | 552 | const pad_byte: u8 = options.fill; |
| 562 | while (leftover_padding > 0) : (leftover_padding -= 1) { | 553 | while (leftover_padding > 0) : (leftover_padding -= 1) { |
| 563 | try output(context, (*const [1]u8)(&pad_byte)[0..1]); | 554 | try output(context, (*const [1]u8)(&pad_byte)[0..1]); |
| 564 | } | 555 | } |
| ... | @@ -569,7 +560,7 @@ pub fn formatBuf( | ... | @@ -569,7 +560,7 @@ pub fn formatBuf( |
| 569 | // same type unambiguously. | 560 | // same type unambiguously. |
| 570 | pub fn formatFloatScientific( | 561 | pub fn formatFloatScientific( |
| 571 | value: var, | 562 | value: var, |
| 572 | maybe_precision: ?usize, | 563 | options: FormatOptions, |
| 573 | context: var, | 564 | context: var, |
| 574 | comptime Errors: type, | 565 | comptime Errors: type, |
| 575 | output: fn (@typeOf(context), []const u8) Errors!void, | 566 | output: fn (@typeOf(context), []const u8) Errors!void, |
| ... | @@ -591,7 +582,7 @@ pub fn formatFloatScientific( | ... | @@ -591,7 +582,7 @@ pub fn formatFloatScientific( |
| 591 | if (x == 0.0) { | 582 | if (x == 0.0) { |
| 592 | try output(context, "0"); | 583 | try output(context, "0"); |
| 593 | | 584 | |
| 594 | if (maybe_precision) |precision| { | 585 | if (options.precision) |precision| { |
| 595 | if (precision != 0) { | 586 | if (precision != 0) { |
| 596 | try output(context, "."); | 587 | try output(context, "."); |
| 597 | var i: usize = 0; | 588 | var i: usize = 0; |
| ... | @@ -610,7 +601,7 @@ pub fn formatFloatScientific( | ... | @@ -610,7 +601,7 @@ pub fn formatFloatScientific( |
| 610 | var buffer: [32]u8 = undefined; | 601 | var buffer: [32]u8 = undefined; |
| 611 | var float_decimal = errol.errol3(x, buffer[0..]); | 602 | var float_decimal = errol.errol3(x, buffer[0..]); |
| 612 | | 603 | |
| 613 | if (maybe_precision) |precision| { | 604 | if (options.precision) |precision| { |
| 614 | errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific); | 605 | errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Scientific); |
| 615 | | 606 | |
| 616 | try output(context, float_decimal.digits[0..1]); | 607 | try output(context, float_decimal.digits[0..1]); |
| ... | @@ -650,13 +641,13 @@ pub fn formatFloatScientific( | ... | @@ -650,13 +641,13 @@ pub fn formatFloatScientific( |
| 650 | if (exp > -10 and exp < 10) { | 641 | if (exp > -10 and exp < 10) { |
| 651 | try output(context, "0"); | 642 | try output(context, "0"); |
| 652 | } | 643 | } |
| 653 | try formatInt(exp, 10, false, 0, context, Errors, output); | 644 | try formatInt(exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output); |
| 654 | } else { | 645 | } else { |
| 655 | try output(context, "-"); | 646 | try output(context, "-"); |
| 656 | if (exp > -10 and exp < 10) { | 647 | if (exp > -10 and exp < 10) { |
| 657 | try output(context, "0"); | 648 | try output(context, "0"); |
| 658 | } | 649 | } |
| 659 | try formatInt(-exp, 10, false, 0, context, Errors, output); | 650 | try formatInt(-exp, 10, false, FormatOptions{ .width = 0 }, context, Errors, output); |
| 660 | } | 651 | } |
| 661 | } | 652 | } |
| 662 | | 653 | |
| ... | @@ -664,7 +655,7 @@ pub fn formatFloatScientific( | ... | @@ -664,7 +655,7 @@ pub fn formatFloatScientific( |
| 664 | // By default floats are printed at full precision (no rounding). | 655 | // By default floats are printed at full precision (no rounding). |
| 665 | pub fn formatFloatDecimal( | 656 | pub fn formatFloatDecimal( |
| 666 | value: var, | 657 | value: var, |
| 667 | maybe_precision: ?usize, | 658 | options: FormatOptions, |
| 668 | context: var, | 659 | context: var, |
| 669 | comptime Errors: type, | 660 | comptime Errors: type, |
| 670 | output: fn (@typeOf(context), []const u8) Errors!void, | 661 | output: fn (@typeOf(context), []const u8) Errors!void, |
| ... | @@ -686,7 +677,7 @@ pub fn formatFloatDecimal( | ... | @@ -686,7 +677,7 @@ pub fn formatFloatDecimal( |
| 686 | if (x == 0.0) { | 677 | if (x == 0.0) { |
| 687 | try output(context, "0"); | 678 | try output(context, "0"); |
| 688 | | 679 | |
| 689 | if (maybe_precision) |precision| { | 680 | if (options.precision) |precision| { |
| 690 | if (precision != 0) { | 681 | if (precision != 0) { |
| 691 | try output(context, "."); | 682 | try output(context, "."); |
| 692 | var i: usize = 0; | 683 | var i: usize = 0; |
| ... | @@ -707,7 +698,7 @@ pub fn formatFloatDecimal( | ... | @@ -707,7 +698,7 @@ pub fn formatFloatDecimal( |
| 707 | var buffer: [32]u8 = undefined; | 698 | var buffer: [32]u8 = undefined; |
| 708 | var float_decimal = errol.errol3(x, buffer[0..]); | 699 | var float_decimal = errol.errol3(x, buffer[0..]); |
| 709 | | 700 | |
| 710 | if (maybe_precision) |precision| { | 701 | if (options.precision) |precision| { |
| 711 | errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Decimal); | 702 | errol.roundToPrecision(&float_decimal, precision, errol.RoundMode.Decimal); |
| 712 | | 703 | |
| 713 | // exp < 0 means the leading is always 0 as errol result is normalized. | 704 | // exp < 0 means the leading is always 0 as errol result is normalized. |
| ... | @@ -809,7 +800,7 @@ pub fn formatFloatDecimal( | ... | @@ -809,7 +800,7 @@ pub fn formatFloatDecimal( |
| 809 | | 800 | |
| 810 | pub fn formatBytes( | 801 | pub fn formatBytes( |
| 811 | value: var, | 802 | value: var, |
| 812 | width: ?usize, | 803 | options: FormatOptions, |
| 813 | comptime radix: usize, | 804 | comptime radix: usize, |
| 814 | context: var, | 805 | context: var, |
| 815 | comptime Errors: type, | 806 | comptime Errors: type, |
| ... | @@ -833,7 +824,7 @@ pub fn formatBytes( | ... | @@ -833,7 +824,7 @@ pub fn formatBytes( |
| 833 | else => unreachable, | 824 | else => unreachable, |
| 834 | }; | 825 | }; |
| 835 | | 826 | |
| 836 | try formatFloatDecimal(new_value, width, context, Errors, output); | 827 | try formatFloatDecimal(new_value, options, context, Errors, output); |
| 837 | | 828 | |
| 838 | if (suffix == ' ') { | 829 | if (suffix == ' ') { |
| 839 | return output(context, "B"); | 830 | return output(context, "B"); |
| ... | @@ -851,7 +842,7 @@ pub fn formatInt( | ... | @@ -851,7 +842,7 @@ pub fn formatInt( |
| 851 | value: var, | 842 | value: var, |
| 852 | base: u8, | 843 | base: u8, |
| 853 | uppercase: bool, | 844 | uppercase: bool, |
| 854 | width: usize, | 845 | options: FormatOptions, |
| 855 | context: var, | 846 | context: var, |
| 856 | comptime Errors: type, | 847 | comptime Errors: type, |
| 857 | output: fn (@typeOf(context), []const u8) Errors!void, | 848 | output: fn (@typeOf(context), []const u8) Errors!void, |
| ... | @@ -863,9 +854,9 @@ pub fn formatInt( | ... | @@ -863,9 +854,9 @@ pub fn formatInt( |
| 863 | value; | 854 | value; |
| 864 | | 855 | |
| 865 | if (@typeOf(int_value).is_signed) { | 856 | if (@typeOf(int_value).is_signed) { |
| 866 | return formatIntSigned(int_value, base, uppercase, width, context, Errors, output); | 857 | return formatIntSigned(int_value, base, uppercase, options, context, Errors, output); |
| 867 | } else { | 858 | } else { |
| 868 | return formatIntUnsigned(int_value, base, uppercase, width, context, Errors, output); | 859 | return formatIntUnsigned(int_value, base, uppercase, options, context, Errors, output); |
| 869 | } | 860 | } |
| 870 | } | 861 | } |
| 871 | | 862 | |
| ... | @@ -873,26 +864,30 @@ fn formatIntSigned( | ... | @@ -873,26 +864,30 @@ fn formatIntSigned( |
| 873 | value: var, | 864 | value: var, |
| 874 | base: u8, | 865 | base: u8, |
| 875 | uppercase: bool, | 866 | uppercase: bool, |
| 876 | width: usize, | 867 | options: FormatOptions, |
| 877 | context: var, | 868 | context: var, |
| 878 | comptime Errors: type, | 869 | comptime Errors: type, |
| 879 | output: fn (@typeOf(context), []const u8) Errors!void, | 870 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 880 | ) Errors!void { | 871 | ) Errors!void { |
| | 872 | const new_options = FormatOptions{ |
| | 873 | .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null, |
| | 874 | .precision = options.precision, |
| | 875 | .fill = options.fill, |
| | 876 | }; |
| | 877 | |
| 881 | const uint = @IntType(false, @typeOf(value).bit_count); | 878 | const uint = @IntType(false, @typeOf(value).bit_count); |
| 882 | if (value < 0) { | 879 | if (value < 0) { |
| 883 | const minus_sign: u8 = '-'; | 880 | const minus_sign: u8 = '-'; |
| 884 | try output(context, (*const [1]u8)(&minus_sign)[0..]); | 881 | try output(context, (*const [1]u8)(&minus_sign)[0..]); |
| 885 | const new_value = @intCast(uint, -(value + 1)) + 1; | 882 | const new_value = @intCast(uint, -(value + 1)) + 1; |
| 886 | const new_width = if (width == 0) 0 else (width - 1); | 883 | return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output); |
| 887 | return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output); | 884 | } else if (options.width == null or options.width.? == 0) { |
| 888 | } else if (width == 0) { | 885 | return formatIntUnsigned(@intCast(uint, value), base, uppercase, options, context, Errors, output); |
| 889 | return formatIntUnsigned(@intCast(uint, value), base, uppercase, width, context, Errors, output); | | |
| 890 | } else { | 886 | } else { |
| 891 | const plus_sign: u8 = '+'; | 887 | const plus_sign: u8 = '+'; |
| 892 | try output(context, (*const [1]u8)(&plus_sign)[0..]); | 888 | try output(context, (*const [1]u8)(&plus_sign)[0..]); |
| 893 | const new_value = @intCast(uint, value); | 889 | const new_value = @intCast(uint, value); |
| 894 | const new_width = if (width == 0) 0 else (width - 1); | 890 | return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output); |
| 895 | return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output); | | |
| 896 | } | 891 | } |
| 897 | } | 892 | } |
| 898 | | 893 | |
| ... | @@ -900,7 +895,7 @@ fn formatIntUnsigned( | ... | @@ -900,7 +895,7 @@ fn formatIntUnsigned( |
| 900 | value: var, | 895 | value: var, |
| 901 | base: u8, | 896 | base: u8, |
| 902 | uppercase: bool, | 897 | uppercase: bool, |
| 903 | width: usize, | 898 | options: FormatOptions, |
| 904 | context: var, | 899 | context: var, |
| 905 | comptime Errors: type, | 900 | comptime Errors: type, |
| 906 | output: fn (@typeOf(context), []const u8) Errors!void, | 901 | output: fn (@typeOf(context), []const u8) Errors!void, |
| ... | @@ -921,31 +916,32 @@ fn formatIntUnsigned( | ... | @@ -921,31 +916,32 @@ fn formatIntUnsigned( |
| 921 | } | 916 | } |
| 922 | | 917 | |
| 923 | const digits_buf = buf[index..]; | 918 | const digits_buf = buf[index..]; |
| | 919 | const width = options.width orelse 0; |
| 924 | const padding = if (width > digits_buf.len) (width - digits_buf.len) else 0; | 920 | const padding = if (width > digits_buf.len) (width - digits_buf.len) else 0; |
| 925 | | 921 | |
| 926 | if (padding > index) { | 922 | if (padding > index) { |
| 927 | const zero_byte: u8 = '0'; | 923 | const zero_byte: u8 = options.fill; |
| 928 | var leftover_padding = padding - index; | 924 | var leftover_padding = padding - index; |
| 929 | while (true) { | 925 | while (true) { |
| 930 | try output(context, (*const [1]u8)(&zero_byte)[0..]); | 926 | try output(context, (*const [1]u8)(&zero_byte)[0..]); |
| 931 | leftover_padding -= 1; | 927 | leftover_padding -= 1; |
| 932 | if (leftover_padding == 0) break; | 928 | if (leftover_padding == 0) break; |
| 933 | } | 929 | } |
| 934 | mem.set(u8, buf[0..index], '0'); | 930 | mem.set(u8, buf[0..index], options.fill); |
| 935 | return output(context, buf); | 931 | return output(context, buf); |
| 936 | } else { | 932 | } else { |
| 937 | const padded_buf = buf[index - padding ..]; | 933 | const padded_buf = buf[index - padding ..]; |
| 938 | mem.set(u8, padded_buf[0..padding], '0'); | 934 | mem.set(u8, padded_buf[0..padding], options.fill); |
| 939 | return output(context, padded_buf); | 935 | return output(context, padded_buf); |
| 940 | } | 936 | } |
| 941 | } | 937 | } |
| 942 | | 938 | |
| 943 | pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, width: usize) usize { | 939 | pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize { |
| 944 | var context = FormatIntBuf{ | 940 | var context = FormatIntBuf{ |
| 945 | .out_buf = out_buf, | 941 | .out_buf = out_buf, |
| 946 | .index = 0, | 942 | .index = 0, |
| 947 | }; | 943 | }; |
| 948 | formatInt(value, base, uppercase, width, &context, error{}, formatIntCallback) catch unreachable; | 944 | formatInt(value, base, uppercase, options, &context, error{}, formatIntCallback) catch unreachable; |
| 949 | return context.index; | 945 | return context.index; |
| 950 | } | 946 | } |
| 951 | const FormatIntBuf = struct { | 947 | const FormatIntBuf = struct { |
| ... | @@ -1088,23 +1084,23 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) { | ... | @@ -1088,23 +1084,23 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) { |
| 1088 | test "bufPrintInt" { | 1084 | test "bufPrintInt" { |
| 1089 | var buffer: [100]u8 = undefined; | 1085 | var buffer: [100]u8 = undefined; |
| 1090 | const buf = buffer[0..]; | 1086 | const buf = buffer[0..]; |
| 1091 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110")); | 1087 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, FormatOptions{}), "-101111000110000101001110")); |
| 1092 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678")); | 1088 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, FormatOptions{}), "-12345678")); |
| 1093 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e")); | 1089 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, FormatOptions{}), "-bc614e")); |
| 1094 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E")); | 1090 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, FormatOptions{}), "-BC614E")); |
| 1095 | | 1091 | |
| 1096 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, 0), "12345678")); | 1092 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, FormatOptions{}), "12345678")); |
| 1097 | | 1093 | |
| 1098 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666")); | 1094 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, FormatOptions{ .width = 6 }), " 666")); |
| 1099 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234")); | 1095 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, FormatOptions{ .width = 6 }), " 1234")); |
| 1100 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234")); | 1096 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, FormatOptions{ .width = 1 }), "1234")); |
| 1101 | | 1097 | |
| 1102 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, 3), "+42")); | 1098 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, FormatOptions{ .width = 3 }), "+42")); |
| 1103 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42")); | 1099 | testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, FormatOptions{ .width = 3 }), "-42")); |
| 1104 | } | 1100 | } |
| 1105 | | 1101 | |
| 1106 | fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) []u8 { | 1102 | fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 { |
| 1107 | return buf[0..formatIntBuf(buf, value, base, uppercase, width)]; | 1103 | return buf[0..formatIntBuf(buf, value, base, uppercase, options)]; |
| 1108 | } | 1104 | } |
| 1109 | | 1105 | |
| 1110 | test "parse u64 digit too big" { | 1106 | test "parse u64 digit too big" { |
| ... | @@ -1162,7 +1158,8 @@ test "int.specifier" { | ... | @@ -1162,7 +1158,8 @@ test "int.specifier" { |
| 1162 | } | 1158 | } |
| 1163 | | 1159 | |
| 1164 | test "int.padded" { | 1160 | test "int.padded" { |
| 1165 | try testFmt("u8: '0001'", "u8: '{:4}'", u8(1)); | 1161 | try testFmt("u8: ' 1'", "u8: '{:4}'", u8(1)); |
| | 1162 | try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", u8(1)); |
| 1166 | } | 1163 | } |
| 1167 | | 1164 | |
| 1168 | test "buffer" { | 1165 | test "buffer" { |
| ... | @@ -1237,7 +1234,7 @@ test "cstr" { | ... | @@ -1237,7 +1234,7 @@ test "cstr" { |
| 1237 | | 1234 | |
| 1238 | test "filesize" { | 1235 | test "filesize" { |
| 1239 | try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024)); | 1236 | try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024)); |
| 1240 | try testFmt("file size: 66.06MB\n", "file size: {B:2}\n", usize(63 * 1024 * 1024)); | 1237 | try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", usize(63 * 1024 * 1024)); |
| 1241 | } | 1238 | } |
| 1242 | | 1239 | |
| 1243 | test "struct" { | 1240 | test "struct" { |
| ... | @@ -1342,7 +1339,7 @@ test "custom" { | ... | @@ -1342,7 +1339,7 @@ test "custom" { |
| 1342 | pub fn format( | 1339 | pub fn format( |
| 1343 | self: SelfType, | 1340 | self: SelfType, |
| 1344 | comptime fmt: []const u8, | 1341 | comptime fmt: []const u8, |
| 1345 | comptime options: FormatOptions, | 1342 | options: FormatOptions, |
| 1346 | context: var, | 1343 | context: var, |
| 1347 | comptime Errors: type, | 1344 | comptime Errors: type, |
| 1348 | output: fn (@typeOf(context), []const u8) Errors!void, | 1345 | output: fn (@typeOf(context), []const u8) Errors!void, |
| ... | @@ -1548,7 +1545,7 @@ test "formatType max_depth" { | ... | @@ -1548,7 +1545,7 @@ test "formatType max_depth" { |
| 1548 | pub fn format( | 1545 | pub fn format( |
| 1549 | self: SelfType, | 1546 | self: SelfType, |
| 1550 | comptime fmt: []const u8, | 1547 | comptime fmt: []const u8, |
| 1551 | comptime options: FormatOptions, | 1548 | options: FormatOptions, |
| 1552 | context: var, | 1549 | context: var, |
| 1553 | comptime Errors: type, | 1550 | comptime Errors: type, |
| 1554 | output: fn (@typeOf(context), []const u8) Errors!void, | 1551 | output: fn (@typeOf(context), []const u8) Errors!void, |