diff options
author | P. J. McDermott <pj@pehjota.net> | 2022-03-22 18:46:20 (EDT) |
---|---|---|
committer | P. J. McDermott <pj@pehjota.net> | 2022-03-22 18:46:20 (EDT) |
commit | 50d117cb76883735faa8864c4978b5819cb167bd (patch) | |
tree | 4a3e2b44e66064dfffc7dc75e8fd70c954830be6 | |
parent | e75ef778d29de6a66373dad8fdda32d33f0c9f52 (diff) | |
download | atsign-50d117cb76883735faa8864c4978b5819cb167bd.zip atsign-50d117cb76883735faa8864c4978b5819cb167bd.tar.gz atsign-50d117cb76883735faa8864c4978b5819cb167bd.tar.bz2 |
datetime, formats: Conform to strptime() space req
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | src/datetime.c | 45 | ||||
-rw-r--r-- | src/formats.h | 30 |
3 files changed, 56 insertions, 22 deletions
@@ -1,6 +1,3 @@ -spaces between specifiers in strptime() formats -- strftime()? - format printing: copy format to another buffer, skipping certain char - parsing: copy format one char at a time, changing placeholder to space test with other libc's (newlib? musl? fbsd? obsd?) `./@ 7:00 PM` doesn't work with musl strptime() test other times diff --git a/src/datetime.c b/src/datetime.c index 8f5051d..f7cdb89 100644 --- a/src/datetime.c +++ b/src/datetime.c @@ -43,6 +43,31 @@ static struct tm DATETIME_EPOCH_ = { }; static void +_datetime_buf_cpy_p(char *dst, const char *src) +{ + for (; *src != '\0'; ++src, ++dst) { + if (*src == '^') { + *dst = ' '; + } else { + *dst = *src; + } + } + *dst = '\0'; +} + +static void +_datetime_buf_cpy_f(char *dst, const char *src) +{ + for (; *src != '\0'; ++src, ++dst) { + if (*src == '^') { + ++src; + } + *dst = *src; + } + *dst = '\0'; +} + +static void _datetime_reset_tm(struct tm *tm) { tm->tm_year = INT_MIN; @@ -142,7 +167,7 @@ datetime_parse(struct tm *now_tm, const char *input, time_t *arg_sec) sec = *arg_sec; /* GCC is dumb. */ got = false; for (t = 0; t < sizeof(FORMATS_TIME) / sizeof(FORMATS_TIME[0]) ; ++t) { - memcpy(fmt_buf, FORMATS_TIME[t], time_fmt_len + 1); + _datetime_buf_cpy_p(fmt_buf, FORMATS_TIME[t]); _datetime_reset_tm(&arg_tm); end = strptime(input, fmt_buf, &arg_tm); if (end != NULL && *end == '\0') { @@ -159,11 +184,11 @@ datetime_parse(struct tm *now_tm, const char *input, time_t *arg_sec) if (FORMATS_DATE[d][0] == '\0') { break; } - memcpy(fmt_buf, FORMATS_DATE[d], date_fmt_len + 1); + _datetime_buf_cpy_p(fmt_buf, FORMATS_DATE[d]); for (t = 0; t < sizeof(FORMATS_TIME) / sizeof(FORMATS_TIME[0]); ++t) { - memcpy(fmt_buf + date_fmt_len, FORMATS_TIME[t], - time_fmt_len + 1); + _datetime_buf_cpy_p(fmt_buf + date_fmt_len, + FORMATS_TIME[t]); _datetime_reset_tm(&arg_tm); end = strptime(input, fmt_buf, &arg_tm); if (end != NULL && *end == '\0') { @@ -178,14 +203,14 @@ datetime_parse(struct tm *now_tm, const char *input, time_t *arg_sec) } } for (t = 0; t < sizeof(FORMATS_TIME) / sizeof(FORMATS_TIME[0]); ++t) { - memcpy(fmt_buf, FORMATS_TIME[t], time_fmt_len + 1); + _datetime_buf_cpy_p(fmt_buf, FORMATS_TIME[t]); for (d = 0; d < sizeof(FORMATS_DATE) / sizeof(FORMATS_DATE[0]); ++d) { if (FORMATS_DATE[d][0] == '\0') { break; } - memcpy(fmt_buf + time_fmt_len, FORMATS_DATE[d], - date_fmt_len + 1); + _datetime_buf_cpy_p(fmt_buf + time_fmt_len, + FORMATS_DATE[d]); _datetime_reset_tm(&arg_tm); end = strptime(input, fmt_buf, &arg_tm); if (end != NULL && *end == '\0') { @@ -200,7 +225,7 @@ datetime_parse(struct tm *now_tm, const char *input, time_t *arg_sec) } } for (d = 0; d < sizeof(FORMATS_MISC) / sizeof(FORMATS_MISC[0]) ; ++d) { - memcpy(fmt_buf, FORMATS_MISC[d], misc_fmt_len + 1); + _datetime_buf_cpy_p(fmt_buf, FORMATS_MISC[d]); _datetime_reset_tm(&arg_tm); end = strptime(input, fmt_buf, &arg_tm); if (end != NULL && *end == '\0') { @@ -280,10 +305,12 @@ _datetime_strftime(const char *fmts[], const struct tm *tm, char **out, ++*i; } + _datetime_buf_cpy_f(*out, fmts[*i]); + resized = 0; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" - while (strftime(*buf, *buf_sz, fmts[*i], tm) == 0) { + while (strftime(*buf, *buf_sz, *out, tm) == 0) { #pragma GCC diagnostic pop ++*buf_sz; *buf = realloc(*buf, *buf_sz * sizeof(**buf)); diff --git a/src/formats.h b/src/formats.h index f4caccd..262912e 100644 --- a/src/formats.h +++ b/src/formats.h @@ -25,6 +25,16 @@ * * All of the format strings in each array must be padded with spaces to be of * equal lengths. + * + * Conversion specifications are used by both strptime() and strftime(). As + * required by the former function, there shall be "white-space or other non- + * alphanumeric characters between any two conversion specifications unless all + * of the adjacent conversion specifications convert a known, fixed number of + * characters." [POSIX] The "^" character may be used to separate conversion + * specifications that should be separated (by a space) when parsing and + * adjacent when formatting for printing. For example, " %I^%M %p " will be + * changed to " %I %M %p " when parsing and to " %I%M %p " when formatting for + * printing. */ static const char *FORMATS_DATE[] = { @@ -220,10 +230,10 @@ static const char *FORMATS_TIME[] = { " %H.%M.%S ", /* 19.00.01 */ " %I.%M %p ", /* 7.00 PM */ " %H.%M ", /* 19.00 */ - " %I%M%S %p ", /* 70001 PM */ - " %H%M%S ", /* 190001 */ - " %I%M %p ", /* 700 PM */ - " %H%M ", /* 1900 */ + " %I^%M^%S %p ", /* 70001 PM */ + " %H^%M^%S ", /* 190001 */ + " %I^%M %p ", /* 700 PM */ + " %H^%M ", /* 1900 */ }; static const char *FORMATS_MISC[] = { @@ -231,13 +241,13 @@ static const char *FORMATS_MISC[] = { " %Y-%m-%dT%H:%M:%S ", " %Y-%m-%dT%H:%M ", /* ISO 8601: 19691231 delimited by "T" */ - " %Y%m%dT%H%M%S ", - " %Y%m%dT%H%M ", + " %Y^%m^%dT%H^%M^%S ", + " %Y^%m^%dT%H^%M ", /* 19691231 */ - " %Y%m%d %I%M%S %p ", - " %Y%m%d %H%M%S ", - " %Y%m%d %I%M %p ", - " %Y%m%d %H%M ", + " %Y^%m^%d %I^%M^%S %p ", + " %Y^%m^%d %H^%M^%S ", + " %Y^%m^%d %I^%M %p ", + " %Y^%m^%d %H^%M ", /* Wed Dec 31 19:00:01 1969 */ " %a %b %d %H:%M:%S %Y ", }; |