aboutsummaryrefslogtreecommitdiff
path: root/util/snprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/snprintf.c')
-rw-r--r--util/snprintf.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/util/snprintf.c b/util/snprintf.c
new file mode 100644
index 0000000..1544a6c
--- /dev/null
+++ b/util/snprintf.c
@@ -0,0 +1,98 @@
+// See LICENSE for license details.
+
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+int vsnprintf(char* out, size_t n, const char* s, va_list vl)
+{
+ bool format = false;
+ bool longarg = false;
+ size_t pos = 0;
+ for( ; *s; s++)
+ {
+ if(format)
+ {
+ switch(*s)
+ {
+ case 'l':
+ longarg = true;
+ break;
+ case 'p':
+ longarg = true;
+ if (++pos < n) out[pos-1] = '0';
+ if (++pos < n) out[pos-1] = 'x';
+ case 'x':
+ {
+ long num = longarg ? va_arg(vl, long) : va_arg(vl, int);
+ for(int i = 2*(longarg ? sizeof(long) : sizeof(int))-1; i >= 0; i--) {
+ int d = (num >> (4*i)) & 0xF;
+ if (++pos < n) out[pos-1] = (d < 10 ? '0'+d : 'a'+d-10);
+ }
+ longarg = false;
+ format = false;
+ break;
+ }
+ case 'd':
+ {
+ long num = longarg ? va_arg(vl, long) : va_arg(vl, int);
+ if (num < 0) {
+ num = -num;
+ if (++pos < n) out[pos-1] = '-';
+ }
+ long digits = 1;
+ for (long nn = num; nn /= 10; digits++)
+ ;
+ for (int i = digits-1; i >= 0; i--) {
+ if (pos + i + 1 < n) out[pos + i] = '0' + (num % 10);
+ num /= 10;
+ }
+ pos += digits;
+ longarg = false;
+ format = false;
+ break;
+ }
+ case 's':
+ {
+ const char* s2 = va_arg(vl, const char*);
+ while (*s2) {
+ if (++pos < n)
+ out[pos-1] = *s2;
+ s2++;
+ }
+ longarg = false;
+ format = false;
+ break;
+ }
+ case 'c':
+ {
+ if (++pos < n) out[pos-1] = (char)va_arg(vl,int);
+ longarg = false;
+ format = false;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else if(*s == '%')
+ format = true;
+ else
+ if (++pos < n) out[pos-1] = *s;
+ }
+ if (pos < n)
+ out[pos] = 0;
+ else if (n)
+ out[n-1] = 0;
+ return pos;
+}
+
+int snprintf(char* out, size_t n, const char* s, ...)
+{
+ va_list vl;
+ va_start(vl, s);
+ int res = vsnprintf(out, n, s, vl);
+ va_end(vl);
+ return res;
+}