1/* Copyright (C) 2000 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3   Contributed by Bruno Haible <haible@clisp.cons.org>, 2000.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library; if not, write to the Free
17   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18   02111-1307 USA.  */
19
20#include <stdint.h>
21
22/* Tables indexed by a wide character are compressed through the use
23   of a multi-level lookup.  The compression effect comes from blocks
24   that don't need particular data and from blocks that can share their
25   data.  */
26
27/* Bit tables are accessed by cutting wc in four blocks of bits:
28   - the high 32-q-p bits,
29   - the next q bits,
30   - the next p bits,
31   - the next 5 bits.
32
33	    +------------------+-----+-----+-----+
34     wc  =  +     32-q-p-5     |  q  |  p  |  5  |
35	    +------------------+-----+-----+-----+
36
37   p and q are variable.  For 16-bit Unicode it is sufficient to
38   choose p and q such that q+p+5 <= 16.
39
40   The table contains the following uint32_t words:
41   - q+p+5,
42   - s = upper exclusive bound for wc >> (q+p+5),
43   - p+5,
44   - 2^q-1,
45   - 2^p-1,
46   - 1st-level table: s offsets, pointing into the 2nd-level table,
47   - 2nd-level table: k*2^q offsets, pointing into the 3rd-level table,
48   - 3rd-level table: j*2^p words, each containing 32 bits of data.
49*/
50
51static __inline int
52wctype_table_lookup (const char *table, uint32_t wc)
53{
54  uint32_t shift1 = ((const uint32_t *) table)[0];
55  uint32_t index1 = wc >> shift1;
56  uint32_t bound = ((const uint32_t *) table)[1];
57  if (index1 < bound)
58    {
59      uint32_t lookup1 = ((const uint32_t *) table)[5 + index1];
60      if (lookup1 != 0)
61	{
62	  uint32_t shift2 = ((const uint32_t *) table)[2];
63	  uint32_t mask2 = ((const uint32_t *) table)[3];
64	  uint32_t index2 = (wc >> shift2) & mask2;
65	  uint32_t lookup2 = ((const uint32_t *)(table + lookup1))[index2];
66	  if (lookup2 != 0)
67	    {
68	      uint32_t mask3 = ((const uint32_t *) table)[4];
69	      uint32_t index3 = (wc >> 5) & mask3;
70	      uint32_t lookup3 = ((const uint32_t *)(table + lookup2))[index3];
71
72	      return (lookup3 >> (wc & 0x1f)) & 1;
73	    }
74	}
75    }
76  return 0;
77}
78
79/* Byte tables are similar to bit tables, except that the addressing
80   unit is a single byte, and no 5 bits are used as a word index.  */
81
82static __inline int
83wcwidth_table_lookup (const char *table, uint32_t wc)
84{
85  uint32_t shift1 = ((const uint32_t *) table)[0];
86  uint32_t index1 = wc >> shift1;
87  uint32_t bound = ((const uint32_t *) table)[1];
88  if (index1 < bound)
89    {
90      uint32_t lookup1 = ((const uint32_t *) table)[5 + index1];
91      if (lookup1 != 0)
92	{
93	  uint32_t shift2 = ((const uint32_t *) table)[2];
94	  uint32_t mask2 = ((const uint32_t *) table)[3];
95	  uint32_t index2 = (wc >> shift2) & mask2;
96	  uint32_t lookup2 = ((const uint32_t *)(table + lookup1))[index2];
97	  if (lookup2 != 0)
98	    {
99	      uint32_t mask3 = ((const uint32_t *) table)[4];
100	      uint32_t index3 = wc & mask3;
101	      uint8_t lookup3 = ((const uint8_t *)(table + lookup2))[index3];
102
103	      return lookup3;
104	    }
105	}
106    }
107  return 0xff;
108}
109
110/* Mapping tables are similar to bit tables, except that the
111   addressing unit is a single signed 32-bit word, containing the
112   difference between the desired result and the argument, and no 5
113   bits are used as a word index.  */
114
115static __inline uint32_t
116wctrans_table_lookup (const char *table, uint32_t wc)
117{
118  uint32_t shift1 = ((const uint32_t *) table)[0];
119  uint32_t index1 = wc >> shift1;
120  uint32_t bound = ((const uint32_t *) table)[1];
121  if (index1 < bound)
122    {
123      uint32_t lookup1 = ((const uint32_t *) table)[5 + index1];
124      if (lookup1 != 0)
125	{
126	  uint32_t shift2 = ((const uint32_t *) table)[2];
127	  uint32_t mask2 = ((const uint32_t *) table)[3];
128	  uint32_t index2 = (wc >> shift2) & mask2;
129	  uint32_t lookup2 = ((const uint32_t *)(table + lookup1))[index2];
130	  if (lookup2 != 0)
131	    {
132	      uint32_t mask3 = ((const uint32_t *) table)[4];
133	      uint32_t index3 = wc & mask3;
134	      int32_t lookup3 = ((const int32_t *)(table + lookup2))[index3];
135
136	      return wc + lookup3;
137	    }
138	}
139    }
140  return wc;
141}
142