SayoriOS 0.3.3

sprintf.c
1 #include <stdarg.h>
2 #include "common.h"
3 #include "lib/math.h"
4 #include "mem/vmm.h"
5 #include "io/ports.h"
6 #include "drv/fpu.h"
7 #include "lib/stdlib.h"
8
9 size_t measure_vsprintf(const char *format, va_list args) {
10 ON_NULLPTR(format, {
11 qemu_log("Format is nullptr!");
12 return 0;
13 });
14
15 char* fmt = (char*)format;
16 size_t size = 0;
17
18 while (*fmt) {
19 if (*fmt == '%') {
20 size_t width = 0;
21 bool left_align = false;
22
23 bool is_precision = false;
24
25 fmt++;
26
27 if(*fmt == '.') {
28 is_precision = true;
29
30 fmt++;
31 }
32
33 if(*fmt == '-') {
34 left_align = true;
35 fmt++;
36 }
37
38 while(isdigit(*fmt)) {
39 width = width * 10 + (*fmt - '0');
40 fmt++;
41 }
42
43 if(*fmt == '*') {
44 width = va_arg(args, int);
45 fmt++;
46 }
47
48 switch (*fmt) {
49 case 's': {
50 char* arg = va_arg(args, char*);
51 arg = arg ? arg : "(nullptr)";
52
53 if(is_precision) {
54 size += width;
55 break;
56 }
57
58 int length = strlen(arg);
59
60 int space = (int)width - length;
61
62 if(space > 0)
63 size += space;
64
65 size += length;
66
67 break;
68 }
69 case 'c': {
70 (void)va_arg(args, int);
71
72 size++;
73
74 break;
75 }
76 case 'f': {
77 double a = va_arg(args, double);
78
79 if(!fpu_isInitialized()) {
80 size += 7;
81 break;
82 }
83
84 if(a < 0) {
85 a = -a;
86 size++;
87 }
88
89 if(a == NAN || a == INFINITY) {
90 size += 3;
91 break;
92 }
93
94 size_t prec = is_precision ? width : 5;
95
96 size += digit_count((int)a) + 1 + prec; // xxxx.xxxx
97
98 break;
99 }
100 case 'i':
101 case 'd': {
102 int num = va_arg(args, int);
103
104 if(num < 0) {
105 num = -num;
106 size++;
107 }
108
109 int space = width - digit_count(num);
110
111 if(left_align)
112 size += digit_count(num);
113
114 if(space > 0) {
115 size += space;
116 }
117
118 if(!left_align)
119 size += digit_count(num);
120
121 break;
122 }
123 case 'u': {
124 unsigned int num = va_arg(args, unsigned int);
125 int space = width - digit_count((int)num);
126
127 if(space > 0) {
128 size += space;
129 }
130
131 size += digit_count(num);
132 }
133 case 'p':
134 case 'x': {
135 int num = va_arg(args, int);
136 int space = width - hex_count(num) - 2;
137
138 if(space > 0) {
139 size += space;
140 }
141
142 size += hex_count(num) + 2;
143
144 break;
145 }
146 case 'v': {
147 int num = va_arg(args, int);
148 int space = width - hex_count(num);
149
150 if(left_align)
151 size += hex_count(num);
152
153 if(space > 0) {
154 size += space;
155 }
156
157 if(!left_align)
158 size += hex_count(num);
159
160 break;
161 }
162 default: {
163 size++;
164 }
165 }
166 } else {
167 size++;
168 }
169
170 fmt++;
171 }
172
173 return size + 1;
174 }
175
176 int vsprintf(char* buffer, const char *format, va_list args) {
177 char* fmt = (char*)format;
178 size_t size = measure_vsprintf(format, args);
179
180 while (*fmt) {
181 if (*fmt == '%') {
182 // NOTE: If is_precision == true, width is a precision.
183
184 size_t width = 0;
185 bool left_align = false;
186 bool is_precision = false;
187 bool zero_padding = false;
188
189 fmt++;
190
191 if(*fmt == '.') {
192 is_precision = true;
193 fmt++;
194 }
195
196 if(*fmt == '-') {
197 left_align = true;
198 fmt++;
199 }
200
201 if(*fmt == '0') {
202 zero_padding = true;
203 fmt++;
204 }
205
206 while(isdigit(*fmt)) {
207 width = width * 10 + (*fmt - '0');
208 fmt++;
209 }
210
211 if(*fmt == '*') {
212 width = va_arg(args, int);
213 fmt++;
214 }
215
216 switch (*fmt) {
217 case 's': {
218 char* arg = va_arg(args, char*);
219 arg = arg ? arg : "(nullptr)";
220
221 size_t length = strlen(arg);
222 int space = (int)width - (int)length;
223
224 if(!is_precision && left_align) {
225 memcpy(buffer, arg, length);
226
227 buffer += length;
228 }
229
230 if(!is_precision) {
231 if(space > 0) {
232 while(space--)
233 *buffer++ = ' ';
234 }
235 }
236
237 if(!is_precision && !left_align) {
238 memcpy(buffer, arg, length);
239
240 buffer += length;
241 }
242
243 if(is_precision) {
244 for(int i = 0; *arg != '\0' && i < width; i++) {
245 *buffer++ = *arg++;
246 }
247 }
248
249 break;
250 }
251
252 case 'c': {
253 *buffer++ = (char)va_arg(args, int); // Standard says that we need int instead of char
254 break;
255 }
256
257 case 'f': {
258 // FIXME: IMPLEMENT PRECISION HERE!
259
260 double a = va_arg(args, double);
261 if(!fpu_isInitialized()) {
262 memcpy(buffer, "0.00000", 7);
263
264 buffer += 7;
265 break;
266 }
267
268 if(a < 0.0) {
269 *buffer++ = '-';
270 a = -a;
271 }
272
273 // if(is_nan((float)a)) {
274 // *buffer++ = 'n';
275 // *buffer++ = 'a';
276 // *buffer++ = 'n';
277 //
278 // break;
279 // }
280 //
281 // if(is_inf((float)a)) {
282 // *buffer++ = 'i';
283 // *buffer++ = 'n';
284 // *buffer++ = 'f';
285 //
286 // break;
287 // }
288
289 double intpart;
290 double floatpart = modf(a, &intpart);
291
292 itoa((int)intpart, buffer);
293
294 buffer += digit_count((int)intpart);
295
296 *buffer++ = '.';
297
298 size_t prec = is_precision ? width : 5;
299
300 for(int i = 0; i < prec; i++) {
301 *buffer++ = '0' + (char)((int)(floatpart * pow(10.0, i + 1)) % 10);
302 }
303
304 break;
305 }
306
307 case 'i':
308 case 'd': {
309 // FIXME: IMPLEMENT PRECISION HERE!
310 int num = va_arg(args, int);
311
312 if(num < 0) {
313 num = -num;
314 *buffer++ = '-';
315 }
316
317 int space = width - digit_count(num);
318
319 if(left_align) {
320 itoa(num, buffer);
321
322 buffer += digit_count(num);
323 }
324
325 if(space > 0) {
326 if(!zero_padding)
327 while(space--)
328 *buffer++ = ' ';
329 else
330 while(space--)
331 *buffer++ = '0';
332 }
333
334 if(!left_align) {
335 itoa(num, buffer);
336
337 buffer += digit_count(num);
338 }
339
340 break;
341 }
342 case 'u': {
343 unsigned int num = va_arg(args, unsigned int);
344 int space = width - digit_count((size_t)num);
345
346 if(left_align) {
347 itou(num, buffer);
348 buffer += digit_count((size_t)num);
349 }
350
351 if(space > 0) {
352 if(!zero_padding)
353 while(space--)
354 *buffer++ = ' ';
355 else
356 while(space--)
357 *buffer++ = '0';
358 }
359
360 if(!left_align) {
361 itou(num, buffer);
362 buffer += digit_count((size_t)num);
363 }
364
365 break;
366 }
367 case 'p':
368 case 'x': {
369 // TODO: IMPLEMENT PRECISION HERE!
370
371 unsigned int num = va_arg(args, unsigned int);
372 int space = (int)width - hex_count(num) - 2;
373
374 if(left_align) {
375 *buffer++ = '0';
376 *buffer++ = 'x';
377
378 itoh(num, buffer);
379
380 buffer += hex_count(num);
381 }
382
383 if(space > 0) {
384 if(!zero_padding)
385 while(space--)
386 *buffer++ = ' ';
387 else
388 while(space--)
389 *buffer++ = '0';
390 }
391
392 if(!left_align) {
393 *buffer++ = '0';
394 *buffer++ = 'x';
395
396 itoh(num, buffer);
397
398 buffer += hex_count(num);
399 }
400
401 break;
402 }
403 case 'v': {
404 // FIXME: IMPLEMENT PRECISION HERE!
405
406 int num = va_arg(args, int);
407 int space = width - hex_count(num);
408
409 if(left_align) {
410 itoh(num, buffer);
411
412 buffer += hex_count(num);
413 }
414
415 if(space > 0) {
416 if(!zero_padding)
417 while(space--)
418 *buffer++ = ' ';
419 else
420 while(space--)
421 *buffer++ = '0';
422 }
423
424 if(!left_align) {
425 itoh(num, buffer);
426
427 buffer += hex_count(num);
428 }
429
430 break;
431 }
432 }
433 } else {
434 *buffer++ = *fmt;
435 }
436
437 fmt++;
438 }
439
440 return (int)size - 1;
441 }
442
443 size_t measure_sprintf(const char* format, ...) {
444 va_list args;
445 va_start(args, format);
446
447 size_t size = measure_vsprintf(format, args);
448
449 va_end(args);
450
451 return size;
452 }
453
454 int sprintf(char* buffer, const char* format, ...) {
455 va_list args;
456 va_start(args, format);
457
458 size_t size = (int)(measure_vsprintf(format, args)) - 1;
459
460 vsprintf(buffer, format, args);
461
462 va_end(args);
463
464 return size;
465 }
466
467 int vasprintf(char** buffer, const char* format, va_list args) {
468 size_t size = measure_vsprintf(format, args);
469
470 *buffer = kcalloc(size, 1);
471
472 vsprintf(*buffer, format, args);
473
474 return (int)size - 1;
475 }
476
477 int asprintf(char** buffer, const char* format, ...) {
478 va_list args;
479 va_start(args, format);
480
481 vasprintf(buffer, format, args);
482
483 size_t size = measure_vsprintf(format, args) - 1;
484
485 va_end(args);
486
487 return (int)size;
488 }
489
490 int vsnprintf(char* buffer, size_t n, const char* format, va_list args) {
491 size_t size = measure_vsprintf(format, args);
492
493 if(buffer == 0 || n == 0) {
494 return size;
495 }
496
497 char* temp = kcalloc(size + 1, 1);
498
499 vsprintf(temp, format, args);
500
501 memcpy(buffer, temp, (size > n ? n : size) - 1);
502
503 kfree(temp);
504
505 return size;
506 }
507
508 int snprintf(char* buffer, size_t n, const char* format, ...) {
509 va_list args;
510 va_start(args, format);
511
512 size_t res = vsnprintf(buffer, n, format, args);
513
514 va_end(args);
515
516 return res;
517 }
common.h
Основные определения ядра
fpu_isInitialized
bool fpu_isInitialized()
Возвращает статус FPU.
Definition: fpu.c:15
strlen
size_t strlen(const char *str)
Возращает длину строки
Definition: string.c:88
memcpy
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
itoa
size_t itoa(int32_t n, char *buffer)
Конвертируем число в символы
Definition: string.c:623
va_list
Definition: stdarg.h:9