1// See LICENSE for license details. 2 3#include <stdint.h> 4#include <string.h> 5#include <stdarg.h> 6#include <stdbool.h> 7 8int vsnprintf(char* out, size_t n, const char* s, va_list vl) 9{ 10 bool format = false; 11 bool longarg = false; 12 size_t pos = 0; 13 for( ; *s; s++) 14 { 15 if(format) 16 { 17 switch(*s) 18 { 19 case 'l': 20 longarg = true; 21 break; 22 case 'p': 23 longarg = true; 24 if (++pos < n) out[pos-1] = '0'; 25 if (++pos < n) out[pos-1] = 'x'; 26 case 'x': 27 { 28 long num = longarg ? va_arg(vl, long) : va_arg(vl, int); 29 for(int i = 2*(longarg ? sizeof(long) : sizeof(int))-1; i >= 0; i--) { 30 int d = (num >> (4*i)) & 0xF; 31 if (++pos < n) out[pos-1] = (d < 10 ? '0'+d : 'a'+d-10); 32 } 33 longarg = false; 34 format = false; 35 break; 36 } 37 case 'd': 38 { 39 long num = longarg ? va_arg(vl, long) : va_arg(vl, int); 40 if (num < 0) { 41 num = -num; 42 if (++pos < n) out[pos-1] = '-'; 43 } 44 long digits = 1; 45 for (long nn = num; nn /= 10; digits++) 46 ; 47 for (int i = digits-1; i >= 0; i--) { 48 if (pos + i + 1 < n) out[pos + i] = '0' + (num % 10); 49 num /= 10; 50 } 51 pos += digits; 52 longarg = false; 53 format = false; 54 break; 55 } 56 case 's': 57 { 58 const char* s2 = va_arg(vl, const char*); 59 while (*s2) { 60 if (++pos < n) 61 out[pos-1] = *s2; 62 s2++; 63 } 64 longarg = false; 65 format = false; 66 break; 67 } 68 case 'c': 69 { 70 if (++pos < n) out[pos-1] = (char)va_arg(vl,int); 71 longarg = false; 72 format = false; 73 break; 74 } 75 default: 76 break; 77 } 78 } 79 else if(*s == '%') 80 format = true; 81 else 82 if (++pos < n) out[pos-1] = *s; 83 } 84 if (pos < n) 85 out[pos] = 0; 86 else if (n) 87 out[n-1] = 0; 88 return pos; 89} 90 91int snprintf(char* out, size_t n, const char* s, ...) 92{ 93 va_list vl; 94 va_start(vl, s); 95 int res = vsnprintf(out, n, s, vl); 96 va_end(vl); 97 return res; 98} 99