AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
snprintf.c
Go to the documentation of this file.
1
9
10#include <core/system.h>
11
13static int snputc(char *s, size_t n, char c)
14{
15 if (n) {
16 *s = c;
17 return 1;
18 }
19
20 return 0;
21}
22
24static int snputs(char *s, size_t n, char *str)
25{
26 /* a NULL string is a bug, but printing it shouldn't cause another */
27 if (!str)
28 str = "(null)";
29
30 unsigned i;
31 for (i = 0; i < n && str[i]; ++i)
32 s[i] = str[i];
33 return i;
34}
35
37static int snputx(char *s, size_t n, uint32_t val)
38{
39 char *enc = "0123456789ABCDEF";
40 char buf[9];
41 buf[8] = '\0';
42 uint8_t i = 8;
43
44 while (i) {
45 buf[--i] = enc[val&0xF];
46 val >>= 4;
47 }
48
49 return snputs(s, n, buf);
50}
51
53static int snputlx(char *s, size_t n, uint64_t val)
54{
55 char *enc = "0123456789ABCDEF";
56 char buf[17];
57 buf[16] = '\0';
58 uint8_t i = 16;
59 while (i) {
60 buf[--i] = enc[val&0xF];
61 val >>= 4;
62 }
63 return snputs(s, n, buf);
64}
65
67static int snputud(char *s, size_t n, uint32_t val)
68{
69 char buf[11];
70 buf[10] = '\0';
71
72 if (!val)
73 return snputc(s, n, '0');
74
75 uint8_t i = 10;
76
77 while (val) {
78 buf[--i] = val%10 + '0';
79 val = (val-val%10)/10;
80 }
81
82 return snputs(s, n, buf+i);
83}
84
86static int snputul(char *s, size_t n, uint64_t val)
87{
88 char buf[21];
89 buf[20] = '\0';
90 uint8_t i = 20;
91
92 if (!val)
93 return snputc(s, n, '0');
94
95 while (val) {
96 buf[--i] = val%10 + '0';
97 val = (val-val%10)/10;
98 }
99
100 return snputs(s, n, buf+i);
101}
102
104static int snputb(char *s, size_t n, uint8_t val)
105{
106 char buf[9];
107 buf[8] = '\0';
108 uint8_t i = 8;
109
110 while (i) {
111 buf[--i] = '0' + (val & 1);
112 val >>= 1;
113 }
114
115 return snputs(s, n, buf);
116}
117
128int vsnprintf(char *s, size_t n, const char *fmt, va_list args)
129{
130 if (!n)
131 return 0;
132
133 /* keep room for the NUL at the end */
134 n -= 1;
135
136 size_t ret = 0;
137
138 while (*fmt) {
139 switch (*fmt) {
140 case '%':
141 ++fmt;
142 switch (*fmt) {
143 case 'c': /* a character */
144 ret += snputc(s + ret, n - ret, (char)va_arg(args, int));
145 break;
146 case 's': /* a string */
147 ret += snputs(s + ret, n - ret, (char*)va_arg(args, char*));
148 break;
149 case 'd': /* a signed decimal */
150 {
151 int32_t val = va_arg(args, int32_t);
152 if (val < 0) {
153 ret += snputc(s + ret, n - ret, '-');
154 ret += snputud(s + ret, n - ret, -(uint32_t) val);
155 } else {
156 ret += snputud(s + ret, n - ret, (uint32_t) val);
157 }
158 }
159 break;
160 case 'u': /* an unsigned decimal */
161 ret += snputud(s + ret, n - ret, (uint32_t)va_arg(args, uint32_t));
162 break;
163 case 'l': /* a 64-bit number */
164 switch (*++fmt) {
165 case 'x': /* in hexadecimal */
166 ret += snputlx(s + ret, n - ret, (uint64_t)va_arg(args, uint64_t));
167 break;
168 case 'd': /* a signed decimal */
169 {
170 int64_t val = va_arg(args, int64_t);
171 if (val < 0) {
172 ret += snputc(s + ret, n - ret, '-');
173 ret += snputul(s + ret, n - ret, -(uint64_t) val);
174 } else {
175 ret += snputul(s + ret, n - ret, (uint64_t) val);
176 }
177 }
178 break;
179 case 'u': /* an unsigned decimal */
180 ret += snputul(s + ret, n - ret, (uint64_t)va_arg(args, uint64_t));
181 break;
182 default:
183 ret += snputc(s + ret, n - ret, *--fmt);
184 }
185 break;
186 case 'p': /* a pointer */
187 ret += snputs(s + ret, n - ret, "0x");
188#if ARCH_BITS==32
189 ret += snputx(s + ret, n - ret, (uint32_t)va_arg(args, uint32_t));
190#else
191 ret += snputlx(s + ret, n - ret, (uint64_t)va_arg(args, uint64_t));
192#endif
193 break;
194
195 case 'b': /* a byte in binary */
196 ret += snputb(s + ret, n - ret, (uint8_t)(uint32_t)va_arg(args, uint32_t));
197 break;
198 case 'x': /* hexadecimal */
199 ret += snputx(s + ret, n - ret, (uint32_t)va_arg(args, uint32_t));
200 break;
201 default:
202 ret += snputc(s + ret, n - ret, *(--fmt));
203 }
204 ++fmt;
205 break;
206 default:
207 ret += snputc(s + ret, n - ret, *fmt);
208 ++fmt;
209 }
210 }
211
212 s[ret] = '\0';
213
214 return ret;
215}
216
226int snprintf(char *s, size_t n, const char *fmt, ...)
227{
228 va_list args;
229 va_start(args, fmt);
230 int ret = vsnprintf(s, n, fmt, args);
231 va_end(args);
232 return ret;
233}
int snprintf(char *s, size_t n, const char *fmt,...)
Formats a string into a buffer.
Definition snprintf.c:226
static int snputs(char *s, size_t n, char *str)
Writes a string, as much of it as fits.
Definition snprintf.c:24
static int snputlx(char *s, size_t n, uint64_t val)
Writes a 64-bit number in hexadecimal, all 16 digits.
Definition snprintf.c:53
static int snputul(char *s, size_t n, uint64_t val)
Writes an unsigned 64-bit number in decimal.
Definition snprintf.c:86
static int snputx(char *s, size_t n, uint32_t val)
Writes a 32-bit number in hexadecimal, all 8 digits.
Definition snprintf.c:37
int vsnprintf(char *s, size_t n, const char *fmt, va_list args)
Formats a string into a buffer, with its arguments in a va_list.
Definition snprintf.c:128
static int snputud(char *s, size_t n, uint32_t val)
Writes an unsigned 32-bit number in decimal.
Definition snprintf.c:67
static int snputb(char *s, size_t n, uint8_t val)
Writes a byte in binary, all 8 digits.
Definition snprintf.c:104
static int snputc(char *s, size_t n, char c)
Writes one character, if there is room.
Definition snprintf.c:13
#define va_list
Definition stdarg.h:6
#define va_end(v)
Definition stdarg.h:8
#define va_arg(v, l)
Definition stdarg.h:9
#define va_start(v, l)
Definition stdarg.h:7
unsigned int uint32_t
Definition stddef.h:22
signed long long int int64_t
Definition stddef.h:19
signed int int32_t
Definition stddef.h:18
unsigned char uint8_t
Definition stddef.h:20
unsigned long long int uint64_t
Definition stddef.h:23