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