changeset 567:b75f42ca08ef

Massage th_vprintf_do() a bit, and factor out the format specifier handling into a separate function and use through a callback. This breaks the th_vprintf_do() API, unfortunately, but should make for further flexibility in future.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 08 Jan 2020 02:17:37 +0200
parents 11f56a652cb0
children 2fbe42d957c4
files th_printf.c th_string.c th_string.h
diffstat 3 files changed, 92 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/th_printf.c	Tue Jan 07 20:09:23 2020 +0200
+++ b/th_printf.c	Wed Jan 08 02:17:37 2020 +0200
@@ -324,7 +324,77 @@
 #endif
 
 
-int th_vprintf_do(th_vprintf_ctx *ctx, th_vprintf_putch vputch, const char *fmt, va_list ap)
+int th_vprintf_do_format(
+    th_vprintf_ctx *ctx, th_vprintf_putch vputch,
+    int f_width, int f_prec, int f_flags,
+    const char fmt, va_list ap)
+{
+    int ret;
+
+    switch (fmt)
+    {
+        case 0:
+            // Unexpected end of format string
+            return -104;
+
+        case 'c':
+            if ((ret = th_printf_pad_pre(ctx, vputch, f_width - 1, f_flags)) == EOF)
+                return ret;
+
+            if ((ret = vputch(ctx, va_arg(ap, int))) == EOF)
+                return ret;
+
+            return th_printf_pad_post(ctx, vputch, f_width - 1, f_flags);
+
+        case 'o':
+            return th_vprintf_put_int(ctx, vputch, ap, 8, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_oct);
+
+        case 'u':
+        case 'i':
+        case 'd':
+            return th_vprintf_put_int(ctx, vputch, ap, 10, f_flags, f_width, f_prec, fmt == 'u', NULL);
+
+        case 'x':
+        case 'X':
+            if (fmt == 'X')
+                f_flags |= TH_PF_UPCASE;
+
+            return th_vprintf_put_int(ctx, vputch, ap, 16, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_hex);
+
+        case 'p':
+            // Check for invalid flags
+            if (f_flags & (TH_PF_LONG | TH_PF_LONGLONG))
+                return -120;
+
+#if (TH_PTRSIZE == 32)
+            f_flags |= TH_PF_LONG;
+#elif (TH_PTRSIZE == 64)
+            f_flags |= TH_PF_LONGLONG;
+#endif
+            f_flags |= TH_PF_ALT | TH_PF_POINTER;
+
+            return th_vprintf_put_int(ctx, vputch, ap, 16, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_hex);
+
+#ifdef TH_WIP_FLOAT_SUPPORT
+        case 'f':
+        case 'F':
+            return th_vprintf_put_float(ctx, vputch, ap,
+                f_flags, f_width, f_prec);
+#endif
+
+        case 's':
+            return th_vprintf_put_str(ctx, vputch, va_arg(ap, char *),
+                f_flags, f_width, f_prec);
+
+        //case '%':
+        default:
+            return vputch(ctx, fmt);
+    }
+}
+
+
+int th_vprintf_do(th_vprintf_ctx *ctx, th_vprintf_putch vputch,
+    th_vprintf_format vformat, const char *fmt, va_list ap)
 {
     int ret = 0;
 
@@ -440,75 +510,12 @@
                     return -202;
             }
 
-            switch (*fmt)
-            {
-                case 0:
-                    return -104;
-
-                case 'c':
-                    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;
-
-                case 'o':
-                    if ((ret = th_vprintf_put_int(ctx, vputch, ap, 8, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_oct)) == EOF)
-                        goto out;
-                    break;
-
-                case 'u':
-                case 'i':
-                case 'd':
-                    if ((ret = th_vprintf_put_int(ctx, vputch, ap, 10, f_flags, f_width, f_prec, *fmt == 'u', NULL)) == EOF)
-                        goto out;
-                    break;
-
-                case 'x':
-                case 'X':
-                    if (*fmt == 'X')
-                        f_flags |= TH_PF_UPCASE;
-                    if ((ret = th_vprintf_put_int(ctx, vputch, ap, 16, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_hex)) == EOF)
-                        goto out;
-                    break;
+            ret = vformat(ctx, vputch, f_width, f_prec, f_flags, *fmt, ap);
+            if (ret == EOF)
+                goto out;
+            if (ret < 0)
+                return ret;
 
-                case 'p':
-                    if (f_flags & (TH_PF_LONG | TH_PF_LONGLONG))
-                        return -120;
-
-#if (TH_PTRSIZE == 32)
-                    f_flags |= TH_PF_LONG;
-#elif (TH_PTRSIZE == 64)
-                    f_flags |= TH_PF_LONGLONG;
-#endif
-                    f_flags |= TH_PF_ALT | TH_PF_POINTER;
-                    if ((ret = th_vprintf_put_int(ctx, vputch, ap, 16, f_flags, f_width, f_prec, TRUE, th_vprintf_altfmt_hex)) == EOF)
-                        goto out;
-                    break;
-
-#ifdef TH_WIP_FLOAT_SUPPORT
-                case 'f':
-                case 'F':
-                    if ((ret = th_vprintf_put_float(ctx, vputch, ap,
-                        f_flags, f_width, f_prec)) == EOF)
-                        goto out;
-                    break;
-#endif
-
-                case 's':
-                    if ((ret = th_vprintf_put_str(ctx, vputch, va_arg(ap, char *),
-                        f_flags, f_width, f_prec)) == EOF)
-                        goto out;
-                    break;
-
-                //case '%':
-                default:
-                    if ((ret = vputch(ctx, *fmt)) == EOF)
-                        goto out;
-                    break;
-            }
         }
         fmt++;
     }
