Embedded Artistry libc
C Standard Library Support for Bare-metal Systems
towccase.c
Go to the documentation of this file.
1 #include "_towcase.h"
2 
3 #define CASEMAP(u1, u2, l) \
4  { \
5  (u1), (l) - (u1), (u2) - (u1) + 1 \
6  }
7 #define CASELACE(u1, u2) CASEMAP((u1), (u2), (u1) + 1)
8 
9 static const struct
10 {
11  unsigned short upper;
12  signed char lower;
13  unsigned char len;
14 } casemaps[] = {CASEMAP(0xc0, 0xde, 0xe0),
15 
16  CASELACE(0x0100, 0x012e), CASELACE(0x0132, 0x0136),
17  CASELACE(0x0139, 0x0147), CASELACE(0x014a, 0x0176),
18  CASELACE(0x0179, 0x017d),
19 
20  CASELACE(0x370, 0x372), CASEMAP(0x391, 0x3a1, 0x3b1),
21  CASEMAP(0x3a3, 0x3ab, 0x3c3), CASEMAP(0x400, 0x40f, 0x450),
22  CASEMAP(0x410, 0x42f, 0x430),
23 
24  CASELACE(0x460, 0x480), CASELACE(0x48a, 0x4be),
25  CASELACE(0x4c1, 0x4cd), CASELACE(0x4d0, 0x50e),
26 
27  CASELACE(0x514, 0x52e), CASEMAP(0x531, 0x556, 0x561),
28 
29  CASELACE(0x01a0, 0x01a4), CASELACE(0x01b3, 0x01b5),
30  CASELACE(0x01cd, 0x01db), CASELACE(0x01de, 0x01ee),
31  CASELACE(0x01f8, 0x021e), CASELACE(0x0222, 0x0232),
32  CASELACE(0x03d8, 0x03ee),
33 
34  CASELACE(0x1e00, 0x1e94), CASELACE(0x1ea0, 0x1efe),
35 
36  CASEMAP(0x1f08, 0x1f0f, 0x1f00), CASEMAP(0x1f18, 0x1f1d, 0x1f10),
37  CASEMAP(0x1f28, 0x1f2f, 0x1f20), CASEMAP(0x1f38, 0x1f3f, 0x1f30),
38  CASEMAP(0x1f48, 0x1f4d, 0x1f40),
39 
40  CASEMAP(0x1f68, 0x1f6f, 0x1f60), CASEMAP(0x1f88, 0x1f8f, 0x1f80),
41  CASEMAP(0x1f98, 0x1f9f, 0x1f90), CASEMAP(0x1fa8, 0x1faf, 0x1fa0),
42  CASEMAP(0x1fb8, 0x1fb9, 0x1fb0), CASEMAP(0x1fba, 0x1fbb, 0x1f70),
43  CASEMAP(0x1fc8, 0x1fcb, 0x1f72), CASEMAP(0x1fd8, 0x1fd9, 0x1fd0),
44  CASEMAP(0x1fda, 0x1fdb, 0x1f76), CASEMAP(0x1fe8, 0x1fe9, 0x1fe0),
45  CASEMAP(0x1fea, 0x1feb, 0x1f7a), CASEMAP(0x1ff8, 0x1ff9, 0x1f78),
46  CASEMAP(0x1ffa, 0x1ffb, 0x1f7c),
47 
48  CASEMAP(0x13f0, 0x13f5, 0x13f8), CASELACE(0xa698, 0xa69a),
49  CASELACE(0xa796, 0xa79e),
50 
51  CASELACE(0x246, 0x24e), CASELACE(0x510, 0x512),
52  CASEMAP(0x2160, 0x216f, 0x2170), CASEMAP(0x2c00, 0x2c2e, 0x2c30),
53  CASELACE(0x2c67, 0x2c6b), CASELACE(0x2c80, 0x2ce2),
54  CASELACE(0x2ceb, 0x2ced),
55 
56  CASELACE(0xa640, 0xa66c), CASELACE(0xa680, 0xa696),
57 
58  CASELACE(0xa722, 0xa72e), CASELACE(0xa732, 0xa76e),
59  CASELACE(0xa779, 0xa77b), CASELACE(0xa77e, 0xa786),
60 
61  CASELACE(0xa790, 0xa792), CASELACE(0xa7a0, 0xa7a8),
62 
63  CASELACE(0xa7b4, 0xa7b6),
64 
65  CASEMAP(0xff21, 0xff3a, 0xff41), {0, 0, 0}};
66 
67 static const unsigned short pairs[][2] = {{'I', 0x0131},
68  {'S', 0x017f},
69  {0x0130, 'i'},
70  {0x0178, 0x00ff},
71  {0x0181, 0x0253},
72  {0x0182, 0x0183},
73  {0x0184, 0x0185},
74  {0x0186, 0x0254},
75  {0x0187, 0x0188},
76  {0x0189, 0x0256},
77  {0x018a, 0x0257},
78  {0x018b, 0x018c},
79  {0x018e, 0x01dd},
80  {0x018f, 0x0259},
81  {0x0190, 0x025b},
82  {0x0191, 0x0192},
83  {0x0193, 0x0260},
84  {0x0194, 0x0263},
85  {0x0196, 0x0269},
86  {0x0197, 0x0268},
87  {0x0198, 0x0199},
88  {0x019c, 0x026f},
89  {0x019d, 0x0272},
90  {0x019f, 0x0275},
91  {0x01a6, 0x0280},
92  {0x01a7, 0x01a8},
93  {0x01a9, 0x0283},
94  {0x01ac, 0x01ad},
95  {0x01ae, 0x0288},
96  {0x01af, 0x01b0},
97  {0x01b1, 0x028a},
98  {0x01b2, 0x028b},
99  {0x01b7, 0x0292},
100  {0x01b8, 0x01b9},
101  {0x01bc, 0x01bd},
102  {0x01c4, 0x01c6},
103  {0x01c4, 0x01c5},
104  {0x01c5, 0x01c6},
105  {0x01c7, 0x01c9},
106  {0x01c7, 0x01c8},
107  {0x01c8, 0x01c9},
108  {0x01ca, 0x01cc},
109  {0x01ca, 0x01cb},
110  {0x01cb, 0x01cc},
111  {0x01f1, 0x01f3},
112  {0x01f1, 0x01f2},
113  {0x01f2, 0x01f3},
114  {0x01f4, 0x01f5},
115  {0x01f6, 0x0195},
116  {0x01f7, 0x01bf},
117  {0x0220, 0x019e},
118  {0x0386, 0x03ac},
119  {0x0388, 0x03ad},
120  {0x0389, 0x03ae},
121  {0x038a, 0x03af},
122  {0x038c, 0x03cc},
123  {0x038e, 0x03cd},
124  {0x038f, 0x03ce},
125  {0x0399, 0x0345},
126  {0x0399, 0x1fbe},
127  {0x03a3, 0x03c2},
128  {0x03f7, 0x03f8},
129  {0x03fa, 0x03fb},
130  {0x1e60, 0x1e9b},
131  {0x1e9e, 0xdf},
132 
133  {0x1f59, 0x1f51},
134  {0x1f5b, 0x1f53},
135  {0x1f5d, 0x1f55},
136  {0x1f5f, 0x1f57},
137  {0x1fbc, 0x1fb3},
138  {0x1fcc, 0x1fc3},
139  {0x1fec, 0x1fe5},
140  {0x1ffc, 0x1ff3},
141 
142  {0x23a, 0x2c65},
143  {0x23b, 0x23c},
144  {0x23d, 0x19a},
145  {0x23e, 0x2c66},
146  {0x241, 0x242},
147  {0x243, 0x180},
148  {0x244, 0x289},
149  {0x245, 0x28c},
150  {0x3f4, 0x3b8},
151  {0x3f9, 0x3f2},
152  {0x3fd, 0x37b},
153  {0x3fe, 0x37c},
154  {0x3ff, 0x37d},
155  {0x4c0, 0x4cf},
156 
157  {0x2126, 0x3c9},
158  {0x212a, 'k'},
159  {0x212b, 0xe5},
160  {0x2132, 0x214e},
161  {0x2183, 0x2184},
162  {0x2c60, 0x2c61},
163  {0x2c62, 0x26b},
164  {0x2c63, 0x1d7d},
165  {0x2c64, 0x27d},
166  {0x2c6d, 0x251},
167  {0x2c6e, 0x271},
168  {0x2c6f, 0x250},
169  {0x2c70, 0x252},
170  {0x2c72, 0x2c73},
171  {0x2c75, 0x2c76},
172  {0x2c7e, 0x23f},
173  {0x2c7f, 0x240},
174  {0x2cf2, 0x2cf3},
175 
176  {0xa77d, 0x1d79},
177  {0xa78b, 0xa78c},
178  {0xa78d, 0x265},
179  {0xa7aa, 0x266},
180 
181  {0x10c7, 0x2d27},
182  {0x10cd, 0x2d2d},
183 
184  /* bogus greek 'symbol' letters */
185  {0x376, 0x377},
186  {0x39c, 0xb5},
187  {0x392, 0x3d0},
188  {0x398, 0x3d1},
189  {0x3a6, 0x3d5},
190  {0x3a0, 0x3d6},
191  {0x39a, 0x3f0},
192  {0x3a1, 0x3f1},
193  {0x395, 0x3f5},
194  {0x3cf, 0x3d7},
195 
196  {0xa7ab, 0x25c},
197  {0xa7ac, 0x261},
198  {0xa7ad, 0x26c},
199  {0xa7ae, 0x26a},
200  {0xa7b0, 0x29e},
201  {0xa7b1, 0x287},
202  {0xa7b2, 0x29d},
203  {0xa7b3, 0xab53},
204 
205  /* special cyrillic lowercase forms */
206  {0x412, 0x1c80},
207  {0x414, 0x1c81},
208  {0x41e, 0x1c82},
209  {0x421, 0x1c83},
210  {0x422, 0x1c84},
211  {0x422, 0x1c85},
212  {0x42a, 0x1c86},
213  {0x462, 0x1c87},
214  {0xa64a, 0x1c88},
215 
216  {0, 0}};
217 
218 wchar_t __towcase(wchar_t wc, int lower)
219 {
220  int i;
221  int lmul = 2 * lower - 1;
222  int lmask = lower - 1;
223  /* no letters with case in these large ranges */
224  if(!iswalpha((wint_t)wc) || (unsigned)wc - 0x0600 <= 0x0fff - 0x0600 ||
225  (unsigned)wc - 0x2e00 <= 0xa63f - 0x2e00 || (unsigned)wc - 0xa800 <= 0xab52 - 0xa800 ||
226  (unsigned)wc - 0xabc0 <= 0xfeff - 0xabc0)
227  {
228  return wc;
229  }
230 
231  /* special case because the diff between upper/lower is too big */
232  if(lower && (unsigned)wc - 0x10a0 < 0x2e)
233  {
234  if(wc > 0x10c5 && wc != 0x10c7 && wc != 0x10cd)
235  {
236  return wc;
237  }
238 
239  return wc + 0x2d00 - 0x10a0;
240  }
241 
242  if(!lower && (unsigned)wc - 0x2d00 < 0x26)
243  {
244  if(wc > 0x2d25 && wc != 0x2d27 && wc != 0x2d2d)
245  {
246  return wc;
247  }
248 
249  return wc + 0x10a0 - 0x2d00;
250  }
251 
252  if(lower && (unsigned)wc - 0x13a0 < 0x50)
253  {
254  return wc + 0xab70 - 0x13a0;
255  }
256 
257  if(!lower && (unsigned)wc - 0xab70 < 0x50)
258  {
259  return wc + 0x13a0 - 0xab70;
260  }
261 
262  for(i = 0; casemaps[i].len; i++)
263  {
264  int base = casemaps[i].upper + (lmask & casemaps[i].lower);
265  if(wc - base < casemaps[i].len)
266  {
267  if(casemaps[i].lower == 1)
268  {
269  return wc + lower - ((wc - casemaps[i].upper) & 1);
270  }
271  return wc + lmul * casemaps[i].lower;
272  }
273  }
274 
275  for(i = 0; pairs[i][1 - lower]; i++)
276  {
277  if(pairs[i][1 - lower] == wc)
278  {
279  return pairs[i][lower];
280  }
281  }
282 
283  if(wc - (0x10428 - 0x28 * lower) < 0x28)
284  {
285  return wc - 0x28 + 0x50 * lower;
286  }
287 
288  if(wc - (0x104d8 - 0x28 * lower) < 0x24)
289  {
290  return wc - 0x28 + 0x50 * lower;
291  }
292 
293  if(wc - (0x10cc0 - 0x40 * lower) < 0x33)
294  {
295  return wc - 0x40 + 0x80 * lower;
296  }
297 
298  if(wc - (0x118c0 - 0x20 * lower) < 0x20)
299  {
300  return wc - 0x20 + 0x40 * lower;
301  }
302 
303  if(wc - (0x1e922 - 0x22 * lower) < 0x22)
304  {
305  return wc - 0x22 + 0x44 * lower;
306  }
307 
308  return wc;
309 }
unsigned wint_t
Definition: wctype.h:11
static const unsigned short pairs[][2]
Definition: towccase.c:67
#define CASEMAP(u1, u2, l)
Definition: towccase.c:3
wchar_t __towcase(wchar_t wc, int lower)
Definition: towccase.c:218
static const struct @2 casemaps[]
#define CASELACE(u1, u2)
Definition: towccase.c:7
int iswalpha(wint_t)
Definition: iswalpha.c:7