1aef5731fSOliver Tappe/*
2aef5731fSOliver Tappe * Copyright (C) 1999-2001 Free Software Foundation, Inc.
3aef5731fSOliver Tappe * This file is part of the GNU LIBICONV Library.
4aef5731fSOliver Tappe *
5aef5731fSOliver Tappe * The GNU LIBICONV Library is free software; you can redistribute it
6aef5731fSOliver Tappe * and/or modify it under the terms of the GNU Library General Public
7aef5731fSOliver Tappe * License as published by the Free Software Foundation; either version 2
8aef5731fSOliver Tappe * of the License, or (at your option) any later version.
9aef5731fSOliver Tappe *
10aef5731fSOliver Tappe * The GNU LIBICONV Library is distributed in the hope that it will be
11aef5731fSOliver Tappe * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12aef5731fSOliver Tappe * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13aef5731fSOliver Tappe * Library General Public License for more details.
14aef5731fSOliver Tappe *
15aef5731fSOliver Tappe * You should have received a copy of the GNU Library General Public
16aef5731fSOliver Tappe * License along with the GNU LIBICONV Library; see the file COPYING.LIB.
17aef5731fSOliver Tappe * If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18aef5731fSOliver Tappe */
19aef5731fSOliver Tappe
20aef5731fSOliver Tappe/*
21aef5731fSOliver Tappe * HZ
22aef5731fSOliver Tappe */
23aef5731fSOliver Tappe
24aef5731fSOliver Tappe/* Specification: RFC 1842, RFC 1843 */
25aef5731fSOliver Tappe
26aef5731fSOliver Tappe/*
27aef5731fSOliver Tappe * The state is 1 in GB mode, 0 in ASCII mode.
28aef5731fSOliver Tappe */
29aef5731fSOliver Tappe
30aef5731fSOliver Tappestatic int
31aef5731fSOliver Tappehz_mbtowc (conv_t conv, ucs4_t *pwc, const unsigned char *s, int n)
32aef5731fSOliver Tappe{
33aef5731fSOliver Tappe  state_t state = conv->istate;
34aef5731fSOliver Tappe  unsigned int count = 0;
35aef5731fSOliver Tappe  unsigned char c;
36aef5731fSOliver Tappe  for (;;) {
37aef5731fSOliver Tappe    c = *s;
38aef5731fSOliver Tappe    if (c == '~') {
39aef5731fSOliver Tappe      if (n < count+2)
40aef5731fSOliver Tappe        goto none;
41aef5731fSOliver Tappe      c = s[1];
42aef5731fSOliver Tappe      if (state == 0) {
43aef5731fSOliver Tappe        if (c == '~') {
44aef5731fSOliver Tappe          *pwc = (ucs4_t) '~';
45aef5731fSOliver Tappe          conv->istate = state;
46aef5731fSOliver Tappe          return count+2;
47aef5731fSOliver Tappe        }
48aef5731fSOliver Tappe        if (c == '{') {
49aef5731fSOliver Tappe          state = 1;
50aef5731fSOliver Tappe          s += 2; count += 2;
51aef5731fSOliver Tappe          if (n < count+1)
52aef5731fSOliver Tappe            goto none;
53aef5731fSOliver Tappe          continue;
54aef5731fSOliver Tappe        }
55aef5731fSOliver Tappe        if (c == '\n') {
56aef5731fSOliver Tappe          s += 2; count += 2;
57aef5731fSOliver Tappe          if (n < count+1)
58aef5731fSOliver Tappe            goto none;
59aef5731fSOliver Tappe          continue;
60aef5731fSOliver Tappe        }
61aef5731fSOliver Tappe      } else {
62aef5731fSOliver Tappe        if (c == '}') {
63aef5731fSOliver Tappe          state = 0;
64aef5731fSOliver Tappe          s += 2; count += 2;
65aef5731fSOliver Tappe          if (n < count+1)
66aef5731fSOliver Tappe            goto none;
67aef5731fSOliver Tappe          continue;
68aef5731fSOliver Tappe        }
69aef5731fSOliver Tappe      }
70aef5731fSOliver Tappe      return RET_ILSEQ;
71aef5731fSOliver Tappe    }
72aef5731fSOliver Tappe    break;
73aef5731fSOliver Tappe  }
74aef5731fSOliver Tappe  if (state == 0) {
75aef5731fSOliver Tappe    *pwc = (ucs4_t) c;
76aef5731fSOliver Tappe    conv->istate = state;
77aef5731fSOliver Tappe    return count+1;
78aef5731fSOliver Tappe  } else {
79aef5731fSOliver Tappe    int ret;
80aef5731fSOliver Tappe    if (n < count+2)
81aef5731fSOliver Tappe      goto none;
82aef5731fSOliver Tappe    ret = gb2312_mbtowc(conv,pwc,s,2);
83aef5731fSOliver Tappe    if (ret == RET_ILSEQ)
84aef5731fSOliver Tappe      return RET_ILSEQ;
85aef5731fSOliver Tappe    if (ret != 2) abort();
86aef5731fSOliver Tappe    conv->istate = state;
87aef5731fSOliver Tappe    return count+2;
88aef5731fSOliver Tappe  }
89aef5731fSOliver Tappe
90aef5731fSOliver Tappenone:
91aef5731fSOliver Tappe  conv->istate = state;
92aef5731fSOliver Tappe  return RET_TOOFEW(count);
93aef5731fSOliver Tappe}
94aef5731fSOliver Tappe
95aef5731fSOliver Tappestatic int
96aef5731fSOliver Tappehz_wctomb (conv_t conv, unsigned char *r, ucs4_t wc, int n)
97aef5731fSOliver Tappe{
98aef5731fSOliver Tappe  state_t state = conv->ostate;
99aef5731fSOliver Tappe  unsigned char buf[2];
100aef5731fSOliver Tappe  int ret;
101aef5731fSOliver Tappe
102aef5731fSOliver Tappe  /* Code set 0 (ASCII or GB 1988-89) */
103aef5731fSOliver Tappe  ret = ascii_wctomb(conv,buf,wc,1);
104aef5731fSOliver Tappe  if (ret != RET_ILUNI) {
105aef5731fSOliver Tappe    if (ret != 1) abort();
106aef5731fSOliver Tappe    if (buf[0] < 0x80) {
107aef5731fSOliver Tappe      int count = (state ? 3 : 1);
108aef5731fSOliver Tappe      if (n < count)
109aef5731fSOliver Tappe        return RET_TOOSMALL;
110aef5731fSOliver Tappe      if (state) {
111aef5731fSOliver Tappe        r[0] = '~';
112aef5731fSOliver Tappe        r[1] = '}';
113aef5731fSOliver Tappe        r += 2;
114aef5731fSOliver Tappe        state = 0;
115aef5731fSOliver Tappe      }
116aef5731fSOliver Tappe      r[0] = buf[0];
117aef5731fSOliver Tappe      conv->ostate = state;
118aef5731fSOliver Tappe      return count;
119aef5731fSOliver Tappe    }
120aef5731fSOliver Tappe  }
121aef5731fSOliver Tappe
122aef5731fSOliver Tappe  /* Code set 1 (GB 2312-1980) */
123aef5731fSOliver Tappe  ret = gb2312_wctomb(conv,buf,wc,2);
124aef5731fSOliver Tappe  if (ret != RET_ILUNI) {
125aef5731fSOliver Tappe    if (ret != 2) abort();
126aef5731fSOliver Tappe    if (buf[0] < 0x80 && buf[1] < 0x80) {
127aef5731fSOliver Tappe      int count = (state ? 2 : 4);
128aef5731fSOliver Tappe      if (n < count)
129aef5731fSOliver Tappe        return RET_TOOSMALL;
130aef5731fSOliver Tappe      if (!state) {
131aef5731fSOliver Tappe        r[0] = '~';
132aef5731fSOliver Tappe        r[1] = '{';
133aef5731fSOliver Tappe        r += 2;
134aef5731fSOliver Tappe        state = 1;
135aef5731fSOliver Tappe      }
136aef5731fSOliver Tappe      r[0] = buf[0];
137aef5731fSOliver Tappe      r[1] = buf[1];
138aef5731fSOliver Tappe      conv->ostate = state;
139aef5731fSOliver Tappe      return count;
140aef5731fSOliver Tappe    }
141aef5731fSOliver Tappe  }
142aef5731fSOliver Tappe
143aef5731fSOliver Tappe  return RET_ILUNI;
144aef5731fSOliver Tappe}
145aef5731fSOliver Tappe
146aef5731fSOliver Tappestatic int
147aef5731fSOliver Tappehz_reset (conv_t conv, unsigned char *r, int n)
148aef5731fSOliver Tappe{
149aef5731fSOliver Tappe  state_t state = conv->ostate;
150aef5731fSOliver Tappe  if (state) {
151aef5731fSOliver Tappe    if (n < 2)
152aef5731fSOliver Tappe      return RET_TOOSMALL;
153aef5731fSOliver Tappe    r[0] = '~';
154aef5731fSOliver Tappe    r[1] = '}';
155aef5731fSOliver Tappe    /* conv->ostate = 0; will be done by the caller */
156aef5731fSOliver Tappe    return 2;
157aef5731fSOliver Tappe  } else
158aef5731fSOliver Tappe    return 0;
159aef5731fSOliver Tappe}
160