aboutsummaryrefslogtreecommitdiffstats
path: root/libcharconv_cards.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libcharconv_cards.c138
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;
+}