libs/libc/stdio/lib_libvsprintf.c: Correct handling of integer 'precision' in all justification types for values 9, 99, 999, 9999, 99999:

Right justification:
  009   099   999  9999 99999  %5.3u
    9    99   999  9999 99999  %5u

Right justification, zero padding
  009   099   999  9999 99999  %05.3u
00009 00099 00999 09999 99999  %05u

Left justification
009   099   999   9999  99999  %-5.3u
9     99    999   9999  99999  %-5u
This commit is contained in:
Gregory Nutt 2018-10-05 13:54:28 -06:00
parent c958dc0f22
commit 055810d9a4

View File

@ -185,9 +185,11 @@ static int getllusize(uint8_t fmt, FAR uint8_t flags,
#endif #endif
static void prejustify(FAR struct lib_outstream_s *obj, uint8_t fmt, static void prejustify(FAR struct lib_outstream_s *obj, uint8_t fmt,
uint8_t flags, int fieldwidth, int valwidth); uint8_t flags, int fieldwidth, int valwidth,
int trunc);
static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt, static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt,
uint8_t flags, int fieldwidth, int valwidth); uint8_t flags, int fieldwidth, int valwidth,
int trunc);
/**************************************************************************** /****************************************************************************
* Private Constant Data * Private Constant Data
@ -961,61 +963,121 @@ static int getllusize(uint8_t fmt, uint8_t flags, unsigned long long lln)
****************************************************************************/ ****************************************************************************/
static void prejustify(FAR struct lib_outstream_s *obj, uint8_t fmt, static void prejustify(FAR struct lib_outstream_s *obj, uint8_t fmt,
uint8_t flags, int fieldwidth, int valwidth) uint8_t flags, int fieldwidth, int valwidth,
int trunc)
{ {
int i; int i;
if (trunc > 0 && fmt == FMT_RJUST0)
{
/* Force right justification in the case. Leading zeros application
* only to "precision" which is implied anyway.
*/
fmt = FMT_RJUST;
}
switch (fmt) switch (fmt)
{ {
default: default:
case FMT_RJUST: case FMT_RJUST:
if (IS_SIGNED(flags)) {
{ /* Pad with spaces up to the size of the precision (aka 'trunc')
valwidth++; * then with zeroes to the size of the value width.
} */
for (i = fieldwidth - valwidth; i > 0; i--) if (trunc > valwidth)
{ {
obj->put(obj, ' '); int padlen = fieldwidth - trunc;
}
if (IS_NEGATE(flags)) if (IS_SIGNED(flags))
{ {
obj->put(obj, '-'); padlen--;
} }
else if (IS_SHOWPLUS(flags))
{ for (i = padlen; i > 0; i--)
obj->put(obj, '+'); {
} obj->put(obj, ' ');
}
if (IS_NEGATE(flags))
{
obj->put(obj, '-');
}
else if (IS_SHOWPLUS(flags))
{
obj->put(obj, '+');
}
for (i = trunc - valwidth; i > 0; i--)
{
obj->put(obj, '0');
}
}
else
{
/* Add a leading minus sign */
if (IS_SIGNED(flags))
{
valwidth++;
}
for (i = fieldwidth - valwidth; i > 0; i--)
{
obj->put(obj, ' ');
}
if (IS_NEGATE(flags))
{
obj->put(obj, '-');
}
else if (IS_SHOWPLUS(flags))
{
obj->put(obj, '+');
}
}
}
break; break;
case FMT_RJUST0: case FMT_RJUST0:
if (IS_NEGATE(flags)) {
{ if (IS_NEGATE(flags))
obj->put(obj, '-'); {
valwidth++; obj->put(obj, '-');
} valwidth++;
else if (IS_SHOWPLUS(flags)) }
{ else if (IS_SHOWPLUS(flags))
obj->put(obj, '+'); {
valwidth++; obj->put(obj, '+');
} valwidth++;
}
for (i = fieldwidth - valwidth; i > 0; i--) for (i = fieldwidth - valwidth; i > 0; i--)
{ {
obj->put(obj, '0'); obj->put(obj, '0');
} }
}
break; break;
case FMT_LJUST: case FMT_LJUST:
if (IS_NEGATE(flags)) {
{ if (IS_NEGATE(flags))
obj->put(obj, '-'); {
} obj->put(obj, '-');
else if (IS_SHOWPLUS(flags)) }
{ else if (IS_SHOWPLUS(flags))
obj->put(obj, '+'); {
} obj->put(obj, '+');
}
/* Pad with zeros up to the size of the value width. */
for (i = trunc - valwidth; i > 0; i--)
{
obj->put(obj, '0');
}
}
break; break;
} }
} }
@ -1025,7 +1087,8 @@ static void prejustify(FAR struct lib_outstream_s *obj, uint8_t fmt,
****************************************************************************/ ****************************************************************************/
static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt, static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt,
uint8_t flags, int fieldwidth, int valwidth) uint8_t flags, int fieldwidth, int valwidth,
int trunc)
{ {
int i; int i;
@ -1039,15 +1102,21 @@ static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt,
break; break;
case FMT_LJUST: case FMT_LJUST:
if (IS_SIGNED(flags)) {
{ int width;
valwidth++;
}
for (i = fieldwidth - valwidth; i > 0; i--) if (IS_SIGNED(flags))
{ {
obj->put(obj, ' '); valwidth++;
} }
width = valwidth < trunc ? trunc : valwidth;
for (i = fieldwidth - width; i > 0; i--)
{
obj->put(obj, ' ');
}
}
break; break;
} }
} }
@ -1242,7 +1311,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
swidth = (IS_HASDOT(flags) && trunc >= 0) swidth = (IS_HASDOT(flags) && trunc >= 0)
? strnlen(ptmp, trunc) : strlen(ptmp); ? strnlen(ptmp, trunc) : strlen(ptmp);
prejustify(obj, fmt, 0, width, swidth); prejustify(obj, fmt, 0, width, swidth, 0);
left = swidth; left = swidth;
/* Concatenate the string into the output */ /* Concatenate the string into the output */
@ -1260,7 +1329,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Perform left-justification operations. */ /* Perform left-justification operations. */
postjustify(obj, fmt, 0, width, swidth); postjustify(obj, fmt, 0, width, swidth, 0);
continue; continue;
} }
@ -1313,21 +1382,10 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Get the width of the output */ /* Get the width of the output */
lluwidth = getllusize(FMT_CHAR, flags, lln); lluwidth = getllusize(FMT_CHAR, flags, lln);
if (trunc > 0)
{
if (lluwidth > trunc)
{
lluwidth = trunc;
}
/* Right justify and zero pad */
fmt = FMT_RJUST0;
}
/* Perform left field justification actions */ /* Perform left field justification actions */
prejustify(obj, fmt, flags, width, lluwidth); prejustify(obj, fmt, flags, width, lluwidth, trunc);
/* Output the number */ /* Output the number */
@ -1335,7 +1393,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Perform right field justification actions */ /* Perform right field justification actions */
postjustify(obj, fmt, flags, width, lluwidth); postjustify(obj, fmt, flags, width, lluwidth, trunc);
} }
else else
#endif /* CONFIG_HAVE_LONG_LONG */ #endif /* CONFIG_HAVE_LONG_LONG */
@ -1356,21 +1414,10 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Get the width of the output */ /* Get the width of the output */
luwidth = getlusize(FMT_CHAR, flags, ln); luwidth = getlusize(FMT_CHAR, flags, ln);
if (trunc > 0)
{
if (luwidth > trunc)
{
luwidth = trunc;
}
/* Right justify and zero pad */
fmt = FMT_RJUST0;
}
/* Perform left field justification actions */ /* Perform left field justification actions */
prejustify(obj, fmt, flags, width, luwidth); prejustify(obj, fmt, flags, width, trunc);
/* Output the number */ /* Output the number */
@ -1378,7 +1425,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Perform right field justification actions */ /* Perform right field justification actions */
postjustify(obj, fmt, flags, width, luwidth); postjustify(obj, fmt, flags, width, luwidth, trunc);
} }
else else
#endif /* CONFIG_LONG_IS_NOT_INT */ #endif /* CONFIG_LONG_IS_NOT_INT */
@ -1402,7 +1449,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Perform left field justification actions */ /* Perform left field justification actions */
prejustify(obj, fmt, flags, width, pwidth); prejustify(obj, fmt, flags, width, pwidth, 0);
/* Output the pointer value */ /* Output the pointer value */
@ -1410,7 +1457,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Perform right field justification actions */ /* Perform right field justification actions */
postjustify(obj, fmt, flags, width, pwidth); postjustify(obj, fmt, flags, width, pwidth, 0);
} }
else else
#endif #endif
@ -1429,21 +1476,10 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Get the width of the output */ /* Get the width of the output */
uwidth = getusize(FMT_CHAR, flags, n); uwidth = getusize(FMT_CHAR, flags, n);
if (trunc > 0)
{
if (uwidth > trunc)
{
uwidth = trunc;
}
/* Right justify and zero pad */
fmt = FMT_RJUST0;
}
/* Perform left field justification actions */ /* Perform left field justification actions */
prejustify(obj, fmt, flags, width, uwidth); prejustify(obj, fmt, flags, width, uwidth, trunc);
/* Output the number */ /* Output the number */
@ -1451,7 +1487,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Perform right field justification actions */ /* Perform right field justification actions */
postjustify(obj, fmt, flags, width, uwidth); postjustify(obj, fmt, flags, width, uwidth, trunc);
} }
} }
@ -1469,7 +1505,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Perform left field justification actions */ /* Perform left field justification actions */
prejustify(obj, fmt, 0, width, dblsize); prejustify(obj, fmt, 0, width, dblsize, 0);
/* Output the number */ /* Output the number */
@ -1477,7 +1513,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
/* Perform right field justification actions */ /* Perform right field justification actions */
postjustify(obj, fmt, 0, width, dblsize); postjustify(obj, fmt, 0, width, dblsize, 0);
} }
#endif /* CONFIG_LIBC_FLOATINGPOINT */ #endif /* CONFIG_LIBC_FLOATINGPOINT */
} }