From ac73d14281056314aa8e1b0d3c6ade0a527aad0a Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 24 Jan 2026 23:09:46 +0100 Subject: Add clock faces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 6 +++-- convert-to-clock-faces.c | 18 +++++++++++++ libcharconv.h | 35 +++++++++++++++++++++++++ libcharconv_clock_faces.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++ libcharconv_latin.c | 29 ++++++++++++++++++++- 5 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 convert-to-clock-faces.c create mode 100644 libcharconv_clock_faces.c diff --git a/Makefile b/Makefile index 3983e26..771cce9 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,8 @@ BIN =\ convert-to-subscript\ convert-to-lydian\ convert-to-lycian\ - convert-to-domino-tiles + convert-to-domino-tiles\ + convert-to-clock-faces LIBOBJ =\ libcharconv_decode_utf8_.o\ @@ -87,7 +88,8 @@ LIBOBJ =\ libcharconv_lydian.o\ libcharconv_lycian.o\ libcharconv_domino_tiles_horizontal.o\ - libcharconv_domino_tiles_vertical.o + libcharconv_domino_tiles_vertical.o\ + libcharconv_clock_faces.o LOBJ = $(LIBOBJ:.o=.lo) diff --git a/convert-to-clock-faces.c b/convert-to-clock-faces.c new file mode 100644 index 0000000..78647c7 --- /dev/null +++ b/convert-to-clock-faces.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE(""); + + +int +main(int argc, char *argv[]) +{ + ARGBEGIN { + default: + usage(); + } ARGEND; + if (argc) + usage(); + + return convert(&libcharconv_clock_faces); +} diff --git a/libcharconv.h b/libcharconv.h index 9eac800..0a34555 100644 --- a/libcharconv.h +++ b/libcharconv.h @@ -1165,4 +1165,39 @@ enum libcharconv_result libcharconv_domino_tiles_horizontal(const char *s, size_ enum libcharconv_result libcharconv_domino_tiles_vertical(const char *s, size_t slen, size_t *n, uint_least32_t *cp, size_t *ncp); +/** + * Convert "0:00", "1:00", ..., '24:00', + * "00:00", "01:00", ..., '24:00', + * "0:30", "1:30", ..., '23:30', and + * "00:30", "01:30", ..., '23:30' to CLOCK FACEs + * + * @param s Text to convert + * @param slen The number of bytes available in `s` + * @param n Output parameter for the number of consumed bytes + * @param cp Output buffer for the codepoints + * @param ncp Input parameter for the number of codepoints that + * fit in `cp`, and output parameter for the number + * of output codepoints (if it exceeds the original + * value of `ncp`, a larger buffer is needed) + * @return LIBCHARCONV_NO_CONVERT: + * `*n` is the number of bytes from the beginning + * of `s` that cannot be converted + * LIBCHARCONV_CONVERTED: + * `*n` is the number of bytes from the beginning + * of `s` that was converted to a codepoint which + * is stored in `*cp` + * LIBCHARCONV_INDETERMINATE: + * If all text has been input, no more can be + * converted, otherwise more of the text most + * be made available before the function can + * determine whether the beginning of `s` can be + * converted or what it should be converted to + * LIBCHARCONV_CONVERT_IF_END: + * As LIBCHARCONV_CONVERTED the entire text has + * been input, as LIBCHARCONV_INDETERMINATE + * otherwise + */ +enum libcharconv_result libcharconv_clock_faces(const char *s, size_t slen, size_t *n, uint_least32_t *cp, size_t *ncp); + + #endif diff --git a/libcharconv_clock_faces.c b/libcharconv_clock_faces.c new file mode 100644 index 0000000..cd49b53 --- /dev/null +++ b/libcharconv_clock_faces.c @@ -0,0 +1,65 @@ +/* See LICENSE file for copyright and license details. */ +#include "lib-common.h" + + +enum libcharconv_result +libcharconv_clock_faces(const char *s, size_t slen, size_t *n, uint_least32_t *cp, size_t *ncp) +{ + int num, thirty; + *n = 0; + for (; slen--; s++) { + if ('0' <= s[0] && s[0] <= '9') { + if (*n) + goto no_conv; + num = (int)(s[0] - '0'); + if (!slen--) + goto indeterminate; + *n = 2u; + if (s[1] == ':') + goto conv; + if ('0' > s[1] || s[1] > '9') + goto no_conv; + num *= 10; + num += (int)(s[1] - '0'); + if (!slen--) + goto indeterminate; + if (num > 24) + goto no_conv; + *n = 3u; + if (s[2] == ':') + goto conv; + goto no_conv; + } else { + *n += 1u; + } + } +no_conv: + return LIBCHARCONV_NO_CONVERT; + +indeterminate: + return LIBCHARCONV_INDETERMINATE; + +conv: + if (!slen--) + goto indeterminate; + if (s[*n] == '3') + thirty = 1; + else if (s[*n] == '0') + thirty = 0; + else + goto no_conv; + if (!slen--) + goto indeterminate; + if (s[*n + 1u] != '0') + goto no_conv; + *n += 2u; + if (num > (thirty ? 23 : 34)) + goto no_conv; + num %= 12; + num = (!num ? 12 : num) - 1; + num += 12 * thirty; + if (*ncp) + *cp = UINT32_C(0x1F550) + (uint_least32_t)num; + *ncp = 1u; + return LIBCHARCONV_CONVERTED; +} diff --git a/libcharconv_latin.c b/libcharconv_latin.c index 77ab4c9..7c70318 100644 --- a/libcharconv_latin.c +++ b/libcharconv_latin.c @@ -7,7 +7,7 @@ libcharconv_latin(const char *s, size_t slen, size_t *n, uint_least32_t *cp, siz { enum libcharconv_result ret = LIBCHARCONV_CONVERTED; uint_least32_t c; - char c1, c2, c3, c4; + char c1, c2, c3, c4, c5; size_t clen; unsigned num; @@ -340,6 +340,16 @@ libcharconv_latin(const char *s, size_t slen, size_t *n, uint_least32_t *cp, siz c2 = '-'; goto conv3; + } else if (UINT32_C(0x1F550) <= c && c <= UINT32_C(0x1F567)) { + /* clock faces */ + c -= UINT32_C(0x1F550); + c1 = (char)((c + 1u) % 12u / 10u + (uint_least32_t)'0'); + c2 = (char)((c + 1u) % 12u % 10u + (uint_least32_t)'0'); + c3 = ':'; + c4 = c < 12u ? '0' : '3'; + c5 = '0'; + goto conv5; + } else { switch (c) { /* shogi */ @@ -538,4 +548,21 @@ conv4: cp[3] = (uint_least32_t)c4; *ncp = 4u; return ret; + +conv5: + if (*n) + goto no_conv; + *n += clen; + if (*ncp >= 1u) + cp[0] = (uint_least32_t)c1; + if (*ncp >= 2u) + cp[1] = (uint_least32_t)c2; + if (*ncp >= 3u) + cp[2] = (uint_least32_t)c3; + if (*ncp >= 4u) + cp[3] = (uint_least32_t)c4; + if (*ncp >= 5u) + cp[4] = (uint_least32_t)c5; + *ncp = 5u; + return ret; } -- cgit v1.2.3-70-g09d2