/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│ │ vi: set noet ft=c ts=8 sw=8 fenc=utf-8 :vi │ ╚──────────────────────────────────────────────────────────────────────────────╝ │ │ │ Musl Libc │ │ Copyright © 2005-2014 Rich Felker, et al. │ │ │ │ Permission is hereby granted, free of charge, to any person obtaining │ │ a copy of this software and associated documentation files (the │ │ "Software"), to deal in the Software without restriction, including │ │ without limitation the rights to use, copy, modify, merge, publish, │ │ distribute, sublicense, and/or sell copies of the Software, and to │ │ permit persons to whom the Software is furnished to do so, subject to │ │ the following conditions: │ │ │ │ The above copyright notice and this permission notice shall be │ │ included in all copies or substantial portions of the Software. │ │ │ │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ │ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE │ │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ │ │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include #include __static_yoink("musl_libc_notice"); static const unsigned char tab[]; static const unsigned char rulebases[512]; static const int rules[]; static const unsigned char exceptions[][2]; #include "casemap.inc" 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_reference(__towupper_l, towupper_l); __weak_reference(__towlower_l, towlower_l);