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