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/>. */
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/misc.h>
39 #include <libpspp/str.h>
44 #define _(msgid) gettext (msgid)
46 /* A representation of a number that can be quickly rounded to
47 any desired number of decimal places (up to a specified
51 char string[64]; /* Magnitude of number with excess precision. */
52 int integer_digits; /* Number of digits before decimal point. */
53 int leading_nines; /* Number of `9's or `.'s at start of string. */
54 int leading_zeros; /* Number of `0's or `.'s at start of string. */
55 bool negative; /* Is the number negative? */
58 static void rounder_init (struct rounder *, double number, int max_decimals);
59 static int rounder_width (const struct rounder *, int decimals,
60 int *integer_digits, bool *negative);
61 static void rounder_format (const struct rounder *, int decimals,
64 /* Format of integers in output (SET WIB). */
65 static enum integer_format output_integer_format = INTEGER_NATIVE;
67 /* Format of reals in output (SET WRB). */
68 static enum float_format output_float_format = FLOAT_NATIVE_DOUBLE;
70 typedef void data_out_converter_func (const union value *,
71 const struct fmt_spec *,
73 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) \
74 static data_out_converter_func output_##METHOD;
77 static bool output_decimal (const struct rounder *, const struct fmt_spec *,
78 bool require_affixes, char *);
79 static bool output_scientific (double, const struct fmt_spec *,
80 bool require_affixes, char *);
82 static double power10 (int) PURE_FUNCTION;
83 static double power256 (int) PURE_FUNCTION;
85 static void output_infinite (double, const struct fmt_spec *, char *);
86 static void output_missing (const struct fmt_spec *, char *);
87 static void output_overflow (const struct fmt_spec *, char *);
88 static bool output_bcd_integer (double, int digits, char *);
89 static void output_binary_integer (uint64_t, int bytes, enum integer_format,
91 static void output_hex (const void *, size_t bytes, char *);
93 /* Converts the INPUT value into printable form in the exactly
94 FORMAT->W characters in OUTPUT according to format
95 specification FORMAT. No null terminator is appended to the
98 data_out (const union value *input, const struct fmt_spec *format,
101 static data_out_converter_func *const converters[FMT_NUMBER_OF_FORMATS] =
103 #define FMT(NAME, METHOD, IMIN, OMIN, IO, CATEGORY) output_##METHOD,
104 #include "format.def"
107 assert (fmt_check_output (format));
109 converters[format->type] (input, format, output);
112 /* Returns the current output integer format. */
114 data_out_get_integer_format (void)
116 return output_integer_format;
119 /* Sets the output integer format to INTEGER_FORMAT. */
121 data_out_set_integer_format (enum integer_format integer_format)
123 output_integer_format = integer_format;
126 /* Returns the current output float format. */
128 data_out_get_float_format (void)
130 return output_float_format;
133 /* Sets the output float format to FLOAT_FORMAT. */
135 data_out_set_float_format (enum float_format float_format)
137 output_float_format = float_format;
140 /* Main conversion functions. */
142 /* Outputs F, COMMA, DOT, DOLLAR, PCT, E, CCA, CCB, CCC, CCD, and
145 output_number (const union value *input, const struct fmt_spec *format,
148 double number = input->f;
150 if (number == SYSMIS)
151 output_missing (format, output);
152 else if (!isfinite (number))
153 output_infinite (number, format, output);
156 if (format->type != FMT_E && fabs (number) < 1.5 * power10 (format->w))
159 rounder_init (&r, number, format->d);
161 if (output_decimal (&r, format, true, output)
162 || output_scientific (number, format, true, output)
163 || output_decimal (&r, format, false, output))
167 if (!output_scientific (number, format, false, output))
168 output_overflow (format, output);
172 /* Outputs N format. */
174 output_N (const union value *input, const struct fmt_spec *format,
177 double number = input->f * power10 (format->d);
178 if (input->f == SYSMIS || number < 0)
179 output_missing (format, output);
183 number = fabs (round (number));
184 if (number < power10 (format->w)
185 && sprintf (buf, "%0*.0f", format->w, number) == format->w)
186 memcpy (output, buf, format->w);
188 output_overflow (format, output);
192 /* Outputs Z format. */
194 output_Z (const union value *input, const struct fmt_spec *format,
197 double number = input->f * power10 (format->d);
199 if (input->f == SYSMIS)
200 output_missing (format, output);
201 else if (fabs (number) >= power10 (format->w)
202 || sprintf (buf, "%0*.0f", format->w,
203 fabs (round (number))) != format->w)
204 output_overflow (format, output);
207 if (number < 0 && strspn (buf, "0") < format->w)
209 char *p = &buf[format->w - 1];
210 *p = "}JKLMNOPQR"[*p - '0'];
212 memcpy (output, buf, format->w);
216 /* Outputs P format. */
218 output_P (const union value *input, const struct fmt_spec *format,
221 if (output_bcd_integer (fabs (input->f * power10 (format->d)),
222 format->w * 2 - 1, output)
224 output[format->w - 1] |= 0xd;
226 output[format->w - 1] |= 0xf;
229 /* Outputs PK format. */
231 output_PK (const union value *input, const struct fmt_spec *format,
234 output_bcd_integer (input->f * power10 (format->d), format->w * 2, output);
237 /* Outputs IB format. */
239 output_IB (const union value *input, const struct fmt_spec *format,
242 double number = round (input->f * power10 (format->d));
243 if (input->f == SYSMIS
244 || number >= power256 (format->w) / 2 - 1
245 || number < -power256 (format->w) / 2)
246 memset (output, 0, format->w);
249 uint64_t integer = fabs (number);
252 output_binary_integer (integer, format->w, output_integer_format,
257 /* Outputs PIB format. */
259 output_PIB (const union value *input, const struct fmt_spec *format,
262 double number = round (input->f * power10 (format->d));
263 if (input->f == SYSMIS
264 || number < 0 || number >= power256 (format->w))
265 memset (output, 0, format->w);
267 output_binary_integer (number, format->w, output_integer_format, output);
270 /* Outputs PIBHEX format. */
272 output_PIBHEX (const union value *input, const struct fmt_spec *format,
275 double number = round (input->f);
276 if (input->f == SYSMIS)
277 output_missing (format, output);
278 else if (input->f < 0 || number >= power256 (format->w / 2))
279 output_overflow (format, output);
283 output_binary_integer (number, format->w / 2, INTEGER_MSB_FIRST, tmp);
284 output_hex (tmp, format->w / 2, output);
288 /* Outputs RB format. */
290 output_RB (const union value *input, const struct fmt_spec *format,
294 memcpy (output, &d, format->w);
297 /* Outputs RBHEX format. */
299 output_RBHEX (const union value *input, const struct fmt_spec *format,
303 output_hex (&d, format->w / 2, output);
306 /* Outputs DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, WKYR,
307 DATETIME, TIME, and DTIME formats. */
309 output_date (const union value *input, const struct fmt_spec *format,
312 double number = input->f;
313 int year, month, day, yday;
315 const char *template = fmt_date_template (format->type);
316 size_t template_width = strlen (template);
317 int excess_width = format->w - template_width;
322 assert (format->w >= template_width);
323 if (number == SYSMIS)
326 if (fmt_get_category (format->type) == FMT_CAT_DATE)
330 calendar_offset_to_gregorian (number / 60. / 60. / 24.,
331 &year, &month, &day, &yday);
332 number = fmod (number, 60. * 60. * 24.);
335 year = month = day = yday = 0;
337 while (*template != '\0')
341 while (template[count] == ch)
349 p += sprintf (p, "%02d", day);
351 p += sprintf (p, "%03d", yday);
355 p += sprintf (p, "%02d", month);
358 static const char *months[12] =
360 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
361 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
363 p = stpcpy (p, months[month - 1]);
367 if (count >= 4 || excess_width >= 2)
370 p += sprintf (p, "%04d", year);
371 else if (format->type == FMT_DATETIME)
372 p = stpcpy (p, "****");
378 int offset = year - get_epoch ();
379 if (offset < 0 || offset > 99)
381 p += sprintf (p, "%02d", abs (year) % 100);
385 p += sprintf (p, "%d", (month - 1) / 3 + 1);
388 p += sprintf (p, "%2d", (yday - 1) / 7 + 1);
393 number = fabs (number);
394 p += sprintf (p, "%*.0f", count, floor (number / 60. / 60. / 24.));
395 number = fmod (number, 60. * 60. * 24.);
400 number = fabs (number);
401 p += sprintf (p, "%0*.0f", count, floor (number / 60. / 60.));
402 number = fmod (number, 60. * 60.);
405 p += sprintf (p, "%02d", (int) floor (number / 60.));
406 number = fmod (number, 60.);
407 excess_width = format->w - (p - tmp);
408 if (excess_width < 0)
410 if (excess_width == 3 || excess_width == 4
411 || (excess_width >= 5 && format->d == 0))
412 p += sprintf (p, ":%02d", (int) number);
413 else if (excess_width >= 5)
415 int d = MIN (format->d, excess_width - 4);
417 sprintf (p, ":%0*.*f", w, d, number);
418 if (fmt_decimal_char (FMT_F) != '.')
420 char *cp = strchr (p, '.');
422 *cp = fmt_decimal_char (FMT_F);
437 buf_copy_lpad (output, format->w, tmp, p - tmp);
441 output_overflow (format, output);
445 output_missing (format, output);
449 /* Outputs WKDAY format. */
451 output_WKDAY (const union value *input, const struct fmt_spec *format,
454 static const char *weekdays[7] =
456 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
457 "THURSDAY", "FRIDAY", "SATURDAY",
460 if (input->f >= 1 && input->f < 8)
461 buf_copy_str_rpad (output, format->w, weekdays[(int) input->f - 1]);
464 if (input->f != SYSMIS)
465 msg (ME, _("Weekday number %f is not between 1 and 7."), input->f);
466 output_missing (format, output);
470 /* Outputs MONTH format. */
472 output_MONTH (const union value *input, const struct fmt_spec *format,
475 static const char *months[12] =
477 "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
478 "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
481 if (input->f >= 1 && input->f < 13)
482 buf_copy_str_rpad (output, format->w, months[(int) input->f - 1]);
485 if (input->f != SYSMIS)
486 msg (ME, _("Month number %f is not between 1 and 12."), input->f);
487 output_missing (format, output);
491 /* Outputs A format. */
493 output_A (const union value *input, const struct fmt_spec *format,
496 memcpy (output, input->s, format->w);
499 /* Outputs AHEX format. */
501 output_AHEX (const union value *input, const struct fmt_spec *format,
504 output_hex (input->s, format->w, output);
507 /* Decimal and scientific formatting. */
509 /* If REQUEST plus the current *WIDTH fits within MAX_WIDTH,
510 increments *WIDTH by REQUEST and return true.
511 Otherwise returns false without changing *WIDTH. */
513 allocate_space (int request, int max_width, int *width)
515 assert (*width <= max_width);
516 if (request + *width <= max_width)
525 /* Tries to compose the number represented by R, in the style of
526 FORMAT, into OUTPUT. Returns true if successful, false on
527 failure, which occurs if FORMAT's width is too narrow. If
528 REQUIRE_AFFIXES is true, then the prefix and suffix specified
529 by FORMAT's style must be included; otherwise, they may be
530 omitted to make the number fit. */
532 output_decimal (const struct rounder *r, const struct fmt_spec *format,
533 bool require_affixes, char *output)
535 const struct fmt_number_style *style = fmt_get_style (format->type);
538 for (decimals = format->d; decimals >= 0; decimals--)
540 /* Formatted version of magnitude of NUMBER. */
543 /* Number of digits in MAGNITUDE's integer and fractional parts. */
546 /* Amount of space within the field width already claimed.
547 Initially this is the width of MAGNITUDE, then it is reduced
548 in stages as space is allocated to prefixes and suffixes and
549 grouping characters. */
552 /* Include various decorations? */
557 /* Position in output. */
560 /* Make sure there's room for the number's magnitude, plus
561 the negative suffix, plus (if negative) the negative
563 width = rounder_width (r, decimals, &integer_digits, &add_neg_prefix);
564 width += ss_length (style->neg_suffix);
566 width += ss_length (style->neg_prefix);
567 if (width > format->w)
570 /* If there's room for the prefix and suffix, allocate
571 space. If the affixes are required, but there's no
573 add_affixes = allocate_space (fmt_affix_width (style),
575 if (!add_affixes && require_affixes)
578 /* Check whether we should include grouping characters.
579 We need room for a complete set or we don't insert any at all.
580 We don't include grouping characters if decimal places were
581 requested but they were all dropped. */
582 add_grouping = (style->grouping != 0
583 && integer_digits > 3
584 && (format->d == 0 || decimals > 0)
585 && allocate_space ((integer_digits - 1) / 3,
588 /* Format the number's magnitude. */
589 rounder_format (r, decimals, magnitude);
591 /* Assemble number. */
593 if (format->w > width)
594 p = mempset (p, ' ', format->w - width);
596 p = mempcpy (p, ss_data (style->neg_prefix),
597 ss_length (style->neg_prefix));
599 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
601 p = mempcpy (p, magnitude, integer_digits);
605 for (i = 0; i < integer_digits; i++)
607 if (i > 0 && (integer_digits - i) % 3 == 0)
608 *p++ = style->grouping;
614 *p++ = style->decimal;
615 p = mempcpy (p, &magnitude[integer_digits + 1], decimals);
618 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
620 p = mempcpy (p, ss_data (style->neg_suffix),
621 ss_length (style->neg_suffix));
623 p = mempset (p, ' ', ss_length (style->neg_suffix));
624 assert (p == output + format->w);
631 /* Formats NUMBER into OUTPUT in scientific notation according to
632 the style of the format specified in FORMAT. */
634 output_scientific (double number, const struct fmt_spec *format,
635 bool require_affixes, char *output)
637 const struct fmt_number_style *style = fmt_get_style (format->type);
643 /* Allocate minimum required space. */
644 width = 6 + ss_length (style->neg_suffix);
646 width += ss_length (style->neg_prefix);
647 if (width > format->w)
650 /* Check for room for prefix and suffix. */
651 add_affixes = allocate_space (fmt_affix_width (style), format->w, &width);
652 if (require_affixes && !add_affixes)
655 /* Figure out number of characters we can use for the fraction,
656 if any. (If that turns out to be 1, then we'll output a
657 decimal point without any digits following; that's what the
658 # flag does in the call to sprintf, below.) */
659 fraction_width = MIN (MIN (format->d + 1, format->w - width), 16);
660 if (format->type != FMT_E && fraction_width == 1)
662 width += fraction_width;
664 /* Format (except suffix). */
666 if (width < format->w)
667 p = mempset (p, ' ', format->w - width);
669 p = mempcpy (p, ss_data (style->neg_prefix),
670 ss_length (style->neg_prefix));
672 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
673 if (fraction_width > 0)
674 sprintf (p, "%#.*E", fraction_width - 1, fabs (number));
676 sprintf (p, "%.0E", fabs (number));
678 /* The C locale always uses a period `.' as a decimal point.
679 Translate to comma if necessary. */
680 if (style->decimal != '.')
682 char *cp = strchr (p, '.');
684 *cp = style->decimal;
687 /* Make exponent have exactly three digits, plus sign. */
689 char *cp = strchr (p, 'E') + 1;
690 long int exponent = strtol (cp, NULL, 10);
691 if (abs (exponent) > 999)
693 sprintf (cp, "%+04ld", exponent);
697 p = strchr (p, '\0');
699 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
701 p = mempcpy (p, ss_data (style->neg_suffix),
702 ss_length (style->neg_suffix));
704 p = mempset (p, ' ', ss_length (style->neg_suffix));
706 assert (p == buf + format->w);
707 memcpy (output, buf, format->w);
712 /* Returns true if the magnitude represented by R should be
713 rounded up when chopped off at DECIMALS decimal places, false
714 if it should be rounded down. */
716 should_round_up (const struct rounder *r, int decimals)
718 int digit = r->string[r->integer_digits + decimals + 1];
719 assert (digit >= '0' && digit <= '9');
723 /* Initializes R for formatting the magnitude of NUMBER to no
724 more than MAX_DECIMAL decimal places. */
726 rounder_init (struct rounder *r, double number, int max_decimals)
728 assert (fabs (number) < 1e41);
729 assert (max_decimals >= 0 && max_decimals <= 16);
730 if (max_decimals == 0)
732 /* Fast path. No rounding needed.
734 We append ".00" to the integer representation because
735 round_up assumes that fractional digits are present. */
736 sprintf (r->string, "%.0f.00", fabs (round (number)));
742 This is more difficult than it really should be because
743 we have to make sure that numbers that are exactly
744 halfway between two representations are always rounded
745 away from zero. This is not what sprintf normally does
746 (usually it rounds to even), so we have to fake it as
747 best we can, by formatting with extra precision and then
748 doing the rounding ourselves.
750 We take up to two rounds to format numbers. In the
751 first round, we obtain 2 digits of precision beyond
752 those requested by the user. If those digits are
753 exactly "50", then in a second round we format with as
754 many digits as are significant in a "double".
756 It might be better to directly implement our own
757 floating-point formatting routine instead of relying on
758 the system's sprintf implementation. But the classic
759 Steele and White paper on printing floating-point
760 numbers does not hint how to do what we want, and it's
761 not obvious how to change their algorithms to do so. It
762 would also be a lot of work. */
763 sprintf (r->string, "%.*f", max_decimals + 2, fabs (number));
764 if (!strcmp (r->string + strlen (r->string) - 2, "50"))
766 int binary_exponent, decimal_exponent, format_decimals;
767 frexp (number, &binary_exponent);
768 decimal_exponent = binary_exponent * 3 / 10;
769 format_decimals = (DBL_DIG + 1) - decimal_exponent;
770 if (format_decimals > max_decimals + 2)
771 sprintf (r->string, "%.*f", format_decimals, fabs (number));
775 if (r->string[0] == '0')
776 memmove (r->string, &r->string[1], strlen (r->string));
778 r->leading_zeros = strspn (r->string, "0.");
779 r->leading_nines = strspn (r->string, "9.");
780 r->integer_digits = strchr (r->string, '.') - r->string;
781 r->negative = number < 0;
784 /* Returns the number of characters required to format the
785 magnitude represented by R to DECIMALS decimal places.
786 The return value includes integer digits and a decimal point
787 and fractional digits, if any, but it does not include any
788 negative prefix or suffix or other affixes.
790 *INTEGER_DIGITS is set to the number of digits before the
791 decimal point in the output, between 0 and 40.
793 If R represents a negative number and its rounded
794 representation would include at least one nonzero digit,
795 *NEGATIVE is set to true; otherwise, it is set to false. */
797 rounder_width (const struct rounder *r, int decimals,
798 int *integer_digits, bool *negative)
800 /* Calculate base measures. */
801 int width = r->integer_digits;
803 width += decimals + 1;
804 *integer_digits = r->integer_digits;
805 *negative = r->negative;
807 /* Rounding can cause adjustments. */
808 if (should_round_up (r, decimals))
810 /* Rounding up leading 9s adds a new digit (a 1). */
811 if (r->leading_nines >= width)
820 if (r->leading_zeros >= width)
822 /* All digits that remain after rounding are zeros.
823 Therefore we drop the negative sign. */
825 if (r->integer_digits == 0 && decimals == 0)
827 /* No digits at all are left. We need to display
828 at least a single digit (a zero). */
838 /* Formats the magnitude represented by R into OUTPUT, rounding
839 to DECIMALS decimal places. Exactly as many characters as
840 indicated by rounder_width are written. No terminating null
843 rounder_format (const struct rounder *r, int decimals, char *output)
845 int base_width = r->integer_digits + (decimals > 0 ? decimals + 1 : 0);
846 if (should_round_up (r, decimals))
848 if (r->leading_nines < base_width)
850 /* Rounding up. This is the common case where rounding
851 up doesn't add an extra digit. */
853 memcpy (output, r->string, base_width);
854 for (p = output + base_width - 1; ; p--)
856 assert (p >= output);
859 else if (*p >= '0' && *p <= '8')
870 /* Rounding up leading 9s causes the result to be a 1
871 followed by a number of 0s, plus a decimal point. */
874 p = mempset (p, '0', r->integer_digits);
878 p = mempset (p, '0', decimals);
880 assert (p == output + base_width + 1);
886 if (r->integer_digits != 0 || decimals != 0)
888 /* Common case: just copy the digits. */
889 memcpy (output, r->string, base_width);
893 /* No digits remain. The output is just a zero. */
899 /* Helper functions. */
902 static double PURE_FUNCTION
905 static const double p[] =
907 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
908 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
909 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
910 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
913 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (10.0, x);
916 /* Returns 256**X. */
917 static double PURE_FUNCTION
920 static const double p[] =
930 18446744073709551616.0
932 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (256.0, x);
935 /* Formats non-finite NUMBER into OUTPUT according to the width
938 output_infinite (double number, const struct fmt_spec *format, char *output)
940 assert (!isfinite (number));
948 else if (isinf (number))
949 s = number > 0 ? "+Infinity" : "-Infinity";
953 buf_copy_str_lpad (output, format->w, s);
956 output_overflow (format, output);
959 /* Formats OUTPUT as a missing value for the given FORMAT. */
961 output_missing (const struct fmt_spec *format, char *output)
963 memset (output, ' ', format->w);
965 if (format->type != FMT_N)
967 int dot_ofs = (format->type == FMT_PCT ? 2
968 : format->type == FMT_E ? 5
970 output[MAX (0, format->w - format->d - dot_ofs)] = '.';
973 output[format->w - 1] = '.';
976 /* Formats OUTPUT for overflow given FORMAT. */
978 output_overflow (const struct fmt_spec *format, char *output)
980 memset (output, '*', format->w);
983 /* Converts the integer part of NUMBER to a packed BCD number
984 with the given number of DIGITS in OUTPUT. If DIGITS is odd,
985 the least significant nibble of the final byte in OUTPUT is
986 set to 0. Returns true if successful, false if NUMBER is not
987 representable. On failure, OUTPUT is cleared to all zero
990 output_bcd_integer (double number, int digits, char *output)
994 assert (digits < sizeof decimal);
997 && number < power10 (digits)
998 && sprintf (decimal, "%0*.0f", digits, round (number)) == digits)
1000 const char *src = decimal;
1003 for (i = 0; i < digits / 2; i++)
1005 int d0 = *src++ - '0';
1006 int d1 = *src++ - '0';
1007 *output++ = (d0 << 4) + d1;
1010 *output = (*src - '0') << 4;
1016 memset (output, 0, DIV_RND_UP (digits, 2));
1021 /* Writes VALUE to OUTPUT as a BYTES-byte binary integer of the
1022 given INTEGER_FORMAT. */
1024 output_binary_integer (uint64_t value, int bytes,
1025 enum integer_format integer_format, char *output)
1027 integer_put (value, integer_format, output, bytes);
1030 /* Converts the BYTES bytes in DATA to twice as many hexadecimal
1031 digits in OUTPUT. */
1033 output_hex (const void *data_, size_t bytes, char *output)
1035 const uint8_t *data = data_;
1038 for (i = 0; i < bytes; i++)
1040 static const char hex_digits[] = "0123456789ABCDEF";
1041 *output++ = hex_digits[data[i] >> 4];
1042 *output++ = hex_digits[data[i] & 15];