Merge pull request #939 from 9rnsr/replace_format

Replacement std.string.format and sformat implementations in November 2012
This commit is contained in:
Andrei Alexandrescu 2012-12-08 19:41:35 -08:00
commit d6100b404f
3 changed files with 150 additions and 189 deletions

View file

@ -33660,7 +33660,7 @@ unittest
this.value = value;
}
string toString()
string toString() const
{
return to!string(value);
}
@ -33963,7 +33963,7 @@ unittest
return this;
}
string toString()
string toString() const
{
return to!string(value);
}
@ -33987,7 +33987,7 @@ unittest
return IntWrapper_BadAssign(mixin("old " ~ op ~ " rhs.value"));
}
string toString()
string toString() const
{
return to!string(value);
}
@ -34009,7 +34009,7 @@ unittest
return IntWrapper_BadReturn(rhs.value);
}
string toString()
string toString() const
{
return to!string(value);
}

View file

@ -5454,20 +5454,20 @@ unittest
debug(format) printf("std.format.format.unittest\n");
s = std.string.format("hello world! %s %s ", true, 57, 1_000_000_000, 'x', " foo");
s = std.string.format("hello world! %s %s %s%s%s", true, 57, 1_000_000_000, 'x', " foo");
assert(s == "hello world! true 57 1000000000x foo");
s = std.string.format(1.67, " %A ", -1.28, float.nan);
s = std.string.format("%s %A %s", 1.67, -1.28, float.nan);
/* The host C library is used to format floats.
* C99 doesn't specify what the hex digit before the decimal point
* is for %A.
*/
version (linux)
assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan");
else version (OSX)
assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan", s);
else
assert(s == "1.67 -0X1.47AE147AE147BP+0 nan");
//version (linux)
// assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan");
//else version (OSX)
// assert(s == "1.67 -0XA.3D70A3D70A3D8P-3 nan", s);
//else
assert(s == "1.67 -0X1.47AE147AE147BP+0 nan", s);
s = std.string.format("%x %X", 0x1234AF, 0xAFAFAFAF);
assert(s == "1234af AFAFAFAF");
@ -5478,19 +5478,19 @@ unittest
s = std.string.format("%d %s", 0x1234AF, 0xAFAFAFAF);
assert(s == "1193135 2947526575");
version(X86_64)
{
pragma(msg, "several format tests disabled on x86_64 due to bug 5625");
}
else
{
//version(X86_64)
//{
// pragma(msg, "several format tests disabled on x86_64 due to bug 5625");
//}
//else
//{
s = std.string.format("%s", 1.2 + 3.4i);
assert(s == "1.2+3.4i");
assert(s == "1.2+3.4i", s);
s = std.string.format("%x %X", 1.32, 6.78f);
assert(s == "3ff51eb851eb851f 40D8F5C3");
//s = std.string.format("%x %X", 1.32, 6.78f);
//assert(s == "3ff51eb851eb851f 40D8F5C3");
}
//}
s = std.string.format("%#06.*f",2,12.345);
assert(s == "012.35");
@ -5558,63 +5558,57 @@ unittest
arrbyte[0] = 100;
arrbyte[1] = -99;
arrbyte[3] = 0;
r = std.string.format(arrbyte);
assert(r == "[100,-99,0,0]");
r = std.string.format("%s", arrbyte);
assert(r == "[100, -99, 0, 0]");
ubyte[] arrubyte = new ubyte[4];
arrubyte[0] = 100;
arrubyte[1] = 200;
arrubyte[3] = 0;
r = std.string.format(arrubyte);
assert(r == "[100,200,0,0]");
r = std.string.format("%s", arrubyte);
assert(r == "[100, 200, 0, 0]");
short[] arrshort = new short[4];
arrshort[0] = 100;
arrshort[1] = -999;
arrshort[3] = 0;
r = std.string.format(arrshort);
assert(r == "[100,-999,0,0]");
r = std.string.format("%s",arrshort);
assert(r == "[100,-999,0,0]");
r = std.string.format("%s", arrshort);
assert(r == "[100, -999, 0, 0]");
ushort[] arrushort = new ushort[4];
arrushort[0] = 100;
arrushort[1] = 20_000;
arrushort[3] = 0;
r = std.string.format(arrushort);
assert(r == "[100,20000,0,0]");
r = std.string.format("%s", arrushort);
assert(r == "[100, 20000, 0, 0]");
int[] arrint = new int[4];
arrint[0] = 100;
arrint[1] = -999;
arrint[3] = 0;
r = std.string.format(arrint);
assert(r == "[100,-999,0,0]");
r = std.string.format("%s",arrint);
assert(r == "[100,-999,0,0]");
r = std.string.format("%s", arrint);
assert(r == "[100, -999, 0, 0]");
long[] arrlong = new long[4];
arrlong[0] = 100;
arrlong[1] = -999;
arrlong[3] = 0;
r = std.string.format(arrlong);
assert(r == "[100,-999,0,0]");
r = std.string.format("%s",arrlong);
assert(r == "[100,-999,0,0]");
r = std.string.format("%s", arrlong);
assert(r == "[100, -999, 0, 0]");
ulong[] arrulong = new ulong[4];
arrulong[0] = 100;
arrulong[1] = 999;
arrulong[3] = 0;
r = std.string.format(arrulong);
assert(r == "[100,999,0,0]");
r = std.string.format("%s", arrulong);
assert(r == "[100, 999, 0, 0]");
string[] arr2 = new string[4];
arr2[0] = "hello";
arr2[1] = "world";
arr2[3] = "foo";
r = std.string.format(arr2);
assert(r == "[hello,world,,foo]");
r = std.string.format("%s", arr2);
assert(r == `["hello", "world", "", "foo"]`);
r = std.string.format("%.8d", 7);
assert(r == "00000007");
@ -5643,7 +5637,7 @@ unittest
assert(r == "ghi");
void* p = cast(void*)0xDEADBEEF;
r = std.string.format(p);
r = std.string.format("%s", p);
assert(r == "DEADBEEF");
r = std.string.format("%#x", 0xabcd);
@ -5716,21 +5710,21 @@ unittest
assert(r == "F");
Object c = null;
r = std.string.format(c);
r = std.string.format("%s", c);
assert(r == "null");
enum TestEnum
{
Value1, Value2
Value1, Value2
}
r = std.string.format("%s", TestEnum.Value2);
assert(r == "1");
assert(r == "Value2");
immutable(char[5])[int] aa = ([3:"hello", 4:"betty"]);
r = std.string.format("%s", aa.values);
assert(r == "[[h,e,l,l,o],[b,e,t,t,y]]");
assert(r == `["hello", "betty"]`);
r = std.string.format("%s", aa);
assert(r == "[3:[h,e,l,l,o],4:[b,e,t,t,y]]");
assert(r == `[3:"hello", 4:"betty"]`);
static const dchar[] ds = ['a','b'];
for (int j = 0; j < ds.length; ++j)
@ -5742,11 +5736,11 @@ unittest
assert(r == " 98");
}
r = std.string.format(">%14d<, ", 15, [1,2,3]);
assert(r == "> 15<, [1,2,3]");
r = std.string.format(">%14d<, %s", 15, [1,2,3]);
assert(r == "> 15<, [1, 2, 3]");
assert(std.string.format("%8s", "bar") == " bar");
assert(std.string.format("%8s", "b\u00e9ll\u00f4") == " b\u00e9ll\u00f4");
assert(std.string.format("%8s", "b\u00e9ll\u00f4") == " b\u00e9ll\u00f4");
}
unittest

