Update after gnulib changed.
[libiconv.git] / lib / hz.h
blob9e78518c57567fb078380f9bca4e75de29f77c1b
1 /*
2 * Copyright (C) 1999-2001, 2008, 2016 Free Software Foundation, Inc.
3 * This file is part of the GNU LIBICONV Library.
5 * The GNU LIBICONV Library is free software; you can redistribute it
6 * and/or modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either version 2.1
8 * of the License, or (at your option) any later version.
10 * The GNU LIBICONV Library is distributed in the hope that it will be
11 * useful, 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.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with the GNU LIBICONV Library; see the file COPYING.LIB.
17 * If not, see <https://www.gnu.org/licenses/>.
21 * HZ
24 /* Specification: RFC 1842, RFC 1843 */
27 * The state is 1 in GB mode, 0 in ASCII mode.
30 static int
31 hz_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, size_t n)
33 state_t state = conv->istate;
34 unsigned int count = 0;
35 unsigned char c;
36 for (;;) {
37 c = *s;
38 if (c == '~') {
39 if (n < count+2)
40 goto none;
41 c = s[1];
42 if (state == 0) {
43 if (c == '~') {
44 *pwc = (ucs4_t) '~';
45 conv->istate = state;
46 return count+2;
48 if (c == '{') {
49 state = 1;
50 s += 2; count += 2;
51 if (n < count+1)
52 goto none;
53 continue;
55 if (c == '\n') {
56 s += 2; count += 2;
57 if (n < count+1)
58 goto none;
59 continue;
61 } else {
62 if (c == '}') {
63 state = 0;
64 s += 2; count += 2;
65 if (n < count+1)
66 goto none;
67 continue;
70 goto ilseq;
72 break;
74 if (state == 0) {
75 *pwc = (ucs4_t) c;
76 conv->istate = state;
77 return count+1;
78 } else {
79 int ret;
80 if (n < count+2)
81 goto none;
82 ret = gb2312_mbtowc(conv,pwc,s,2);
83 if (ret == RET_ILSEQ)
84 goto ilseq;
85 if (ret != 2) abort();
86 conv->istate = state;
87 return count+2;
90 none:
91 conv->istate = state;
92 return RET_TOOFEW(count);
94 ilseq:
95 conv->istate = state;
96 return RET_SHIFT_ILSEQ(count);
99 static int
100 hz_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, size_t n)
102 state_t state = conv->ostate;
103 unsigned char buf[2];
104 int ret;
106 /* Code set 0 (ASCII or GB 1988-89) */
107 ret = ascii_wctomb(conv,buf,wc,1);
108 if (ret != RET_ILUNI) {
109 if (ret != 1) abort();
110 if (buf[0] < 0x80) {
111 int count = (state ? 3 : 1);
112 if (n < count)
113 return RET_TOOSMALL;
114 if (state) {
115 r[0] = '~';
116 r[1] = '}';
117 r += 2;
118 state = 0;
120 r[0] = buf[0];
121 conv->ostate = state;
122 return count;
126 /* Code set 1 (GB 2312-1980) */
127 ret = gb2312_wctomb(conv,buf,wc,2);
128 if (ret != RET_ILUNI) {
129 if (ret != 2) abort();
130 if (buf[0] < 0x80 && buf[1] < 0x80) {
131 int count = (state ? 2 : 4);
132 if (n < count)
133 return RET_TOOSMALL;
134 if (!state) {
135 r[0] = '~';
136 r[1] = '{';
137 r += 2;
138 state = 1;
140 r[0] = buf[0];
141 r[1] = buf[1];
142 conv->ostate = state;
143 return count;
147 return RET_ILUNI;
150 static int
151 hz_reset (conv_t conv, unsigned char *r, size_t n)
153 state_t state = conv->ostate;
154 if (state) {
155 if (n < 2)
156 return RET_TOOSMALL;
157 r[0] = '~';
158 r[1] = '}';
159 /* conv->ostate = 0; will be done by the caller */
160 return 2;
161 } else
162 return 0;