1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006 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 /* Converts the INPUT value into printable form in the exactly
87 FORMAT->W characters in OUTPUT according to format
88 specification FORMAT. The output is recoded from native form
89 into the given legacy character ENCODING. No null terminator
90 is appended to the buffer. */
92 data_out_legacy (const union value *input, enum legacy_encoding encoding,
93 const struct fmt_spec *format, char *output)
95 static data_out_converter_func *const converters[FMT_NUMBER_OF_FORMATS] =
97 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) output_##METHOD,
101 assert (fmt_check_output (format));
103 converters[format->type] (input, format, output);
104 if (encoding != LEGACY_NATIVE
105 && fmt_get_category (format->type) != FMT_CAT_BINARY)
106 legacy_recode (LEGACY_NATIVE, output, encoding, output, format->w);
109 /* Same as data_out_legacy with ENCODING set to LEGACY_NATIVE. */
111 data_out (const union value *value, const struct fmt_spec *format,
114 return data_out_legacy (value, LEGACY_NATIVE, format, output);
118 /* Main conversion functions. */
120 /* Outputs F, COMMA, DOT, DOLLAR, PCT, E, CCA, CCB, CCC, CCD, and
123 output_number (const union value *input, const struct fmt_spec *format,
126 double number = input->f;
128 if (number == SYSMIS)
129 output_missing (format, output);
130 else if (!isfinite (number))
131 output_infinite (number, format, output);
134 if (format->type != FMT_E && fabs (number) < 1.5 * power10 (format->w))
137 rounder_init (&r, number, format->d);
139 if (output_decimal (&r, format, true, output)
140 || output_scientific (number, format, true, output)
141 || output_decimal (&r, format, false, output))
145 if (!output_scientific (number, format, false, output))
146 output_overflow (format, output);
150 /* Outputs N format. */
152 output_N (const union value *input, const struct fmt_spec *format,
155 double number = input->f * power10 (format->d);
156 if (input->f == SYSMIS || number < 0)
157 output_missing (format, output);
161 number = fabs (round (number));
162 if (number < power10 (format->w)
163 && sprintf (buf, "%0*.0f", format->w, number) == format->w)
164 memcpy (output, buf, format->w);
166 output_overflow (format, output);
170 /* Outputs Z format. */
172 output_Z (const union value *input, const struct fmt_spec *format,
175 double number = input->f * power10 (format->d);
177 if (input->f == SYSMIS)
178 output_missing (format, output);
179 else if (fabs (number) >= power10 (format->w)
180 || sprintf (buf, "%0*.0f", format->w,
181 fabs (round (number))) != format->w)
182 output_overflow (format, output);
185 if (number < 0 && strspn (buf, "0") < format->w)
187 char *p = &buf[format->w - 1];
188 *p = "}JKLMNOPQR"[*p - '0'];
190 memcpy (output, buf, format->w);
194 /* Outputs P format. */
196 output_P (const union value *input, const struct fmt_spec *format,
199 if (output_bcd_integer (fabs (input->f * power10 (format->d)),
200 format->w * 2 - 1, output)
202 output[format->w - 1] |= 0xd;
204 output[format->w - 1] |= 0xf;
207 /* Outputs PK format. */
209 output_PK (const union value *input, const struct fmt_spec *format,
212 output_bcd_integer (input->f * power10 (format->d), format->w * 2, output);
215 /* Outputs IB format. */
217 output_IB (const union value *input, const struct fmt_spec *format,
220 double number = round (input->f * power10 (format->d));
221 if (input->f == SYSMIS
222 || number >= power256 (format->w) / 2 - 1
223 || number < -power256 (format->w) / 2)
224 memset (output, 0, format->w);
227 uint64_t integer = fabs (number);
230 output_binary_integer (integer, format->w,
231 settings_get_output_integer_format (),
236 /* Outputs PIB format. */
238 output_PIB (const union value *input, const struct fmt_spec *format,
241 double number = round (input->f * power10 (format->d));
242 if (input->f == SYSMIS
243 || number < 0 || number >= power256 (format->w))
244 memset (output, 0, format->w);
246 output_binary_integer (number, format->w,
247 settings_get_output_integer_format (), output);
250 /* Outputs PIBHEX format. */
252 output_PIBHEX (const union value *input, const struct fmt_spec *format,
255 double number = round (input->f);
256 if (input->f == SYSMIS)
257 output_missing (format, output);
258 else if (input->f < 0 || number >= power256 (format->w / 2))
259 output_overflow (format, output);
263 output_binary_integer (number, format->w / 2, INTEGER_MSB_FIRST, tmp);
264 output_hex (tmp, format->w / 2, output);
268 /* Outputs RB format. */
270 output_RB (const union value *input, const struct fmt_spec *format,
274 memcpy (output, &d, format->w);
277 /* Outputs RBHEX format. */
279 output_RBHEX (const union value *input, const struct fmt_spec *format,
283 output_hex (&d, format->w / 2, output);
286 /* Outputs DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, WKYR,
287 DATETIME, TIME, and DTIME formats. */
289 output_date (const union value *input, const struct fmt_spec *format,
292 double number = input->f;
293 int year, month, day, yday;
295 const char *template = fmt_date_template (format->type);
296 size_t template_width = strlen (template);
297 int excess_width = format->w - template_width;
302 assert (format->w >= template_width);
303 if (number == SYSMIS)
306 if (fmt_get_category (format->type) == FMT_CAT_DATE)
310 calendar_offset_to_gregorian (number / 60. / 60. / 24.,
311 &year, &month, &day, &yday);
312 number = fmod (number, 60. * 60. * 24.);
315 year = month = day = yday = 0;
317 while (*template != '\0')
321 while (template[count] == ch)
329 p += sprintf (p, "%02d", day);
331 p += sprintf (p, "%03d", yday);
335 p += sprintf (p, "%02d", month);
338 static const char *const months[12] =
340 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
341 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
343 p = stpcpy (p, months[month - 1]);
347 if (count >= 4 || excess_width >= 2)
350 p += sprintf (p, "%04d", year);
351 else if (format->type == FMT_DATETIME)
352 p = stpcpy (p, "****");
358 int epoch = settings_get_epoch ();
359 int offset = year - epoch;
360 if (offset < 0 || offset > 99)
362 p += sprintf (p, "%02d", abs (year) % 100);
366 p += sprintf (p, "%d", (month - 1) / 3 + 1);
369 p += sprintf (p, "%2d", (yday - 1) / 7 + 1);
374 number = fabs (number);
375 p += sprintf (p, "%*.0f", count, floor (number / 60. / 60. / 24.));
376 number = fmod (number, 60. * 60. * 24.);
381 number = fabs (number);
382 p += sprintf (p, "%0*.0f", count, floor (number / 60. / 60.));
383 number = fmod (number, 60. * 60.);
386 p += sprintf (p, "%02d", (int) floor (number / 60.));
387 number = fmod (number, 60.);
388 excess_width = format->w - (p - tmp);
389 if (excess_width < 0)
391 if (excess_width == 3 || excess_width == 4
392 || (excess_width >= 5 && format->d == 0))
393 p += sprintf (p, ":%02d", (int) number);
394 else if (excess_width >= 5)
396 int d = MIN (format->d, excess_width - 4);
398 sprintf (p, ":%0*.*f", w, d, number);
399 if (settings_get_decimal_char (FMT_F) != '.')
401 char *cp = strchr (p, '.');
403 *cp = settings_get_decimal_char (FMT_F);
418 buf_copy_lpad (output, format->w, tmp, p - tmp);
422 output_overflow (format, output);
426 output_missing (format, output);
430 /* Outputs WKDAY format. */
432 output_WKDAY (const union value *input, const struct fmt_spec *format,
435 static const char *const weekdays[7] =
437 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
438 "THURSDAY", "FRIDAY", "SATURDAY",
441 if (input->f >= 1 && input->f < 8)
442 buf_copy_str_rpad (output, format->w, weekdays[(int) input->f - 1]);
445 if (input->f != SYSMIS)
446 msg (ME, _("Weekday number %f is not between 1 and 7."), input->f);
447 output_missing (format, output);
451 /* Outputs MONTH format. */
453 output_MONTH (const union value *input, const struct fmt_spec *format,
456 static const char *const months[12] =
458 "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
459 "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
462 if (input->f >= 1 && input->f < 13)
463 buf_copy_str_rpad (output, format->w, months[(int) input->f - 1]);
466 if (input->f != SYSMIS)
467 msg (ME, _("Month number %f is not between 1 and 12."), input->f);
468 output_missing (format, output);
472 /* Outputs A format. */
474 output_A (const union value *input, const struct fmt_spec *format,
477 memcpy (output, input->s, format->w);
480 /* Outputs AHEX format. */
482 output_AHEX (const union value *input, const struct fmt_spec *format,
485 output_hex (input->s, format->w / 2, output);
488 /* Decimal and scientific formatting. */
490 /* If REQUEST plus the current *WIDTH fits within MAX_WIDTH,
491 increments *WIDTH by REQUEST and return true.
492 Otherwise returns false without changing *WIDTH. */
494 allocate_space (int request, int max_width, int *width)
496 assert (*width <= max_width);
497 if (request + *width <= max_width)
506 /* Tries to compose the number represented by R, in the style of
507 FORMAT, into OUTPUT. Returns true if successful, false on
508 failure, which occurs if FORMAT's width is too narrow. If
509 REQUIRE_AFFIXES is true, then the prefix and suffix specified
510 by FORMAT's style must be included; otherwise, they may be
511 omitted to make the number fit. */
513 output_decimal (const struct rounder *r, const struct fmt_spec *format,
514 bool require_affixes, char *output)
516 const struct fmt_number_style *style =
517 settings_get_style (format->type);
521 for (decimals = format->d; decimals >= 0; decimals--)
523 /* Formatted version of magnitude of NUMBER. */
526 /* Number of digits in MAGNITUDE's integer and fractional parts. */
529 /* Amount of space within the field width already claimed.
530 Initially this is the width of MAGNITUDE, then it is reduced
531 in stages as space is allocated to prefixes and suffixes and
532 grouping characters. */
535 /* Include various decorations? */
540 /* Position in output. */
543 /* Make sure there's room for the number's magnitude, plus
544 the negative suffix, plus (if negative) the negative
546 width = rounder_width (r, decimals, &integer_digits, &add_neg_prefix);
547 width += ss_length (style->neg_suffix);
549 width += ss_length (style->neg_prefix);
550 if (width > format->w)
553 /* If there's room for the prefix and suffix, allocate
554 space. If the affixes are required, but there's no
556 add_affixes = allocate_space (fmt_affix_width (style),
558 if (!add_affixes && require_affixes)
561 /* Check whether we should include grouping characters.
562 We need room for a complete set or we don't insert any at all.
563 We don't include grouping characters if decimal places were
564 requested but they were all dropped. */
565 add_grouping = (style->grouping != 0
566 && integer_digits > 3
567 && (format->d == 0 || decimals > 0)
568 && allocate_space ((integer_digits - 1) / 3,
571 /* Format the number's magnitude. */
572 rounder_format (r, decimals, magnitude);
574 /* Assemble number. */
576 if (format->w > width)
577 p = mempset (p, ' ', format->w - width);
579 p = mempcpy (p, ss_data (style->neg_prefix),
580 ss_length (style->neg_prefix));
582 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
584 p = mempcpy (p, magnitude, integer_digits);
588 for (i = 0; i < integer_digits; i++)
590 if (i > 0 && (integer_digits - i) % 3 == 0)
591 *p++ = style->grouping;
597 *p++ = style->decimal;
598 p = mempcpy (p, &magnitude[integer_digits + 1], decimals);
601 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
603 p = mempcpy (p, ss_data (style->neg_suffix),
604 ss_length (style->neg_suffix));
606 p = mempset (p, ' ', ss_length (style->neg_suffix));
607 assert (p == output + format->w);
614 /* Formats NUMBER into OUTPUT in scientific notation according to
615 the style of the format specified in FORMAT. */
617 output_scientific (double number, const struct fmt_spec *format,
618 bool require_affixes, char *output)
620 const struct fmt_number_style *style =
621 settings_get_style (format->type);
627 /* Allocate minimum required space. */
628 width = 6 + ss_length (style->neg_suffix);
630 width += ss_length (style->neg_prefix);
631 if (width > format->w)
634 /* Check for room for prefix and suffix. */
635 add_affixes = allocate_space (fmt_affix_width (style), format->w, &width);
636 if (require_affixes && !add_affixes)
639 /* Figure out number of characters we can use for the fraction,
640 if any. (If that turns out to be 1, then we'll output a
641 decimal point without any digits following; that's what the
642 # flag does in the call to sprintf, below.) */
643 fraction_width = MIN (MIN (format->d + 1, format->w - width), 16);
644 if (format->type != FMT_E && fraction_width == 1)
646 width += fraction_width;
648 /* Format (except suffix). */
650 if (width < format->w)
651 p = mempset (p, ' ', format->w - width);
653 p = mempcpy (p, ss_data (style->neg_prefix),
654 ss_length (style->neg_prefix));
656 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
657 if (fraction_width > 0)
658 sprintf (p, "%#.*E", fraction_width - 1, fabs (number));
660 sprintf (p, "%.0E", fabs (number));
662 /* The C locale always uses a period `.' as a decimal point.
663 Translate to comma if necessary. */
664 if (style->decimal != '.')
666 char *cp = strchr (p, '.');
668 *cp = style->decimal;
671 /* Make exponent have exactly three digits, plus sign. */
673 char *cp = strchr (p, 'E') + 1;
674 long int exponent = strtol (cp, NULL, 10);
675 if (abs (exponent) > 999)
677 sprintf (cp, "%+04ld", exponent);
681 p = strchr (p, '\0');
683 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
685 p = mempcpy (p, ss_data (style->neg_suffix),
686 ss_length (style->neg_suffix));
688 p = mempset (p, ' ', ss_length (style->neg_suffix));
690 assert (p == buf + format->w);
691 memcpy (output, buf, format->w);
696 /* Returns true if the magnitude represented by R should be
697 rounded up when chopped off at DECIMALS decimal places, false
698 if it should be rounded down. */
700 should_round_up (const struct rounder *r, int decimals)
702 int digit = r->string[r->integer_digits + decimals + 1];
703 assert (digit >= '0' && digit <= '9');
707 /* Initializes R for formatting the magnitude of NUMBER to no
708 more than MAX_DECIMAL decimal places. */
710 rounder_init (struct rounder *r, double number, int max_decimals)
712 assert (fabs (number) < 1e41);
713 assert (max_decimals >= 0 && max_decimals <= 16);
714 if (max_decimals == 0)
716 /* Fast path. No rounding needed.
718 We append ".00" to the integer representation because
719 round_up assumes that fractional digits are present. */
720 sprintf (r->string, "%.0f.00", fabs (round (number)));
726 This is more difficult than it really should be because
727 we have to make sure that numbers that are exactly
728 halfway between two representations are always rounded
729 away from zero. This is not what sprintf normally does
730 (usually it rounds to even), so we have to fake it as
731 best we can, by formatting with extra precision and then
732 doing the rounding ourselves.
734 We take up to two rounds to format numbers. In the
735 first round, we obtain 2 digits of precision beyond
736 those requested by the user. If those digits are
737 exactly "50", then in a second round we format with as
738 many digits as are significant in a "double".
740 It might be better to directly implement our own
741 floating-point formatting routine instead of relying on
742 the system's sprintf implementation. But the classic
743 Steele and White paper on printing floating-point
744 numbers does not hint how to do what we want, and it's
745 not obvious how to change their algorithms to do so. It
746 would also be a lot of work. */
747 sprintf (r->string, "%.*f", max_decimals + 2, fabs (number));
748 if (!strcmp (r->string + strlen (r->string) - 2, "50"))
750 int binary_exponent, decimal_exponent, format_decimals;
751 frexp (number, &binary_exponent);
752 decimal_exponent = binary_exponent * 3 / 10;
753 format_decimals = (DBL_DIG + 1) - decimal_exponent;
754 if (format_decimals > max_decimals + 2)
755 sprintf (r->string, "%.*f", format_decimals, fabs (number));
759 if (r->string[0] == '0')
760 memmove (r->string, &r->string[1], strlen (r->string));
762 r->leading_zeros = strspn (r->string, "0.");
763 r->leading_nines = strspn (r->string, "9.");
764 r->integer_digits = strchr (r->string, '.') - r->string;
765 r->negative = number < 0;
768 /* Returns the number of characters required to format the
769 magnitude represented by R to DECIMALS decimal places.
770 The return value includes integer digits and a decimal point
771 and fractional digits, if any, but it does not include any
772 negative prefix or suffix or other affixes.
774 *INTEGER_DIGITS is set to the number of digits before the
775 decimal point in the output, between 0 and 40.
777 If R represents a negative number and its rounded
778 representation would include at least one nonzero digit,
779 *NEGATIVE is set to true; otherwise, it is set to false. */
781 rounder_width (const struct rounder *r, int decimals,
782 int *integer_digits, bool *negative)
784 /* Calculate base measures. */
785 int width = r->integer_digits;
787 width += decimals + 1;
788 *integer_digits = r->integer_digits;
789 *negative = r->negative;
791 /* Rounding can cause adjustments. */
792 if (should_round_up (r, decimals))
794 /* Rounding up leading 9s adds a new digit (a 1). */
795 if (r->leading_nines >= width)
804 if (r->leading_zeros >= width)
806 /* All digits that remain after rounding are zeros.
807 Therefore we drop the negative sign. */
809 if (r->integer_digits == 0 && decimals == 0)
811 /* No digits at all are left. We need to display
812 at least a single digit (a zero). */
822 /* Formats the magnitude represented by R into OUTPUT, rounding
823 to DECIMALS decimal places. Exactly as many characters as
824 indicated by rounder_width are written. No terminating null
827 rounder_format (const struct rounder *r, int decimals, char *output)
829 int base_width = r->integer_digits + (decimals > 0 ? decimals + 1 : 0);
830 if (should_round_up (r, decimals))
832 if (r->leading_nines < base_width)
834 /* Rounding up. This is the common case where rounding
835 up doesn't add an extra digit. */
837 memcpy (output, r->string, base_width);
838 for (p = output + base_width - 1; ; p--)
840 assert (p >= output);
843 else if (*p >= '0' && *p <= '8')
854 /* Rounding up leading 9s causes the result to be a 1
855 followed by a number of 0s, plus a decimal point. */
858 p = mempset (p, '0', r->integer_digits);
862 p = mempset (p, '0', decimals);
864 assert (p == output + base_width + 1);
870 if (r->integer_digits != 0 || decimals != 0)
872 /* Common case: just copy the digits. */
873 memcpy (output, r->string, base_width);
877 /* No digits remain. The output is just a zero. */
883 /* Helper functions. */
886 static double PURE_FUNCTION
889 static const double p[] =
891 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
892 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
893 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
894 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
897 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (10.0, x);
900 /* Returns 256**X. */
901 static double PURE_FUNCTION
904 static const double p[] =
914 18446744073709551616.0
916 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (256.0, x);
919 /* Formats non-finite NUMBER into OUTPUT according to the width
922 output_infinite (double number, const struct fmt_spec *format, char *output)
924 assert (!isfinite (number));
932 else if (isinf (number))
933 s = number > 0 ? "+Infinity" : "-Infinity";
937 buf_copy_str_lpad (output, format->w, s);
940 output_overflow (format, output);
943 /* Formats OUTPUT as a missing value for the given FORMAT. */
945 output_missing (const struct fmt_spec *format, char *output)
947 memset (output, ' ', format->w);
949 if (format->type != FMT_N)
951 int dot_ofs = (format->type == FMT_PCT ? 2
952 : format->type == FMT_E ? 5
954 output[MAX (0, format->w - format->d - dot_ofs)] = '.';
957 output[format->w - 1] = '.';
960 /* Formats OUTPUT for overflow given FORMAT. */
962 output_overflow (const struct fmt_spec *format, char *output)
964 memset (output, '*', format->w);
967 /* Converts the integer part of NUMBER to a packed BCD number
968 with the given number of DIGITS in OUTPUT. If DIGITS is odd,
969 the least significant nibble of the final byte in OUTPUT is
970 set to 0. Returns true if successful, false if NUMBER is not
971 representable. On failure, OUTPUT is cleared to all zero
974 output_bcd_integer (double number, int digits, char *output)
978 assert (digits < sizeof decimal);
981 && number < power10 (digits)
982 && sprintf (decimal, "%0*.0f", digits, round (number)) == digits)
984 const char *src = decimal;
987 for (i = 0; i < digits / 2; i++)
989 int d0 = *src++ - '0';
990 int d1 = *src++ - '0';
991 *output++ = (d0 << 4) + d1;
994 *output = (*src - '0') << 4;
1000 memset (output, 0, DIV_RND_UP (digits, 2));
1005 /* Writes VALUE to OUTPUT as a BYTES-byte binary integer of the
1006 given INTEGER_FORMAT. */
1008 output_binary_integer (uint64_t value, int bytes,
1009 enum integer_format integer_format, char *output)
1011 integer_put (value, integer_format, output, bytes);
1014 /* Converts the BYTES bytes in DATA to twice as many hexadecimal
1015 digits in OUTPUT. */
1017 output_hex (const void *data_, size_t bytes, char *output)
1019 const uint8_t *data = data_;
1022 for (i = 0; i < bytes; i++)
1024 static const char hex_digits[] = "0123456789ABCDEF";
1025 *output++ = hex_digits[data[i] >> 4];
1026 *output++ = hex_digits[data[i] & 15];