summaryrefslogtreecommitdiff
path: root/graphs/piscine/tinyprintf/src
diff options
context:
space:
mode:
Diffstat (limited to 'graphs/piscine/tinyprintf/src')
-rw-r--r--graphs/piscine/tinyprintf/src/tinyprintf.c251
-rw-r--r--graphs/piscine/tinyprintf/src/tinyprintf.h15
2 files changed, 266 insertions, 0 deletions
diff --git a/graphs/piscine/tinyprintf/src/tinyprintf.c b/graphs/piscine/tinyprintf/src/tinyprintf.c
new file mode 100644
index 0000000..d005db7
--- /dev/null
+++ b/graphs/piscine/tinyprintf/src/tinyprintf.c
@@ -0,0 +1,251 @@
+#include "tinyprintf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int tinyprintf(const char *format, ...)
+{
+ if (format == NULL || *format == '\0')
+ {
+ return 0;
+ }
+
+ va_list ap;
+ va_start(ap, format);
+ int res = 0;
+
+ size_t i = 0;
+ while (format[i])
+ {
+ if (format[i] != '%')
+ {
+ putchar(format[i]);
+ res++;
+ }
+ else
+ {
+ dispatch(format[i + 1], ap, &res);
+ format++;
+ }
+ format++;
+ }
+ va_end(ap);
+ return res;
+}
+
+void dispatch(char c, va_list ap, int *res)
+{
+ switch (c)
+ {
+ case '%':
+ putchar('%');
+ (*res)++;
+ break;
+ case 'd':
+ handle_d(va_arg(ap, int), res);
+ break;
+ case 'u':
+ handle_u(va_arg(ap, unsigned int), res);
+ break;
+ case 'x':
+ handle_x(va_arg(ap, unsigned int), res);
+ break;
+ case 'o':
+ handle_o(va_arg(ap, unsigned int), res);
+ break;
+ case 'c':
+ putchar(va_arg(ap, int));
+ (*res)++;
+ break;
+ case 's':
+ handle_s(va_arg(ap, char *), res);
+ break;
+ default:
+ putchar('%');
+ putchar(c);
+ *res += 2;
+ break;
+ }
+}
+
+void handle_d(int val, int *res)
+{
+ if (val < 0)
+ {
+ putchar('-');
+ (*res)++;
+ val = -val;
+ }
+
+ if (val == 0)
+ {
+ putchar('0');
+ (*res)++;
+ }
+
+ int t = val;
+ int n = 0;
+ while (t > 0)
+ {
+ t /= 10;
+ n++;
+ }
+
+ char *s = malloc(n * sizeof(char));
+ int m = n;
+ if (s == NULL)
+ {
+ return;
+ }
+ n--;
+ for (; n >= 0; n--)
+ {
+ s[n] = val % 10 + '0';
+ val /= 10;
+ }
+
+ // actual printing
+ for (int i = 0; i < m; i++)
+ {
+ putchar(s[i]);
+ (*res)++;
+ }
+ free(s);
+}
+
+void handle_s(char *s, int *res)
+{
+ if (s == NULL)
+ {
+ char *text = "(null)";
+ for (; *text; text++)
+ {
+ putchar(*text);
+ (*res)++;
+ }
+ return;
+ }
+ for (; *s; s++)
+ {
+ putchar(*s);
+ (*res)++;
+ }
+}
+
+void handle_u(unsigned int val, int *res)
+{
+ if (val == 0)
+ {
+ putchar('0');
+ (*res)++;
+ }
+
+ unsigned int t = val;
+ int n = 0;
+ while (t > 0)
+ {
+ t /= 10;
+ n++;
+ }
+
+ char *s = malloc(n * sizeof(char));
+ int m = n;
+ if (s == NULL)
+ {
+ return;
+ }
+ n--;
+ for (; n >= 0; n--)
+ {
+ s[n] = val % 10 + '0';
+ val /= 10;
+ }
+
+ // actual printing
+ for (int i = 0; i < m; i++)
+ {
+ putchar(s[i]);
+ (*res)++;
+ }
+ free(s);
+}
+
+void handle_x(unsigned int val, int *res)
+{
+ if (val == 0)
+ {
+ putchar('0');
+ (*res)++;
+ }
+
+ unsigned int t = val;
+ int n = 0;
+ while (t > 0)
+ {
+ t /= 16;
+ n++;
+ }
+
+ char *s = malloc(n * sizeof(char));
+ int m = n;
+ if (s == NULL)
+ {
+ return;
+ }
+ n--;
+ for (; n >= 0; n--)
+ {
+ s[n] = val % 16 + '0';
+ if (s[n] > '9')
+ {
+ s[n] = (s[n] - '0') % 10 + 'a';
+ }
+ val /= 16;
+ }
+
+ // actual printing
+ for (int i = 0; i < m; i++)
+ {
+ putchar(s[i]);
+ (*res)++;
+ }
+ free(s);
+}
+
+void handle_o(unsigned int val, int *res)
+{
+ if (val == 0)
+ {
+ putchar('0');
+ (*res)++;
+ }
+
+ unsigned int t = val;
+ int n = 0;
+ while (t > 0)
+ {
+ t /= 8;
+ n++;
+ }
+
+ char *s = malloc(n * sizeof(char));
+ int m = n;
+ if (s == NULL)
+ {
+ return;
+ }
+ n--;
+ for (; n >= 0; n--)
+ {
+ s[n] = val % 8 + '0';
+ val /= 8;
+ }
+
+ // actual printing
+ for (int i = 0; i < m; i++)
+ {
+ putchar(s[i]);
+ (*res)++;
+ }
+ free(s);
+}
diff --git a/graphs/piscine/tinyprintf/src/tinyprintf.h b/graphs/piscine/tinyprintf/src/tinyprintf.h
new file mode 100644
index 0000000..fd1f0b4
--- /dev/null
+++ b/graphs/piscine/tinyprintf/src/tinyprintf.h
@@ -0,0 +1,15 @@
+#ifndef TINYPRINTF_H
+#define TINYPRINTF_H
+
+#include <stdarg.h>
+#include <stddef.h>
+
+int tinyprintf(const char *format, ...);
+void handle_d(int val, int *res);
+void handle_u(unsigned int val, int *res);
+void handle_x(unsigned int val, int *res);
+void handle_o(unsigned int val, int *res);
+void handle_s(char *s, int *res);
+void dispatch(char c, va_list ap, int *res);
+
+#endif /* ! TINYPRINTF_H */