1 /* Modified (m) 2017 Thomas Wolff: revise Unicode and locale/wchar handling */
9 struct caseconv_entry describes the case conversion behaviour
10 of a range of Unicode characters.
11 It was designed to be compact for a minimal table size.
12 The range is first...first + diff.
13 Conversion behaviour for a character c in the respective range:
14 mode == TOLO towlower (c) = c + delta
15 mode == TOUP towupper (c) = c + delta
16 mode == TOBOTH (titling case characters)
19 mode == TO1 capital/small letters are alternating
20 delta == EVENCAP even codes are capital
21 delta == ODDCAP odd codes are capital
22 (this correlates with an even/odd first range value
23 as of Unicode 10.0 but we do not rely on this)
24 As of Unicode 10.0, the following field lengths are sufficient
29 The reserve of 4 bits (to limit the struct to 6 bytes)
30 is currently added to the 'first' field;
31 should a future Unicode version make it necessary to expand the others,
32 the 'first' field could be reduced as needed, or larger ranges could
33 be split up (reduce limit max=255 e.g. to max=127 or max=63 in
34 script mkcaseconv, check increasing table size).
36 enum {TO1
, TOLO
, TOUP
, TOBOTH
};
37 enum {EVENCAP
, ODDCAP
};
38 static struct caseconv_entry
{
39 uint_least32_t first
: 21;
40 uint_least32_t diff
: 8;
41 uint_least32_t mode
: 2;
42 int_least32_t delta
: 17;
43 } __attribute__ ((packed
))
47 #define first(ce) ce.first
48 #define last(ce) (ce.first + ce.diff)
50 /* auxiliary function for binary search in interval properties table */
51 static const struct caseconv_entry
*
52 bisearch (wint_t ucs
, const struct caseconv_entry
*table
, int max
)
57 if (ucs
< first(table
[0]) || ucs
> last(table
[max
]))
61 mid
= (min
+ max
) / 2;
62 if (ucs
> last(table
[mid
]))
64 else if (ucs
< first(table
[mid
]))
75 const struct caseconv_entry
* cce
=
76 bisearch(c
, caseconv_table
,
77 sizeof(caseconv_table
) / sizeof(*caseconv_table
) - 1);
83 return c
+ cce
->delta
;
110 const struct caseconv_entry
* cce
=
111 bisearch(c
, caseconv_table
,
112 sizeof(caseconv_table
) / sizeof(*caseconv_table
) - 1);
118 return c
+ cce
->delta
;
143 towctrans_l (wint_t c
, wctrans_t w
, struct __locale_t
*locale
)
145 wint_t u
= _jp2uc_l (c
, locale
);
147 if (w
== WCT_TOLOWER
)
149 else if (w
== WCT_TOUPPER
)
153 // skipping the errno setting that was previously involved
154 // by delegating to towctrans; it was causing trouble (cygwin crash)
155 // and there is no errno specified for towctrans
159 return _uc2jp_l (res
, locale
);