towctrans.c raw

   1  #include <wctype.h>
   2  
   3  static const unsigned char tab[];
   4  
   5  static const unsigned char rulebases[512];
   6  static const int rules[];
   7  
   8  static const unsigned char exceptions[][2];
   9  
  10  #include "casemap.h"
  11  
  12  static int casemap(unsigned c, int dir)
  13  {
  14  	unsigned b, x, y, v, rt, xb, xn;
  15  	int r, rd, c0 = c;
  16  
  17  	if (c >= 0x20000) return c;
  18  
  19  	b = c>>8;
  20  	c &= 255;
  21  	x = c/3;
  22  	y = c%3;
  23  
  24  	/* lookup entry in two-level base-6 table */
  25  	v = tab[tab[b]*86+x];
  26  	static const int mt[] = { 2048, 342, 57 };
  27  	v = (v*mt[y]>>11)%6;
  28  
  29  	/* use the bit vector out of the tables as an index into
  30  	 * a block-specific set of rules and decode the rule into
  31  	 * a type and a case-mapping delta. */
  32  	r = rules[rulebases[b]+v];
  33  	rt = r & 255;
  34  	rd = r >> 8;
  35  
  36  	/* rules 0/1 are simple lower/upper case with a delta.
  37  	 * apply according to desired mapping direction. */
  38  	if (rt < 2) return c0 + (rd & -(rt^dir));
  39  
  40  	/* binary search. endpoints of the binary search for
  41  	 * this block are stored in the rule delta field. */
  42  	xn = rd & 0xff;
  43  	xb = (unsigned)rd >> 8;
  44  	while (xn) {
  45  		unsigned try = exceptions[xb+xn/2][0];
  46  		if (try == c) {
  47  			r = rules[exceptions[xb+xn/2][1]];
  48  			rt = r & 255;
  49  			rd = r >> 8;
  50  			if (rt < 2) return c0 + (rd & -(rt^dir));
  51  			/* Hard-coded for the four exceptional titlecase */
  52  			return c0 + (dir ? -1 : 1);
  53  		} else if (try > c) {
  54  			xn /= 2;
  55  		} else {
  56  			xb += xn/2;
  57  			xn -= xn/2;
  58  		}
  59  	}
  60  	return c0;
  61  }
  62  
  63  wint_t towlower(wint_t wc)
  64  {
  65  	return casemap(wc, 0);
  66  }
  67  
  68  wint_t towupper(wint_t wc)
  69  {
  70  	return casemap(wc, 1);
  71  }
  72  
  73  wint_t __towupper_l(wint_t c, locale_t l)
  74  {
  75  	return towupper(c);
  76  }
  77  
  78  wint_t __towlower_l(wint_t c, locale_t l)
  79  {
  80  	return towlower(c);
  81  }
  82  
  83  weak_alias(__towupper_l, towupper_l);
  84  weak_alias(__towlower_l, towlower_l);
  85