aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--convert-to-metrical.c4
-rw-r--r--libcharconv.h14
-rw-r--r--libcharconv_latin.c13
-rw-r--r--libcharconv_metrical.c51
5 files changed, 86 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 615f7f2..0fa5b3a 100644
--- a/Makefile
+++ b/Makefile
@@ -81,7 +81,8 @@ BIN =\
convert-to-rotated-45deg-ccw\
convert-to-rotated-90deg-ccw\
convert-to-invisible\
- convert-to-enclosed
+ convert-to-enclosed\
+ convert-to-metrical
LIBOBJ =\
libcharconv_decode_utf8_.o\
@@ -155,7 +156,8 @@ LIBOBJ =\
libcharconv_rotated_90deg_ccw.o\
libcharconv_invisible.o\
libcharconv_enclosed_positive.o\
- libcharconv_enclosed_negative.o
+ libcharconv_enclosed_negative.o\
+ libcharconv_metrical.o
LOBJ = $(LIBOBJ:.o=.lo)
diff --git a/convert-to-metrical.c b/convert-to-metrical.c
new file mode 100644
index 0000000..3f7b843
--- /dev/null
+++ b/convert-to-metrical.c
@@ -0,0 +1,4 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+SIMPLE(libcharconv_metrical)
diff --git a/libcharconv.h b/libcharconv.h
index 1c8c4b9..6693376 100644
--- a/libcharconv.h
+++ b/libcharconv.h
@@ -472,6 +472,20 @@ LIBCHARCONV_FUNC_(libcharconv_enclosed_positive);
*/
LIBCHARCONV_FUNC_(libcharconv_enclosed_negative);
+/**
+ * Convert
+ * '1' to METRICAL BREVE,
+ * '2' to METRICAL TWO SHORTS JOINED,
+ * '-1' to METRICAL LONG OVER SHORT,
+ * '-2' to METRICAL LONG OVER TWO SHORTS,
+ * '_1' to METRICAL SHORT OVER LONG,
+ * '_2' to METRICAL TWO SHORTS OVER LONG,
+ * '3' to METRICAL TRISEME,
+ * '4' to METRICAL TETRASEME, and
+ * '5' to METRICAL PENTASEME
+ */
+LIBCHARCONV_FUNC_(libcharconv_metrical);
+
#undef LIBCHARCONV_FUNC_
#endif
diff --git a/libcharconv_latin.c b/libcharconv_latin.c
index 4b41391..2693ea4 100644
--- a/libcharconv_latin.c
+++ b/libcharconv_latin.c
@@ -550,6 +550,16 @@ libcharconv_latin(const char *s, size_t slen, size_t *n, uint_least32_t *cp, siz
c2 = (char)(c - (UINT32_C(0x278A) - (uint_least32_t)'1'));
c3 = ')';
goto conv3;
+ } else if (UINT32_C(0x23D6) <= c && c <= UINT32_C(0x23D9)) {
+ /* metrical */
+ c -= (uint_least32_t)UINT32_C(0x23D6) - (uint_least32_t)'2';
+ goto conv;
+ } else if (UINT32_C(0x23D2) <= c && c <= UINT32_C(0x23D5)) {
+ /* metrical */
+ c -= (uint_least32_t)UINT32_C(0x23D2);
+ c1 = (c & 1u) ? '_' : '-';
+ c2 = (c & 2u) ? '2' : '1';
+ goto conv2;
} else {
use_switch:
@@ -981,6 +991,9 @@ libcharconv_latin(const char *s, size_t slen, size_t *n, uint_least32_t *cp, siz
case UINT32_C(0x2793): c1 = '('; c2 = '1'; c3 = '0'; c4 = ')'; goto conv4;
case UINT32_C(0x1F10C): c1 = '('; c2 = '0'; c3 = ')'; goto conv3;
+ /* metrical */
+ case UINT32_C(0x23D1): c1 = '1'; goto conv1;
+
default:
no_match:
*n += clen;
diff --git a/libcharconv_metrical.c b/libcharconv_metrical.c
new file mode 100644
index 0000000..2518a2b
--- /dev/null
+++ b/libcharconv_metrical.c
@@ -0,0 +1,51 @@
+/* See LICENSE file for copyright and license details. */
+#include "lib-common.h"
+
+
+enum libcharconv_result
+libcharconv_metrical(const char *s, size_t slen, size_t *n, uint_least32_t *cp, size_t *ncp)
+{
+ uint_least32_t c;
+ *n = 0;
+ for (; slen--; s++) {
+ switch (*s) {
+ case '1': c = UINT32_C(0x23D1); goto conv;
+ case '2': c = UINT32_C(0x23D6); goto conv;
+ case '3': c = UINT32_C(0x23D7); goto conv;
+ case '4': c = UINT32_C(0x23D8); goto conv;
+ case '5': c = UINT32_C(0x23D9); goto conv;
+ case '-':
+ case '_':
+ if (!slen)
+ return LIBCHARCONV_INDETERMINATE;
+ if (s[1] != '1' && s[1] != '2')
+ goto no_match;
+ c = UINT32_C(0x23D2) + (s[0] == '_' ? 1u : 0u) + (s[1] == '2' ? 2u : 0u);
+ goto conv2;
+ default:
+ no_match:
+ *n += 1u;
+ break;
+ }
+ }
+no_conv:
+ return LIBCHARCONV_NO_CONVERT;
+
+conv:
+ if (*n)
+ goto no_conv;
+ if (*ncp)
+ *cp = c;
+ *n += 1u;
+ *ncp = 1u;
+ return LIBCHARCONV_CONVERTED;
+
+conv2:
+ if (*n)
+ goto no_conv;
+ if (*ncp)
+ *cp = c;
+ *n += 2u;
+ *ncp = 1u;
+ return LIBCHARCONV_CONVERTED;
+}