3 * Copyright (C) TSUBAKIMOTO Hiroya <zorac@4000do.co.jp> 2004
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program 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
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #endif /* HAVE_CONFIG_H */
26 #include "generic_cjk.h"
29 static size_t cjk_iconv(void *cd, char **inbuf, char *end,
30 char **outbuf, size_t *outbytesleft)
32 size_t n = end - *inbuf;
33 if (iconv(cd, (ICONV_CONST char**)inbuf, &n, outbuf, outbytesleft) == (size_t)-1) {
34 iconv(cd, NULL, NULL, NULL, NULL);
39 size_t cjk_generic_push(size_t (*char_func)(uint8_t*, const ucs2_t*, size_t*),
40 void *cd, char **inbuf, size_t *inbytesleft,
41 char **outbuf, size_t *outbytesleft)
45 while (*inbytesleft >= sizeof(ucs2_t) && *outbytesleft > 0) {
46 uint8_t buf[CJK_PUSH_BUFFER];
47 size_t size = *inbytesleft / sizeof(ucs2_t);
48 size_t n = (char_func)(buf, (const ucs2_t*)in, &size);
50 in += size * sizeof(ucs2_t);
51 *inbytesleft -= size * sizeof(ucs2_t);
57 *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft);
58 if (in != *inbuf) return -1;
61 if (n == (size_t)-1) return -1;
62 if (*outbytesleft < n) break;
63 memcpy(*outbuf, buf, n);
66 in += size * sizeof(ucs2_t);
67 *inbytesleft -= size * sizeof(ucs2_t);
71 *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft);
72 if (in != *inbuf) return -1;
74 if (*inbytesleft > 0) {
75 errno = (*inbytesleft < sizeof(ucs2_t) ? EINVAL : E2BIG);
81 size_t cjk_generic_pull(size_t (*char_func)(ucs2_t*, const uint8_t*, size_t*),
82 void *cd, char **inbuf, size_t *inbytesleft,
83 char **outbuf, size_t *outbytesleft)
87 while (*inbytesleft > 0 && *outbytesleft >= sizeof(ucs2_t)) {
88 ucs2_t buf[CJK_PULL_BUFFER];
89 size_t size = *inbytesleft;
90 size_t n = (char_func)(buf, (const uint8_t*)in, &size);
99 *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft);
100 if (in != *inbuf) return -1;
103 if (n == (size_t)-1) return -1;
104 if (*outbytesleft < n * sizeof(ucs2_t)) break;
105 memcpy(*outbuf, buf, n * sizeof(ucs2_t));
106 *outbuf += n * sizeof(ucs2_t);
107 *outbytesleft -= n * sizeof(ucs2_t);
109 *inbytesleft -= size;
113 *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft);
114 if (in != *inbuf) return -1;
116 if (*inbytesleft > 0) {
123 size_t cjk_char_push(uint16_t c, uint8_t *out)
126 if (c == (uint16_t)-1) {
134 out[0] = (uint8_t)(c >> 8);
139 size_t cjk_char_pull(ucs2_t wc, ucs2_t* out, const uint32_t* compose)
142 if ((wc & 0xf000) == 0xe000) {
143 ucs2_t buf[CJK_PULL_BUFFER];
144 size_t i = sizeof(buf) / sizeof(*buf) - 1;
146 uint32_t v = compose[wc & 0xfff];
148 wc = (ucs2_t)(v >> 16);
149 } while (--i && (wc & 0xf000) == 0xe000);
151 memcpy(out, buf + i, sizeof(buf) - sizeof(*buf) * i);
152 return sizeof(buf) / sizeof(*buf) - i;
158 uint16_t cjk_lookup(uint16_t c, const cjk_index_t *index, const uint16_t *charset)
160 while (index->summary && c >= index->range[0]) {
161 if (c <= index->range[1]) {
162 const uint16_t* summary = index->summary[(c - index->range[0]) >> 4];
163 uint16_t used = 1 << (c & 15);
165 if (summary[0] & used) {
166 used = summary[0] & (used - 1);
167 charset += summary[1];
168 while (used) used &= used - 1, ++charset;
178 ucs2_t cjk_compose(ucs2_t base, ucs2_t comb, const uint32_t* table, size_t size)
180 uint32_t v = ((uint32_t)base << 16) | comb;
183 size_t n = (low + size) / 2;
184 if (table[n] == v) return 0xe000 + n;
194 ucs2_t cjk_compose_seq(const ucs2_t* in, size_t* len, const uint32_t* table, size_t size)
196 static uint8_t sz[] = { 3, 4, 5, 5, 5, 5, 5, 3 };
198 size_t n = sz[wc & 7];
206 wc = cjk_compose(wc, in[i], table, size);