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