3 # (c)Copyright 2020-2021, Matthew Dillon, All Rights Reserved.
4 # See the COPYRIGHT file at the base of the Rune distribution.
6 # Show generated simple auto-formatted output
15 for (i = 0; i < self.__varcount; ++i) {
22 * Type comparisons ignore storage qualifiers by default.
23 * You can specify them in your cases to require particular
24 * qualifiers such as const.
26 switch(self.__vartype[i]) {
34 case typeof(uint16_t):
35 case typeof(uint32_t):
36 case typeof(uint64_t):
38 * Decode various integer types
42 usize_t j = arysize(buf);
44 switch(self.__vartype[i]) {
46 v = (int8_t)self.__vardata[i];
49 v = (int16_t)self.__vardata[i];
52 v = (int32_t)self.__vardata[i];
55 v = (int64_t)self.__vardata[i];
58 v = (uint8_t)self.__vardata[i];
60 case typeof(uint16_t):
61 v = (uint16_t)self.__vardata[i];
63 case typeof(uint32_t):
64 v = (uint32_t)self.__vardata[i];
66 case typeof(uint64_t):
67 v = (uint64_t)self.__vardata[i];
80 if (negative_ok && v < 0L) {
86 buf[--j] = (char)(vv % 10UL) + '0';
92 this->fwrite(&buf[j], arysize(buf) - (usize_t)j);
96 /* XXX doesn't work */
97 uint64_t v = (uint64_t)(int *)self.__vardata[i];
106 buf[j] = (char)vv + '0';
108 buf[j] = (char)vv + 'a' - (char)10;
113 this->fwrite(&buf[j], arysize(buf) - (usize_t)j);
116 case typeof(string_p):
117 string_p str = (string_p)self.__vardata[i];
120 this->fputs("(null)");
126 case typeof(string_rw_p):
128 * Decode the standard string type
130 string_rw_p str = (string_rw_p)self.__vardata[i];
133 this->fputs("(null)");
141 char c = (char)self.__vardata[i];
147 if ((bool)self.__vardata[i]) {
150 this->fputs("FALSE");
155 this->format_fp('f', 0, ' ', -1, 6, 6,
156 (ldouble)(float)self.__vardata[i],
157 (ldouble)float.epsilon);
161 this->format_fp('f', 0, ' ', -1, 6, 15,
162 (ldouble)(double)self.__vardata[i],
163 (ldouble)double.epsilon);
166 case typeof(ldouble):
167 this->format_fp('f', 0, ' ', -1, 6, 19,
168 (ldouble)self.__vardata[i],
181 # Format is more printf-like, but without integer size specifiers.
182 # So e.g. %6.2f %08x %d %u %6u %06u %8.8s %*.*s and so forth.
185 const int STATE_SCAN = 0;
186 const int STATE_W1 = 1;
187 const int STATE_W2 = 2;
188 const int STATE_CTL = 3;
190 const int32_t FLAG_PL = 0x0001; # + (always show sign)
191 const int32_t FLAG_PL2 = 0x0002; # + (always show sign)
192 const int32_t FLAG_LJ = 0x0004; # - (left justify)
193 const int32_t FLAG_ALT = 0x0008; # # (alternative form)
194 const int32_t FLAG_UP = 0x0010; # (upper-case form)
197 File.format(string_p fmt, ...)
226 zf = ' '; # - overrides 0
230 flags |= FLAG_PL | FLAG_PL2;
238 # left-justify overrides zero-fill.
241 if ((flags & FLAG_LJ) == 0)
254 for (ptr = base; *ptr && *ptr != '%'; ++ptr)
256 this->fwrite(base, ptr - base);
264 switch(self.__vartype[i]) {
266 t = (int8_t)self.__vardata[i];
268 case typeof(int16_t):
269 t = (int16_t)self.__vardata[i];
271 case typeof(int32_t):
272 t = (int32_t)self.__vardata[i];
274 case typeof(int64_t):
275 t = (int64_t)self.__vardata[i];
277 case typeof(uint8_t):
278 t = (uint8_t)self.__vardata[i];
280 case typeof(uint16_t):
281 t = (uint16_t)self.__vardata[i];
283 case typeof(uint32_t):
284 t = (uint32_t)self.__vardata[i];
286 case typeof(uint64_t):
287 t = (uint64_t)self.__vardata[i];
290 this->format("(badw%d)", state);
296 } else if (*base >= '0' && *base <= '9') {
298 while (*base >= '0' && *base <= '9') {
299 t = t * 10 + (int)(*base - '0');
303 if (state == STATE_W1) {
320 # Determine if we ran out of arguments.
322 if (i >= self.__varcount) {
323 this->fputs("(noarg)");
329 # Control designator. Note that the format command
330 # can take any argument of the correct type but
331 # does not cast arguments to make them correct.
337 switch(self.__vartype[i]) {
339 t = (int8_t)self.__vardata[i];
341 case typeof(int16_t):
342 t = (int16_t)self.__vardata[i];
344 case typeof(int32_t):
345 t = (int32_t)self.__vardata[i];
347 case typeof(int64_t):
348 t = (int64_t)self.__vardata[i];
350 case typeof(uint8_t):
351 t = (uint8_t)self.__vardata[i];
353 case typeof(uint16_t):
354 t = (uint16_t)self.__vardata[i];
356 case typeof(uint32_t):
357 t = (uint32_t)self.__vardata[i];
359 case typeof(uint64_t):
360 t = (uint64_t)self.__vardata[i];
363 this->format("(badchar)");
384 # Signed or unsigned integral values, based
385 # on format above. 'd' is the only signed
386 # integer printing format.
390 switch(self.__vartype[i]) {
392 t = (int8_t)self.__vardata[i];
394 case typeof(int16_t):
395 t = (int16_t)self.__vardata[i];
397 case typeof(int32_t):
398 t = (int32_t)self.__vardata[i];
400 case typeof(int64_t):
401 t = (int64_t)self.__vardata[i];
403 case typeof(uint8_t):
404 t = (uint8_t)self.__vardata[i];
406 case typeof(uint16_t):
407 t = (uint16_t)self.__vardata[i];
409 case typeof(uint32_t):
410 t = (uint32_t)self.__vardata[i];
412 case typeof(uint64_t):
413 t = (uint64_t)self.__vardata[i];
416 this->format("(badint)");
422 this->format_int(nbase, neg_ok, flags, zf, w1, t);
425 # Pointer address - caller must cast to
426 # void * or const void *.
430 t = (uint64_t)(intptr_t)self.__vardata[i];
431 this->format_int(16, 0, FLAG_ALT, '0', 16, t);
433 case 'F': /* standard float notation */
434 case 'E': /* scientific notation */
435 case 'G': /* choose f/e */
436 case 'A': /* hex notation */
437 case 'R': /* engineering notation */
440 case 'f': /* standard float notation */
441 case 'e': /* scientific notation */
442 case 'g': /* choose f/e */
443 case 'a': /* hex notation */
444 case 'r': /* engineering notation */
447 switch(self.__vartype[i]) {
449 t = (ldouble)(float)self.__vardata[i];
452 this->format_fp(*base, flags, zf, w1, w2, 6, t,
453 (ldouble)float.epsilon);
456 t = (ldouble)(double)self.__vardata[i];
459 this->format_fp(*base, flags, zf, w1, w2, 15, t,
460 (ldouble)double.epsilon);
462 case typeof(ldouble):
463 t = (ldouble)self.__vardata[i];
466 this->format_fp(*base, flags, zf, w1, w2, 19, t,
467 (ldouble)ldouble.epsilon);
470 this->format("(badflt)");
475 switch(self.__vartype[i]) {
476 case typeof(string_rw_p):
477 string_p str = (string_p)(string_rw_p)self.__vardata[i];
478 this->format_str(flags, zf, w1, w2, str);
480 case typeof(string_p):
481 string_p str = (string_p)self.__vardata[i];
482 this->format_str(flags, zf, w1, w2, str);
485 this->fputs("(badstr)");
490 this->format("(badctl)");
508 File.format_str(int32_t flags, char zf, int w1, int w2, string_p str)
512 # Handle null case (do not pad "(null)" for now)
515 this->fputs("(null)");
518 len = Str.strlen(str);
522 # Pad on the left when not left-justified
524 if (w2 < w1 && (flags & FLAG_LJ) == 0) {
531 # Output. w2 forces output to w2 length with space padding at end.
534 this->fwrite(str, w2);
536 this->fwrite(str, len);
543 # Pad on the right when left-justified
545 if (w2 < w1 && (flags & FLAG_LJ)) {
557 File.format_int(int nbase, int neg_ok, int32_t flags, char zf,
558 int w1, uint64_t val)
561 usize_t bi = sizeof(buf);
563 int didhexprefix = 0;
567 if (neg_ok && (int64_t)val < 0L) {
568 neg_ok = 1; # flag negative value
575 buf[--bi] = (char)(val % 10UL) + '0';
577 } else if (nbase == 16) {
578 if ((val & 15UL) < 10UL)
579 buf[--bi] = (char)(val & 15UL) + '0';
581 buf[--bi] = (char)(val & 15UL) + 'a' - 10UB;
583 } else if (nbase == 8) {
584 buf[--bi] = (char)(val & 7UL) + '0';
588 if (bi == sizeof(buf))
591 # Alternative form adjustments
593 if (flags & FLAG_ALT) {
595 # Prefix with 0x or 0X for hex
603 } else if (nbase == 8) {
604 # Require leading 0 for octal
611 len = sizeof(buf) - bi;
615 if (zf != '0' && (flags & FLAG_LJ) == 0 && w1 >= 0) {
617 if (neg_ok || (flags & FLAG_PL))
629 else if (flags & FLAG_PL2)
631 else if (flags & FLAG_PL)
636 if (zf == '0' && (flags & FLAG_LJ) == 0 && w1 >= 0) {
638 this->fputc(buf[bi]);
639 this->fputc(buf[bi+1L]);
644 if (neg_ok || (flags & FLAG_PL))
654 this->fwrite(&buf[bi], len);
658 if ((flags & FLAG_LJ) && w1 >= 0) {
667 # Format floating point numbers
669 # Generally speaking use log10() and pow() to extract the base-10 exponent
670 # of a floating point number, then normalize it to 1.0-9.99* (except for 0)
671 # and use a simple int-conversion/subtract/multiply loop to extract the
674 # To avoid base-10/base-2 representation artifacts, we also round up the
675 # absolute value by half a LSB at the requested precision.
679 File.format_fp(char mode, int32_t flags, char zf,
680 int w1, int w2, int realdig, ldouble val, ldouble epsilon)
692 force_ee = 0; # debugging safety, not needed in Rune
693 isneg = 0; # debugging safety, not needed in Rune
694 ee = 0; # debugging safety, not needed in Rune
696 # Handle negative values
703 # Calculate the exponent and normalize.
706 xp = (int)ldouble.log10(val);
708 xp = (int)ldouble.log10(val) - 1;
709 val = val * ldouble.pow(10.0X, (ldouble)-xp);
711 # Adjust by half an lsb to deal with boundary conditions, otherwise
712 # numbers may not print nicely.
714 # WARNING! At the very least adjust by epsilon.
716 prec = ldouble.pow(10.0X, (ldouble)-(xp + w2 + 1)) * 5.0X;
717 if (prec < epsilon * 5.0X)
718 prec = epsilon * 5.0X;
721 # Possible boundary condition due to adjustment.
728 # Dump digits to buffer
730 if (realdig > (int)sizeof(buf))
731 realdig = (int)sizeof(buf);
732 while (bi < realdig) {
733 char c = (char)(int)val;
736 val = (val - (ldouble)c) * 10.0X;
740 # xp is the power of 10 exponent. e.g. a value 1.000-9.999 will have
746 # Normal float display.
751 # Best precision with zero stripping.
753 if ((flags & FLAG_ALT) == 0)
755 if (xp > -realdig || xp < realdig)
763 # Scientific mode, d.dddpe+/-dd
771 # Engineering mode, exponent in multiples of 3 only
782 # Ok, we have our displayed exponent (ee). Adjust (xp) to represent
783 # the number of digits in the buffer to the left of the decimal point
784 # to reduce confusion.
788 # If stripping fractional zeros attempt to truncate bi (so we get the
789 # rounded result), then strip zeros from there. It's ok if the
790 # stripping digs into the left-of-decimal-point digits.
794 bi = xp + w2; # can go oob
795 if (bi < 1) # fix if so
798 while (bi > 1 && buf[bi-1] == '0')
802 # Now calculate the output space we will use so we can figure out
803 # what prefix padding to add.
806 if (isneg || (flags & FLAG_PL)) # plus, space, or minus
810 count += xp; # left of decimal
812 ++count; # left of decimal a single 0
814 if (w2 == 0) { # right of decimal (incl decimal pt)
815 if (flags & FLAG_ALT) # force decimal point
817 } else if (stripzeros) {
818 if (xp <= bi && bi - xp < w2) {
821 w2 = 0; # nothing left
823 count += w2 + 1; # something left
830 if (force_ee || ee) {
836 if (tmp >= 10) # additional digits
846 # Space-fill in front.
848 if (zf != '0' && (flags & FLAG_LJ) == 0 && count < w1) {
855 # Plus, minus, space, nothing
859 else if (flags & FLAG_PL2)
861 else if (flags & FLAG_PL)
866 if (zf == '0' && (flags & FLAG_LJ) == 0 && count < w1) {
873 # Digits before decimal point
877 this->fwrite(buf, bi);
883 this->fwrite(buf, xp);
889 # Digits after decimal point
892 if (flags & FLAG_ALT) # force decimal point
900 } else if (xp < bi) {
901 this->fputc(buf[xp]);
903 } else if (!stripzeros) {
912 if (force_ee || ee) {
914 this->format("E%+d", ee);
916 this->format("e%+d", ee);
919 # If left-justified space-fill remainder
921 if ((flags & FLAG_LJ) && count < w1) {