1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2009 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>
43 #define _(msgid) gettext (msgid)
45 /* A representation of a number that can be quickly rounded to
46 any desired number of decimal places (up to a specified
50 char string[64]; /* Magnitude of number with excess precision. */
51 int integer_digits; /* Number of digits before decimal point. */
52 int leading_nines; /* Number of `9's or `.'s at start of string. */
53 int leading_zeros; /* Number of `0's or `.'s at start of string. */
54 bool negative; /* Is the number negative? */
57 static void rounder_init (struct rounder *, double number, int max_decimals);
58 static int rounder_width (const struct rounder *, int decimals,
59 int *integer_digits, bool *negative);
60 static void rounder_format (const struct rounder *, int decimals,
63 typedef void data_out_converter_func (const union value *,
64 const struct fmt_spec *,
66 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
67 static data_out_converter_func output_##METHOD;
70 static bool output_decimal (const struct rounder *, const struct fmt_spec *,
71 bool require_affixes, char *);
72 static bool output_scientific (double, const struct fmt_spec *,
73 bool require_affixes, char *);
75 static double power10 (int) PURE_FUNCTION;
76 static double power256 (int) PURE_FUNCTION;
78 static void output_infinite (double, const struct fmt_spec *, char *);
79 static void output_missing (const struct fmt_spec *, char *);
80 static void output_overflow (const struct fmt_spec *, char *);
81 static bool output_bcd_integer (double, int digits, char *);
82 static void output_binary_integer (uint64_t, int bytes, enum integer_format,
84 static void output_hex (const void *, size_t bytes, char *);
86 /* Same as data_out, and additionally recodes the output from
87 native form into the given legacy character ENCODING. */
89 data_out_legacy (const union value *input, enum legacy_encoding encoding,
90 const struct fmt_spec *format, char *output)
92 static data_out_converter_func *const converters[FMT_NUMBER_OF_FORMATS] =
94 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) output_##METHOD,
98 assert (fmt_check_output (format));
100 converters[format->type] (input, format, output);
101 if (encoding != LEGACY_NATIVE
102 && fmt_get_category (format->type) != FMT_CAT_BINARY)
103 legacy_recode (LEGACY_NATIVE, output, encoding, output, format->w);
106 /* Converts the INPUT value into printable form in the exactly
107 FORMAT->W characters in OUTPUT according to format
108 specification FORMAT. No null terminator is appended to the
111 VALUE must be the correct width for FORMAT, that is, its
112 width must be fmt_var_width(FORMAT). */
114 data_out (const union value *input, const struct fmt_spec *format,
117 return data_out_legacy (input, LEGACY_NATIVE, format, output);
121 /* Main conversion functions. */
123 /* Outputs F, COMMA, DOT, DOLLAR, PCT, E, CCA, CCB, CCC, CCD, and
126 output_number (const union value *input, const struct fmt_spec *format,
129 double number = input->f;
131 if (number == SYSMIS)
132 output_missing (format, output);
133 else if (!isfinite (number))
134 output_infinite (number, format, output);
137 if (format->type != FMT_E && fabs (number) < 1.5 * power10 (format->w))
140 rounder_init (&r, number, format->d);
142 if (output_decimal (&r, format, true, output)
143 || output_scientific (number, format, true, output)
144 || output_decimal (&r, format, false, output))
148 if (!output_scientific (number, format, false, output))
149 output_overflow (format, output);
153 /* Outputs N format. */
155 output_N (const union value *input, const struct fmt_spec *format,
158 double number = input->f * power10 (format->d);
159 if (input->f == SYSMIS || number < 0)
160 output_missing (format, output);
164 number = fabs (round (number));
165 if (number < power10 (format->w)
166 && sprintf (buf, "%0*.0f", format->w, number) == format->w)
167 memcpy (output, buf, format->w);
169 output_overflow (format, output);
173 /* Outputs Z format. */
175 output_Z (const union value *input, const struct fmt_spec *format,
178 double number = input->f * power10 (format->d);
180 if (input->f == SYSMIS)
181 output_missing (format, output);
182 else if (fabs (number) >= power10 (format->w)
183 || sprintf (buf, "%0*.0f", format->w,
184 fabs (round (number))) != format->w)
185 output_overflow (format, output);
188 if (number < 0 && strspn (buf, "0") < format->w)
190 char *p = &buf[format->w - 1];
191 *p = "}JKLMNOPQR"[*p - '0'];
193 memcpy (output, buf, format->w);
197 /* Outputs P format. */
199 output_P (const union value *input, const struct fmt_spec *format,
202 if (output_bcd_integer (fabs (input->f * power10 (format->d)),
203 format->w * 2 - 1, output)
205 output[format->w - 1] |= 0xd;
207 output[format->w - 1] |= 0xf;
210 /* Outputs PK format. */
212 output_PK (const union value *input, const struct fmt_spec *format,
215 output_bcd_integer (input->f * power10 (format->d), format->w * 2, output);
218 /* Outputs IB format. */
220 output_IB (const union value *input, const struct fmt_spec *format,
223 double number = round (input->f * power10 (format->d));
224 if (input->f == SYSMIS
225 || number >= power256 (format->w) / 2 - 1
226 || number < -power256 (format->w) / 2)
227 memset (output, 0, format->w);
230 uint64_t integer = fabs (number);
233 output_binary_integer (integer, format->w,
234 settings_get_output_integer_format (),
239 /* Outputs PIB format. */
241 output_PIB (const union value *input, const struct fmt_spec *format,
244 double number = round (input->f * power10 (format->d));
245 if (input->f == SYSMIS
246 || number < 0 || number >= power256 (format->w))
247 memset (output, 0, format->w);
249 output_binary_integer (number, format->w,
250 settings_get_output_integer_format (), output);
253 /* Outputs PIBHEX format. */
255 output_PIBHEX (const union value *input, const struct fmt_spec *format,
258 double number = round (input->f);
259 if (input->f == SYSMIS)
260 output_missing (format, output);
261 else if (input->f < 0 || number >= power256 (format->w / 2))
262 output_overflow (format, output);
266 output_binary_integer (number, format->w / 2, INTEGER_MSB_FIRST, tmp);
267 output_hex (tmp, format->w / 2, output);
271 /* Outputs RB format. */
273 output_RB (const union value *input, const struct fmt_spec *format,
277 memcpy (output, &d, format->w);
280 /* Outputs RBHEX format. */
282 output_RBHEX (const union value *input, const struct fmt_spec *format,
286 output_hex (&d, format->w / 2, output);
289 /* Outputs DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, WKYR,
290 DATETIME, TIME, and DTIME formats. */
292 output_date (const union value *input, const struct fmt_spec *format,
295 double number = input->f;
296 int year, month, day, yday;
298 const char *template = fmt_date_template (format->type);
299 size_t template_width = strlen (template);
300 int excess_width = format->w - template_width;
305 assert (format->w >= template_width);
306 if (number == SYSMIS)
309 if (fmt_get_category (format->type) == FMT_CAT_DATE)
313 calendar_offset_to_gregorian (number / 60. / 60. / 24.,
314 &year, &month, &day, &yday);
315 number = fmod (number, 60. * 60. * 24.);
318 year = month = day = yday = 0;
320 while (*template != '\0')
324 while (template[count] == ch)
332 p += sprintf (p, "%02d", day);
334 p += sprintf (p, "%03d", yday);
338 p += sprintf (p, "%02d", month);
341 static const char *const months[12] =
343 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
344 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
346 p = stpcpy (p, months[month - 1]);
350 if (count >= 4 || excess_width >= 2)
353 p += sprintf (p, "%04d", year);
354 else if (format->type == FMT_DATETIME)
355 p = stpcpy (p, "****");
361 int epoch = settings_get_epoch ();
362 int offset = year - epoch;
363 if (offset < 0 || offset > 99)
365 p += sprintf (p, "%02d", abs (year) % 100);
369 p += sprintf (p, "%d", (month - 1) / 3 + 1);
372 p += sprintf (p, "%2d", (yday - 1) / 7 + 1);
377 number = fabs (number);
378 p += sprintf (p, "%*.0f", count, floor (number / 60. / 60. / 24.));
379 number = fmod (number, 60. * 60. * 24.);
384 number = fabs (number);
385 p += sprintf (p, "%0*.0f", count, floor (number / 60. / 60.));
386 number = fmod (number, 60. * 60.);
389 p += sprintf (p, "%02d", (int) floor (number / 60.));
390 number = fmod (number, 60.);
391 excess_width = format->w - (p - tmp);
392 if (excess_width < 0)
394 if (excess_width == 3 || excess_width == 4
395 || (excess_width >= 5 && format->d == 0))
396 p += sprintf (p, ":%02d", (int) number);
397 else if (excess_width >= 5)
399 int d = MIN (format->d, excess_width - 4);
401 sprintf (p, ":%0*.*f", w, d, number);
402 if (settings_get_decimal_char (FMT_F) != '.')
404 char *cp = strchr (p, '.');
406 *cp = settings_get_decimal_char (FMT_F);
421 buf_copy_lpad (output, format->w, tmp, p - tmp, ' ');
425 output_overflow (format, output);
429 output_missing (format, output);
433 /* Outputs WKDAY format. */
435 output_WKDAY (const union value *input, const struct fmt_spec *format,
438 static const char *const weekdays[7] =
440 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
441 "THURSDAY", "FRIDAY", "SATURDAY",
444 if (input->f >= 1 && input->f < 8)
445 buf_copy_str_rpad (output, format->w, weekdays[(int) input->f - 1], ' ');
448 if (input->f != SYSMIS)
449 msg (ME, _("Weekday number %f is not between 1 and 7."), input->f);
450 output_missing (format, output);
454 /* Outputs MONTH format. */
456 output_MONTH (const union value *input, const struct fmt_spec *format,
459 static const char *const months[12] =
461 "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
462 "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
465 if (input->f >= 1 && input->f < 13)
466 buf_copy_str_rpad (output, format->w, months[(int) input->f - 1], ' ');
469 if (input->f != SYSMIS)
470 msg (ME, _("Month number %f is not between 1 and 12."), input->f);
471 output_missing (format, output);
475 /* Outputs A format. */
477 output_A (const union value *input, const struct fmt_spec *format,
480 memcpy (output, value_str (input, format->w), format->w);
483 /* Outputs AHEX format. */
485 output_AHEX (const union value *input, const struct fmt_spec *format,
488 output_hex (value_str (input, format->w), format->w / 2, output);
491 /* Decimal and scientific formatting. */
493 /* If REQUEST plus the current *WIDTH fits within MAX_WIDTH,
494 increments *WIDTH by REQUEST and return true.
495 Otherwise returns false without changing *WIDTH. */
497 allocate_space (int request, int max_width, int *width)
499 assert (*width <= max_width);
500 if (request + *width <= max_width)
509 /* Tries to compose the number represented by R, in the style of
510 FORMAT, into OUTPUT. Returns true if successful, false on
511 failure, which occurs if FORMAT's width is too narrow. If
512 REQUIRE_AFFIXES is true, then the prefix and suffix specified
513 by FORMAT's style must be included; otherwise, they may be
514 omitted to make the number fit. */
516 output_decimal (const struct rounder *r, const struct fmt_spec *format,
517 bool require_affixes, char *output)
519 const struct fmt_number_style *style =
520 settings_get_style (format->type);
524 for (decimals = format->d; decimals >= 0; decimals--)
526 /* Formatted version of magnitude of NUMBER. */
529 /* Number of digits in MAGNITUDE's integer and fractional parts. */
532 /* Amount of space within the field width already claimed.
533 Initially this is the width of MAGNITUDE, then it is reduced
534 in stages as space is allocated to prefixes and suffixes and
535 grouping characters. */
538 /* Include various decorations? */
543 /* Position in output. */
546 /* Make sure there's room for the number's magnitude, plus
547 the negative suffix, plus (if negative) the negative
549 width = rounder_width (r, decimals, &integer_digits, &add_neg_prefix);
550 width += ss_length (style->neg_suffix);
552 width += ss_length (style->neg_prefix);
553 if (width > format->w)
556 /* If there's room for the prefix and suffix, allocate
557 space. If the affixes are required, but there's no
559 add_affixes = allocate_space (fmt_affix_width (style),
561 if (!add_affixes && require_affixes)
564 /* Check whether we should include grouping characters.
565 We need room for a complete set or we don't insert any at all.
566 We don't include grouping characters if decimal places were
567 requested but they were all dropped. */
568 add_grouping = (style->grouping != 0
569 && integer_digits > 3
570 && (format->d == 0 || decimals > 0)
571 && allocate_space ((integer_digits - 1) / 3,
574 /* Format the number's magnitude. */
575 rounder_format (r, decimals, magnitude);
577 /* Assemble number. */
579 if (format->w > width)
580 p = mempset (p, ' ', format->w - width);
582 p = mempcpy (p, ss_data (style->neg_prefix),
583 ss_length (style->neg_prefix));
585 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
587 p = mempcpy (p, magnitude, integer_digits);
591 for (i = 0; i < integer_digits; i++)
593 if (i > 0 && (integer_digits - i) % 3 == 0)
594 *p++ = style->grouping;
600 *p++ = style->decimal;
601 p = mempcpy (p, &magnitude[integer_digits + 1], decimals);
604 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
606 p = mempcpy (p, ss_data (style->neg_suffix),
607 ss_length (style->neg_suffix));
609 p = mempset (p, ' ', ss_length (style->neg_suffix));
610 assert (p == output + format->w);
617 /* Formats NUMBER into OUTPUT in scientific notation according to
618 the style of the format specified in FORMAT. */
620 output_scientific (double number, const struct fmt_spec *format,
621 bool require_affixes, char *output)
623 const struct fmt_number_style *style =
624 settings_get_style (format->type);
630 /* Allocate minimum required space. */
631 width = 6 + ss_length (style->neg_suffix);
633 width += ss_length (style->neg_prefix);
634 if (width > format->w)
637 /* Check for room for prefix and suffix. */
638 add_affixes = allocate_space (fmt_affix_width (style), format->w, &width);
639 if (require_affixes && !add_affixes)
642 /* Figure out number of characters we can use for the fraction,
643 if any. (If that turns out to be 1, then we'll output a
644 decimal point without any digits following; that's what the
645 # flag does in the call to sprintf, below.) */
646 fraction_width = MIN (MIN (format->d + 1, format->w - width), 16);
647 if (format->type != FMT_E && fraction_width == 1)
649 width += fraction_width;
651 /* Format (except suffix). */
653 if (width < format->w)
654 p = mempset (p, ' ', format->w - width);
656 p = mempcpy (p, ss_data (style->neg_prefix),
657 ss_length (style->neg_prefix));
659 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
660 if (fraction_width > 0)
661 sprintf (p, "%#.*E", fraction_width - 1, fabs (number));
663 sprintf (p, "%.0E", fabs (number));
665 /* The C locale always uses a period `.' as a decimal point.
666 Translate to comma if necessary. */
667 if (style->decimal != '.')
669 char *cp = strchr (p, '.');
671 *cp = style->decimal;
674 /* Make exponent have exactly three digits, plus sign. */
676 char *cp = strchr (p, 'E') + 1;
677 long int exponent = strtol (cp, NULL, 10);
678 if (abs (exponent) > 999)
680 sprintf (cp, "%+04ld", exponent);
684 p = strchr (p, '\0');
686 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
688 p = mempcpy (p, ss_data (style->neg_suffix),
689 ss_length (style->neg_suffix));
691 p = mempset (p, ' ', ss_length (style->neg_suffix));
693 assert (p == buf + format->w);
694 memcpy (output, buf, format->w);
699 /* Returns true if the magnitude represented by R should be
700 rounded up when chopped off at DECIMALS decimal places, false
701 if it should be rounded down. */
703 should_round_up (const struct rounder *r, int decimals)
705 int digit = r->string[r->integer_digits + decimals + 1];
706 assert (digit >= '0' && digit <= '9');
710 /* Initializes R for formatting the magnitude of NUMBER to no
711 more than MAX_DECIMAL decimal places. */
713 rounder_init (struct rounder *r, double number, int max_decimals)
715 assert (fabs (number) < 1e41);
716 assert (max_decimals >= 0 && max_decimals <= 16);
717 if (max_decimals == 0)
719 /* Fast path. No rounding needed.
721 We append ".00" to the integer representation because
722 round_up assumes that fractional digits are present. */
723 sprintf (r->string, "%.0f.00", fabs (round (number)));
729 This is more difficult than it really should be because
730 we have to make sure that numbers that are exactly
731 halfway between two representations are always rounded
732 away from zero. This is not what sprintf normally does
733 (usually it rounds to even), so we have to fake it as
734 best we can, by formatting with extra precision and then
735 doing the rounding ourselves.
737 We take up to two rounds to format numbers. In the
738 first round, we obtain 2 digits of precision beyond
739 those requested by the user. If those digits are
740 exactly "50", then in a second round we format with as
741 many digits as are significant in a "double".
743 It might be better to directly implement our own
744 floating-point formatting routine instead of relying on
745 the system's sprintf implementation. But the classic
746 Steele and White paper on printing floating-point
747 numbers does not hint how to do what we want, and it's
748 not obvious how to change their algorithms to do so. It
749 would also be a lot of work. */
750 sprintf (r->string, "%.*f", max_decimals + 2, fabs (number));
751 if (!strcmp (r->string + strlen (r->string) - 2, "50"))
753 int binary_exponent, decimal_exponent, format_decimals;
754 frexp (number, &binary_exponent);
755 decimal_exponent = binary_exponent * 3 / 10;
756 format_decimals = (DBL_DIG + 1) - decimal_exponent;
757 if (format_decimals > max_decimals + 2)
758 sprintf (r->string, "%.*f", format_decimals, fabs (number));
762 if (r->string[0] == '0')
763 memmove (r->string, &r->string[1], strlen (r->string));
765 r->leading_zeros = strspn (r->string, "0.");
766 r->leading_nines = strspn (r->string, "9.");
767 r->integer_digits = strchr (r->string, '.') - r->string;
768 r->negative = number < 0;
771 /* Returns the number of characters required to format the
772 magnitude represented by R to DECIMALS decimal places.
773 The return value includes integer digits and a decimal point
774 and fractional digits, if any, but it does not include any
775 negative prefix or suffix or other affixes.
777 *INTEGER_DIGITS is set to the number of digits before the
778 decimal point in the output, between 0 and 40.
780 If R represents a negative number and its rounded
781 representation would include at least one nonzero digit,
782 *NEGATIVE is set to true; otherwise, it is set to false. */
784 rounder_width (const struct rounder *r, int decimals,
785 int *integer_digits, bool *negative)
787 /* Calculate base measures. */
788 int width = r->integer_digits;
790 width += decimals + 1;
791 *integer_digits = r->integer_digits;
792 *negative = r->negative;
794 /* Rounding can cause adjustments. */
795 if (should_round_up (r, decimals))
797 /* Rounding up leading 9s adds a new digit (a 1). */
798 if (r->leading_nines >= width)
807 if (r->leading_zeros >= width)
809 /* All digits that remain after rounding are zeros.
810 Therefore we drop the negative sign. */
812 if (r->integer_digits == 0 && decimals == 0)
814 /* No digits at all are left. We need to display
815 at least a single digit (a zero). */
825 /* Formats the magnitude represented by R into OUTPUT, rounding
826 to DECIMALS decimal places. Exactly as many characters as
827 indicated by rounder_width are written. No terminating null
830 rounder_format (const struct rounder *r, int decimals, char *output)
832 int base_width = r->integer_digits + (decimals > 0 ? decimals + 1 : 0);
833 if (should_round_up (r, decimals))
835 if (r->leading_nines < base_width)
837 /* Rounding up. This is the common case where rounding
838 up doesn't add an extra digit. */
840 memcpy (output, r->string, base_width);
841 for (p = output + base_width - 1; ; p--)
843 assert (p >= output);
846 else if (*p >= '0' && *p <= '8')
857 /* Rounding up leading 9s causes the result to be a 1
858 followed by a number of 0s, plus a decimal point. */
861 p = mempset (p, '0', r->integer_digits);
865 p = mempset (p, '0', decimals);
867 assert (p == output + base_width + 1);
873 if (r->integer_digits != 0 || decimals != 0)
875 /* Common case: just copy the digits. */
876 memcpy (output, r->string, base_width);
880 /* No digits remain. The output is just a zero. */
886 /* Helper functions. */
889 static double PURE_FUNCTION
892 static const double p[] =
894 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
895 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
896 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
897 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
900 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (10.0, x);
903 /* Returns 256**X. */
904 static double PURE_FUNCTION
907 static const double p[] =
917 18446744073709551616.0
919 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (256.0, x);
922 /* Formats non-finite NUMBER into OUTPUT according to the width
925 output_infinite (double number, const struct fmt_spec *format, char *output)
927 assert (!isfinite (number));
935 else if (isinf (number))
936 s = number > 0 ? "+Infinity" : "-Infinity";
940 buf_copy_str_lpad (output, format->w, s, ' ');
943 output_overflow (format, output);
946 /* Formats OUTPUT as a missing value for the given FORMAT. */
948 output_missing (const struct fmt_spec *format, char *output)
950 memset (output, ' ', format->w);
952 if (format->type != FMT_N)
954 int dot_ofs = (format->type == FMT_PCT ? 2
955 : format->type == FMT_E ? 5
957 output[MAX (0, format->w - format->d - dot_ofs)] = '.';
960 output[format->w - 1] = '.';
963 /* Formats OUTPUT for overflow given FORMAT. */
965 output_overflow (const struct fmt_spec *format, char *output)
967 memset (output, '*', format->w);
970 /* Converts the integer part of NUMBER to a packed BCD number
971 with the given number of DIGITS in OUTPUT. If DIGITS is odd,
972 the least significant nibble of the final byte in OUTPUT is
973 set to 0. Returns true if successful, false if NUMBER is not
974 representable. On failure, OUTPUT is cleared to all zero
977 output_bcd_integer (double number, int digits, char *output)
981 assert (digits < sizeof decimal);
984 && number < power10 (digits)
985 && sprintf (decimal, "%0*.0f", digits, round (number)) == digits)
987 const char *src = decimal;
990 for (i = 0; i < digits / 2; i++)
992 int d0 = *src++ - '0';
993 int d1 = *src++ - '0';
994 *output++ = (d0 << 4) + d1;
997 *output = (*src - '0') << 4;
1003 memset (output, 0, DIV_RND_UP (digits, 2));
1008 /* Writes VALUE to OUTPUT as a BYTES-byte binary integer of the
1009 given INTEGER_FORMAT. */
1011 output_binary_integer (uint64_t value, int bytes,
1012 enum integer_format integer_format, char *output)
1014 integer_put (value, integer_format, output, bytes);
1017 /* Converts the BYTES bytes in DATA to twice as many hexadecimal
1018 digits in OUTPUT. */
1020 output_hex (const void *data_, size_t bytes, char *output)
1022 const uint8_t *data = data_;
1025 for (i = 0; i < bytes; i++)
1027 static const char hex_digits[] = "0123456789ABCDEF";
1028 *output++ = hex_digits[data[i] >> 4];
1029 *output++ = hex_digits[data[i] & 15];