View file

@ -1179,7 +1179,7 @@ deprecated S capwords(S)(S s) if (isSomeString!S)
return cast(S)retval.data;
}
unittest
deprecated unittest
{
debug(string) printf("string.capwords.unittest\n");
@ -2482,7 +2482,7 @@ unittest
//Explicitly undocumented. Do not use. To be removed in March 2013.
deprecated("Please use std.string.makeTrans instead.") alias makeTrans maketrans;
unittest
deprecated unittest
{
debug(string) printf("string.translate.unittest\n");
@ -2501,83 +2501,55 @@ unittest
}
// @@@BUG@@@ workaround for bugzilla 2479
private string bug2479format(TypeInfo[] arguments, va_list argptr)
{
char[] s;
void putc(dchar c)
{
std.utf.encode(s, c);
}
std.format.doFormat(&putc, arguments, argptr);
return assumeUnique(s);
}
// @@@BUG@@@ workaround for bugzilla 2479
private char[] bug2479sformat(char[] s, TypeInfo[] arguments, va_list argptr)
{
size_t i;
void putc(dchar c)
{
if(std.ascii.isASCII(c))
{
if (i >= s.length)
onRangeError("std.string.sformat", 0);
s[i] = cast(char)c;
++i;
}
else
{ char[4] buf;
auto b = std.utf.toUTF8(buf, c);
if (i + b.length > s.length)
onRangeError("std.string.sformat", 0);
s[i..i+b.length] = b[];
i += b.length;
}
}
std.format.doFormat(&putc, arguments, argptr);
return s[0 .. i];
}
/*****************************************************
* Format arguments into a string.
*
* $(RED format's current implementation is scheduled for replacement in
* November 2012. It will then be replaced with $(LREF xformat)'s implementation.
* This will be seamless for most code, but it will make it so that the
* only argument that can be a format string is the first one, so any
* code which uses multiple format strings will break. Please change
* $(RED format's current implementation has been replaced with $(LREF xformat)'s
* implementation. in November 2012.
* This is seamless for most code, but it makes it so that the only
* argument that can be a format string is the first one, so any
* code which used multiple format strings has broken. Please change
* your calls to format accordingly.
*
* e.g.:
----
format("key = %s", key, ", value = %s", value)
----
* will need to be rewritten as:
* needs to be rewritten as:
----
format("key = %s, value = %s", key, value)
----
* )
*/
string format(...)
string format(Char, Args...)(in Char[] fmt, Args args)
{
/+ // @@@BUG@@@ Fails due to regression bug 2479.
char[] s;
void putc(dchar c)
auto w = appender!string();
auto n = formattedWrite(w, fmt, args);
version (all)
{
std.utf.encode(s, c);
// In the future, this check will be removed to increase consistency
// with formattedWrite
enforce(n == args.length, new FormatException(
text("Orphan format arguments: args[", n, "..", args.length, "]")));
}
return w.data;
}
std.format.doFormat(&putc, _arguments, _argptr);
return assumeUnique(s);
+/
return bug2479format(_arguments, _argptr);
unittest
{
debug(string) printf("std.string.format.unittest\n");
// assert(format(null) == "");
assert(format("foo") == "foo");
assert(format("foo%%") == "foo%");
assert(format("foo%s", 'C') == "fooC");
assert(format("%s foo", "bar") == "bar foo");
assert(format("%s foo %s", "bar", "abc") == "bar foo abc");
assert(format("foo %d", -123) == "foo -123");
assert(format("foo %d", 123) == "foo 123");
assertThrown!FormatError(format("foo %s"));
assertThrown!FormatError(format("foo %s", 123, 456));
}
@ -2586,103 +2558,97 @@ string format(...)
* enough to hold the result. Throws RangeError if it is not.
* Returns: s
*
* $(RED sformat's current implementation is scheduled for replacement in
* November 2012. It will then be replaced with $(LREF xsformat)'s implementation.
* This will be seamless for most code, but it will make it so that the
* only argument that can be a format string is the first one, so any
* code which uses multiple format strings will break. Please change
* $(RED sformat's current implementation has been replaced with $(LREF xsformat)'s
* implementation. in November 2012.
* This is seamless for most code, but it makes it so that the only
* argument that can be a format string is the first one, so any
* code which used multiple format strings has broken. Please change
* your calls to sformat accordingly.
*
* e.g.:
----
sformat(buf, "key = %s", key, ", value = %s", value)
----
* will need to be rewritten as:
* needs to be rewritten as:
----
sformat(buf, "key = %s, value = %s", key, value)
----
* )
*/
char[] sformat(char[] s, ...)
char[] sformat(Char, Args...)(char[] buf, in Char[] fmt, Args args)
{
/+ // @@@BUG@@@ Fails due to regression bug 2479.
size_t i;
size_t i;
void putc(dchar c)
struct Sink
{
if(std.ascii.isASCII(c))
{
if (i >= s.length)
onRangeError("std.string.sformat", 0);
s[i] = cast(char)c;
++i;
}
else
{ char[4] buf;
auto b = std.utf.toUTF8(buf, c);
if (i + b.length > s.length)
onRangeError("std.string.sformat", 0);
s[i..i+b.length] = b[];
i += b.length;
}
}
void put(dchar c)
{
char[4] enc;
auto n = encode(enc, c);
std.format.doFormat(&putc, _arguments, _argptr);
return s[0 .. i];
+/
return bug2479sformat(s, _arguments, _argptr);
if (buf.length < i + n)
onRangeError("std.string.sformat", 0);
buf[i .. i + n] = enc[0 .. n];
i += n;
}
void put(const(char)[] s)
{
if (buf.length < i + s.length)
onRangeError("std.string.sformat", 0);
buf[i .. i + s.length] = s[];
i += s.length;
}
void put(const(wchar)[] s)
{
for (; !s.empty; s.popFront())
put(s.front);
}
void put(const(dchar)[] s)
{
for (; !s.empty; s.popFront())
put(s.front);
}
}
auto n = formattedWrite(Sink(), fmt, args);
version (all)
{
// In the future, this check will be removed to increase consistency
// with formattedWrite
enforce(n == args.length, new FormatException(
text("Orphan format arguments: args[", n, "..", args.length, "]")));
}
return buf[0 .. i];
}
unittest
{
debug(string) printf("std.string.format.unittest\n");
debug(string) printf("std.string.sformat.unittest\n");
string r;
int i;
/+
r = format(null);
i = cmp(r, "");
assert(i == 0);
+/
r = format("foo");
i = cmp(r, "foo");
assert(i == 0);
char[10] buf;
r = format("foo%%");
i = cmp(r, "foo%");
assert(i == 0);
assert(sformat(buf[], "foo") == "foo");
assert(sformat(buf[], "foo%%") == "foo%");
assert(sformat(buf[], "foo%s", 'C') == "fooC");
assert(sformat(buf[], "%s foo", "bar") == "bar foo");
assertThrown!RangeError(sformat(buf[], "%s foo %s", "bar", "abc"));
assert(sformat(buf[], "foo %d", -123) == "foo -123");
assert(sformat(buf[], "foo %d", 123) == "foo 123");
r = format("foo%s", 'C');
i = cmp(r, "fooC");
assert(i == 0);
assertThrown!FormatError(sformat(buf[], "foo %s"));
assertThrown!FormatError(sformat(buf[], "foo %s", 123, 456));
r = format("%s foo", "bar");
i = cmp(r, "bar foo");
assert(i == 0);
r = format("%s foo %s", "bar", "abc");
i = cmp(r, "bar foo abc");
assert(i == 0);
r = format("foo %d", -123);
i = cmp(r, "foo -123");
assert(i == 0);
r = format("foo %d", 123);
i = cmp(r, "foo 123");
assert(i == 0);
assert(sformat(buf[], "%s %s %s", "c"c, "w"w, "d"d) == "c w d");
}
/*****************************************************
* Format arguments into a string.
*
* xformat is a version of $(LREF format) whose behavior matches that of
* $(XREF stdio, writef). $(LREF format) will be changed to use this
* implementation in November 2012. In the interim, xformat is provided for
* those who need the improved implementation. It will be scheduled for
* deprecation once format has been updated.
* $(LREF format) has been changed to use this implementation in November 2012.
* Then xformat has been scheduled for deprecation at the same time.
* It will be deprecateed in May 2013.
*/
string xformat(Char, Args...)(in Char[] fmt, Args args)
@ -2699,7 +2665,7 @@ string xformat(Char, Args...)(in Char[] fmt, Args args)
return w.data;
}
unittest
deprecated unittest
{
debug(string) printf("std.string.xformat.unittest\n");
@ -2721,11 +2687,9 @@ unittest
* Format arguments into string $(D_PARAM buf) which must be large
* enough to hold the result. Throws RangeError if it is not.
*
* xsformat is a version of $(LREF sformat) whose behavior matches that of
* $(XREF stdio, writef). $(LREF sformat) will be changed to use this
* implementation in November 2012. In the interim, xsformat is provided for
* those who need the improved implementation. It will be scheduled for
* deprecation once sformat has been updated.
* $(LREF sformat) has been changed to use this implementation in November 2012.
* Then xsformat has been scheduled for deprecation at the same time.
* It will be deprecateed in May 2013.
*
* Returns: filled slice of $(D_PARAM buf)
*/
@ -2777,7 +2741,7 @@ char[] xsformat(Char, Args...)(char[] buf, in Char[] fmt, Args args)
return buf[0 .. i];
}
unittest
deprecated unittest
{
debug(string) printf("std.string.xsformat.unittest\n");
@ -3674,7 +3638,10 @@ unittest
assert(isNumeric(s[1..s.length - 2]) == true);
assert(isNumeric(s) == false);
assert(isNumeric(s[0..s.length - 1]) == false);
}
deprecated unittest
{
// These test calling the isNumeric(...) function
assert(isNumeric(1,123UL) == true);
assert(isNumeric('2') == true);