1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2009, 2011 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
28 #include <data/calendar.h>
29 #include <data/format.h>
30 #include <data/settings.h>
31 #include <data/value.h>
33 #include <libpspp/assertion.h>
34 #include <libpspp/float-format.h>
35 #include <libpspp/integer-format.h>
36 #include <libpspp/message.h>
37 #include <libpspp/misc.h>
38 #include <libpspp/str.h>
39 #include <libpspp/pool.h>
40 #include <libpspp/i18n.h>
45 #define _(msgid) gettext (msgid)
47 /* A representation of a number that can be quickly rounded to
48 any desired number of decimal places (up to a specified
52 char string[64]; /* Magnitude of number with excess precision. */
53 int integer_digits; /* Number of digits before decimal point. */
54 int leading_nines; /* Number of `9's or `.'s at start of string. */
55 int leading_zeros; /* Number of `0's or `.'s at start of string. */
56 bool negative; /* Is the number negative? */
59 static void rounder_init (struct rounder *, double number, int max_decimals);
60 static int rounder_width (const struct rounder *, int decimals,
61 int *integer_digits, bool *negative);
62 static void rounder_format (const struct rounder *, int decimals,
65 typedef void data_out_converter_func (const union value *,
66 const struct fmt_spec *,
68 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
69 static data_out_converter_func output_##METHOD;
72 static bool output_decimal (const struct rounder *, const struct fmt_spec *,
73 bool require_affixes, char *);
74 static bool output_scientific (double, const struct fmt_spec *,
75 bool require_affixes, char *);
77 static double power10 (int) PURE_FUNCTION;
78 static double power256 (int) PURE_FUNCTION;
80 static void output_infinite (double, const struct fmt_spec *, char *);
81 static void output_missing (const struct fmt_spec *, char *);
82 static void output_overflow (const struct fmt_spec *, char *);
83 static bool output_bcd_integer (double, int digits, char *);
84 static void output_binary_integer (uint64_t, int bytes, enum integer_format,
86 static void output_hex (const void *, size_t bytes, char *);
89 static data_out_converter_func *const converters[FMT_NUMBER_OF_FORMATS] =
91 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) output_##METHOD,
95 /* Similar to data_out. Additionally recodes the output from
96 native form into the given legacy character ENCODING.
97 OUTPUT must be provided by the caller and must be at least
98 FORMAT->w long. No null terminator is appended to OUTPUT.
101 data_out_legacy (const union value *input, const char *encoding,
102 const struct fmt_spec *format, char *output)
104 assert (fmt_check_output (format));
106 converters[format->type] (input, format, output);
107 if (0 != strcmp (encoding, C_ENCODING)
108 && fmt_get_category (format->type) != FMT_CAT_BINARY)
110 char *s = recode_string (encoding, C_ENCODING, output, format->w );
111 memcpy (output, s, format->w);
116 /* Converts the INPUT value into a UTF8 encoded string, according
117 to format specification FORMAT.
119 VALUE must be the correct width for FORMAT, that is, its
120 width must be fmt_var_width(FORMAT).
122 ENCODING must be the encoding of INPUT. Normally this can
123 be obtained by calling dict_get_encoding on the dictionary
124 with which INPUT is associated.
126 The return value is dynamically allocated, and must be freed
127 by the caller. If POOL is non-null, then the return value is
128 allocated on that pool.
131 data_out_pool (const union value *input, const char *encoding,
132 const struct fmt_spec *format, struct pool *pool)
134 char *output = xmalloc (format->w + 1);
136 assert (fmt_check_output (format));
138 converters[format->type] (input, format, output);
140 t = recode_string_pool (UTF8, encoding, output, format->w, pool);
146 data_out (const union value *input, const char *encoding, const struct fmt_spec *format)
148 return data_out_pool (input, encoding, format, NULL);
152 /* Main conversion functions. */
154 /* Outputs F, COMMA, DOT, DOLLAR, PCT, E, CCA, CCB, CCC, CCD, and
157 output_number (const union value *input, const struct fmt_spec *format,
160 double number = input->f;
162 if (number == SYSMIS)
163 output_missing (format, output);
164 else if (!isfinite (number))
165 output_infinite (number, format, output);
168 if (format->type != FMT_E && fabs (number) < 1.5 * power10 (format->w))
171 rounder_init (&r, number, format->d);
173 if (output_decimal (&r, format, true, output)
174 || output_scientific (number, format, true, output)
175 || output_decimal (&r, format, false, output))
179 if (!output_scientific (number, format, false, output))
180 output_overflow (format, output);
184 /* Outputs N format. */
186 output_N (const union value *input, const struct fmt_spec *format,
189 double number = input->f * power10 (format->d);
190 if (input->f == SYSMIS || number < 0)
191 output_missing (format, output);
195 number = fabs (round (number));
196 if (number < power10 (format->w)
197 && sprintf (buf, "%0*.0f", format->w, number) == format->w)
198 memcpy (output, buf, format->w);
200 output_overflow (format, output);
203 output[format->w] = '\0';
206 /* Outputs Z format. */
208 output_Z (const union value *input, const struct fmt_spec *format,
211 double number = input->f * power10 (format->d);
213 if (input->f == SYSMIS)
214 output_missing (format, output);
215 else if (fabs (number) >= power10 (format->w)
216 || sprintf (buf, "%0*.0f", format->w,
217 fabs (round (number))) != format->w)
218 output_overflow (format, output);
221 if (number < 0 && strspn (buf, "0") < format->w)
223 char *p = &buf[format->w - 1];
224 *p = "}JKLMNOPQR"[*p - '0'];
226 memcpy (output, buf, format->w);
227 output[format->w] = '\0';
231 /* Outputs P format. */
233 output_P (const union value *input, const struct fmt_spec *format,
236 if (output_bcd_integer (fabs (input->f * power10 (format->d)),
237 format->w * 2 - 1, output)
239 output[format->w - 1] |= 0xd;
241 output[format->w - 1] |= 0xf;
244 /* Outputs PK format. */
246 output_PK (const union value *input, const struct fmt_spec *format,
249 output_bcd_integer (input->f * power10 (format->d), format->w * 2, output);
252 /* Outputs IB format. */
254 output_IB (const union value *input, const struct fmt_spec *format,
257 double number = round (input->f * power10 (format->d));
258 if (input->f == SYSMIS
259 || number >= power256 (format->w) / 2 - 1
260 || number < -power256 (format->w) / 2)
261 memset (output, 0, format->w);
264 uint64_t integer = fabs (number);
267 output_binary_integer (integer, format->w,
268 settings_get_output_integer_format (),
272 output[format->w] = '\0';
275 /* Outputs PIB format. */
277 output_PIB (const union value *input, const struct fmt_spec *format,
280 double number = round (input->f * power10 (format->d));
281 if (input->f == SYSMIS
282 || number < 0 || number >= power256 (format->w))
283 memset (output, 0, format->w);
285 output_binary_integer (number, format->w,
286 settings_get_output_integer_format (), output);
288 output[format->w] = '\0';
291 /* Outputs PIBHEX format. */
293 output_PIBHEX (const union value *input, const struct fmt_spec *format,
296 double number = round (input->f);
297 if (input->f == SYSMIS)
298 output_missing (format, output);
299 else if (input->f < 0 || number >= power256 (format->w / 2))
300 output_overflow (format, output);
304 output_binary_integer (number, format->w / 2, INTEGER_MSB_FIRST, tmp);
305 output_hex (tmp, format->w / 2, output);
310 /* Outputs RB format. */
312 output_RB (const union value *input, const struct fmt_spec *format,
316 memcpy (output, &d, format->w);
318 output[format->w] = '\0';
321 /* Outputs RBHEX format. */
323 output_RBHEX (const union value *input, const struct fmt_spec *format,
328 output_hex (&d, format->w / 2, output);
331 /* Outputs DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, WKYR,
332 DATETIME, TIME, and DTIME formats. */
334 output_date (const union value *input, const struct fmt_spec *format,
337 double number = input->f;
338 int year, month, day, yday;
340 const char *template = fmt_date_template (format->type);
341 size_t template_width = strlen (template);
342 int excess_width = format->w - template_width;
347 assert (format->w >= template_width);
348 if (number == SYSMIS)
351 if (fmt_get_category (format->type) == FMT_CAT_DATE)
355 calendar_offset_to_gregorian (number / 60. / 60. / 24.,
356 &year, &month, &day, &yday);
357 number = fmod (number, 60. * 60. * 24.);
360 year = month = day = yday = 0;
362 while (*template != '\0')
366 while (template[count] == ch)
374 p += sprintf (p, "%02d", day);
376 p += sprintf (p, "%03d", yday);
380 p += sprintf (p, "%02d", month);
383 static const char *const months[12] =
385 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
386 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
388 p = stpcpy (p, months[month - 1]);
392 if (count >= 4 || excess_width >= 2)
395 p += sprintf (p, "%04d", year);
396 else if (format->type == FMT_DATETIME)
397 p = stpcpy (p, "****");
403 int epoch = settings_get_epoch ();
404 int offset = year - epoch;
405 if (offset < 0 || offset > 99)
407 p += sprintf (p, "%02d", abs (year) % 100);
411 p += sprintf (p, "%d", (month - 1) / 3 + 1);
414 p += sprintf (p, "%2d", (yday - 1) / 7 + 1);
419 number = fabs (number);
420 p += sprintf (p, "%*.0f", count, floor (number / 60. / 60. / 24.));
421 number = fmod (number, 60. * 60. * 24.);
426 number = fabs (number);
427 p += sprintf (p, "%0*.0f", count, floor (number / 60. / 60.));
428 number = fmod (number, 60. * 60.);
431 p += sprintf (p, "%02d", (int) floor (number / 60.));
432 number = fmod (number, 60.);
433 excess_width = format->w - (p - tmp);
434 if (excess_width < 0)
436 if (excess_width == 3 || excess_width == 4
437 || (excess_width >= 5 && format->d == 0))
438 p += sprintf (p, ":%02d", (int) number);
439 else if (excess_width >= 5)
441 int d = MIN (format->d, excess_width - 4);
443 sprintf (p, ":%0*.*f", w, d, number);
444 if (settings_get_decimal_char (FMT_F) != '.')
446 char *cp = strchr (p, '.');
448 *cp = settings_get_decimal_char (FMT_F);
463 buf_copy_lpad (output, format->w, tmp, p - tmp, ' ');
464 output[format->w] = '\0';
468 output_overflow (format, output);
472 output_missing (format, output);
476 /* Outputs WKDAY format. */
478 output_WKDAY (const union value *input, const struct fmt_spec *format,
481 static const char *const weekdays[7] =
483 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
484 "THURSDAY", "FRIDAY", "SATURDAY",
487 if (input->f >= 1 && input->f < 8)
489 buf_copy_str_rpad (output, format->w,
490 weekdays[(int) input->f - 1], ' ');
491 output[format->w] = '\0';
495 if (input->f != SYSMIS)
496 msg (ME, _("Weekday number %f is not between 1 and 7."), input->f);
497 output_missing (format, output);
502 /* Outputs MONTH format. */
504 output_MONTH (const union value *input, const struct fmt_spec *format,
507 static const char *const months[12] =
509 "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
510 "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
513 if (input->f >= 1 && input->f < 13)
515 buf_copy_str_rpad (output, format->w, months[(int) input->f - 1], ' ');
516 output[format->w] = '\0';
520 if (input->f != SYSMIS)
521 msg (ME, _("Month number %f is not between 1 and 12."), input->f);
522 output_missing (format, output);
527 /* Outputs A format. */
529 output_A (const union value *input, const struct fmt_spec *format,
532 memcpy (output, value_str (input, format->w), format->w);
533 output[format->w] = '\0';
536 /* Outputs AHEX format. */
538 output_AHEX (const union value *input, const struct fmt_spec *format,
541 output_hex (value_str (input, format->w), format->w / 2, output);
544 /* Decimal and scientific formatting. */
546 /* If REQUEST plus the current *WIDTH fits within MAX_WIDTH,
547 increments *WIDTH by REQUEST and return true.
548 Otherwise returns false without changing *WIDTH. */
550 allocate_space (int request, int max_width, int *width)
552 assert (*width <= max_width);
553 if (request + *width <= max_width)
562 /* Tries to compose the number represented by R, in the style of
563 FORMAT, into OUTPUT. Returns true if successful, false on
564 failure, which occurs if FORMAT's width is too narrow. If
565 REQUIRE_AFFIXES is true, then the prefix and suffix specified
566 by FORMAT's style must be included; otherwise, they may be
567 omitted to make the number fit. */
569 output_decimal (const struct rounder *r, const struct fmt_spec *format,
570 bool require_affixes, char *output)
572 const struct fmt_number_style *style =
573 settings_get_style (format->type);
577 for (decimals = format->d; decimals >= 0; decimals--)
579 /* Formatted version of magnitude of NUMBER. */
582 /* Number of digits in MAGNITUDE's integer and fractional parts. */
585 /* Amount of space within the field width already claimed.
586 Initially this is the width of MAGNITUDE, then it is reduced
587 in stages as space is allocated to prefixes and suffixes and
588 grouping characters. */
591 /* Include various decorations? */
596 /* Position in output. */
599 /* Make sure there's room for the number's magnitude, plus
600 the negative suffix, plus (if negative) the negative
602 width = rounder_width (r, decimals, &integer_digits, &add_neg_prefix);
603 width += ss_length (style->neg_suffix);
605 width += ss_length (style->neg_prefix);
606 if (width > format->w)
609 /* If there's room for the prefix and suffix, allocate
610 space. If the affixes are required, but there's no
612 add_affixes = allocate_space (fmt_affix_width (style),
614 if (!add_affixes && require_affixes)
617 /* Check whether we should include grouping characters.
618 We need room for a complete set or we don't insert any at all.
619 We don't include grouping characters if decimal places were
620 requested but they were all dropped. */
621 add_grouping = (style->grouping != 0
622 && integer_digits > 3
623 && (format->d == 0 || decimals > 0)
624 && allocate_space ((integer_digits - 1) / 3,
627 /* Format the number's magnitude. */
628 rounder_format (r, decimals, magnitude);
630 /* Assemble number. */
632 if (format->w > width)
633 p = mempset (p, ' ', format->w - width);
635 p = mempcpy (p, ss_data (style->neg_prefix),
636 ss_length (style->neg_prefix));
638 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
640 p = mempcpy (p, magnitude, integer_digits);
644 for (i = 0; i < integer_digits; i++)
646 if (i > 0 && (integer_digits - i) % 3 == 0)
647 *p++ = style->grouping;
653 *p++ = style->decimal;
654 p = mempcpy (p, &magnitude[integer_digits + 1], decimals);
657 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
659 p = mempcpy (p, ss_data (style->neg_suffix),
660 ss_length (style->neg_suffix));
662 p = mempset (p, ' ', ss_length (style->neg_suffix));
663 assert (p == output + format->w);
670 /* Formats NUMBER into OUTPUT in scientific notation according to
671 the style of the format specified in FORMAT. */
673 output_scientific (double number, const struct fmt_spec *format,
674 bool require_affixes, char *output)
676 const struct fmt_number_style *style =
677 settings_get_style (format->type);
683 /* Allocate minimum required space. */
684 width = 6 + ss_length (style->neg_suffix);
686 width += ss_length (style->neg_prefix);
687 if (width > format->w)
690 /* Check for room for prefix and suffix. */
691 add_affixes = allocate_space (fmt_affix_width (style), format->w, &width);
692 if (require_affixes && !add_affixes)
695 /* Figure out number of characters we can use for the fraction,
696 if any. (If that turns out to be 1, then we'll output a
697 decimal point without any digits following; that's what the
698 # flag does in the call to sprintf, below.) */
699 fraction_width = MIN (MIN (format->d + 1, format->w - width), 16);
700 if (format->type != FMT_E && fraction_width == 1)
702 width += fraction_width;
704 /* Format (except suffix). */
706 if (width < format->w)
707 p = mempset (p, ' ', format->w - width);
709 p = mempcpy (p, ss_data (style->neg_prefix),
710 ss_length (style->neg_prefix));
712 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
713 if (fraction_width > 0)
714 sprintf (p, "%#.*E", fraction_width - 1, fabs (number));
716 sprintf (p, "%.0E", fabs (number));
718 /* The C locale always uses a period `.' as a decimal point.
719 Translate to comma if necessary. */
720 if (style->decimal != '.')
722 char *cp = strchr (p, '.');
724 *cp = style->decimal;
727 /* Make exponent have exactly three digits, plus sign. */
729 char *cp = strchr (p, 'E') + 1;
730 long int exponent = strtol (cp, NULL, 10);
731 if (abs (exponent) > 999)
733 sprintf (cp, "%+04ld", exponent);
737 p = strchr (p, '\0');
739 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
741 p = mempcpy (p, ss_data (style->neg_suffix),
742 ss_length (style->neg_suffix));
744 p = mempset (p, ' ', ss_length (style->neg_suffix));
746 assert (p == buf + format->w);
747 memcpy (output, buf, format->w);
748 output[format->w] = '\0';
753 /* Returns true if the magnitude represented by R should be
754 rounded up when chopped off at DECIMALS decimal places, false
755 if it should be rounded down. */
757 should_round_up (const struct rounder *r, int decimals)
759 int digit = r->string[r->integer_digits + decimals + 1];
760 assert (digit >= '0' && digit <= '9');
764 /* Initializes R for formatting the magnitude of NUMBER to no
765 more than MAX_DECIMAL decimal places. */
767 rounder_init (struct rounder *r, double number, int max_decimals)
769 assert (fabs (number) < 1e41);
770 assert (max_decimals >= 0 && max_decimals <= 16);
771 if (max_decimals == 0)
773 /* Fast path. No rounding needed.
775 We append ".00" to the integer representation because
776 round_up assumes that fractional digits are present. */
777 sprintf (r->string, "%.0f.00", fabs (round (number)));
783 This is more difficult than it really should be because
784 we have to make sure that numbers that are exactly
785 halfway between two representations are always rounded
786 away from zero. This is not what sprintf normally does
787 (usually it rounds to even), so we have to fake it as
788 best we can, by formatting with extra precision and then
789 doing the rounding ourselves.
791 We take up to two rounds to format numbers. In the
792 first round, we obtain 2 digits of precision beyond
793 those requested by the user. If those digits are
794 exactly "50", then in a second round we format with as
795 many digits as are significant in a "double".
797 It might be better to directly implement our own
798 floating-point formatting routine instead of relying on
799 the system's sprintf implementation. But the classic
800 Steele and White paper on printing floating-point
801 numbers does not hint how to do what we want, and it's
802 not obvious how to change their algorithms to do so. It
803 would also be a lot of work. */
804 sprintf (r->string, "%.*f", max_decimals + 2, fabs (number));
805 if (!strcmp (r->string + strlen (r->string) - 2, "50"))
807 int binary_exponent, decimal_exponent, format_decimals;
808 frexp (number, &binary_exponent);
809 decimal_exponent = binary_exponent * 3 / 10;
810 format_decimals = (DBL_DIG + 1) - decimal_exponent;
811 if (format_decimals > max_decimals + 2)
812 sprintf (r->string, "%.*f", format_decimals, fabs (number));
816 if (r->string[0] == '0')
817 memmove (r->string, &r->string[1], strlen (r->string));
819 r->leading_zeros = strspn (r->string, "0.");
820 r->leading_nines = strspn (r->string, "9.");
821 r->integer_digits = strchr (r->string, '.') - r->string;
822 r->negative = number < 0;
825 /* Returns the number of characters required to format the
826 magnitude represented by R to DECIMALS decimal places.
827 The return value includes integer digits and a decimal point
828 and fractional digits, if any, but it does not include any
829 negative prefix or suffix or other affixes.
831 *INTEGER_DIGITS is set to the number of digits before the
832 decimal point in the output, between 0 and 40.
834 If R represents a negative number and its rounded
835 representation would include at least one nonzero digit,
836 *NEGATIVE is set to true; otherwise, it is set to false. */
838 rounder_width (const struct rounder *r, int decimals,
839 int *integer_digits, bool *negative)
841 /* Calculate base measures. */
842 int width = r->integer_digits;
844 width += decimals + 1;
845 *integer_digits = r->integer_digits;
846 *negative = r->negative;
848 /* Rounding can cause adjustments. */
849 if (should_round_up (r, decimals))
851 /* Rounding up leading 9s adds a new digit (a 1). */
852 if (r->leading_nines >= width)
861 if (r->leading_zeros >= width)
863 /* All digits that remain after rounding are zeros.
864 Therefore we drop the negative sign. */
866 if (r->integer_digits == 0 && decimals == 0)
868 /* No digits at all are left. We need to display
869 at least a single digit (a zero). */
879 /* Formats the magnitude represented by R into OUTPUT, rounding
880 to DECIMALS decimal places. Exactly as many characters as
881 indicated by rounder_width are written. No terminating null
884 rounder_format (const struct rounder *r, int decimals, char *output)
886 int base_width = r->integer_digits + (decimals > 0 ? decimals + 1 : 0);
887 if (should_round_up (r, decimals))
889 if (r->leading_nines < base_width)
891 /* Rounding up. This is the common case where rounding
892 up doesn't add an extra digit. */
894 memcpy (output, r->string, base_width);
895 for (p = output + base_width - 1; ; p--)
897 assert (p >= output);
900 else if (*p >= '0' && *p <= '8')
911 /* Rounding up leading 9s causes the result to be a 1
912 followed by a number of 0s, plus a decimal point. */
915 p = mempset (p, '0', r->integer_digits);
919 p = mempset (p, '0', decimals);
921 assert (p == output + base_width + 1);
927 if (r->integer_digits != 0 || decimals != 0)
929 /* Common case: just copy the digits. */
930 memcpy (output, r->string, base_width);
934 /* No digits remain. The output is just a zero. */
940 /* Helper functions. */
943 static double PURE_FUNCTION
946 static const double p[] =
948 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
949 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
950 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
951 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
954 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (10.0, x);
957 /* Returns 256**X. */
958 static double PURE_FUNCTION
961 static const double p[] =
971 18446744073709551616.0
973 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (256.0, x);
976 /* Formats non-finite NUMBER into OUTPUT according to the width
979 output_infinite (double number, const struct fmt_spec *format, char *output)
981 assert (!isfinite (number));
989 else if (isinf (number))
990 s = number > 0 ? "+Infinity" : "-Infinity";
994 buf_copy_str_lpad (output, format->w, s, ' ');
997 output_overflow (format, output);
999 output[format->w] = '\0';
1002 /* Formats OUTPUT as a missing value for the given FORMAT. */
1004 output_missing (const struct fmt_spec *format, char *output)
1006 memset (output, ' ', format->w);
1008 if (format->type != FMT_N)
1010 int dot_ofs = (format->type == FMT_PCT ? 2
1011 : format->type == FMT_E ? 5
1013 output[MAX (0, format->w - format->d - dot_ofs)] = '.';
1016 output[format->w - 1] = '.';
1018 output[format->w] = '\0';
1021 /* Formats OUTPUT for overflow given FORMAT. */
1023 output_overflow (const struct fmt_spec *format, char *output)
1025 memset (output, '*', format->w);
1026 output[format->w] = '\0';
1029 /* Converts the integer part of NUMBER to a packed BCD number
1030 with the given number of DIGITS in OUTPUT. If DIGITS is odd,
1031 the least significant nibble of the final byte in OUTPUT is
1032 set to 0. Returns true if successful, false if NUMBER is not
1033 representable. On failure, OUTPUT is cleared to all zero
1036 output_bcd_integer (double number, int digits, char *output)
1040 assert (digits < sizeof decimal);
1042 output[DIV_RND_UP (digits, 2)] = '\0';
1043 if (number != SYSMIS
1045 && number < power10 (digits)
1046 && sprintf (decimal, "%0*.0f", digits, round (number)) == digits)
1048 const char *src = decimal;
1051 for (i = 0; i < digits / 2; i++)
1053 int d0 = *src++ - '0';
1054 int d1 = *src++ - '0';
1055 *output++ = (d0 << 4) + d1;
1058 *output = (*src - '0') << 4;
1064 memset (output, 0, DIV_RND_UP (digits, 2));
1069 /* Writes VALUE to OUTPUT as a BYTES-byte binary integer of the
1070 given INTEGER_FORMAT. */
1072 output_binary_integer (uint64_t value, int bytes,
1073 enum integer_format integer_format, char *output)
1075 integer_put (value, integer_format, output, bytes);
1078 /* Converts the BYTES bytes in DATA to twice as many hexadecimal
1079 digits in OUTPUT. */
1081 output_hex (const void *data_, size_t bytes, char *output)
1083 const uint8_t *data = data_;
1086 for (i = 0; i < bytes; i++)
1088 static const char hex_digits[] = "0123456789ABCDEF";
1089 *output++ = hex_digits[data[i] >> 4];
1090 *output++ = hex_digits[data[i] & 15];