XWOS API  4.0
XWOS C/C++ API参考手册
载入中...
搜索中...
未找到
xwspf.c
浏览该文件的文档.
1
13#include <xwos/standard.h>
14#include <string.h>
15#include <ctype.h>
16#include <stddef.h>
17#include <math.h>
18#include <float.h>
19#include <xwos/lib/div64.h>
20
21#define XWVSNPF_F_ZEROPAD 0x01
22#define XWVSNPF_F_SIGN 0x02
23#define XWVSNPF_F_PLUS 0x04
24#define XWVSNPF_F_SPACE 0x08
25#define XWVSNPF_F_LEFT 0x10
26#define XWVSNPF_F_SMALL 0x20
27#define XWVSNPF_F_SPECIAL 0x40
30 XWVSNPF_FT_NONE, /* a string part */
49#if defined(XWLIBCFG_SPF_FLOAT) && (1U == XWLIBCFG_SPF_FLOAT)
50 XWVSNPF_FT_FLOAT,
51 XWVSNPF_FT_FLOAT_SCI,
52# if defined(XWLIBCFG_SPF_LONG_DOUBLE) && (1U == XWLIBCFG_SPF_LONG_DOUBLE)
53 XWVSNPF_FT_LONG_DOUBLE,
54 XWVSNPF_FT_LONG_DOUBLE_SCI,
55# endif /* XWLIBCFG_SPF_LONG_DOUBLE */
56#endif /* XWLIBCFG_SPF_FLOAT */
57};
58
60 xwu8_t type; /* format_type enum */
61 xwu8_t flags; /* flags to number() */
62 xwu8_t base; /* number base, 8, 10 or 16 only */
63 xwu8_t qualifier; /* number qualifier, one of 'hHlLtzZ' */
64 xws16_t field_width; /* width of output field */
65 xws16_t precision; /* # of digits/chars */
66};
67
68static const char xwvsnpf_digits[] = "0123456789ABCDEF";
69static const char xwvsnpf_nullstr[] = "(null)";
70
71static inline
72int xwvsnpf_skip_atoi(const char ** s)
73{
74 int i = 0;
75
76 while (isdigit((int)(**s))) {
77 i = i * 10 + **s - '0';
78 (*s)++;
79 }
80 return i;
81}
82
83static inline
84char * xwvsnpf_put_dec_trunc(char * buf, unsigned int q)
85{
86 unsigned int d3, d2, d1, d0;
87
88 d1 = (q >> 4) & 0xf;
89 d2 = (q >> 8) & 0xf;
90 d3 = (q >> 12);
91
92 d0 = 6 * (d3 + d2 + d1) + (q & 0xf);
93 q = (d0 * 0xcd) >> 11;
94 d0 = d0 - 10 * q;
95 *buf++ = (char)d0 + '0';
96
97 d1 = q + 9 * d3 + 5 * d2 + d1;
98 if (d1 != 0) {
99 q = (d1 * 0xcd) >> 11;
100 d1 = d1 - 10 * q;
101 *buf++ = (char)d1 + '0'; /* next digit */
102
103 d2 = q + 2 * d2;
104 if ((d2 != 0) || (d3 != 0)) {
105 q = (d2 * 0xd) >> 7;
106 d2 = d2 - 10 * q;
107 *buf++ = (char)d2 + '0'; /* next digit */
108
109 d3 = q + 4 * d3;
110 if (d3 != 0) {
111 q = (d3 * 0xcd) >> 11;
112 d3 = d3 - 10 * q;
113 *buf++ = (char)d3 + '0'; /* next digit */
114 if (q != 0) {
115 *buf++ = (char)q + '0'; /* most sign. digit */
116 }
117 }
118 }
119 }
120 return buf;
121}
122
123static inline
124char * xwvsnpf_put_dec_full(char * buf, unsigned int q)
125{
126 unsigned int d3, d2, d1, d0;
127
128 d1 = (q >> 4) & 0xf;
129 d2 = (q >> 8) & 0xf;
130 d3 = (q >> 12);
131
132 d0 = 6 * (d3 + d2 + d1) + (q & 0xf);
133 q = (d0 * 0xcd) >> 11;
134 d0 = d0 - 10 * q;
135 *buf++ = (char)d0 + '0';
136
137 d1 = q + 9 * d3 + 5 * d2 + d1;
138 q = (d1 * 0xcd) >> 11;
139 d1 = d1 - 10 * q;
140 *buf++ = (char)d1 + '0';
141
142 d2 = q + 2 * d2;
143 q = (d2 * 0xd) >> 7;
144 d2 = d2 - 10 * q;
145 *buf++ = (char)d2 + '0';
146
147 d3 = q + 4 * d3;
148 q = (d3 * 0xcd) >> 11; /* - shorter code */
149 /* q = (d3 * 0x67) >> 10; - would also work */
150 d3 = d3 - 10 * q;
151 *buf++ = (char)d3 + '0';
152 *buf++ = (char)q + '0';
153
154 return buf;
155}
156
157static inline
158char * xwvsnpf_put_dec(char * buf, unsigned long long num)
159{
160 while (true) {
161 unsigned int rem;
162 if (num < 100000) {
163 return xwvsnpf_put_dec_trunc(buf, (unsigned int)num);
164 }
165 rem = xwdiv64((xwu64_t *)&num, 100000);
166 buf = xwvsnpf_put_dec_full(buf, rem);
167 }
168}
169
170static inline
171char * xwvsnpf_format_number(char * buf, char * end,
172 xwu64_t num,
173 struct xwvsnpf_format_spec spec)
174{
175 char tmp[66];
176 char sign;
177 char locase;
178 int need_pfx = ((spec.flags & XWVSNPF_F_SPECIAL) && spec.base != 10);
179 int i;
180 bool is_zero = num == 0LL;
181
182 locase = (char)(spec.flags & XWVSNPF_F_SMALL);
183 if (spec.flags & XWVSNPF_F_LEFT) {
184 spec.flags &= (xwu8_t)(~XWVSNPF_F_ZEROPAD);
185 }
186 sign = 0;
187 if (spec.flags & XWVSNPF_F_SIGN) {
188 if ((signed long long)num < 0) {
189 sign = '-';
190 num = (unsigned long long)(-(signed long long)num);
191 spec.field_width--;
192 } else if (spec.flags & XWVSNPF_F_PLUS) {
193 sign = '+';
194 spec.field_width--;
195 } else if (spec.flags & XWVSNPF_F_SPACE) {
196 sign = ' ';
197 spec.field_width--;
198 } else {}
199 }
200 if (need_pfx) {
201 if (16 == spec.base || 2 == spec.base) {
202 spec.field_width -= 2;
203 } else if (!is_zero) {
204 spec.field_width--;
205 } else {}
206 }
207
208 /* generate full string in tmp[], in reverse order */
209 i = 0;
210 if (num < spec.base) {
211 tmp[i++] = xwvsnpf_digits[num] | locase;
212 /* Generic code, for any base:
213 } else {
214 do {
215 tmp[i++] = (xwvsnpf_digits[xwdiv64(&num, base)] | locase);
216 } while (num != 0);
217 */
218 } else if (spec.base != 10) { /* 2, 8 or 16 */
219 int mask = spec.base - 1;
220 int shift = 3;
221
222 if (spec.base == 16) {
223 shift = 4;
224 } else if (spec.base == 2) {
225 shift = 1;
226 }
227 do {
228 tmp[i++] = (xwvsnpf_digits[((char)num) & mask] |
229 locase);
230 num >>= shift;
231 } while (num);
232 } else { /* base 10 */
233 i = xwvsnpf_put_dec(tmp, num) - tmp;
234 }
235
236 /* printing 100 using %2d gives "100", not "00" */
237 if (i > spec.precision) {
238 spec.precision = (xws16_t)i;
239 }
240 /* leading space padding */
241 spec.field_width -= spec.precision;
242 if (!(spec.flags & (XWVSNPF_F_ZEROPAD + XWVSNPF_F_LEFT))) {
243 while (--spec.field_width >= 0) {
244 if (buf < end) {
245 *buf = ' ';
246 }
247 buf++;
248 }
249 }
250 /* sign */
251 if (sign) {
252 if (buf < end) {
253 *buf = sign;
254 }
255 buf++;
256 }
257 /* "0x" / "0b" / "0" prefix */
258 if (need_pfx) {
259 if (spec.base == 16 || spec.base == 2 || !is_zero) {
260 if (buf < end) {
261 *buf = '0';
262 }
263 buf++;
264 }
265 if (spec.base == 16) {
266 if (buf < end) {
267 *buf = ('X' | locase);
268 }
269 buf++;
270 } else if (spec.base == 2) {
271 if (buf < end) {
272 *buf = ('B' | locase);
273 }
274 buf++;
275 }
276 }
277 /* zero or space padding */
278 if (!(spec.flags & XWVSNPF_F_LEFT)) {
279 char c = (spec.flags & XWVSNPF_F_ZEROPAD) ? '0' : ' ';
280 while (--spec.field_width >= 0) {
281 if (buf < end) {
282 *buf = c;
283 }
284 buf++;
285 }
286 }
287 /* hmm even more zero padding? */
288 while (i <= --spec.precision) {
289 if (buf < end) {
290 *buf = '0';
291 }
292 buf++;
293 }
294 /* actual xwvsnpf_digits of result */
295 while (--i >= 0) {
296 if (buf < end) {
297 *buf = tmp[i];
298 }
299 buf++;
300 }
301 /* trailing space padding */
302 while (--spec.field_width >= 0) {
303 if (buf < end) {
304 *buf = ' ';
305 }
306 buf++ ;
307 }
308
309 return buf;
310}
311
312static inline
313void xwvsnpf_format_move_right(char * buf, char * end, xwssz_t len, xwssz_t spaces)
314{
315 xwssz_t size;
316
317 if (buf >= end) {
318 goto end;
319 }
320 size = (xwssz_t)((xwptr_t)end - (xwptr_t)buf);
321 if (size <= spaces) {
322 memset(buf, ' ', (xwsz_t)size);
323 goto end;
324 }
325 if (len > 0) {
326 if (len > size - spaces) {
327 len = size - spaces;
328 }
329 memmove(buf + spaces, buf, (xwsz_t)len);
330 }
331 memset(buf, ' ', (xwsz_t)spaces);
332end:
333 return;
334}
335
336static inline
337char * xwvsnpf_format_widen_string(char * buf, xwssz_t n, char * end,
338 struct xwvsnpf_format_spec spec)
339{
340 xwssz_t spaces;
341
342 if (n >= (xwssz_t)spec.field_width) {
343 return buf;
344 }
345 spaces = (xwssz_t)spec.field_width - n;
346 if (0 == (spec.flags & XWVSNPF_F_LEFT)) {
347 xwvsnpf_format_move_right(buf - n, end, n, spaces);
348 return buf + spaces;
349 }
350 while (spaces > 0) {
351 spaces--;
352 if (buf < end) {
353 *buf = ' ';
354 }
355 buf++;
356 }
357 return buf;
358}
359
360static inline
361char * xwvsnpf_format_string_nocheck(char * buf, char * end,
362 const char * s,
363 struct xwvsnpf_format_spec spec)
364{
365 xwssz_t len = 0;
366 xwssz_t limit = spec.precision;
367
368 while (limit) {
369 char c = *s;
370 s++;
371 if (0 == c) {
372 break;
373 }
374 if (buf < end) {
375 *buf = c;
376 }
377 buf++;
378 len++;
379 limit--;
380 }
381 return xwvsnpf_format_widen_string(buf, len, end, spec);
382}
383
384static inline
385char * xwvsnpf_format_string(char * buf, char * end, const char * s,
386 struct xwvsnpf_format_spec spec)
387{
388
389 if (NULL == s) {
390 s = xwvsnpf_nullstr;
391 if (spec.precision == -1) {
392 spec.precision = 2 * sizeof(void *);
393 }
394 }
395 return xwvsnpf_format_string_nocheck(buf, end, s, spec);
396}
397
398static inline
399char * xwvsnpf_format_pointer(const char * fmt, char * buf, char * end, void * ptr,
400 struct xwvsnpf_format_spec spec)
401{
402 int default_width;
403
404 (void)fmt;
405 default_width = (int)(2 * sizeof(void *) +
406 (spec.flags & XWVSNPF_F_SPECIAL ? 2 : 0));
407 spec.flags |= XWVSNPF_F_SMALL;
408 if (spec.field_width == -1) {
409 spec.field_width = (xws16_t)default_width;
410 spec.flags |= XWVSNPF_F_ZEROPAD;
411 }
412 spec.base = 16;
413
414 return xwvsnpf_format_number(buf, end, (xwptr_t)ptr, spec);
415}
416
417#if defined(XWLIBCFG_SPF_FLOAT) && (1U == XWLIBCFG_SPF_FLOAT)
418static inline
419char * xwvsnpf_put_float_decimal(char * buf, char * end, unsigned long long num, int digits)
420{
421 char tmp[30];
422 int i = 0;
423 int j;
424
425 if (num == 0) {
426 tmp[i++] = '0';
427 } else {
428 while (num > 0 && i < 29) {
429 tmp[i++] = (char)('0' + (num % 10));
430 num = num / 10;
431 }
432 }
433
434 while (i < digits && i < 29) {
435 tmp[i++] = '0';
436 }
437
438 for (j = i - 1; j >= 0; j--) {
439 if (buf < end) {
440 *buf = tmp[j];
441 }
442 buf++;
443 }
444 return buf;
445}
446
447static inline
448char * xwvsnpf_format_float(char * buf, char * end, double num,
449 struct xwvsnpf_format_spec spec)
450{
451 char tmp[100];
452 char * p = tmp;
453 char sign = 0;
454 int precision = (spec.precision == -1) ? 6 : spec.precision;
455 int is_sci = (spec.type == XWVSNPF_FT_FLOAT_SCI);
456 int exp = 0;
457 unsigned long long int_part = 0;
458 unsigned long long frac_part = 0;
459 double abs_num;
460 int i, len;
461 int need_sign = 0;
462 char exp_char = (spec.flags & XWVSNPF_F_SMALL) ? 'e' : 'E';
463
464 if (isnan(num)) {
465 if (buf < end) *buf++ = 'n';
466 if (buf < end) *buf++ = 'a';
467 if (buf < end) *buf++ = 'n';
468 return buf;
469 }
470
471 if (isinf(num)) {
472 if (num < 0) {
473 if (buf < end) *buf++ = '-';
474 }
475 if (buf < end) *buf++ = 'i';
476 if (buf < end) *buf++ = 'n';
477 if (buf < end) *buf++ = 'f';
478 return buf;
479 }
480
481 if (num < 0) {
482 sign = '-';
483 abs_num = -num;
484 } else {
485 if (spec.flags & XWVSNPF_F_PLUS) {
486 sign = '+';
487 } else if (spec.flags & XWVSNPF_F_SPACE) {
488 sign = ' ';
489 }
490 abs_num = num;
491 }
492
493 if (sign) {
494 need_sign = 1;
495 }
496
497 if (is_sci) {
498 if (abs_num == 0.0) {
499 exp = 0;
500 } else if (abs_num >= 1.0) {
501 while (abs_num >= 10.0) {
502 abs_num /= 10.0;
503 exp++;
504 }
505 } else {
506 while (abs_num < 1.0) {
507 abs_num *= 10.0;
508 exp--;
509 }
510 }
511 }
512
513 int_part = (unsigned long long)abs_num;
514 double frac = abs_num - (double)int_part;
515 double mult = 1.0;
516 for (i = 0; i < precision; i++) {
517 mult *= 10.0;
518 }
519 frac_part = (unsigned long long)(frac * mult + 0.5);
520
521 if (frac_part >= (unsigned long long)mult) {
522 frac_part -= (unsigned long long)mult;
523 int_part++;
524 }
525
526 p = xwvsnpf_put_float_decimal(p, tmp + 99, int_part, 1);
527
528 if (precision > 0 || (spec.flags & XWVSNPF_F_SPECIAL)) {
529 *p++ = '.';
530 p = xwvsnpf_put_float_decimal(p, tmp + 99, frac_part, precision);
531 }
532
533 if (is_sci) {
534 *p++ = exp_char;
535 if (exp >= 0) {
536 *p++ = '+';
537 } else {
538 *p++ = '-';
539 exp = -exp;
540 }
541 if (exp < 10) {
542 *p++ = '0';
543 }
544 p = xwvsnpf_put_float_decimal(p, tmp + 99, (unsigned long long)exp, 1);
545 }
546
547 len = (int)(p - tmp);
548 int total_width = (spec.field_width != -1) ? spec.field_width : 0;
549 int pad_len = (total_width > len + need_sign) ? (total_width - len - need_sign) : 0;
550
551 if (!(spec.flags & XWVSNPF_F_LEFT) && pad_len > 0) {
552 char pad_char = (spec.flags & XWVSNPF_F_ZEROPAD) ? '0' : ' ';
553 if (pad_char == '0' && sign) {
554 if (buf < end) *buf++ = sign;
555 sign = 0;
556 need_sign = 0;
557 }
558 for (i = 0; i < pad_len; i++) {
559 if (buf < end) *buf++ = pad_char;
560 }
561 }
562
563 if (sign) {
564 if (buf < end) *buf++ = sign;
565 }
566
567 for (i = 0; i < len; i++) {
568 if (buf < end) *buf++ = tmp[i];
569 }
570
571 if ((spec.flags & XWVSNPF_F_LEFT) && pad_len > 0) {
572 for (i = 0; i < pad_len; i++) {
573 if (buf < end) *buf++ = ' ';
574 }
575 }
576
577 return buf;
578}
579
580# if defined(XWLIBCFG_SPF_LONG_DOUBLE) && (1U == XWLIBCFG_SPF_LONG_DOUBLE)
581static inline
582char * xwvsnpf_format_long_double(char * buf, char * end, long double num,
583 struct xwvsnpf_format_spec spec)
584{
585 char tmp[100];
586 char *p = tmp;
587 char sign = 0;
588 int precision = (spec.precision == -1) ? 6 : spec.precision;
589 int is_sci = (spec.type == XWVSNPF_FT_LONG_DOUBLE_SCI);
590 int exp = 0;
591 unsigned long long int_part = 0;
592 unsigned long long frac_part = 0;
593 long double abs_num;
594 int i, len;
595 int need_sign = 0;
596 char exp_char = (spec.flags & XWVSNPF_F_SMALL) ? 'e' : 'E';
597
598 if (isnan(num)) {
599 if (buf < end) *buf++ = 'n';
600 if (buf < end) *buf++ = 'a';
601 if (buf < end) *buf++ = 'n';
602 return buf;
603 }
604
605 if (isinf(num)) {
606 if (num < 0) {
607 if (buf < end) *buf++ = '-';
608 }
609 if (buf < end) *buf++ = 'i';
610 if (buf < end) *buf++ = 'n';
611 if (buf < end) *buf++ = 'f';
612 return buf;
613 }
614
615 if (num < 0) {
616 sign = '-';
617 abs_num = -num;
618 } else {
619 if (spec.flags & XWVSNPF_F_PLUS) {
620 sign = '+';
621 } else if (spec.flags & XWVSNPF_F_SPACE) {
622 sign = ' ';
623 }
624 abs_num = num;
625 }
626
627 if (sign) {
628 need_sign = 1;
629 }
630
631 if (is_sci) {
632 if (abs_num == 0.0L) {
633 exp = 0;
634 } else if (abs_num >= 1.0L) {
635 while (abs_num >= 10.0L) {
636 abs_num /= 10.0L;
637 exp++;
638 }
639 } else {
640 while (abs_num < 1.0L) {
641 abs_num *= 10.0L;
642 exp--;
643 }
644 }
645 }
646
647 int_part = (unsigned long long)abs_num;
648 long double frac = abs_num - (long double)int_part;
649 long double mult = 1.0L;
650 for (i = 0; i < precision; i++) {
651 mult *= 10.0L;
652 }
653 frac_part = (unsigned long long)(frac * mult + 0.5L);
654
655 if (frac_part >= (unsigned long long)mult) {
656 frac_part -= (unsigned long long)mult;
657 int_part++;
658 }
659
660 p = xwvsnpf_put_float_decimal(p, tmp + 99, int_part, 1);
661
662 if (precision > 0 || (spec.flags & XWVSNPF_F_SPECIAL)) {
663 *p++ = '.';
664 p = xwvsnpf_put_float_decimal(p, tmp + 99, frac_part, precision);
665 }
666
667 if (is_sci) {
668 *p++ = exp_char;
669 if (exp >= 0) {
670 *p++ = '+';
671 } else {
672 *p++ = '-';
673 exp = -exp;
674 }
675 if (exp < 10) {
676 *p++ = '0';
677 }
678 p = xwvsnpf_put_float_decimal(p, tmp + 99, (unsigned long long)exp, 1);
679 }
680
681 len = (int)(p - tmp);
682 int total_width = (spec.field_width != -1) ? spec.field_width : 0;
683 int pad_len = (total_width > len + need_sign) ? (total_width - len - need_sign) : 0;
684
685 if (!(spec.flags & XWVSNPF_F_LEFT) && pad_len > 0) {
686 char pad_char = (spec.flags & XWVSNPF_F_ZEROPAD) ? '0' : ' ';
687 if (pad_char == '0' && sign) {
688 if (buf < end) *buf++ = sign;
689 sign = 0;
690 need_sign = 0;
691 }
692 for (i = 0; i < pad_len; i++) {
693 if (buf < end) *buf++ = pad_char;
694 }
695 }
696
697 if (sign) {
698 if (buf < end) *buf++ = sign;
699 }
700
701 for (i = 0; i < len; i++) {
702 if (buf < end) *buf++ = tmp[i];
703 }
704
705 if ((spec.flags & XWVSNPF_F_LEFT) && pad_len > 0) {
706 for (i = 0; i < pad_len; i++) {
707 if (buf < end) *buf++ = ' ';
708 }
709 }
710
711 return buf;
712}
713# endif /* XWLIBCFG_SPF_LONG_DOUBLE */
714#endif /* XWLIBCFG_SPF_FLOAT */
715
716static inline
717int xwvsnpf_format_decode(const char * fmt,
718 struct xwvsnpf_format_spec * spec)
719{
720 const char * start = fmt;
721
722 /* we finished early by reading the field width */
723 if (spec->type == XWVSNPF_FT_WIDTH) {
724 if (spec->field_width < 0) {
725 spec->field_width = -spec->field_width;
726 spec->flags |= XWVSNPF_F_LEFT;
727 }
728 spec->type = XWVSNPF_FT_NONE;
729 goto precision;
730 }
731
732 /* we finished early by reading the precision */
733 if (spec->type == XWVSNPF_FT_PRECISION) {
734 if (spec->precision < 0) {
735 spec->precision = 0;
736 }
737 spec->type = XWVSNPF_FT_NONE;
738 goto qualifier;
739 }
740
741 /* By default */
742 spec->type = XWVSNPF_FT_NONE;
743 for (; *fmt ; fmt++) {
744 if ('%' == *fmt) {
745 break;
746 }
747 }
748
749 /* Return the current non-format string */
750 if ((fmt != start) || !(*fmt)) {
751 return fmt - start;
752 }
753
754 /* Process flags */
755 spec->flags = 0;
756 while (true) {
757 bool found = true;
758 fmt++;
759 switch (*fmt) {
760 case '-':
761 spec->flags |= XWVSNPF_F_LEFT;
762 break;
763 case '+':
764 spec->flags |= XWVSNPF_F_PLUS;
765 break;
766 case ' ':
767 spec->flags |= XWVSNPF_F_SPACE;
768 break;
769 case '#':
770 spec->flags |= XWVSNPF_F_SPECIAL;
771 break;
772 case '0':
773 spec->flags |= XWVSNPF_F_ZEROPAD;
774 break;
775 default:
776 found = false;
777 break;
778 }
779
780 if (!found) {
781 break;
782 }
783 }
784
785 /* get field width */
786 spec->field_width = -1;
787 if (isdigit((int)(*fmt))) {
789 } else if ('*' == *fmt) {
790 /* The next argument */
791 spec->type = XWVSNPF_FT_WIDTH;
792 fmt++;
793 return fmt - start;
794 } else {}
795
796precision:
797 /* get the precision */
798 spec->precision = -1;
799 if ('.' == (*fmt)) {
800 fmt++;
801 if (isdigit((int)(*fmt))) {
802 spec->precision = (xws16_t)xwvsnpf_skip_atoi(&fmt);
803 if (spec->precision < 0) {
804 spec->precision = 0;
805 }
806 } else if (*fmt == '*') {
807 /* it's the next argument */
809 fmt++;
810 return fmt - start;
811 } else {}
812 }
813
814qualifier:
815 /* get the conversion qualifier */
816 spec->qualifier = 0;
817 if (('h' == *fmt) || ('l' == *fmt) || ('L' == *fmt) ||
818 ('z' == *fmt) || ('Z' == *fmt) || ('t' == *fmt)) {
819 spec->qualifier = *fmt++;
820 if (spec->qualifier == *fmt) {
821 if ('l' == spec->qualifier) {
822 spec->qualifier = 'L';
823 fmt++;
824 } else if ('h' == spec->qualifier) {
825 spec->qualifier = 'H';
826 fmt++;
827 }
828 }
829 }
830
831 /* default base */
832 spec->base = 10;
833 switch (*fmt) {
834 case 'c':
835 spec->type = XWVSNPF_FT_CHAR;
836 fmt++;
837 return fmt - start;
838
839 case 's':
840 spec->type = XWVSNPF_FT_STR;
841 fmt++;
842 return fmt - start;
843
844 case 'p':
845 spec->type = XWVSNPF_FT_PTR;
846 return fmt - start;
847 /* skip alnum */
848
849 case '%':
851 fmt++;
852 return fmt - start;
853
854 case 'o':
855 spec->base = 8;
856 break;
857
858 case 'b':
859 spec->flags |= XWVSNPF_F_SMALL;
860 spec->base = 2;
861 break;
862
863 case 'B':
864 spec->base = 2;
865 break;
866
867 case 'x':
868 spec->flags |= XWVSNPF_F_SMALL;
869 spec->base = 16;
870 break;
871
872 case 'X':
873 spec->base = 16;
874 break;
875
876#if defined(XWLIBCFG_SPF_FLOAT) && (1U == XWLIBCFG_SPF_FLOAT)
877 case 'f':
878# if defined(XWLIBCFG_SPF_LONG_DOUBLE) && (1U == XWLIBCFG_SPF_LONG_DOUBLE)
879 if ('L' == spec->qualifier) {
880 spec->type = XWVSNPF_FT_LONG_DOUBLE;
881 } else {
882 spec->type = XWVSNPF_FT_FLOAT;
883 }
884# else
885 spec->type = XWVSNPF_FT_FLOAT;
886# endif
887 fmt++;
888 return fmt - start;
889
890 case 'e':
891 spec->flags |= XWVSNPF_F_SMALL;
892# if defined(XWLIBCFG_SPF_LONG_DOUBLE) && (1U == XWLIBCFG_SPF_LONG_DOUBLE)
893 if ('L' == spec->qualifier) {
894 spec->type = XWVSNPF_FT_LONG_DOUBLE_SCI;
895 } else {
896 spec->type = XWVSNPF_FT_FLOAT_SCI;
897 }
898# else
899 spec->type = XWVSNPF_FT_FLOAT_SCI;
900# endif
901 fmt++;
902 return fmt - start;
903
904 case 'E':
905# if defined(XWLIBCFG_SPF_LONG_DOUBLE) && (1U == XWLIBCFG_SPF_LONG_DOUBLE)
906 if ('L' == spec->qualifier) {
907 spec->type = XWVSNPF_FT_LONG_DOUBLE_SCI;
908 } else {
909 spec->type = XWVSNPF_FT_FLOAT_SCI;
910 }
911# else
912 spec->type = XWVSNPF_FT_FLOAT_SCI;
913# endif
914 fmt++;
915 return fmt - start;
916#endif /* XWLIBCFG_SPF_FLOAT */
917
918 case 'd':
919 case 'i':
920 spec->flags |= XWVSNPF_F_SIGN;
921 break;
922 case 'u':
923 break;
924
925 default:
926 spec->type = XWVSNPF_FT_INVALID;
927 return fmt - start;
928 }
929
930 if ('L' == spec->qualifier) {
932 } else if ('l' == spec->qualifier) {
933 if (spec->flags & XWVSNPF_F_SIGN) {
934 spec->type = XWVSNPF_FT_LONG;
935 } else {
936 spec->type = XWVSNPF_FT_ULONG;
937 }
938 } else if (('z' == spec->qualifier) || ('Z' == spec->qualifier)) {
939 spec->type = XWVSNPF_FT_XWSZ_T;
940 } else if ('t' == spec->qualifier) {
941 spec->type = XWVSNPF_FT_PTRDIFF;
942 } else if ('H' == spec->qualifier) {
943 if (spec->flags & XWVSNPF_F_SIGN) {
944 spec->type = XWVSNPF_FT_BYTE;
945 } else {
946 spec->type = XWVSNPF_FT_UBYTE;
947 }
948 } else if ('h' == spec->qualifier) {
949 if (spec->flags & XWVSNPF_F_SIGN) {
950 spec->type = XWVSNPF_FT_SHORT;
951 } else {
952 spec->type = XWVSNPF_FT_USHORT;
953 }
954 } else {
955 if (spec->flags & XWVSNPF_F_SIGN) {
956 spec->type = XWVSNPF_FT_INT;
957 } else {
958 spec->type = XWVSNPF_FT_UINT;
959 }
960 }
961 fmt++;
962 return fmt - start;
963}
964
965int xwvsnpf(char * buf, xwsz_t size, const char * fmt, va_list args)
966{
967 int rc;
968 xwu64_t num;
969 char * str, * end;
970 struct xwvsnpf_format_spec spec = {0};
971
972 if (size > XWSSZ_MAX) {
973 /* Reject out-of-range values early. */
974 rc = 0;
975 goto err_oor;
976 }
977
978 str = buf;
979 end = buf + size;
980
981 /* Make sure end is always >= buf */
982 if (end < buf) {
983 end = ((void *)-1);
984 size = (xwsz_t)(end - buf);
985 }
986
987 while (*fmt) {
988 const char * oldfmt = fmt;
989 int read = xwvsnpf_format_decode(fmt, &spec);
990 fmt += read;
991 switch (spec.type) {
992 case XWVSNPF_FT_NONE: {
993 int copy = read;
994 if (str < end) {
995 if (copy > end - str) {
996 copy = end - str;
997 }
998 memcpy(str, oldfmt, (xwsz_t)copy);
999 }
1000 str += read;
1001 break;
1002 }
1003
1004 case XWVSNPF_FT_WIDTH:
1005 spec.field_width = (xws16_t)va_arg(args, int);
1006 break;
1007
1009 spec.precision = (xws16_t)va_arg(args, int);
1010 break;
1011
1012 case XWVSNPF_FT_CHAR: {
1013 char c;
1014
1015 if (!(spec.flags & XWVSNPF_F_LEFT)) {
1016 while (--spec.field_width > 0) {
1017 if (str < end) {
1018 *str = ' ';
1019 }
1020 ++str;
1021 }
1022 }
1023 c = (char)va_arg(args, int);
1024 if (str < end) {
1025 *str = c;
1026 }
1027 ++str;
1028 while (--spec.field_width > 0) {
1029 if (str < end) {
1030 *str = ' ';
1031 }
1032 ++str;
1033 }
1034 break;
1035 }
1036
1037 case XWVSNPF_FT_STR:
1038 str = xwvsnpf_format_string(str, end, va_arg(args, char *),
1039 spec);
1040 break;
1041
1042 case XWVSNPF_FT_PTR:
1043 str = xwvsnpf_format_pointer(fmt+1, str, end,
1044 va_arg(args, void *), spec);
1045 while (isalnum((int)(*fmt))) {
1046 fmt++;
1047 }
1048 break;
1049
1051 if (str < end) {
1052 *str = '%';
1053 }
1054 ++str;
1055 break;
1056
1057 case XWVSNPF_FT_INVALID:
1058 if (str < end) {
1059 *str = '%';
1060 }
1061 ++str;
1062 break;
1063
1064#if defined(XWLIBCFG_SPF_FLOAT) && (1U == XWLIBCFG_SPF_FLOAT)
1065 case XWVSNPF_FT_FLOAT:
1066 case XWVSNPF_FT_FLOAT_SCI:
1067 str = xwvsnpf_format_float(str, end, va_arg(args, double), spec);
1068 break;
1069
1070# if defined(XWLIBCFG_SPF_LONG_DOUBLE) && (1U == XWLIBCFG_SPF_LONG_DOUBLE)
1071 case XWVSNPF_FT_LONG_DOUBLE:
1072 case XWVSNPF_FT_LONG_DOUBLE_SCI:
1073 str = xwvsnpf_format_long_double(str, end, va_arg(args, long double), spec);
1074 break;
1075# endif /* XWLIBCFG_SPF_LONG_DOUBLE */
1076#endif /* XWLIBCFG_SPF_FLOAT */
1077
1078 default:
1079 switch (spec.type) {
1081 num = (xwu64_t)va_arg(args, long long);
1082 break;
1083 case XWVSNPF_FT_ULONG:
1084 num = (xwu64_t)va_arg(args, unsigned long);
1085 break;
1086 case XWVSNPF_FT_LONG:
1087 num = (xwu64_t)va_arg(args, long);
1088 break;
1089 case XWVSNPF_FT_XWSZ_T:
1090 if (spec.flags & XWVSNPF_F_SIGN) {
1091 num = (xwu64_t)va_arg(args, xwssz_t);
1092 } else {
1093 num = (xwu64_t)va_arg(args, xwsz_t);
1094 }
1095 break;
1096 case XWVSNPF_FT_PTRDIFF:
1097 num = (xwu64_t)va_arg(args, ptrdiff_t);
1098 break;
1099 case XWVSNPF_FT_UBYTE:
1100 num = (xwu64_t)va_arg(args, int);
1101 break;
1102 case XWVSNPF_FT_BYTE:
1103 num = (xwu64_t)va_arg(args, int);
1104 break;
1105 case XWVSNPF_FT_USHORT:
1106 num = (xwu64_t)va_arg(args, int);
1107 break;
1108 case XWVSNPF_FT_SHORT:
1109 num = (xwu64_t)va_arg(args, int);
1110 break;
1111 case XWVSNPF_FT_INT:
1112 num = (xwu64_t)va_arg(args, int);
1113 break;
1114 default:
1115 num = (xwu64_t)va_arg(args, unsigned int);
1116 }
1117 str = xwvsnpf_format_number(str, end, num, spec);
1118 }
1119 }
1120
1121 if (size > 0) {
1122 if (str < end) {
1123 *str = '\0';
1124 } else {
1125 end[-1] = '\0';
1126 }
1127 }
1128 rc = str - buf;
1129err_oor:
1130 return rc;
1131}
1132
1133int xwsnpf(char * buf, xwsz_t size, const char * fmt, ...)
1134{
1135 va_list args;
1136 int i;
1137
1138 va_start(args, fmt);
1139 i = xwvsnpf(buf, size, fmt, args);
1140 va_end(args);
1141
1142 return i;
1143}
1144
1145int xwvspf(char * buf, const char * fmt, va_list args)
1146{
1147 return xwvsnpf(buf, INT_MAX, fmt, args);
1148}
1149
1150int xwspf(char * buf, const char * fmt, ...)
1151{
1152 va_list args;
1153 int i;
1154
1155 va_start(args, fmt);
1156 i = xwvspf(buf, fmt, args);
1157 va_end(args);
1158 return i;
1159}
XWOS通用库:64位除法
xwu32_t xwdiv64(xwu64_t *n, xwu32_t divisor)
64位除法运算
Definition div64.c:28
int xwspf(char *buf, const char *fmt,...)
格式化字符串(同sprintf)
Definition xwspf.c:1150
int xwsnpf(char *buf, xwsz_t size, const char *fmt,...)
格式化字符串(同snprintf)
Definition xwspf.c:1133
int xwvsnpf(char *buf, xwsz_t size, const char *fmt, va_list args)
格式化字符串(同vsnprintf)
Definition xwspf.c:965
int xwvspf(char *buf, const char *fmt, va_list args)
格式化字符串(同vsprintf)
Definition xwspf.c:1145
#define NULL
Definition type.h:28
unsigned long xwsz_t
Definition type.h:339
uint8_t xwu8_t
Definition type.h:194
uint64_t xwu64_t
Definition type.h:303
#define INT_MAX
Definition type.h:95
signed long xwssz_t
Definition type.h:355
unsigned long xwptr_t
Definition type.h:375
#define XWSSZ_MAX
Definition type.h:367
int16_t xws16_t
Definition type.h:246
xws16_t precision
Definition xwspf.c:65
xws16_t field_width
Definition xwspf.c:64
xwu8_t qualifier
Definition xwspf.c:63
XWOS的标准头文件
static char * xwvsnpf_format_widen_string(char *buf, xwssz_t n, char *end, struct xwvsnpf_format_spec spec)
Definition xwspf.c:337
static int xwvsnpf_format_decode(const char *fmt, struct xwvsnpf_format_spec *spec)
Definition xwspf.c:717
#define XWVSNPF_F_PLUS
Definition xwspf.c:23
static char * xwvsnpf_format_string(char *buf, char *end, const char *s, struct xwvsnpf_format_spec spec)
Definition xwspf.c:385
#define XWVSNPF_F_LEFT
Definition xwspf.c:25
static char * xwvsnpf_format_pointer(const char *fmt, char *buf, char *end, void *ptr, struct xwvsnpf_format_spec spec)
Definition xwspf.c:399
#define XWVSNPF_F_SPACE
Definition xwspf.c:24
static char * xwvsnpf_format_string_nocheck(char *buf, char *end, const char *s, struct xwvsnpf_format_spec spec)
Definition xwspf.c:361
xwvsnpf_format_type_em
Definition xwspf.c:29
@ XWVSNPF_FT_NONE
Definition xwspf.c:30
@ XWVSNPF_FT_LONG
Definition xwspf.c:40
@ XWVSNPF_FT_PTRDIFF
Definition xwspf.c:48
@ XWVSNPF_FT_WIDTH
Definition xwspf.c:31
@ XWVSNPF_FT_PRECISION
Definition xwspf.c:32
@ XWVSNPF_FT_UINT
Definition xwspf.c:45
@ XWVSNPF_FT_SHORT
Definition xwspf.c:44
@ XWVSNPF_FT_INT
Definition xwspf.c:46
@ XWVSNPF_FT_BYTE
Definition xwspf.c:42
@ XWVSNPF_FT_STR
Definition xwspf.c:34
@ XWVSNPF_FT_LONG_LONG
Definition xwspf.c:38
@ XWVSNPF_FT_UBYTE
Definition xwspf.c:41
@ XWVSNPF_FT_XWSZ_T
Definition xwspf.c:47
@ XWVSNPF_FT_PERCENT_CHAR
Definition xwspf.c:36
@ XWVSNPF_FT_ULONG
Definition xwspf.c:39
@ XWVSNPF_FT_INVALID
Definition xwspf.c:37
@ XWVSNPF_FT_CHAR
Definition xwspf.c:33
@ XWVSNPF_FT_PTR
Definition xwspf.c:35
@ XWVSNPF_FT_USHORT
Definition xwspf.c:43
static char * xwvsnpf_put_dec_trunc(char *buf, unsigned int q)
Definition xwspf.c:84
#define XWVSNPF_F_SPECIAL
Definition xwspf.c:27
static void xwvsnpf_format_move_right(char *buf, char *end, xwssz_t len, xwssz_t spaces)
Definition xwspf.c:313
static const char xwvsnpf_nullstr[]
Definition xwspf.c:69
#define XWVSNPF_F_SIGN
Definition xwspf.c:22
static char * xwvsnpf_put_dec_full(char *buf, unsigned int q)
Definition xwspf.c:124
#define XWVSNPF_F_ZEROPAD
Definition xwspf.c:21
static const char xwvsnpf_digits[]
Definition xwspf.c:68
static char * xwvsnpf_format_number(char *buf, char *end, xwu64_t num, struct xwvsnpf_format_spec spec)
Definition xwspf.c:171
static int xwvsnpf_skip_atoi(const char **s)
Definition xwspf.c:72
static char * xwvsnpf_put_dec(char *buf, unsigned long long num)
Definition xwspf.c:158
#define XWVSNPF_F_SMALL
Definition xwspf.c:26