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