summaryrefslogtreecommitdiff
path: root/src/ctype/towctrans.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ctype/towctrans.c')
-rw-r--r--src/ctype/towctrans.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/ctype/towctrans.c b/src/ctype/towctrans.c
new file mode 100644
index 0000000..76d1376
--- /dev/null
+++ b/src/ctype/towctrans.c
@@ -0,0 +1,84 @@
+#include <wctype.h>
+
+static const unsigned char tab[];
+
+static const unsigned char rulebases[512];
+static const int rules[];
+
+static const unsigned char exceptions[][2];
+
+#include "casemap.h"
+
+static int casemap(unsigned c, int dir)
+{
+ unsigned b, x, y, v, rt, xb, xn;
+ int r, rd, c0 = c;
+
+ if (c >= 0x20000) return c;
+
+ b = c>>8;
+ c &= 255;
+ x = c/3;
+ y = c%3;
+
+ /* lookup entry in two-level base-6 table */
+ v = tab[tab[b]*86+x];
+ static const int mt[] = { 2048, 342, 57 };
+ v = (v*mt[y]>>11)%6;
+
+ /* use the bit vector out of the tables as an index into
+ * a block-specific set of rules and decode the rule into
+ * a type and a case-mapping delta. */
+ r = rules[rulebases[b]+v];
+ rt = r & 255;
+ rd = r >> 8;
+
+ /* rules 0/1 are simple lower/upper case with a delta.
+ * apply according to desired mapping direction. */
+ if (rt < 2) return c0 + (rd & -(rt^dir));
+
+ /* binary search. endpoints of the binary search for
+ * this block are stored in the rule delta field. */
+ xn = rd & 0xff;
+ xb = (unsigned)rd >> 8;
+ while (xn) {
+ unsigned try = exceptions[xb+xn/2][0];
+ if (try == c) {
+ r = rules[exceptions[xb+xn/2][1]];
+ rt = r & 255;
+ rd = r >> 8;
+ if (rt < 2) return c0 + (rd & -(rt^dir));
+ /* Hard-coded for the four exceptional titlecase */
+ return c0 + (dir ? -1 : 1);
+ } else if (try > c) {
+ xn /= 2;
+ } else {
+ xb += xn/2;
+ xn -= xn/2;
+ }
+ }
+ return c0;
+}
+
+wint_t towlower(wint_t wc)
+{
+ return casemap(wc, 0);
+}
+
+wint_t towupper(wint_t wc)
+{
+ return casemap(wc, 1);
+}
+
+wint_t __towupper_l(wint_t c, locale_t l)
+{
+ return towupper(c);
+}
+
+wint_t __towlower_l(wint_t c, locale_t l)
+{
+ return towlower(c);
+}
+
+weak_alias(__towupper_l, towupper_l);
+weak_alias(__towlower_l, towlower_l);