Skip to content

Commit

Permalink
Merge pull request #536 from Aatch/std-format-changes
Browse files Browse the repository at this point in the history
Std format changes
  • Loading branch information
9rnsr committed May 12, 2012
2 parents 98b34a2 + 03673b1 commit c27262c
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
generated
GNUmakefile
.DS_Store
.*.sw*
94 changes: 87 additions & 7 deletions std/format.d
Expand Up @@ -69,7 +69,7 @@ class FormatException : Exception
}

/**
$(RED Scheduled for deprecation. Please use $(D FormatException)) instead.
$(RED Scheduled for deprecation. Please use $(D FormatException) instead.)
*/
/*deprecated*/ alias FormatException FormatError;

Expand Down Expand Up @@ -567,8 +567,29 @@ template FormatSpec(Char)
}

/**
A compiled version of an individual format specifier, backwards
compatible with $(D printf) specifiers.
A General handler for $(D printf) style format specifiers. Used for building more
specific formatting functions.
Example:
----
auto a = appender!(string)();
auto fmt = "Number: %2.4e\nString: %s";
auto f = FormatSpec!char(fmt);
f.writeUpToNextSpec(a);
assert(a.data == "Number: ");
assert(f.trailing == "\nString: %s");
assert(f.spec == 'e');
assert(f.width == 2);
assert(f.precision == 4);
f.writeUpToNextSpec(a);
assert(a.data == "Number: \nString: ");
assert(f.trailing == "");
assert(f.spec == 's');
----
*/
struct FormatSpec(Char)
if (is(Unqual!Char == Char))
Expand Down Expand Up @@ -695,10 +716,8 @@ struct FormatSpec(Char)
enum immutable(Char)[] seqSeparator = ", ";

/**
Given a string format specification fmt, parses a format
specifier. The string is assumed to start with the character
immediately following the $(D '%'). The string is advanced to
right after the end of the format specifier.
Construct a new $(D FormatSpec) using the format string $(D fmt), no
processing is done until needed.
*/
this(in Char[] fmt)
{
Expand Down Expand Up @@ -1093,6 +1112,67 @@ struct FormatSpec(Char)
"\ntrailing = ", trailing, "\n");
}
}
unittest
{
//Test the example
auto a = appender!(string)();
auto fmt = "Number: %2.4e\nString: %s";
auto f = FormatSpec!char(fmt);

f.writeUpToNextSpec(a);

assert(a.data == "Number: ");
assert(f.trailing == "\nString: %s");
assert(f.spec == 'e');
assert(f.width == 2);
assert(f.precision == 4);

f.writeUpToNextSpec(a);

assert(a.data == "Number: \nString: ");
assert(f.trailing == "");
assert(f.spec == 's');
}

/**
Helper function that returns a $(D FormatSpec) for a single specifier given
in $(D fmt)
Returns a $(D FormatSpec) with the specifier parsed.
Enforces giving only one specifier to the function.
*/
FormatSpec!Char singleSpec(Char)(Char[] fmt)
{
enforce(fmt.length >= 2, new Exception("fmt must be at least 2 characters long"));
enforce(fmt.front == '%', new Exception("fmt must start with a '%' character"));

static struct DummyOutputRange {
void put(C)(C[] buf) {} // eat elements
}
auto a = DummyOutputRange();
auto spec = FormatSpec!Char(fmt);
//dummy write
spec.writeUpToNextSpec(a);

enforce(spec.trailing.empty,
new Exception(text("Trailing characters in fmt string: '", spec.trailing)));

return spec;
}
unittest
{
auto spec = singleSpec("%2.3e");

assert(spec.trailing == "");
assert(spec.spec == 'e');
assert(spec.width == 2);
assert(spec.precision == 3);

assertThrown(singleSpec(""));
assertThrown(singleSpec("2.3e"));
assertThrown(singleSpec("%2.3eTest"));
}

/**
$(D bool)s are formatted as "true" or "false" with %s and as "1" or
Expand Down

0 comments on commit c27262c

Please sign in to comment.