• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.0/libatalk/unicode/charsets/
1/*
2 * generic_cjk
3 * Copyright (C) TSUBAKIMOTO Hiroya <zorac@4000do.co.jp> 2004
4 *
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.
9 *
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.
14 *
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.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif /* HAVE_CONFIG_H */
23
24#if HAVE_USABLE_ICONV
25
26#include "generic_cjk.h"
27#include <string.h>
28
29static size_t cjk_iconv(void *cd, char **inbuf, char *end,
30			char **outbuf, size_t *outbytesleft)
31{
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);
35  }
36  return n;
37}
38
39size_t cjk_generic_push(size_t (*char_func)(u_int8_t*, const ucs2_t*, size_t*),
40			void *cd, char **inbuf, size_t *inbytesleft,
41			char **outbuf, size_t *outbytesleft)
42{
43  char *in = *inbuf;
44
45  while (*inbytesleft >= sizeof(ucs2_t) && *outbytesleft > 0) {
46    u_int8_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);
49    if (n == 0) {
50      in += size * sizeof(ucs2_t);
51      *inbytesleft -= size * sizeof(ucs2_t);
52      continue;
53    }
54    if (in != *inbuf) {
55      int err = errno;
56
57      *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft);
58      if (in != *inbuf) return -1;
59      errno = err;
60    }
61    if (n == (size_t)-1) return -1;
62    if (*outbytesleft < n) break;
63    memcpy(*outbuf, buf, n);
64    *outbuf += n;
65    *outbytesleft -= n;
66    in += size * sizeof(ucs2_t);
67    *inbytesleft -= size * sizeof(ucs2_t);
68    *inbuf = in;
69  }
70  if (in != *inbuf) {
71    *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft);
72    if (in != *inbuf) return -1;
73  }
74  if (*inbytesleft > 0) {
75    errno = (*inbytesleft < sizeof(ucs2_t) ? EINVAL : E2BIG);
76    return -1;
77  }
78  return 0;
79}
80
81size_t cjk_generic_pull(size_t (*char_func)(ucs2_t*, const u_int8_t*, size_t*),
82			void *cd, char **inbuf, size_t *inbytesleft,
83			char **outbuf, size_t *outbytesleft)
84{
85  char *in = *inbuf;
86
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 u_int8_t*)in, &size);
91    if (n == 0) {
92      in += size;
93      *inbytesleft -= size;
94      continue;
95    }
96    if (in != *inbuf) {
97      int err = errno;
98
99      *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft);
100      if (in != *inbuf) return -1;
101      errno = err;
102    }
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);
108    in += size;
109    *inbytesleft -= size;
110    *inbuf = in;
111  }
112  if (in != *inbuf) {
113    *inbytesleft += cjk_iconv(cd, inbuf, in, outbuf, outbytesleft);
114    if (in != *inbuf) return -1;
115  }
116  if (*inbytesleft > 0) {
117    errno = E2BIG;
118    return -1;
119  }
120  return 0;
121}
122
123size_t cjk_char_push(u_int16_t c, u_int8_t *out)
124{
125  if (!c) return 0;
126  if (c == (u_int16_t)-1) {
127    errno = EILSEQ;
128    return (size_t)-1;
129  }
130  if (c <= 0xff) {
131    out[0] = (u_int8_t)c;
132    return 1;
133  }
134  out[0] = (u_int8_t)(c >> 8);
135  out[1] = (u_int8_t)c;
136  return 2;
137}
138
139size_t cjk_char_pull(ucs2_t wc, ucs2_t* out, const u_int32_t* compose)
140{
141  if (!wc) return 0;
142  if ((wc & 0xf000) == 0xe000) {
143    ucs2_t buf[CJK_PULL_BUFFER];
144    size_t i = sizeof(buf) / sizeof(*buf) - 1;
145    do {
146      u_int32_t v = compose[wc & 0xfff];
147      buf[i] = (ucs2_t)v;
148      wc = (ucs2_t)(v >> 16);
149    } while (--i && (wc & 0xf000) == 0xe000);
150    buf[i] = wc;
151    memcpy(out, buf + i, sizeof(buf) - sizeof(*buf) * i);
152    return sizeof(buf) / sizeof(*buf) - i;
153  }
154  *out = wc;
155  return 1;
156}
157
158u_int16_t cjk_lookup(u_int16_t c, const cjk_index_t *index, const u_int16_t *charset)
159{
160  while (index->summary && c >= index->range[0]) {
161    if (c <= index->range[1]) {
162      const u_int16_t* summary = index->summary[(c - index->range[0]) >> 4];
163      u_int16_t used = 1 << (c & 15);
164
165      if (summary[0] & used) {
166	used = summary[0] & (used - 1);
167	charset += summary[1];
168	while (used) used &= used - 1, ++charset;
169	return *charset;
170      }
171      return 0;
172    }
173    ++index;
174  }
175  return 0;
176}
177
178ucs2_t cjk_compose(ucs2_t base, ucs2_t comb, const u_int32_t* table, size_t size)
179{
180  u_int32_t v = ((u_int32_t)base << 16) | comb;
181  size_t low = 0;
182  while (size > low) {
183    size_t n = (low + size) / 2;
184    if (table[n] == v) return 0xe000 + n;
185    if (table[n] < v) {
186      low = n + 1;
187    } else {
188      size = n;
189    }
190  }
191  return 0;
192}
193
194ucs2_t cjk_compose_seq(const ucs2_t* in, size_t* len, const u_int32_t* table, size_t size)
195{
196  static u_int8_t sz[] = { 3, 4, 5, 5, 5, 5, 5, 3 };
197  ucs2_t wc = in[0];
198  size_t n = sz[wc & 7];
199  size_t i = 0;
200
201  if (n > *len) {
202    errno = EINVAL;
203    return 0;
204  }
205  while (++i < n) {
206    wc = cjk_compose(wc, in[i], table, size);
207    if (!wc) {
208      errno = EILSEQ;
209      return 0;
210    }
211  }
212  *len = n;
213  return wc;
214}
215#endif
216