OSDN Git Service

Factor duplicate snprintf code into functions.
authorBruce Momjian <bruce@momjian.us>
Thu, 17 Mar 2005 03:18:14 +0000 (03:18 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 17 Mar 2005 03:18:14 +0000 (03:18 +0000)
src/port/snprintf.c

index e50555d..544ab3d 100644 (file)
@@ -65,7 +65,7 @@
  * causing nasty effects.
  **************************************************************/
 
-/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.23 2005/03/16 21:27:23 momjian Exp $";*/
+/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.24 2005/03/17 03:18:14 momjian Exp $";*/
 
 static void dopr(char *buffer, const char *format, va_list args, char *end);
 
@@ -149,16 +149,18 @@ pg_printf(const char *fmt,...)
        return len;
 }
 
-/*
- * dopr(): poor man's version of doprintf
- */
+static int adjust_sign(int is_negative, int forcesign, int *signvalue);
+static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen);
+static void leading_pad(int zpad, int *signvalue, int *padlen, char *end,
+                                char **output);
+static void trailing_pad(int *padlen, char *end, char **output);
 
-static void fmtstr(char *value, int ljust, int len, int maxwidth,
+static void fmtstr(char *value, int leftjust, int minlen, int maxwidth,
           char *end, char **output);
-static void fmtnum(int64 value, int base, int dosign, int forcesign,
-          int ljust, int len, int zpad, char *end, char **output);
+static void fmtint(int64 value, int base, int dosign, int forcesign,
+          int leftjust, int minlen, int zpad, char *end, char **output);
 static void fmtfloat(double value, char type, int forcesign,
-          int ljust, int len, int zpad, int precision, int pointflag, char *end,
+          int leftjust, int minlen, int zpad, int precision, int pointflag, char *end,
           char **output);
 static void dostr(char *str, int cut, char *end, char **output);
 static void dopr_outch(int c, char *end, char **output);
@@ -171,6 +173,10 @@ static void dopr_outch(int c, char *end, char **output);
 #define FMTWIDTH       6
 #define FMTLEN         7
 
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
 static void
 dopr(char *buffer, const char *format, va_list args, char *end)
 {
@@ -179,8 +185,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
        int                     longflag;
        int                     pointflag;
        int                     maxwidth;
-       int                     ljust;
-       int                     len;
+       int                     leftjust;
+       int                     minlen;
        int                     zpad;
        int                     forcesign;
        int                     i;
@@ -201,8 +207,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                int64           numvalue;
                double          fvalue;
                int                     charvalue;
-               int                     ljust;
-               int                     len;
+               int                     leftjust;
+               int                     minlen;
                int                     zpad;
                int                     maxwidth;
                int                     base;
@@ -245,7 +251,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                switch (ch)
                {
                        case '%':
-                               ljust = len = zpad = forcesign = maxwidth = 0;
+                               leftjust = minlen = zpad = forcesign = maxwidth = 0;
                                longflag = longlongflag = pointflag = 0;
                                fmtbegin = format - 1;
                                realpos = 0;
@@ -257,13 +263,13 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                        case '\0':
                                                goto performpr;
                                        case '-':
-                                               ljust = 1;
+                                               leftjust = 1;
                                                goto nextch;
                                        case '+':
                                                forcesign = 1;
                                                goto nextch;
-                                       case '0':       /* set zero padding if len not set */
-                                               if (len == 0 && !pointflag)
+                                       case '0':       /* set zero padding if minlen not set */
+                                               if (minlen == 0 && !pointflag)
                                                        zpad = '0';
                                        case '1':
                                        case '2':
@@ -276,7 +282,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                        case '9':
                                                if (!pointflag)
                                                {
-                                                       len = len * 10 + ch - '0';
+                                                       minlen = minlen * 10 + ch - '0';
                                                        position = position * 10 + ch - '0';
                                                }
                                                else
@@ -287,7 +293,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                                goto nextch;
                                        case '$':
                                                realpos = position;
-                                               len = 0;
+                                               minlen = 0;
                                                goto nextch;
                                        case '*':
                                                MemSet(&fmtpar[fmtpos], 0, sizeof(fmtpar[fmtpos]));
@@ -340,8 +346,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                                fmtpar[fmtpos].base = 10;
                                                fmtpar[fmtpos].dosign = 0;
                                                fmtpar[fmtpos].forcesign = forcesign;
-                                               fmtpar[fmtpos].ljust = ljust;
-                                               fmtpar[fmtpos].len = len;
+                                               fmtpar[fmtpos].leftjust = leftjust;
+                                               fmtpar[fmtpos].minlen = minlen;
                                                fmtpar[fmtpos].zpad = zpad;
                                                fmtpar[fmtpos].func = FMTNUM_U;
                                                fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
@@ -356,8 +362,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                                fmtpar[fmtpos].base = 8;
                                                fmtpar[fmtpos].dosign = 0;
                                                fmtpar[fmtpos].forcesign = forcesign;
-                                               fmtpar[fmtpos].ljust = ljust;
-                                               fmtpar[fmtpos].len = len;
+                                               fmtpar[fmtpos].leftjust = leftjust;
+                                               fmtpar[fmtpos].minlen = minlen;
                                                fmtpar[fmtpos].zpad = zpad;
                                                fmtpar[fmtpos].func = FMTNUM_U;
                                                fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
@@ -372,8 +378,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                                fmtpar[fmtpos].base = 10;
                                                fmtpar[fmtpos].dosign = 1;
                                                fmtpar[fmtpos].forcesign = forcesign;
-                                               fmtpar[fmtpos].ljust = ljust;
-                                               fmtpar[fmtpos].len = len;
+                                               fmtpar[fmtpos].leftjust = leftjust;
+                                               fmtpar[fmtpos].minlen = minlen;
                                                fmtpar[fmtpos].zpad = zpad;
                                                fmtpar[fmtpos].func = FMTNUM;
                                                fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
@@ -387,8 +393,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                                fmtpar[fmtpos].base = 16;
                                                fmtpar[fmtpos].dosign = 0;
                                                fmtpar[fmtpos].forcesign = forcesign;
-                                               fmtpar[fmtpos].ljust = ljust;
-                                               fmtpar[fmtpos].len = len;
+                                               fmtpar[fmtpos].leftjust = leftjust;
+                                               fmtpar[fmtpos].minlen = minlen;
                                                fmtpar[fmtpos].zpad = zpad;
                                                fmtpar[fmtpos].func = FMTNUM_U;
                                                fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
@@ -402,8 +408,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                                fmtpar[fmtpos].base = -16;
                                                fmtpar[fmtpos].dosign = 1;
                                                fmtpar[fmtpos].forcesign = forcesign;
-                                               fmtpar[fmtpos].ljust = ljust;
-                                               fmtpar[fmtpos].len = len;
+                                               fmtpar[fmtpos].leftjust = leftjust;
+                                               fmtpar[fmtpos].minlen = minlen;
                                                fmtpar[fmtpos].zpad = zpad;
                                                fmtpar[fmtpos].func = FMTNUM_U;
                                                fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
@@ -412,8 +418,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                        case 's':
                                                fmtpar[fmtpos].fmtbegin = fmtbegin;
                                                fmtpar[fmtpos].fmtend = format;
-                                               fmtpar[fmtpos].ljust = ljust;
-                                               fmtpar[fmtpos].len = len;
+                                               fmtpar[fmtpos].leftjust = leftjust;
+                                               fmtpar[fmtpos].minlen = minlen;
                                                fmtpar[fmtpos].zpad = zpad;
                                                fmtpar[fmtpos].maxwidth = maxwidth;
                                                fmtpar[fmtpos].func = FMTSTR;
@@ -436,8 +442,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
                                                fmtpar[fmtpos].fmtend = format;
                                                fmtpar[fmtpos].type = ch;
                                                fmtpar[fmtpos].forcesign = forcesign;
-                                               fmtpar[fmtpos].ljust = ljust;
-                                               fmtpar[fmtpos].len = len;
+                                               fmtpar[fmtpos].leftjust = leftjust;
+                                               fmtpar[fmtpos].minlen = minlen;
                                                fmtpar[fmtpos].zpad = zpad;
                                                fmtpar[fmtpos].precision = precision;
                                                fmtpar[fmtpos].pointflag = pointflag;
@@ -499,11 +505,27 @@ performpr:
                                fmtparptr[i]->charvalue = va_arg(args, int);
                                break;
                        case FMTLEN:
-                               if (i + 1 < fmtpos && fmtparptr[i + 1]->func != FMTWIDTH)
-                                       fmtparptr[i + 1]->len = va_arg(args, int);
-                               /* For "%*.*f", use the second arg */
-                               if (i + 2 < fmtpos && fmtparptr[i + 1]->func == FMTWIDTH)
-                                       fmtparptr[i + 2]->len = va_arg(args, int);
+                               {
+                                       int minlen = va_arg(args, int);
+                                       int leftjust = 0;
+
+                                       if (minlen < 0)
+                                       {
+                                               minlen = -minlen;
+                                               leftjust = 1;
+                                       }
+                                       if (i + 1 < fmtpos && fmtparptr[i + 1]->func != FMTWIDTH)
+                                       {
+                                               fmtparptr[i + 1]->minlen = minlen;
+                                               fmtparptr[i + 1]->leftjust |= leftjust;
+                                       }
+                                       /* For "%*.*f", use the second arg */
+                                       if (i + 2 < fmtpos && fmtparptr[i + 1]->func == FMTWIDTH)
+                                       {
+                                               fmtparptr[i + 2]->minlen = minlen;
+                                               fmtparptr[i + 2]->leftjust |= leftjust;
+                                       }
+                               }
                                break;
                        case FMTWIDTH:
                                if (i + 1 < fmtpos)
@@ -530,21 +552,21 @@ performpr:
                                switch (fmtparptr[i]->func)
                                {
                                        case FMTSTR:
-                                               fmtstr(fmtparptr[i]->value, fmtparptr[i]->ljust,
-                                                          fmtparptr[i]->len, fmtparptr[i]->maxwidth,
+                                               fmtstr(fmtparptr[i]->value, fmtparptr[i]->leftjust,
+                                                          fmtparptr[i]->minlen, fmtparptr[i]->maxwidth,
                                                           end, &output);
                                                break;
                                        case FMTNUM:
                                        case FMTNUM_U:
-                                               fmtnum(fmtparptr[i]->numvalue, fmtparptr[i]->base,
+                                               fmtint(fmtparptr[i]->numvalue, fmtparptr[i]->base,
                                                           fmtparptr[i]->dosign, fmtparptr[i]->forcesign,
-                                                          fmtparptr[i]->ljust, fmtparptr[i]->len,
+                                                          fmtparptr[i]->leftjust, fmtparptr[i]->minlen,
                                                           fmtparptr[i]->zpad, end, &output);
                                                break;
                                        case FMTFLOAT:
                                                fmtfloat(fmtparptr[i]->fvalue, fmtparptr[i]->type,
-                                                          fmtparptr[i]->forcesign, fmtparptr[i]->ljust,
-                                                          fmtparptr[i]->len, fmtparptr[i]->zpad,
+                                                          fmtparptr[i]->forcesign, fmtparptr[i]->leftjust,
+                                                          fmtparptr[i]->minlen, fmtparptr[i]->zpad,
                                                           fmtparptr[i]->precision, fmtparptr[i]->pointflag,
                                                           end, &output);
                                                break;
@@ -574,7 +596,7 @@ nochar:
 }
 
 static void
-fmtstr(char *value, int ljust, int len, int maxwidth, char *end,
+fmtstr(char *value, int leftjust, int minlen, int maxwidth, char *end,
           char **output)
 {
        int                     padlen,
@@ -582,185 +604,90 @@ fmtstr(char *value, int ljust, int len, int maxwidth, char *end,
 
        if (value == NULL)
                value = "<NULL>";
+
        vallen = strlen(value);
-       if (vallen > maxwidth && maxwidth)
+       if (maxwidth && vallen > maxwidth)
                vallen = maxwidth;
-       if (len < 0)
-       {
-               /* this could happen with a "*" width spec */
-               ljust = 1;
-               len = -len;
-       }
-       padlen = len - vallen;
-       if (padlen < 0)
-               padlen = 0;
-       if (ljust)
-               padlen = -padlen;
+
+       adjust_padlen(minlen, vallen, leftjust, &padlen);
+
        while (padlen > 0)
        {
                dopr_outch(' ', end, output);
                --padlen;
        }
        dostr(value, maxwidth, end, output);
-       while (padlen < 0)
-       {
-               dopr_outch(' ', end, output);
-               ++padlen;
-       }
+
+       trailing_pad(&padlen, end, output);
 }
 
 static void
-fmtnum(int64 value, int base, int dosign, int forcesign, int ljust,
-          int len, int zpad, char *end, char **output)
+fmtint(int64 value, int base, int dosign, int forcesign, int leftjust,
+          int minlen, int zpad, char *end, char **output)
 {
        int                     signvalue = 0;
-       uint64          uvalue;
        char            convert[64];
-       int                     place = 0;
+       int                     vallen = 0;
        int                     padlen = 0;             /* amount to pad */
        int                     caps = 0;
 
-       /*
-        * DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
-        * value, base, dosign, ljust, len, zpad ));
-        */
-       uvalue = value;
-       if (dosign)
-       {
-               if (value < 0)
-               {
-                       signvalue = '-';
-                       uvalue = -value;
-               }
-               else if (forcesign)
-                       signvalue = '+';
-       }
+       /* Handle +/- and %X (uppercase hex) */
+       if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
+                       value = -value;
        if (base < 0)
        {
                caps = 1;
                base = -base;
        }
+
+       /* make integer string */
        do
        {
-               convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
-                       [uvalue % (unsigned) base];
-               uvalue = (uvalue / (unsigned) base);
-       } while (uvalue);
-       convert[place] = 0;
+               convert[vallen++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+                       [value % (unsigned) base];
+               value = (value / (unsigned) base);
+       } while (value);
+       convert[vallen] = 0;
 
-       if (len < 0)
-       {
-               /* this could happen with a "*" width spec */
-               ljust = 1;
-               len = -len;
-       }
-       padlen = len - place;
-       if (padlen < 0)
-               padlen = 0;
-       if (ljust)
-               padlen = -padlen;
-
-       /*
-        * DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
-        * convert,place,signvalue,padlen));
-        */
-       if (zpad && padlen > 0)
-       {
-               if (signvalue)
-               {
-                       dopr_outch(signvalue, end, output);
-                       --padlen;
-                       signvalue = 0;
-               }
-               while (padlen > 0)
-               {
-                       dopr_outch(zpad, end, output);
-                       --padlen;
-               }
-       }
-       while (padlen > 0)
-       {
-               dopr_outch(' ', end, output);
-               --padlen;
-       }
-       if (signvalue)
-               dopr_outch(signvalue, end, output);
-       while (place > 0)
-               dopr_outch(convert[--place], end, output);
-       while (padlen < 0)
-       {
-               dopr_outch(' ', end, output);
-               ++padlen;
-       }
+       adjust_padlen(minlen, vallen, leftjust, &padlen);
+
+       leading_pad(zpad, &signvalue, &padlen, end, output);
+       
+       while (vallen > 0)
+               dopr_outch(convert[--vallen], end, output);
+
+       trailing_pad(&padlen, end, output);
 }
 
 static void
-fmtfloat(double value, char type, int forcesign, int ljust,
-                int len, int zpad, int precision, int pointflag, char *end,
+fmtfloat(double value, char type, int forcesign, int leftjust,
+                int minlen, int zpad, int precision, int pointflag, char *end,
                 char **output)
 {
        int                     signvalue = 0;
-       double          uvalue;
+       int                     vallen;
        char            fmt[32];
        char            convert[512];
        int                     padlen = 0;             /* amount to pad */
 
-       uvalue = value;
        /* we rely on regular C library's sprintf to do the basic conversion */
        if (pointflag)
                sprintf(fmt, "%%.%d%c", precision, type);
        else
                sprintf(fmt, "%%%c", type);
 
-       if (value < 0)
-       {
-               signvalue = '-';
-               uvalue = -value;
-       }
-       else if (forcesign)
-               signvalue = '+';
+       if (adjust_sign((value < 0), forcesign, &signvalue))
+                       value = -value;
 
-       sprintf(convert, fmt, uvalue);
+       vallen = sprintf(convert, fmt, value);
 
-       if (len < 0)
-       {
-               /* this could happen with a "*" width spec */
-               ljust = 1;
-               len = -len;
-       }
-       padlen = len - strlen(convert);
-       if (padlen < 0)
-               padlen = 0;
-       if (ljust)
-               padlen = -padlen;
+       adjust_padlen(minlen, vallen, leftjust, &padlen);
+
+       leading_pad(zpad, &signvalue, &padlen, end, output);
 
-       if (zpad && padlen > 0)
-       {
-               if (signvalue)
-               {
-                       dopr_outch(signvalue, end, output);
-                       --padlen;
-                       signvalue = 0;
-               }
-               while (padlen > 0)
-               {
-                       dopr_outch(zpad, end, output);
-                       --padlen;
-               }
-       }
-       while (padlen > 0)
-       {
-               dopr_outch(' ', end, output);
-               --padlen;
-       }
-       if (signvalue)
-               dopr_outch(signvalue, end, output);
        dostr(convert, 0, end, output);
-       while (padlen < 0)
-       {
-               dopr_outch(' ', end, output);
-               ++padlen;
-       }
+
+       trailing_pad(&padlen, end, output);
 }
 
 static void
@@ -788,3 +715,73 @@ dopr_outch(int c, char *end, char **output)
        if (end == 0 || *output < end)
                *(*output)++ = c;
 }
+
+
+static int
+adjust_sign(int is_negative, int forcesign, int *signvalue)
+{
+       if (is_negative)
+       {
+               *signvalue = '-';
+               return true;
+       }
+       else if (forcesign)
+               *signvalue = '+';
+       return false;
+}
+
+
+static void
+adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
+{
+       *padlen = minlen - vallen;
+       if (*padlen < 0)
+               *padlen = 0;
+       if (leftjust)
+               *padlen = -*padlen;
+}
+
+
+static void
+leading_pad(int zpad, int *signvalue, int *padlen, char *end, char **output)
+{
+       if (*padlen > 0 && zpad)
+       {
+               if (*signvalue)
+               {
+                       dopr_outch(*signvalue, end, output);
+                       --*padlen;
+                       *signvalue = 0;
+               }
+               while (*padlen > 0)
+               {
+                       dopr_outch(zpad, end, output);
+                       --*padlen;
+               }
+       }
+       while (*padlen > 0 + (*signvalue != 0))
+       {
+               dopr_outch(' ', end, output);
+               --*padlen;
+       }
+       if (*signvalue)
+       {
+               dopr_outch(*signvalue, end, output);
+               if (*padlen > 0)
+                       --*padlen;
+               if (padlen < 0)
+                       ++padlen;
+       }
+}
+
+
+static void
+trailing_pad(int *padlen, char *end, char **output)
+{
+       while (*padlen < 0)
+       {
+               dopr_outch(' ', end, output);
+               ++*padlen;
+       }
+}
+