Merge pull request #3470 from WalterBright/betterFormatU

std.format.formatUnsigned: refactor
This commit is contained in:
Hara Kenji 2015-07-04 14:36:23 +09:00
commit c3a39c5461

View file

@ -1489,9 +1489,8 @@ unittest
assert(w.data == "1337"); assert(w.data == "1337");
} }
private void formatIntegral(Writer, T, Char)(Writer w, const(T) val, ref FormatSpec!Char f, uint base, ulong mask) private void formatIntegral(Writer, T, Char)(Writer w, const(T) val, const ref FormatSpec!Char fs, uint base, ulong mask)
{ {
FormatSpec!Char fs = f; // fs is copy for change its values.
T arg = val; T arg = val;
bool negative = (base == 10 && arg < 0); bool negative = (base == 10 && arg < 0);
@ -1507,105 +1506,93 @@ private void formatIntegral(Writer, T, Char)(Writer w, const(T) val, ref FormatS
formatUnsigned(w, (cast(ulong) arg) & mask, fs, base, negative); formatUnsigned(w, (cast(ulong) arg) & mask, fs, base, negative);
} }
private void formatUnsigned(Writer, T, Char)(Writer w, T arg, ref FormatSpec!Char fs, uint base, bool negative) private void formatUnsigned(Writer, T, Char)(Writer w, T arg, const ref FormatSpec!Char fs, uint base, bool negative)
{ {
if (fs.precision == fs.UNSPECIFIED) /* Write string:
{ * leftpad prefix1 prefix2 zerofill digits rightpad
// default precision for integrals is 1 */
fs.precision = 1;
}
else
{
// if a precision is specified, the '0' flag is ignored.
fs.flZero = false;
}
char leftPad = void; /* Convert arg to digits[].
if (!fs.flDash && !fs.flZero) * Note that 0 becomes an empty digits[]
leftPad = ' '; */
else if (!fs.flDash && fs.flZero) char[64] buffer = void; // 64 bits in base 2 at most
leftPad = '0';
else
leftPad = 0;
// figure out sign and continue in unsigned mode
char forcedPrefix = void;
if (fs.flPlus) forcedPrefix = '+';
else if (fs.flSpace) forcedPrefix = ' ';
else forcedPrefix = 0;
if (base != 10)
{
// non-10 bases are always unsigned
forcedPrefix = 0;
}
else if (negative)
{
// argument is signed
forcedPrefix = '-';
}
// fill the digits
char[64] buffer; // 64 bits in base 2 at most
char[] digits; char[] digits;
{ {
uint i = buffer.length; size_t i = buffer.length;
auto n = arg; while (arg)
do
{ {
--i; --i;
buffer[i] = cast(char) (n % base); char c = cast(char) (arg % base);
n /= base; arg /= base;
if (buffer[i] < 10) buffer[i] += '0'; if (c < 10)
else buffer[i] += (fs.spec == 'x' ? 'a' : 'A') - 10; buffer[i] = cast(char)(c + '0');
} while (n); else
buffer[i] = cast(char)(c + (fs.spec == 'x' ? 'a' - 10 : 'A' - 10));
}
digits = buffer[i .. $]; // got the digits without the sign digits = buffer[i .. $]; // got the digits without the sign
} }
// adjust precision to print a '0' for octal if alternate format is on
if (base == 8 && fs.flHash
&& (fs.precision <= digits.length)) // too low precision int precision = (fs.precision == fs.UNSPECIFIED) ? 1 : fs.precision;
char padChar = 0;
if (!fs.flDash)
{ {
//fs.precision = digits.length + (arg != 0); padChar = (fs.flZero && fs.precision == fs.UNSPECIFIED) ? '0' : ' ';
forcedPrefix = '0';
} }
// write left pad; write sign; write 0x or 0X; write digits;
// write right pad // Compute prefix1 and prefix2
// Writing left pad char prefix1 = 0;
ptrdiff_t spacesToPrint = char prefix2 = 0;
fs.width // start with the minimum width if (base == 10)
- digits.length // take away digits to print {
- (forcedPrefix != 0) // take away the sign if any if (negative)
- (base == 16 && fs.flHash && arg ? 2 : 0); // 0x or 0X prefix1 = '-';
const ptrdiff_t delta = fs.precision - digits.length; else if (fs.flPlus)
if (delta > 0) spacesToPrint -= delta; prefix1 = '+';
else if (fs.flSpace)
prefix1 = ' ';
}
else if (base == 16 && fs.flHash && digits.length)
{
prefix1 = '0';
prefix2 = fs.spec == 'x' ? 'x' : 'X';
}
// adjust precision to print a '0' for octal if alternate format is on
else if (base == 8 && fs.flHash &&
(precision <= 1 || precision <= digits.length)) // too low precision
prefix1 = '0';
size_t zerofill = precision > digits.length ? precision - digits.length : 0;
size_t leftpad = 0;
size_t rightpad = 0;
ptrdiff_t spacesToPrint = fs.width - ((prefix1 != 0) + (prefix2 != 0) + zerofill + digits.length);
if (spacesToPrint > 0) // need to do some padding if (spacesToPrint > 0) // need to do some padding
{ {
if (leftPad == '0') if (padChar == '0')
{ zerofill += spacesToPrint;
// pad with zeros else if (padChar)
leftpad = spacesToPrint;
else
rightpad = spacesToPrint;
}
fs.precision = /**** Print ****/
cast(typeof(fs.precision)) (spacesToPrint + digits.length);
//to!(typeof(fs.precision))(spacesToPrint + digits.length); foreach (i ; 0 .. leftpad)
} put(w, ' ');
else if (leftPad) foreach (i ; 0 .. spacesToPrint) put(w, ' ');
} if (prefix1) put(w, prefix1);
// write sign if (prefix2) put(w, prefix2);
if (forcedPrefix) put(w, forcedPrefix);
// write 0x or 0X foreach (i ; 0 .. zerofill)
if (base == 16 && fs.flHash && arg) {
// @@@ overcome bug in dmd;
//w.write(fs.spec == 'x' ? "0x" : "0X"); //crashes the compiler
put(w, '0'); put(w, '0');
put(w, fs.spec == 'x' ? 'x' : 'X'); // x or X
}
// write the digits
if (arg || fs.precision)
{
ptrdiff_t zerosToPrint = fs.precision - digits.length;
foreach (i ; 0 .. zerosToPrint) put(w, '0');
put(w, digits); put(w, digits);
}
// write the spaces to the right if left-align foreach (i ; 0 .. rightpad)
if (!leftPad) foreach (i ; 0 .. spacesToPrint) put(w, ' '); put(w, ' ');
} }
@safe pure unittest @safe pure unittest