changeset 299:0311f139fcf6

Refactor how various printf modifier flags etc. are handled. Still needs work and refining.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 22 Feb 2016 18:31:11 +0200
parents 86fe17a2ed81
children 385d0b40a6c8
files th_string.c th_string.h
diffstat 2 files changed, 106 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/th_string.c	Mon Feb 22 18:29:53 2016 +0200
+++ b/th_string.c	Mon Feb 22 18:31:11 2016 +0200
@@ -124,21 +124,43 @@
 //
 // Simple implementations of printf() type functions
 //
-static int th_printf_vput_pad(th_printf_ctx *ctx, th_printf_vputch vputch, int nwidth, const char padChar)
+static int th_printf_pad_pre(th_printf_ctx *ctx, th_printf_vputch vputch,
+    int f_width, const int f_flags)
 {
-    while (nwidth--)
+    if (f_width > 0 && (f_flags & TH_PF_LEFT) == 0)
     {
-        int ret;
-        if ((ret = vputch(ctx, padChar)) == EOF)
-            return ret;
+        char pad = (f_flags & TH_PF_ZERO) ? '0' : ' ';
+        while (f_width--)
+        {
+            int ret;
+            if ((ret = vputch(ctx, pad)) == EOF)
+                return ret;
+        }
+    }
+    return 0;
+}
+
+
+static int th_printf_pad_post(th_printf_ctx *ctx, th_printf_vputch vputch,
+    int f_width, const int f_flags)
+{
+    if (f_width > 0 && (f_flags & TH_PF_LEFT))
+    {
+        char pad = ' ';
+        while (f_width--)
+        {
+            int ret;
+            if ((ret = vputch(ctx, pad)) == EOF)
+                return ret;
+        }
     }
     return 0;
 }
 
 
 static int th_printf_vput_int(th_printf_ctx *ctx, th_printf_vputch vputch,
-    int pval, const int radix, const char padMode, const char padChar,
-    const int f_width, const BOOL unsig, const BOOL upcase, const BOOL f_sign)
+    int pval, const int radix, const int f_flags,
+    const int f_width, const BOOL unsig, const BOOL upcase)
 {
     char buf[64];
     size_t pos = 0;
@@ -177,7 +199,7 @@
     // Do we want a sign prefix? Not for unsigned values
     if (!unsig)
     {
-        char ch = f_sign ? (neg ? '-' : '+') : (neg ? '-' : 0);
+        char ch = (f_flags & TH_PF_SIGN) ? (neg ? '-' : '+') : (neg ? '-' : ((f_flags & TH_PF_SPACE) ? ' ' : 0));
         if (ch && (ret = vputch(ctx, ch)) == EOF)
             goto out;
     }
@@ -186,7 +208,7 @@
     int nwidth = f_width - pos;
 
     // Prefix padding?
-    if (padMode != '-' && nwidth > 0 && (ret = th_printf_vput_pad(ctx, vputch, nwidth, padMode)) == EOF)
+    if ((ret = th_printf_pad_pre(ctx, vputch, nwidth, f_flags)) == EOF)
         goto out;
 
     // Output the value
@@ -197,7 +219,7 @@
     }
 
     // Postfix padding?
-    if (padMode == '-' && nwidth > 0 && (ret = th_printf_vput_pad(ctx, vputch, nwidth, ' ')) == EOF)
+    if ((ret = th_printf_pad_post(ctx, vputch, nwidth, f_flags)) == EOF)
         goto out;
 
 out:
@@ -206,8 +228,7 @@
 
 
 static int th_printf_vput_str(th_printf_ctx *ctx, th_printf_vputch vputch,
-    const char *str, const char padMode, const char padChar,
-    const int f_width, const int f_prec)
+    const char *str, const int f_flags, const int f_width, const int f_prec)
 {
     int nwidth, ret = 0;
 
@@ -218,7 +239,7 @@
     nwidth = f_width - strlen(str);
 
     // Prefix padding?
-    if (padMode != '-' && nwidth > 0 && (ret = th_printf_vput_pad(ctx, vputch, nwidth, padMode)) == EOF)
+    if ((ret = th_printf_pad_pre(ctx, vputch, nwidth, f_flags)) == EOF)
         goto out;
 
     while (*str)
@@ -228,7 +249,7 @@
     }
 
     // Postfix padding?
-    if (padMode == '-' && nwidth > 0 && (ret = th_printf_vput_pad(ctx, vputch, nwidth, ' ')) == EOF)
+    if ((ret = th_printf_pad_post(ctx, vputch, nwidth, f_flags)) == EOF)
         goto out;
 
 out:
