mirror of
https://github.com/dlang/phobos.git
synced 2025-05-13 07:39:15 +03:00
Merge pull request #3470 from WalterBright/betterFormatU
std.format.formatUnsigned: refactor
This commit is contained in:
commit
c3a39c5461
1 changed files with 74 additions and 87 deletions
161
std/format.d
161
std/format.d
|
@ -1489,9 +1489,8 @@ unittest
|
|||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// default precision for integrals is 1
|
||||
fs.precision = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if a precision is specified, the '0' flag is ignored.
|
||||
fs.flZero = false;
|
||||
}
|
||||
/* Write string:
|
||||
* leftpad prefix1 prefix2 zerofill digits rightpad
|
||||
*/
|
||||
|
||||
char leftPad = void;
|
||||
if (!fs.flDash && !fs.flZero)
|
||||
leftPad = ' ';
|
||||
else if (!fs.flDash && fs.flZero)
|
||||
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
|
||||
/* Convert arg to digits[].
|
||||
* Note that 0 becomes an empty digits[]
|
||||
*/
|
||||
char[64] buffer = void; // 64 bits in base 2 at most
|
||||
char[] digits;
|
||||
{
|
||||
uint i = buffer.length;
|
||||
auto n = arg;
|
||||
do
|
||||
size_t i = buffer.length;
|
||||
while (arg)
|
||||
{
|
||||
--i;
|
||||
buffer[i] = cast(char) (n % base);
|
||||
n /= base;
|
||||
if (buffer[i] < 10) buffer[i] += '0';
|
||||
else buffer[i] += (fs.spec == 'x' ? 'a' : 'A') - 10;
|
||||
} while (n);
|
||||
char c = cast(char) (arg % base);
|
||||
arg /= base;
|
||||
if (c < 10)
|
||||
buffer[i] = cast(char)(c + '0');
|
||||
else
|
||||
buffer[i] = cast(char)(c + (fs.spec == 'x' ? 'a' - 10 : 'A' - 10));
|
||||
}
|
||||
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);
|
||||
forcedPrefix = '0';
|
||||
padChar = (fs.flZero && fs.precision == fs.UNSPECIFIED) ? '0' : ' ';
|
||||
}
|
||||
// write left pad; write sign; write 0x or 0X; write digits;
|
||||
// write right pad
|
||||
// Writing left pad
|
||||
ptrdiff_t spacesToPrint =
|
||||
fs.width // start with the minimum width
|
||||
- digits.length // take away digits to print
|
||||
- (forcedPrefix != 0) // take away the sign if any
|
||||
- (base == 16 && fs.flHash && arg ? 2 : 0); // 0x or 0X
|
||||
const ptrdiff_t delta = fs.precision - digits.length;
|
||||
if (delta > 0) spacesToPrint -= delta;
|
||||
|
||||
// Compute prefix1 and prefix2
|
||||
char prefix1 = 0;
|
||||
char prefix2 = 0;
|
||||
if (base == 10)
|
||||
{
|
||||
if (negative)
|
||||
prefix1 = '-';
|
||||
else if (fs.flPlus)
|
||||
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 (leftPad == '0')
|
||||
{
|
||||
// pad with zeros
|
||||
if (padChar == '0')
|
||||
zerofill += spacesToPrint;
|
||||
else if (padChar)
|
||||
leftpad = spacesToPrint;
|
||||
else
|
||||
rightpad = spacesToPrint;
|
||||
}
|
||||
|
||||
fs.precision =
|
||||
cast(typeof(fs.precision)) (spacesToPrint + digits.length);
|
||||
//to!(typeof(fs.precision))(spacesToPrint + digits.length);
|
||||
}
|
||||
else if (leftPad) foreach (i ; 0 .. spacesToPrint) put(w, ' ');
|
||||
}
|
||||
// write sign
|
||||
if (forcedPrefix) put(w, forcedPrefix);
|
||||
// write 0x or 0X
|
||||
if (base == 16 && fs.flHash && arg) {
|
||||
// @@@ overcome bug in dmd;
|
||||
//w.write(fs.spec == 'x' ? "0x" : "0X"); //crashes the compiler
|
||||
/**** Print ****/
|
||||
|
||||
foreach (i ; 0 .. leftpad)
|
||||
put(w, ' ');
|
||||
|
||||
if (prefix1) put(w, prefix1);
|
||||
if (prefix2) put(w, prefix2);
|
||||
|
||||
foreach (i ; 0 .. zerofill)
|
||||
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);
|
||||
}
|
||||
// write the spaces to the right if left-align
|
||||
if (!leftPad) foreach (i ; 0 .. spacesToPrint) put(w, ' ');
|
||||
|
||||
put(w, digits);
|
||||
|
||||
foreach (i ; 0 .. rightpad)
|
||||
put(w, ' ');
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue