diff options
Diffstat (limited to 'libcharconv_cards.c')
| -rw-r--r-- | libcharconv_cards.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/libcharconv_cards.c b/libcharconv_cards.c new file mode 100644 index 0000000..9e6b468 --- /dev/null +++ b/libcharconv_cards.c @@ -0,0 +1,138 @@ +/* See LICENSE file for copyright and license details. */ +#include "lib-common.h" + + +enum libcharconv_result +libcharconv_cards(const char *s, size_t slen, size_t *n, uint_least32_t *cp, size_t *ncp) +{ + uint_least32_t c; + unsigned value; + unsigned j; + int num; + + *n = 0; + for (; slen--; s++) { + switch (*s) { + case '#': c = UINT32_C(0x1F0A0); goto conv; + case 'f': case 'F': case '0': c = UINT32_C(0x1F0E0); goto conv; + case 'r': case 'R': c = UINT32_C(0x1F0BF); goto conv; + case 'b': case 'B': c = UINT32_C(0x1F0CF); goto conv; + case 'w': case 'W': c = UINT32_C(0x1F0DF); goto conv; + case 'S': c = UINT32_C(0x2660); goto conv; + case 'h': c = UINT32_C(0x2661); goto conv; + case 'd': c = UINT32_C(0x2662); goto conv; + case 's': c = UINT32_C(0x2664); goto conv; + case 'H': c = UINT32_C(0x2665); goto conv; + case 'D': c = UINT32_C(0x2666); goto conv; + + case 'A': case 'a': value = 1u; goto face; + case 'J': case 'j': value = 11u; goto face; + case 'C': case 'c': value = 12u; goto face; + case 'Q': case 'q': value = 13u; goto face; + case 'K': case 'k': value = 14u; face: + j = 1u; + if (!slen) { + if (*s == 'C') + c = UINT32_C(0x2663); + else if (*s == 'c') + c = UINT32_C(0x2667); + else + return LIBCHARCONV_INDETERMINATE; + goto conv_if_end; + } + if (value == 14u && (s[j] == 'N' || s[j] == 'n')) { + value = 12u; + j++; + if (slen == 1u) + return LIBCHARCONV_INDETERMINATE; + } + num = 0; + common: + if (s[j] == 'S' || s[j] == 's') + c = UINT32_C(0x1F0A0) + value; + else if (s[j] == 'H' || s[j] == 'h') + c = UINT32_C(0x1F0B0) + value; + else if (s[j] == 'D' || s[j] == 'd') + c = UINT32_C(0x1F0C0) + value; + else if (s[j] == 'C' || s[j] == 'c') + c = UINT32_C(0x1F0D0) + value; + else if (num) + goto trump; + else if (s[0] == 'C' || s[0] == 'c') + goto clubs; + else + goto no_match; + j++; + goto convj; + + clubs: + j = 1u; + c = *s == 'C' ? UINT32_C(0x2663) : UINT32_C(0x2667); + goto conv; + + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': + case '9': + value = (unsigned)(*s - '0'); + j = 1u; + if (!slen) { + c = UINT32_C(0x1F0E0) + value; + goto conv_if_end; + } + if ('0' <= s[j] && s[j] <= '9') { + value *= 10u; + value += (unsigned)(s[j] - '0'); + j++; + if (value > 10u) { + if (value > 21u) { + value /= 10u; + j--; + } + trump: + c = UINT32_C(0x1F0E0) + value; + goto convj; + } + if (slen == 1u) { + c = UINT32_C(0x1F0E0) + value; + goto conv_if_end; + } + } + num = 1; + goto common; + + default: + no_match: + *n += 1u; + break; + } + } +no_conv: + return LIBCHARCONV_NO_CONVERT; + +conv_if_end: + if (*n) + goto no_conv; + if (*ncp) + *cp = c; + *n += j; + *ncp = 1u; + return LIBCHARCONV_CONVERT_IF_END; + +conv: + if (*n) + goto no_conv; + if (*ncp) + *cp = c; + *n += 1u; + *ncp = 1u; + return LIBCHARCONV_CONVERTED; + +convj: + if (*n) + goto no_conv; + if (*ncp) + *cp = c; + *n += j; + *ncp = 1u; + return LIBCHARCONV_CONVERTED; +} |
