49 #include "qofdate-p.h"
53 #define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len))
54 #define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len))
71 : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0))
77 #define INT_strlen _BOUND(t) \
78 ((sizeof (t) * CHAR_BIT - 1) * 146 / 485 + 2)
82 #define TM_YEAR_BASE 0
88 gint _delta = width - _n; \
89 gint _incr = _n + (_delta > 0 ? _delta : 0); \
90 if ((size_t) _incr >= maxsize - i) \
94 if (digits == 0 && _delta > 0) \
97 memset_zero (p, _delta); \
99 memset_space (p, _delta); \
102 p += FPRINTFTIME ? 0 : _n; \
107 # define add1(C) add (1, *p = C)
112 memcpy_lowcase (p, (s), _n); \
113 else if (to_uppcase) \
114 memcpy_uppcase (p, (s), _n); \
116 memcpy ((void *) p, (void const *) (s), _n))
118 #define TOUPPER(Ch, L) (islower (Ch) ? toupper (Ch) : (Ch))
119 #define TOLOWER(Ch, L) (isupper (Ch) ? tolower (Ch) : (Ch))
125 #define ISDIGIT(Ch) ((guint) (Ch) - ('0') <= 9)
130 #define ISO_WEEK_START_WDAY 1
131 #define ISO_WEEK1_WDAY 4
132 #define YDAY_MINIMUM (-366)
134 static const mbstate_t mbstate_zero;
135 const gchar *format_end = NULL;
138 memcpy_lowcase (gchar * dest,
const gchar * src,
size_t len)
141 dest[len] = TOLOWER ((guchar) src[len], loc);
146 memcpy_uppcase (gchar * dest,
const gchar * src,
size_t len)
149 dest[len] = TOUPPER ((guchar) src[len], loc);
154 iso_week_days (gint yday, gint wday)
157 gint big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7;
159 - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
160 + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY);
164 strftime_case (gboolean upcase, gchar * s,
165 size_t maxsize,
const gchar *format,
const QofDate *qd,
175 zone = (
const gchar *) qd->
qd_zone;
178 if (!(zone && *zone))
180 setenv (
"TZ",
"GMT", 1);
193 else if (hour12 == 0)
196 for (f = format; *f !=
'\0'; ++f)
202 guint u_number_value;
203 gboolean negative_number;
204 gboolean always_output_a_sign;
211 gboolean to_lowcase = FALSE;
212 gboolean to_uppcase = upcase;
214 gboolean change_case = FALSE;
331 mbstate_t mbstate = mbstate_zero;
336 format_end = f + strlen (f) + 1;
337 fsize = format_end - f;
341 size_t bytes = mbrlen (f + len, fsize - len, &mbstate);
346 if (bytes == (
size_t) - 2)
348 len += strlen (f + len);
352 if (bytes == (
size_t) - 1)
360 while (!mbsinit (&mbstate));
400 if (width > INT_MAX / 10
401 || (width == INT_MAX / 10
402 && *f - (
'0') > INT_MAX % 10))
412 while (ISDIGIT (*f));
432 #define DO_NUMBER(d, v) \
434 number_value = v; goto do_number
435 #define DO_SIGNED_NUMBER(d, negative, v) \
437 negative_number = negative; \
438 u_number_value = v; goto do_signed_number
443 #define DO_TZ_OFFSET(d, negative, mask, v) \
445 negative_number = negative; \
446 tz_colon_mask = mask; \
447 u_number_value = v; goto do_tz_offset
448 #define DO_NUMBER_SPACEPAD(d, v) \
450 number_value = v; goto do_number_spacepad
466 goto underlying_strftime;
476 goto underlying_strftime;
487 goto underlying_strftime;
497 goto underlying_strftime;
500 if (modifier == (
'O'))
502 goto underlying_strftime;
506 size_t len = strftime_case (to_uppcase,
507 NULL, ((
size_t) - 1),
509 add (len, strftime_case (to_uppcase, p,
510 (maxsize - i), subfmt, qd, ut, ns));
542 PERR (
" locale format out of range.");
545 len = strftime (ubuf,
sizeof ubuf, ufmt, &bad);
548 cpy (len - 1, ubuf + 1);
553 if (modifier == (
'O'))
555 if (modifier == (
'E'))
557 goto underlying_strftime;
562 gint century = qd->
qd_year / 100 + TM_YEAR_BASE / 100;
563 century -= qd->
qd_year % 100 < 0 && 0 < century;
565 qd->
qd_year < -TM_YEAR_BASE, century);
569 if (modifier == (
'O'))
571 goto underlying_strftime;
575 subfmt = (
"%m/%d/%y");
579 if (modifier == (
'E'))
585 if (modifier == (
'E'))
588 DO_NUMBER_SPACEPAD (2, qd->
qd_mday);
593 always_output_a_sign = TRUE;
598 if (pad != (
'0') && pad != (
'-'))
603 negative_number = number_value < 0;
604 u_number_value = number_value;
607 always_output_a_sign = FALSE;
616 if (modifier == (
'O') && !negative_number)
618 goto underlying_strftime;
621 bufp = buf +
sizeof (buf) /
sizeof (buf[0]);
624 u_number_value = -u_number_value;
628 if (tz_colon_mask & 1)
631 *--bufp = u_number_value % 10 + (
'0');
632 u_number_value /= 10;
634 while (u_number_value != 0 || tz_colon_mask != 0);
636 do_number_sign_and_padding:
640 sign_char = (negative_number ? (
'-')
641 : always_output_a_sign ? (
'+') : 0);
651 digits - (buf + (
sizeof (buf) /
sizeof (buf[0])) -
658 if ((
size_t) padding >= maxsize - i)
662 memset_space (p, padding);
664 width = width > padding ? width - padding : 0;
670 if ((
size_t) digits >= maxsize - i)
677 memset_zero (p, padding);
689 cpy (buf +
sizeof (buf) /
sizeof (buf[0]) - bufp, bufp);
695 subfmt = (
"%Y-%m-%d");
699 if (modifier == (
'E'))
705 if (modifier == (
'E'))
708 DO_NUMBER (2, hour12);
711 if (modifier == (
'E'))
714 DO_NUMBER_SPACEPAD (2, qd->
qd_hour);
717 if (modifier == (
'E'))
720 DO_NUMBER_SPACEPAD (2, hour12);
723 if (modifier == (
'E'))
729 if (modifier == (
'E'))
732 DO_NUMBER (2, qd->
qd_min);
735 if (modifier == (
'E'))
741 if (modifier == (
'E'))
751 for (j = width; j < 9; j++)
755 DO_NUMBER (width, number_value);
771 goto underlying_strftime;
778 goto underlying_strftime;
781 if (modifier == (
'E'))
784 DO_NUMBER (2, qd->
qd_sec);
802 bufp = buf +
sizeof (buf) /
sizeof (buf[0]);
803 negative_number = t < 0;
809 *--bufp = (negative_number ? -d : d) + (
'0');
814 always_output_a_sign = FALSE;
815 goto do_number_sign_and_padding;
819 if (modifier == (
'O'))
821 goto underlying_strftime;
823 subfmt = (
"%H:%M:%S");
831 DO_NUMBER (1, (qd->
qd_wday - 1 + 7) % 7 + 1);
834 if (modifier == (
'E'))
842 if (modifier == (
'E'))
845 gint year_adjust = 0;
860 iso_week_days (qd->
qd_yday - (365 +
876 gint yy = (qd->
qd_year % 100 + year_adjust) % 100;
877 DO_NUMBER (2, (0 <= yy
880 year_adjust ? -yy : yy + 100));
887 -TM_YEAR_BASE - year_adjust,
888 (qd->
qd_year + (guint) TM_YEAR_BASE +
892 DO_NUMBER (2, days / 7 + 1);
897 if (modifier == (
'E'))
904 if (modifier == (
'E'))
912 goto underlying_strftime;
914 if (modifier == (
'O'))
918 DO_SIGNED_NUMBER (4, qd->
qd_year < -TM_YEAR_BASE,
922 if (modifier == (
'E'))
924 goto underlying_strftime;
930 yy = qd->
qd_year < -TM_YEAR_BASE ? -yy : yy + 100;
942 if (!(zone && *zone) && qd->
qd_is_dst >= 0)
947 cpy (strlen (zone), zone);
953 for (colons = 1; f[colons] == (
':'); colons++)
955 if (f[colons] != (
'z'))
958 goto do_z_conversion;
973 hour_diff = diff / 60 / 60;
974 min_diff = diff / 60 % 60;
975 sec_diff = diff % 60;
980 DO_TZ_OFFSET (5, diff < 0, 0,
981 hour_diff * 100 + min_diff);
985 DO_TZ_OFFSET (6, diff < 0, 04,
986 hour_diff * 100 + min_diff);
990 DO_TZ_OFFSET (9, diff < 0, 024,
991 hour_diff * 10000 + min_diff * 100 + sec_diff);
998 DO_TZ_OFFSET (3, diff < 0, 0, hour_diff);
1015 for (flen = 1; f[1 - flen] != (
'%'); flen++)
1017 cpy (flen, &f[1 - flen]);