remove calls to standard fprintf function
[compress.git] / fprintf.c
diff --git a/fprintf.c b/fprintf.c
new file mode 100644 (file)
index 0000000..47b19c7
--- /dev/null
+++ b/fprintf.c
@@ -0,0 +1,102 @@
+/*
+  File name        : fprintf.c
+  Date of creation : 05/12/2022
+  Version          : 1.0
+  Copyright        : Soft'n'design
+  Author           : Laurent Mazet <mazet@softndesign.org>
+
+  Description      : This file contains embedded printf
+
+  History          :
+  - initial version
+*/
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+
+inline unsigned int nextpow10 (unsigned int x) {
+    unsigned int n = 0;
+    while (x) {
+        n++;
+        x = x / 10;
+    }
+    return (n == 0) ? 1 : n;
+}
+
+/* simple fprintf function */
+
+size_t _fprintf (FILE *fid, const char *fmt, ...)
+{
+    char buffer[1024 + 1] = { 0 };
+    char *str = buffer;
+
+    va_list ap;
+    va_start (ap, fmt);
+    while (*fmt) {
+        char *s;
+        int d = 0;
+        unsigned int u;
+        void *p;
+        char c = *fmt++;
+
+        /* copy standard char */
+        if (c != '%') {
+            *str++ = c;
+        } else {
+            int t = 0;
+            size_t i;
+
+            /* process format char */
+            switch (*fmt++) {
+            case 'c': /* char */
+                c = (char) va_arg (ap, int);
+                *str++ = c;
+                break;
+            case 'd': /* int */
+                d = va_arg (ap, int);
+                if (d < 0) {
+                    *str++ = '-';
+                    d = -d;
+                }
+                t = 1;
+                /* fall through */
+            case 'u': /* unsigned int */
+                u = (t) ? (unsigned int)d : va_arg (ap, unsigned int);
+                for (i = nextpow10 (u), s = str; i > 0; i--, s++) {
+                    str[i - 1] = '0' + (u % 10);
+                    u /= 10;
+                }
+                str = s;
+                break;
+            case 'p': /* pointer */
+                p = va_arg (ap, void *);
+                *str++ = '0';
+                *str++ = 'x';
+                for (i = sizeof (void *) * 2; i > 0; i--) {
+                    char x = (char)(((uintptr_t)p >> (i * 4 - 4)) & 0xf);
+                    *str++ = (x > 9) ? 'a' + x - 10 : '0' + x;
+                }
+                break;
+            case 's': /* string */
+                s = va_arg (ap, char *);
+                while (s && *s)
+                    *str++ = *s++;
+                break;
+            default:
+                *str++ = '?';
+            }
+        }
+    }
+    va_end (ap);
+
+    /* output string */
+    size_t n = str - buffer;
+    if (n < sizeof (buffer) - 1) {
+        fwrite (buffer, n, 1, fid);
+        return n;
+    }
+    return 0;
+}
+
+/* vim: set ts=4 sw=4 et */