@@ -249,33 +270,45 @@
         }
         else
         {
-            char padMode = ' ', padChar = 0;
-            int f_width = 0, f_prec = -1;
-            BOOL f_sign = FALSE;
+            int f_width = 0, f_prec = 1, f_flags = 0;
+            BOOL end = FALSE;
 
             fmt++;
 
-            // Check for field sign
-            if (*fmt == '+')
-            {
-                f_sign = TRUE;
-                fmt++;
-            }
-
-            // Check for padding
-            if (*fmt == '0' || *fmt == '-' || *fmt == '\'')
+            // Check for flags
+            while (!end)
             {
-                padMode = *fmt++;
-                if (padMode == '\'')
+                switch (*fmt)
                 {
-                    padChar = *fmt++;
-                    if (*fmt != '\'')
-                        return -101;
-                    fmt++;
+                    case '#':
+                        f_flags |= TH_PF_ALT;
+                        break;
+
+                    case '+':
+                        f_flags |= TH_PF_SIGN;
+                        break;
+
+                    case '0':
+                        f_flags |= TH_PF_ZERO;
+                        break;
+
+                    case '-':
+                        f_flags |= TH_PF_LEFT;
+                        break;
+
+                    case ' ':
+                        f_flags |= TH_PF_SPACE;
+                        break;
+
+                    case '\'':
+                        f_flags |= TH_PF_GROUP;
+                        break;
+
+                    default:
+                        end = TRUE;
+                        break;
                 }
-
-                if (*fmt == 0)
-                    return -102;
+                if (!end) fmt++;
             }
 
             // Get field width
@@ -286,13 +319,12 @@
             if (*fmt == '.')
             {
                 fmt++;
-                if (!th_isdigit(*fmt))
-                    return -103;
-
                 // If no digit after '.', precision is to be 0
                 f_prec = 0;
                 while (th_isdigit(*fmt))
                     f_prec = f_prec * 10 + (*fmt++ - '0');
+
+                f_flags &= ~ TH_PF_ZERO;
             }
 
             // Check for length modifiers (NOT SUPPORTED CURRENTLY)
@@ -313,42 +345,49 @@
                     return -104;
 
                 case 'c':
-                    if (padMode != ' ' || f_width > 0 || f_prec >= 0 || f_sign)
-                        return -105;
+                    if ((ret = th_printf_pad_pre(ctx, vputch, f_width - 1, f_flags)) == EOF)
+                        goto out;
+                    if ((ret = vputch(ctx, va_arg(ap, int))) == EOF)
+                        goto out;
+                    if ((ret = th_printf_pad_post(ctx, vputch, f_width - 1, f_flags)) == EOF)
+                        goto out;
+                    break;
 
-                    if ((ret = vputch(ctx, va_arg(ap, int))) == EOF)
+                case 'o':
+                    if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, unsigned int),
+                        8, f_flags, f_width, FALSE, FALSE)) == EOF)
                         goto out;
                     break;
 
                 case 'u':
+                case 'i':
                 case 'd':
-                    if ((padMode != '0' && padMode != '-' && padMode != ' ') || f_prec >= 0)
-                        return -105;
-
                     if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, unsigned int),
-                        10, padMode, padChar, f_width, *fmt == 'u', FALSE, f_sign)) == EOF)
+                        10, f_flags, f_width, *fmt == 'u', FALSE)) == EOF)
                         goto out;
                     break;
 
                 case 'x':
                 case 'X':
-                    if ((padMode != '0' && padMode != '-' && padMode != ' ') || f_prec >= 0)
-                        return -106;
+                    if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, unsigned int),
+                        16, f_flags, f_width, TRUE, *fmt == 'X')) == EOF)
+                        goto out;
+                    break;
 
-                    if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, unsigned int),
-                        16, padMode, padChar, f_width, TRUE, *fmt == 'X', FALSE)) == EOF)
+                case 'p':
+                    if ((ret = th_printf_vput_int(ctx, vputch, va_arg(ap, void *),
+                        16, f_flags, f_width, TRUE, FALSE)) == EOF)
                         goto out;
                     break;
 
                 case 'f':
-                    goto out;
+                case 'F':
+                    return -112;
                     break;
 
                 case 's':
-                    if ((padMode != '-' && padMode != ' ') || f_sign)
-                        return -108;
-
-                    if ((ret = th_printf_vput_str(ctx, vputch, va_arg(ap, char *), padMode, padChar, f_width, f_prec)) == EOF)
+                    if ((ret = th_printf_vput_str(ctx, vputch, va_arg(ap, char *),
+                        f_flags, f_width, f_prec)) == EOF)
                         goto out;
                     break;
 
--- a/th_string.h	Mon Feb 22 18:29:53 2016 +0200
+++ b/th_string.h	Mon Feb 22 18:31:11 2016 +0200
@@ -48,6 +48,19 @@
 };
 
 
+enum
+{
+    TH_PF_NONE  = 0x00,
+    TH_PF_ALT   = 0x01,
+    TH_PF_SIGN  = 0x02,
+    TH_PF_SPACE = 0x04,
+    TH_PF_GROUP = 0x08,
+
+    TH_PF_ZERO  = 0x10,
+    TH_PF_LEFT  = 0x20,
+};
+
+
 typedef struct
 {
     char *buf;