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>
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, LEGACY_NATIVE)
108 && fmt_get_category (format->type) != FMT_CAT_BINARY)
110 char *s = recode_string (encoding, LEGACY_NATIVE, 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);
139 output[format->w] = '\0';
141 t = recode_string_pool (UTF8, encoding, output, format->w, pool);
147 data_out (const union value *input, const char *encoding, const struct fmt_spec *format)
149 return data_out_pool (input, encoding, format, NULL);
153 /* Main conversion functions. */
155 /* Outputs F, COMMA, DOT, DOLLAR, PCT, E, CCA, CCB, CCC, CCD, and
158 output_number (const union value *input, const struct fmt_spec *format,
161 double number = input->f;
163 if (number == SYSMIS)
164 output_missing (format, output);
165 else if (!isfinite (number))
166 output_infinite (number, format, output);
169 if (format->type != FMT_E && fabs (number) < 1.5 * power10 (format->w))
172 rounder_init (&r, number, format->d);
174 if (output_decimal (&r, format, true, output)
175 || output_scientific (number, format, true, output)
176 || output_decimal (&r, format, false, output))
180 if (!output_scientific (number, format, false, output))
181 output_overflow (format, output);
185 /* Outputs N format. */
187 output_N (const union value *input, const struct fmt_spec *format,
190 double number = input->f * power10 (format->d);
191 if (input->f == SYSMIS || number < 0)
192 output_missing (format, output);
196 number = fabs (round (number));
197 if (number < power10 (format->w)
198 && sprintf (buf, "%0*.0f", format->w, number) == format->w)
199 memcpy (output, buf, format->w);
201 output_overflow (format, output);
205 /* Outputs Z format. */
207 output_Z (const union value *input, const struct fmt_spec *format,
210 double number = input->f * power10 (format->d);
212 if (input->f == SYSMIS)
213 output_missing (format, output);
214 else if (fabs (number) >= power10 (format->w)
215 || sprintf (buf, "%0*.0f", format->w,
216 fabs (round (number))) != format->w)
217 output_overflow (format, output);
220 if (number < 0 && strspn (buf, "0") < format->w)
222 char *p = &buf[format->w - 1];
223 *p = "}JKLMNOPQR"[*p - '0'];
225 memcpy (output, buf, format->w);
229 /* Outputs P format. */
231 output_P (const union value *input, const struct fmt_spec *format,
234 if (output_bcd_integer (fabs (input->f * power10 (format->d)),
235 format->w * 2 - 1, output)
237 output[format->w - 1] |= 0xd;
239 output[format->w - 1] |= 0xf;
242 /* Outputs PK format. */
244 output_PK (const union value *input, const struct fmt_spec *format,
247 output_bcd_integer (input->f * power10 (format->d), format->w * 2, output);
250 /* Outputs IB format. */
252 output_IB (const union value *input, const struct fmt_spec *format,
255 double number = round (input->f * power10 (format->d));
256 if (input->f == SYSMIS
257 || number >= power256 (format->w) / 2 - 1
258 || number < -power256 (format->w) / 2)
259 memset (output, 0, format->w);
262 uint64_t integer = fabs (number);
265 output_binary_integer (integer, format->w,
266 settings_get_output_integer_format (),
271 /* Outputs PIB format. */
273 output_PIB (const union value *input, const struct fmt_spec *format,
276 double number = round (input->f * power10 (format->d));
277 if (input->f == SYSMIS
278 || number < 0 || number >= power256 (format->w))
279 memset (output, 0, format->w);
281 output_binary_integer (number, format->w,
282 settings_get_output_integer_format (), output);
285 /* Outputs PIBHEX format. */
287 output_PIBHEX (const union value *input, const struct fmt_spec *format,
290 double number = round (input->f);
291 if (input->f == SYSMIS)
292 output_missing (format, output);
293 else if (input->f < 0 || number >= power256 (format->w / 2))
294 output_overflow (format, output);
298 output_binary_integer (number, format->w / 2, INTEGER_MSB_FIRST, tmp);
299 output_hex (tmp, format->w / 2, output);
303 /* Outputs RB format. */
305 output_RB (const union value *input, const struct fmt_spec *format,
309 memcpy (output, &d, format->w);
312 /* Outputs RBHEX format. */
314 output_RBHEX (const union value *input, const struct fmt_spec *format,
318 output_hex (&d, format->w / 2, output);
321 /* Outputs DATE, ADATE, EDATE, JDATE, SDATE, QYR, MOYR, WKYR,
322 DATETIME, TIME, and DTIME formats. */
324 output_date (const union value *input, const struct fmt_spec *format,
327 double number = input->f;
328 int year, month, day, yday;
330 const char *template = fmt_date_template (format->type);
331 size_t template_width = strlen (template);
332 int excess_width = format->w - template_width;
337 assert (format->w >= template_width);
338 if (number == SYSMIS)
341 if (fmt_get_category (format->type) == FMT_CAT_DATE)
345 calendar_offset_to_gregorian (number / 60. / 60. / 24.,
346 &year, &month, &day, &yday);
347 number = fmod (number, 60. * 60. * 24.);
350 year = month = day = yday = 0;
352 while (*template != '\0')
356 while (template[count] == ch)
364 p += sprintf (p, "%02d", day);
366 p += sprintf (p, "%03d", yday);
370 p += sprintf (p, "%02d", month);
373 static const char *const months[12] =
375 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
376 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
378 p = stpcpy (p, months[month - 1]);
382 if (count >= 4 || excess_width >= 2)
385 p += sprintf (p, "%04d", year);
386 else if (format->type == FMT_DATETIME)
387 p = stpcpy (p, "****");
393 int epoch = settings_get_epoch ();
394 int offset = year - epoch;
395 if (offset < 0 || offset > 99)
397 p += sprintf (p, "%02d", abs (year) % 100);
401 p += sprintf (p, "%d", (month - 1) / 3 + 1);
404 p += sprintf (p, "%2d", (yday - 1) / 7 + 1);
409 number = fabs (number);
410 p += sprintf (p, "%*.0f", count, floor (number / 60. / 60. / 24.));
411 number = fmod (number, 60. * 60. * 24.);
416 number = fabs (number);
417 p += sprintf (p, "%0*.0f", count, floor (number / 60. / 60.));
418 number = fmod (number, 60. * 60.);
421 p += sprintf (p, "%02d", (int) floor (number / 60.));
422 number = fmod (number, 60.);
423 excess_width = format->w - (p - tmp);
424 if (excess_width < 0)
426 if (excess_width == 3 || excess_width == 4
427 || (excess_width >= 5 && format->d == 0))
428 p += sprintf (p, ":%02d", (int) number);
429 else if (excess_width >= 5)
431 int d = MIN (format->d, excess_width - 4);
433 sprintf (p, ":%0*.*f", w, d, number);
434 if (settings_get_decimal_char (FMT_F) != '.')
436 char *cp = strchr (p, '.');
438 *cp = settings_get_decimal_char (FMT_F);
453 buf_copy_lpad (output, format->w, tmp, p - tmp, ' ');
457 output_overflow (format, output);
461 output_missing (format, output);
465 /* Outputs WKDAY format. */
467 output_WKDAY (const union value *input, const struct fmt_spec *format,
470 static const char *const weekdays[7] =
472 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
473 "THURSDAY", "FRIDAY", "SATURDAY",
476 if (input->f >= 1 && input->f < 8)
477 buf_copy_str_rpad (output, format->w, weekdays[(int) input->f - 1], ' ');
480 if (input->f != SYSMIS)
481 msg (ME, _("Weekday number %f is not between 1 and 7."), input->f);
482 output_missing (format, output);
486 /* Outputs MONTH format. */
488 output_MONTH (const union value *input, const struct fmt_spec *format,
491 static const char *const months[12] =
493 "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
494 "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
497 if (input->f >= 1 && input->f < 13)
498 buf_copy_str_rpad (output, format->w, months[(int) input->f - 1], ' ');
501 if (input->f != SYSMIS)
502 msg (ME, _("Month number %f is not between 1 and 12."), input->f);
503 output_missing (format, output);
507 /* Outputs A format. */
509 output_A (const union value *input, const struct fmt_spec *format,
512 memcpy (output, value_str (input, format->w), format->w);
515 /* Outputs AHEX format. */
517 output_AHEX (const union value *input, const struct fmt_spec *format,
520 output_hex (value_str (input, format->w), format->w / 2, output);
523 /* Decimal and scientific formatting. */
525 /* If REQUEST plus the current *WIDTH fits within MAX_WIDTH,
526 increments *WIDTH by REQUEST and return true.
527 Otherwise returns false without changing *WIDTH. */
529 allocate_space (int request, int max_width, int *width)
531 assert (*width <= max_width);
532 if (request + *width <= max_width)
541 /* Tries to compose the number represented by R, in the style of
542 FORMAT, into OUTPUT. Returns true if successful, false on
543 failure, which occurs if FORMAT's width is too narrow. If
544 REQUIRE_AFFIXES is true, then the prefix and suffix specified
545 by FORMAT's style must be included; otherwise, they may be
546 omitted to make the number fit. */
548 output_decimal (const struct rounder *r, const struct fmt_spec *format,
549 bool require_affixes, char *output)
551 const struct fmt_number_style *style =
552 settings_get_style (format->type);
556 for (decimals = format->d; decimals >= 0; decimals--)
558 /* Formatted version of magnitude of NUMBER. */
561 /* Number of digits in MAGNITUDE's integer and fractional parts. */
564 /* Amount of space within the field width already claimed.
565 Initially this is the width of MAGNITUDE, then it is reduced
566 in stages as space is allocated to prefixes and suffixes and
567 grouping characters. */
570 /* Include various decorations? */
575 /* Position in output. */
578 /* Make sure there's room for the number's magnitude, plus
579 the negative suffix, plus (if negative) the negative
581 width = rounder_width (r, decimals, &integer_digits, &add_neg_prefix);
582 width += ss_length (style->neg_suffix);
584 width += ss_length (style->neg_prefix);
585 if (width > format->w)
588 /* If there's room for the prefix and suffix, allocate
589 space. If the affixes are required, but there's no
591 add_affixes = allocate_space (fmt_affix_width (style),
593 if (!add_affixes && require_affixes)
596 /* Check whether we should include grouping characters.
597 We need room for a complete set or we don't insert any at all.
598 We don't include grouping characters if decimal places were
599 requested but they were all dropped. */
600 add_grouping = (style->grouping != 0
601 && integer_digits > 3
602 && (format->d == 0 || decimals > 0)
603 && allocate_space ((integer_digits - 1) / 3,
606 /* Format the number's magnitude. */
607 rounder_format (r, decimals, magnitude);
609 /* Assemble number. */
611 if (format->w > width)
612 p = mempset (p, ' ', format->w - width);
614 p = mempcpy (p, ss_data (style->neg_prefix),
615 ss_length (style->neg_prefix));
617 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
619 p = mempcpy (p, magnitude, integer_digits);
623 for (i = 0; i < integer_digits; i++)
625 if (i > 0 && (integer_digits - i) % 3 == 0)
626 *p++ = style->grouping;
632 *p++ = style->decimal;
633 p = mempcpy (p, &magnitude[integer_digits + 1], decimals);
636 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
638 p = mempcpy (p, ss_data (style->neg_suffix),
639 ss_length (style->neg_suffix));
641 p = mempset (p, ' ', ss_length (style->neg_suffix));
642 assert (p == output + format->w);
649 /* Formats NUMBER into OUTPUT in scientific notation according to
650 the style of the format specified in FORMAT. */
652 output_scientific (double number, const struct fmt_spec *format,
653 bool require_affixes, char *output)
655 const struct fmt_number_style *style =
656 settings_get_style (format->type);
662 /* Allocate minimum required space. */
663 width = 6 + ss_length (style->neg_suffix);
665 width += ss_length (style->neg_prefix);
666 if (width > format->w)
669 /* Check for room for prefix and suffix. */
670 add_affixes = allocate_space (fmt_affix_width (style), format->w, &width);
671 if (require_affixes && !add_affixes)
674 /* Figure out number of characters we can use for the fraction,
675 if any. (If that turns out to be 1, then we'll output a
676 decimal point without any digits following; that's what the
677 # flag does in the call to sprintf, below.) */
678 fraction_width = MIN (MIN (format->d + 1, format->w - width), 16);
679 if (format->type != FMT_E && fraction_width == 1)
681 width += fraction_width;
683 /* Format (except suffix). */
685 if (width < format->w)
686 p = mempset (p, ' ', format->w - width);
688 p = mempcpy (p, ss_data (style->neg_prefix),
689 ss_length (style->neg_prefix));
691 p = mempcpy (p, ss_data (style->prefix), ss_length (style->prefix));
692 if (fraction_width > 0)
693 sprintf (p, "%#.*E", fraction_width - 1, fabs (number));
695 sprintf (p, "%.0E", fabs (number));
697 /* The C locale always uses a period `.' as a decimal point.
698 Translate to comma if necessary. */
699 if (style->decimal != '.')
701 char *cp = strchr (p, '.');
703 *cp = style->decimal;
706 /* Make exponent have exactly three digits, plus sign. */
708 char *cp = strchr (p, 'E') + 1;
709 long int exponent = strtol (cp, NULL, 10);
710 if (abs (exponent) > 999)
712 sprintf (cp, "%+04ld", exponent);
716 p = strchr (p, '\0');
718 p = mempcpy (p, ss_data (style->suffix), ss_length (style->suffix));
720 p = mempcpy (p, ss_data (style->neg_suffix),
721 ss_length (style->neg_suffix));
723 p = mempset (p, ' ', ss_length (style->neg_suffix));
725 assert (p == buf + format->w);
726 memcpy (output, buf, format->w);
731 /* Returns true if the magnitude represented by R should be
732 rounded up when chopped off at DECIMALS decimal places, false
733 if it should be rounded down. */
735 should_round_up (const struct rounder *r, int decimals)
737 int digit = r->string[r->integer_digits + decimals + 1];
738 assert (digit >= '0' && digit <= '9');
742 /* Initializes R for formatting the magnitude of NUMBER to no
743 more than MAX_DECIMAL decimal places. */
745 rounder_init (struct rounder *r, double number, int max_decimals)
747 assert (fabs (number) < 1e41);
748 assert (max_decimals >= 0 && max_decimals <= 16);
749 if (max_decimals == 0)
751 /* Fast path. No rounding needed.
753 We append ".00" to the integer representation because
754 round_up assumes that fractional digits are present. */
755 sprintf (r->string, "%.0f.00", fabs (round (number)));
761 This is more difficult than it really should be because
762 we have to make sure that numbers that are exactly
763 halfway between two representations are always rounded
764 away from zero. This is not what sprintf normally does
765 (usually it rounds to even), so we have to fake it as
766 best we can, by formatting with extra precision and then
767 doing the rounding ourselves.
769 We take up to two rounds to format numbers. In the
770 first round, we obtain 2 digits of precision beyond
771 those requested by the user. If those digits are
772 exactly "50", then in a second round we format with as
773 many digits as are significant in a "double".
775 It might be better to directly implement our own
776 floating-point formatting routine instead of relying on
777 the system's sprintf implementation. But the classic
778 Steele and White paper on printing floating-point
779 numbers does not hint how to do what we want, and it's
780 not obvious how to change their algorithms to do so. It
781 would also be a lot of work. */
782 sprintf (r->string, "%.*f", max_decimals + 2, fabs (number));
783 if (!strcmp (r->string + strlen (r->string) - 2, "50"))
785 int binary_exponent, decimal_exponent, format_decimals;
786 frexp (number, &binary_exponent);
787 decimal_exponent = binary_exponent * 3 / 10;
788 format_decimals = (DBL_DIG + 1) - decimal_exponent;
789 if (format_decimals > max_decimals + 2)
790 sprintf (r->string, "%.*f", format_decimals, fabs (number));
794 if (r->string[0] == '0')
795 memmove (r->string, &r->string[1], strlen (r->string));
797 r->leading_zeros = strspn (r->string, "0.");
798 r->leading_nines = strspn (r->string, "9.");
799 r->integer_digits = strchr (r->string, '.') - r->string;
800 r->negative = number < 0;
803 /* Returns the number of characters required to format the
804 magnitude represented by R to DECIMALS decimal places.
805 The return value includes integer digits and a decimal point
806 and fractional digits, if any, but it does not include any
807 negative prefix or suffix or other affixes.
809 *INTEGER_DIGITS is set to the number of digits before the
810 decimal point in the output, between 0 and 40.
812 If R represents a negative number and its rounded
813 representation would include at least one nonzero digit,
814 *NEGATIVE is set to true; otherwise, it is set to false. */
816 rounder_width (const struct rounder *r, int decimals,
817 int *integer_digits, bool *negative)
819 /* Calculate base measures. */
820 int width = r->integer_digits;
822 width += decimals + 1;
823 *integer_digits = r->integer_digits;
824 *negative = r->negative;
826 /* Rounding can cause adjustments. */
827 if (should_round_up (r, decimals))
829 /* Rounding up leading 9s adds a new digit (a 1). */
830 if (r->leading_nines >= width)
839 if (r->leading_zeros >= width)
841 /* All digits that remain after rounding are zeros.
842 Therefore we drop the negative sign. */
844 if (r->integer_digits == 0 && decimals == 0)
846 /* No digits at all are left. We need to display
847 at least a single digit (a zero). */
857 /* Formats the magnitude represented by R into OUTPUT, rounding
858 to DECIMALS decimal places. Exactly as many characters as
859 indicated by rounder_width are written. No terminating null
862 rounder_format (const struct rounder *r, int decimals, char *output)
864 int base_width = r->integer_digits + (decimals > 0 ? decimals + 1 : 0);
865 if (should_round_up (r, decimals))
867 if (r->leading_nines < base_width)
869 /* Rounding up. This is the common case where rounding
870 up doesn't add an extra digit. */
872 memcpy (output, r->string, base_width);
873 for (p = output + base_width - 1; ; p--)
875 assert (p >= output);
878 else if (*p >= '0' && *p <= '8')
889 /* Rounding up leading 9s causes the result to be a 1
890 followed by a number of 0s, plus a decimal point. */
893 p = mempset (p, '0', r->integer_digits);
897 p = mempset (p, '0', decimals);
899 assert (p == output + base_width + 1);
905 if (r->integer_digits != 0 || decimals != 0)
907 /* Common case: just copy the digits. */
908 memcpy (output, r->string, base_width);
912 /* No digits remain. The output is just a zero. */
918 /* Helper functions. */
921 static double PURE_FUNCTION
924 static const double p[] =
926 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
927 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
928 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
929 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
932 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (10.0, x);
935 /* Returns 256**X. */
936 static double PURE_FUNCTION
939 static const double p[] =
949 18446744073709551616.0
951 return x >= 0 && x < sizeof p / sizeof *p ? p[x] : pow (256.0, x);
954 /* Formats non-finite NUMBER into OUTPUT according to the width
957 output_infinite (double number, const struct fmt_spec *format, char *output)
959 assert (!isfinite (number));
967 else if (isinf (number))
968 s = number > 0 ? "+Infinity" : "-Infinity";
972 buf_copy_str_lpad (output, format->w, s, ' ');
975 output_overflow (format, output);
978 /* Formats OUTPUT as a missing value for the given FORMAT. */
980 output_missing (const struct fmt_spec *format, char *output)
982 memset (output, ' ', format->w);
984 if (format->type != FMT_N)
986 int dot_ofs = (format->type == FMT_PCT ? 2
987 : format->type == FMT_E ? 5
989 output[MAX (0, format->w - format->d - dot_ofs)] = '.';
992 output[format->w - 1] = '.';
995 /* Formats OUTPUT for overflow given FORMAT. */
997 output_overflow (const struct fmt_spec *format, char *output)
999 memset (output, '*', format->w);
1002 /* Converts the integer part of NUMBER to a packed BCD number
1003 with the given number of DIGITS in OUTPUT. If DIGITS is odd,
1004 the least significant nibble of the final byte in OUTPUT is
1005 set to 0. Returns true if successful, false if NUMBER is not
1006 representable. On failure, OUTPUT is cleared to all zero
1009 output_bcd_integer (double number, int digits, char *output)
1013 assert (digits < sizeof decimal);
1014 if (number != SYSMIS
1016 && number < power10 (digits)
1017 && sprintf (decimal, "%0*.0f", digits, round (number)) == digits)
1019 const char *src = decimal;
1022 for (i = 0; i < digits / 2; i++)
1024 int d0 = *src++ - '0';
1025 int d1 = *src++ - '0';
1026 *output++ = (d0 << 4) + d1;
1029 *output = (*src - '0') << 4;
1035 memset (output, 0, DIV_RND_UP (digits, 2));
1040 /* Writes VALUE to OUTPUT as a BYTES-byte binary integer of the
1041 given INTEGER_FORMAT. */
1043 output_binary_integer (uint64_t value, int bytes,
1044 enum integer_format integer_format, char *output)
1046 integer_put (value, integer_format, output, bytes);
1049 /* Converts the BYTES bytes in DATA to twice as many hexadecimal
1050 digits in OUTPUT. */
1052 output_hex (const void *data_, size_t bytes, char *output)
1054 const uint8_t *data = data_;
1057 for (i = 0; i < bytes; i++)
1059 static const char hex_digits[] = "0123456789ABCDEF";
1060 *output++ = hex_digits[data[i] >> 4];
1061 *output++ = hex_digits[data[i] & 15];