--- a/th_string.c	Tue Jan 07 20:09:23 2020 +0200
+++ b/th_string.c	Wed Jan 08 02:17:37 2020 +0200
@@ -157,7 +157,7 @@
     ctx.pos = 0;
     ctx.ipos = 0;
 
-    ret = th_vprintf_do(&ctx, th_pbuf_vputch, fmt, ap);
+    ret = th_vprintf_do(&ctx, th_pbuf_vputch, th_vprintf_do_format, fmt, ap);
 
     if (ctx.pos < size)
         buf[ctx.pos] = 0;
@@ -205,7 +205,7 @@
     ctx.pos = 0;
     ctx.ipos = 0;
 
-    return th_vprintf_do(&ctx, th_stdio_vputch, fmt, ap);
+    return th_vprintf_do(&ctx, th_stdio_vputch, th_vprintf_do_format, fmt, ap);
 #else
     return vfprintf(fh, fmt, ap);
 #endif
@@ -226,7 +226,7 @@
     ctx.pos = 0;
     ctx.ipos = 0;
 
-    ret = th_vprintf_do(&ctx, th_stdio_vputch, fmt, ap);
+    ret = th_vprintf_do(&ctx, th_stdio_vputch, th_vprintf_do_format, fmt, ap);
 #else
     ret = fprintf(fh, fmt, ap);
 #endif
@@ -263,7 +263,7 @@
     // Get size
     va_copy(ap, args);
     ctx.pos = 0;
-    th_vprintf_do(&ctx, th_pbuf_alloc_vputch1, fmt, ap);
+    th_vprintf_do(&ctx, th_pbuf_alloc_vputch1, th_vprintf_do_format, fmt, ap);
     va_end(ap);
 
     // Allocate memory
@@ -273,7 +273,7 @@
 
     va_copy(ap, args);
     ctx.pos = 0;
-    th_vprintf_do(&ctx, th_pbuf_alloc_vputch2, fmt, ap);
+    th_vprintf_do(&ctx, th_pbuf_alloc_vputch2, th_vprintf_do_format, fmt, ap);
     va_end(ap);
     ctx.buf[ctx.pos] = 0;
 
--- a/th_string.h	Tue Jan 07 20:09:23 2020 +0200
+++ b/th_string.h	Wed Jan 08 02:17:37 2020 +0200
@@ -88,6 +88,14 @@
 typedef int (*th_vprintf_putch)(th_vprintf_ctx *ctx, const char ch);
 
 
+/** @def formatting helper function typedef for internal printf() implementation
+ */
+typedef int (*th_vprintf_format)(
+    th_vprintf_ctx *ctx, th_vprintf_putch vputch,
+    int f_width, int f_prec, int f_flags,
+    const char fmt, va_list ap);
+
+
 /* Normal NUL-terminated string functions
  */
 char    *th_strdup(const char *src);
@@ -128,7 +136,9 @@
     const char *buf, const size_t len, const int vret, int *prec, int *flags);
 
 
-int     th_vprintf_do(th_vprintf_ctx *ctx, th_vprintf_putch vputch, const char *fmt, va_list ap);
+int     th_vprintf_do(th_vprintf_ctx *ctx, th_vprintf_putch vputch,
+    th_vprintf_format vformat, const char *fmt, va_list ap);
+
 int     th_vprintf_put_str(th_vprintf_ctx *ctx, th_vprintf_putch vputch,
         const char *str, int f_flags, const int f_width, const int f_prec);