Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #787 (closed defect: fixed)

Opened 12 years ago

Last modified 11 years ago

Layout.convert("{:d2}", 100) errors out with "{output width too small}"

Reported by: Deewiant Assigned to: kris
Priority: major Milestone: 1.0
Component: Core Functionality Version: trunk
Keywords: triage Cc: baxissimo


Currently, the width specification in a format string, for instance the 4 in {:d4}, is an exact width. An argument with a width less than 4 is zero-padded to width 4, and an argument with a width equal to 4 is left unchanged. The problem is that passing an argument with a width greater than 4 causes an error, "{output width too small}".

I feel that zero-padding an integer to a certain minimum length is a relatively commonplace task, and thus making the format strings assign exact, instead of minimum, widths is a mistake. It's additional functionality with no loss, and it makes apps more robust.

Consider a program which reads integers from a file, uses them for some mysterious internal purpose, and displays them as hexadecimal. The format string might be "0x{:x4}". The program expects only values in the range 0-65535, but one day the value 99999 comes up. The program works fine---until it has to output the integer. Now Layout.convert says "oh noes, this integer is of width 5, greater than 4! impossible!" and throws an error. The program crashes unexpectedly, and has to be amended with a manual routine which converts an integer to its hexadecimal representation in string form, pads it with zeroes if it is less than 4 width, and otherwise outputs it normally.

Why do we have to jump through such hoops? C's printf, Java's Formatter, hell, even C#'s String.Format formatting strings, which Tango's are based on, use minimum widths.

Change History

11/26/07 07:05:10 changed by kris

  • owner changed from sean to kris.

02/11/08 03:02:15 changed by kris

  • status changed from new to assigned.
  • milestone set to 0.99.6.

still don't have a good resolution for this :(

04/09/08 02:06:53 changed by baxissimo

  • priority changed from normal to major.

I just ran into this too.

The Tango book clearly states that the value is supposed to be a "minimum number of digits" to print, not a maximum.

04/09/08 03:01:13 changed by kris

The book has an unfortunate misprint, since it is/was intended to be a maximum width. We may have to re-evaluate this, but that's currently how it stands

04/18/08 03:50:56 changed by kris

  • milestone changed from 0.99.6 to 1.0.

05/24/08 17:24:03 changed by larsivi

  • keywords set to triage.

06/09/08 02:48:11 changed by kris

  • cc set to baxissimo.
  • status changed from assigned to closed.
  • resolution set to fixed.

Checked in a revised version of Integer.format() which takes a different approach to handling flags and formatting. This version supports the following styling:

        type width prefix

        Type is one of [d, g, u, b, x, o] or uppercase equivalent, and
        dictates the conversion radix or other semantics.

        Width is optional and indicates a minimum width for zero-padding,
        while the optional prefix is one of ['#', ' ', '+'] and indicates
        what variety of prefix should be placed in the output. e.g.
        "d"     => integer
        "u"     => unsigned
        "o"     => octal
        "b"     => binary
        "x"     => hexadecimal
        "X"     => hexadecimal uppercase

        "d+"    => integer prefixed with "+"
        "b#"    => binary prefixed with "0b"
        "x#"    => hexadecimal prefixed with "0x"
        "X#"    => hexadecimal prefixed with "0X"

        "d8"    => decimal padded to 8 places as required
        "b8"    => binary padded to 8 places as required
        "b8#"   => binary padded to 8 places and prefixed with "0b"

Note that the specified width is exclusive of the prefix, though the width padding will be shrunk as necessary in order to ensure a requested prefix can be inserted into the provided output.

We'll change various other API signatures to match this, and roll over to this revised approach in the next release or so.