19ca40936STijl Coosemans /* $NetBSD: citrus_ues.c,v 1.3 2012/02/12 13:51:29 wiz Exp $ */
2ad30f8e7SGabor Kovesdan
3ad30f8e7SGabor Kovesdan /*-
4*5e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause
5*5e53a4f9SPedro F. Giffuni *
6ad30f8e7SGabor Kovesdan * Copyright (c)2006 Citrus Project,
7ad30f8e7SGabor Kovesdan * All rights reserved.
8ad30f8e7SGabor Kovesdan *
9ad30f8e7SGabor Kovesdan * Redistribution and use in source and binary forms, with or without
10ad30f8e7SGabor Kovesdan * modification, are permitted provided that the following conditions
11ad30f8e7SGabor Kovesdan * are met:
12ad30f8e7SGabor Kovesdan * 1. Redistributions of source code must retain the above copyright
13ad30f8e7SGabor Kovesdan * notice, this list of conditions and the following disclaimer.
14ad30f8e7SGabor Kovesdan * 2. Redistributions in binary form must reproduce the above copyright
15ad30f8e7SGabor Kovesdan * notice, this list of conditions and the following disclaimer in the
16ad30f8e7SGabor Kovesdan * documentation and/or other materials provided with the distribution.
17ad30f8e7SGabor Kovesdan *
18ad30f8e7SGabor Kovesdan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19ad30f8e7SGabor Kovesdan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20ad30f8e7SGabor Kovesdan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ad30f8e7SGabor Kovesdan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22ad30f8e7SGabor Kovesdan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23ad30f8e7SGabor Kovesdan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24ad30f8e7SGabor Kovesdan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25ad30f8e7SGabor Kovesdan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26ad30f8e7SGabor Kovesdan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27ad30f8e7SGabor Kovesdan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28ad30f8e7SGabor Kovesdan * SUCH DAMAGE.
29ad30f8e7SGabor Kovesdan */
30ad30f8e7SGabor Kovesdan
31ad30f8e7SGabor Kovesdan #include <sys/cdefs.h>
32ad30f8e7SGabor Kovesdan
33ad30f8e7SGabor Kovesdan #include <assert.h>
34ad30f8e7SGabor Kovesdan #include <errno.h>
35ad30f8e7SGabor Kovesdan #include <limits.h>
36ad30f8e7SGabor Kovesdan #include <stdio.h>
37ad30f8e7SGabor Kovesdan #include <stdint.h>
38ad30f8e7SGabor Kovesdan #include <stdlib.h>
39ad30f8e7SGabor Kovesdan #include <string.h>
40ad30f8e7SGabor Kovesdan #include <wchar.h>
41ad30f8e7SGabor Kovesdan
42ad30f8e7SGabor Kovesdan #include "citrus_namespace.h"
43ad30f8e7SGabor Kovesdan #include "citrus_types.h"
44ad30f8e7SGabor Kovesdan #include "citrus_bcs.h"
45ad30f8e7SGabor Kovesdan #include "citrus_module.h"
46ad30f8e7SGabor Kovesdan #include "citrus_stdenc.h"
47ad30f8e7SGabor Kovesdan #include "citrus_ues.h"
48ad30f8e7SGabor Kovesdan
49ad30f8e7SGabor Kovesdan typedef struct {
50ad30f8e7SGabor Kovesdan size_t mb_cur_max;
51ad30f8e7SGabor Kovesdan int mode;
52ad30f8e7SGabor Kovesdan #define MODE_C99 1
53ad30f8e7SGabor Kovesdan } _UESEncodingInfo;
54ad30f8e7SGabor Kovesdan
55ad30f8e7SGabor Kovesdan typedef struct {
56ad30f8e7SGabor Kovesdan int chlen;
57ad30f8e7SGabor Kovesdan char ch[12];
58ad30f8e7SGabor Kovesdan } _UESState;
59ad30f8e7SGabor Kovesdan
60ad30f8e7SGabor Kovesdan #define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
61ad30f8e7SGabor Kovesdan #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
62ad30f8e7SGabor Kovesdan
63ad30f8e7SGabor Kovesdan #define _FUNCNAME(m) _citrus_UES_##m
64ad30f8e7SGabor Kovesdan #define _ENCODING_INFO _UESEncodingInfo
65ad30f8e7SGabor Kovesdan #define _ENCODING_STATE _UESState
66ad30f8e7SGabor Kovesdan #define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max
67ad30f8e7SGabor Kovesdan #define _ENCODING_IS_STATE_DEPENDENT 0
68ad30f8e7SGabor Kovesdan #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
69ad30f8e7SGabor Kovesdan
70ad30f8e7SGabor Kovesdan static __inline void
71ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_UES_init_state(_UESEncodingInfo * __restrict ei __unused,_UESState * __restrict psenc)72ad30f8e7SGabor Kovesdan _citrus_UES_init_state(_UESEncodingInfo * __restrict ei __unused,
73ad30f8e7SGabor Kovesdan _UESState * __restrict psenc)
74ad30f8e7SGabor Kovesdan {
75ad30f8e7SGabor Kovesdan
76ad30f8e7SGabor Kovesdan psenc->chlen = 0;
77ad30f8e7SGabor Kovesdan }
78ad30f8e7SGabor Kovesdan
79b61949ddSDimitry Andric #if 0
80ad30f8e7SGabor Kovesdan static __inline void
81ad30f8e7SGabor Kovesdan /*ARGSUSED*/
82ad30f8e7SGabor Kovesdan _citrus_UES_pack_state(_UESEncodingInfo * __restrict ei __unused,
83ad30f8e7SGabor Kovesdan void *__restrict pspriv, const _UESState * __restrict psenc)
84ad30f8e7SGabor Kovesdan {
85ad30f8e7SGabor Kovesdan
86ad30f8e7SGabor Kovesdan memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
87ad30f8e7SGabor Kovesdan }
88ad30f8e7SGabor Kovesdan
89ad30f8e7SGabor Kovesdan static __inline void
90ad30f8e7SGabor Kovesdan /*ARGSUSED*/
91ad30f8e7SGabor Kovesdan _citrus_UES_unpack_state(_UESEncodingInfo * __restrict ei __unused,
92ad30f8e7SGabor Kovesdan _UESState * __restrict psenc, const void * __restrict pspriv)
93ad30f8e7SGabor Kovesdan {
94ad30f8e7SGabor Kovesdan
95ad30f8e7SGabor Kovesdan memcpy((void *)psenc, pspriv, sizeof(*psenc));
96ad30f8e7SGabor Kovesdan }
97b61949ddSDimitry Andric #endif
98ad30f8e7SGabor Kovesdan
99ad30f8e7SGabor Kovesdan static __inline int
to_int(int ch)100ad30f8e7SGabor Kovesdan to_int(int ch)
101ad30f8e7SGabor Kovesdan {
102ad30f8e7SGabor Kovesdan
103ad30f8e7SGabor Kovesdan if (ch >= '0' && ch <= '9')
104ad30f8e7SGabor Kovesdan return (ch - '0');
105ad30f8e7SGabor Kovesdan else if (ch >= 'A' && ch <= 'F')
106ad30f8e7SGabor Kovesdan return ((ch - 'A') + 10);
107ad30f8e7SGabor Kovesdan else if (ch >= 'a' && ch <= 'f')
108ad30f8e7SGabor Kovesdan return ((ch - 'a') + 10);
109ad30f8e7SGabor Kovesdan return (-1);
110ad30f8e7SGabor Kovesdan }
111ad30f8e7SGabor Kovesdan
112ad30f8e7SGabor Kovesdan #define ESCAPE '\\'
113ad30f8e7SGabor Kovesdan #define UCS2_ESC 'u'
114ad30f8e7SGabor Kovesdan #define UCS4_ESC 'U'
115ad30f8e7SGabor Kovesdan
116ad30f8e7SGabor Kovesdan #define UCS2_BIT 16
117ad30f8e7SGabor Kovesdan #define UCS4_BIT 32
118ad30f8e7SGabor Kovesdan #define BMP_MAX UINT32_C(0xFFFF)
119ad30f8e7SGabor Kovesdan #define UCS2_MAX UINT32_C(0x10FFFF)
120ad30f8e7SGabor Kovesdan #define UCS4_MAX UINT32_C(0x7FFFFFFF)
121ad30f8e7SGabor Kovesdan
122ad30f8e7SGabor Kovesdan static const char *xdig = "0123456789abcdef";
123ad30f8e7SGabor Kovesdan
124ad30f8e7SGabor Kovesdan static __inline int
to_str(char * s,wchar_t wc,int bit)125ad30f8e7SGabor Kovesdan to_str(char *s, wchar_t wc, int bit)
126ad30f8e7SGabor Kovesdan {
127ad30f8e7SGabor Kovesdan char *p;
128ad30f8e7SGabor Kovesdan
129ad30f8e7SGabor Kovesdan p = s;
130ad30f8e7SGabor Kovesdan *p++ = ESCAPE;
131ad30f8e7SGabor Kovesdan switch (bit) {
132ad30f8e7SGabor Kovesdan case UCS2_BIT:
133ad30f8e7SGabor Kovesdan *p++ = UCS2_ESC;
134ad30f8e7SGabor Kovesdan break;
135ad30f8e7SGabor Kovesdan case UCS4_BIT:
136ad30f8e7SGabor Kovesdan *p++ = UCS4_ESC;
137ad30f8e7SGabor Kovesdan break;
138ad30f8e7SGabor Kovesdan default:
139ad30f8e7SGabor Kovesdan abort();
140ad30f8e7SGabor Kovesdan }
141ad30f8e7SGabor Kovesdan do {
142ad30f8e7SGabor Kovesdan *p++ = xdig[(wc >> (bit -= 4)) & 0xF];
143ad30f8e7SGabor Kovesdan } while (bit > 0);
144ad30f8e7SGabor Kovesdan return (p - s);
145ad30f8e7SGabor Kovesdan }
146ad30f8e7SGabor Kovesdan
147ad30f8e7SGabor Kovesdan static __inline bool
is_hi_surrogate(wchar_t wc)148ad30f8e7SGabor Kovesdan is_hi_surrogate(wchar_t wc)
149ad30f8e7SGabor Kovesdan {
150ad30f8e7SGabor Kovesdan
151ad30f8e7SGabor Kovesdan return (wc >= 0xD800 && wc <= 0xDBFF);
152ad30f8e7SGabor Kovesdan }
153ad30f8e7SGabor Kovesdan
154ad30f8e7SGabor Kovesdan static __inline bool
is_lo_surrogate(wchar_t wc)155ad30f8e7SGabor Kovesdan is_lo_surrogate(wchar_t wc)
156ad30f8e7SGabor Kovesdan {
157ad30f8e7SGabor Kovesdan
158ad30f8e7SGabor Kovesdan return (wc >= 0xDC00 && wc <= 0xDFFF);
159ad30f8e7SGabor Kovesdan }
160ad30f8e7SGabor Kovesdan
161ad30f8e7SGabor Kovesdan static __inline wchar_t
surrogate_to_ucs(wchar_t hi,wchar_t lo)162ad30f8e7SGabor Kovesdan surrogate_to_ucs(wchar_t hi, wchar_t lo)
163ad30f8e7SGabor Kovesdan {
164ad30f8e7SGabor Kovesdan
165ad30f8e7SGabor Kovesdan hi -= 0xD800;
166ad30f8e7SGabor Kovesdan lo -= 0xDC00;
167ad30f8e7SGabor Kovesdan return ((hi << 10 | lo) + 0x10000);
168ad30f8e7SGabor Kovesdan }
169ad30f8e7SGabor Kovesdan
170ad30f8e7SGabor Kovesdan static __inline void
ucs_to_surrogate(wchar_t wc,wchar_t * __restrict hi,wchar_t * __restrict lo)171ad30f8e7SGabor Kovesdan ucs_to_surrogate(wchar_t wc, wchar_t * __restrict hi, wchar_t * __restrict lo)
172ad30f8e7SGabor Kovesdan {
173ad30f8e7SGabor Kovesdan
174ad30f8e7SGabor Kovesdan wc -= 0x10000;
175ad30f8e7SGabor Kovesdan *hi = (wc >> 10) + 0xD800;
176ad30f8e7SGabor Kovesdan *lo = (wc & 0x3FF) + 0xDC00;
177ad30f8e7SGabor Kovesdan }
178ad30f8e7SGabor Kovesdan
179ad30f8e7SGabor Kovesdan static __inline bool
is_basic(wchar_t wc)180ad30f8e7SGabor Kovesdan is_basic(wchar_t wc)
181ad30f8e7SGabor Kovesdan {
182ad30f8e7SGabor Kovesdan
183ad30f8e7SGabor Kovesdan return ((uint32_t)wc <= 0x9F && wc != 0x24 && wc != 0x40 &&
184ad30f8e7SGabor Kovesdan wc != 0x60);
185ad30f8e7SGabor Kovesdan }
186ad30f8e7SGabor Kovesdan
187ad30f8e7SGabor Kovesdan static int
_citrus_UES_mbrtowc_priv(_UESEncodingInfo * __restrict ei,wchar_t * __restrict pwc,char ** __restrict s,size_t n,_UESState * __restrict psenc,size_t * __restrict nresult)188ad30f8e7SGabor Kovesdan _citrus_UES_mbrtowc_priv(_UESEncodingInfo * __restrict ei,
1891243a98eSTijl Coosemans wchar_t * __restrict pwc, char ** __restrict s, size_t n,
190ad30f8e7SGabor Kovesdan _UESState * __restrict psenc, size_t * __restrict nresult)
191ad30f8e7SGabor Kovesdan {
1921243a98eSTijl Coosemans char *s0;
193ad30f8e7SGabor Kovesdan int ch, head, num, tail;
194ad30f8e7SGabor Kovesdan wchar_t hi, wc;
195ad30f8e7SGabor Kovesdan
196ad30f8e7SGabor Kovesdan if (*s == NULL) {
197ad30f8e7SGabor Kovesdan _citrus_UES_init_state(ei, psenc);
198ad30f8e7SGabor Kovesdan *nresult = 0;
199ad30f8e7SGabor Kovesdan return (0);
200ad30f8e7SGabor Kovesdan }
201ad30f8e7SGabor Kovesdan s0 = *s;
202ad30f8e7SGabor Kovesdan
203ad30f8e7SGabor Kovesdan hi = (wchar_t)0;
204ad30f8e7SGabor Kovesdan tail = 0;
205ad30f8e7SGabor Kovesdan
206ad30f8e7SGabor Kovesdan surrogate:
207ad30f8e7SGabor Kovesdan wc = (wchar_t)0;
208ad30f8e7SGabor Kovesdan head = tail;
209ad30f8e7SGabor Kovesdan if (psenc->chlen == head) {
210ad30f8e7SGabor Kovesdan if (n-- < 1)
211ad30f8e7SGabor Kovesdan goto restart;
212ad30f8e7SGabor Kovesdan psenc->ch[psenc->chlen++] = *s0++;
213ad30f8e7SGabor Kovesdan }
214ad30f8e7SGabor Kovesdan ch = (unsigned char)psenc->ch[head++];
215ad30f8e7SGabor Kovesdan if (ch == ESCAPE) {
216ad30f8e7SGabor Kovesdan if (psenc->chlen == head) {
217ad30f8e7SGabor Kovesdan if (n-- < 1)
218ad30f8e7SGabor Kovesdan goto restart;
219ad30f8e7SGabor Kovesdan psenc->ch[psenc->chlen++] = *s0++;
220ad30f8e7SGabor Kovesdan }
221ad30f8e7SGabor Kovesdan switch (psenc->ch[head]) {
222ad30f8e7SGabor Kovesdan case UCS2_ESC:
223ad30f8e7SGabor Kovesdan tail += 6;
224ad30f8e7SGabor Kovesdan break;
225ad30f8e7SGabor Kovesdan case UCS4_ESC:
226ad30f8e7SGabor Kovesdan if (ei->mode & MODE_C99) {
227ad30f8e7SGabor Kovesdan tail = 10;
228ad30f8e7SGabor Kovesdan break;
229ad30f8e7SGabor Kovesdan }
230ad30f8e7SGabor Kovesdan /*FALLTHROUGH*/
231ad30f8e7SGabor Kovesdan default:
232ad30f8e7SGabor Kovesdan tail = 0;
233ad30f8e7SGabor Kovesdan }
234ad30f8e7SGabor Kovesdan ++head;
235ad30f8e7SGabor Kovesdan }
236ad30f8e7SGabor Kovesdan for (; head < tail; ++head) {
237ad30f8e7SGabor Kovesdan if (psenc->chlen == head) {
238ad30f8e7SGabor Kovesdan if (n-- < 1) {
239ad30f8e7SGabor Kovesdan restart:
240ad30f8e7SGabor Kovesdan *s = s0;
241ad30f8e7SGabor Kovesdan *nresult = (size_t)-2;
242ad30f8e7SGabor Kovesdan return (0);
243ad30f8e7SGabor Kovesdan }
244ad30f8e7SGabor Kovesdan psenc->ch[psenc->chlen++] = *s0++;
245ad30f8e7SGabor Kovesdan }
246ad30f8e7SGabor Kovesdan num = to_int((int)(unsigned char)psenc->ch[head]);
247ad30f8e7SGabor Kovesdan if (num < 0) {
248ad30f8e7SGabor Kovesdan tail = 0;
249ad30f8e7SGabor Kovesdan break;
250ad30f8e7SGabor Kovesdan }
251ad30f8e7SGabor Kovesdan wc = (wc << 4) | num;
252ad30f8e7SGabor Kovesdan }
253ad30f8e7SGabor Kovesdan head = 0;
254ad30f8e7SGabor Kovesdan switch (tail) {
255ad30f8e7SGabor Kovesdan case 0:
256ad30f8e7SGabor Kovesdan break;
257ad30f8e7SGabor Kovesdan case 6:
258ad30f8e7SGabor Kovesdan if (hi != (wchar_t)0)
259ad30f8e7SGabor Kovesdan break;
260ad30f8e7SGabor Kovesdan if ((ei->mode & MODE_C99) == 0) {
261ad30f8e7SGabor Kovesdan if (is_hi_surrogate(wc) != 0) {
262ad30f8e7SGabor Kovesdan hi = wc;
263ad30f8e7SGabor Kovesdan goto surrogate;
264ad30f8e7SGabor Kovesdan }
265ad30f8e7SGabor Kovesdan if ((uint32_t)wc <= 0x7F /* XXX */ ||
266ad30f8e7SGabor Kovesdan is_lo_surrogate(wc) != 0)
267ad30f8e7SGabor Kovesdan break;
268ad30f8e7SGabor Kovesdan goto done;
269ad30f8e7SGabor Kovesdan }
270ad30f8e7SGabor Kovesdan /*FALLTHROUGH*/
271ad30f8e7SGabor Kovesdan case 10:
272ad30f8e7SGabor Kovesdan if (is_basic(wc) == 0 && (uint32_t)wc <= UCS4_MAX &&
273ad30f8e7SGabor Kovesdan is_hi_surrogate(wc) == 0 && is_lo_surrogate(wc) == 0)
274ad30f8e7SGabor Kovesdan goto done;
275ad30f8e7SGabor Kovesdan *nresult = (size_t)-1;
276ad30f8e7SGabor Kovesdan return (EILSEQ);
277ad30f8e7SGabor Kovesdan case 12:
278ad30f8e7SGabor Kovesdan if (is_lo_surrogate(wc) == 0)
279ad30f8e7SGabor Kovesdan break;
280ad30f8e7SGabor Kovesdan wc = surrogate_to_ucs(hi, wc);
281ad30f8e7SGabor Kovesdan goto done;
282ad30f8e7SGabor Kovesdan }
283ad30f8e7SGabor Kovesdan ch = (unsigned char)psenc->ch[0];
284ad30f8e7SGabor Kovesdan head = psenc->chlen;
285ad30f8e7SGabor Kovesdan if (--head > 0)
286ad30f8e7SGabor Kovesdan memmove(&psenc->ch[0], &psenc->ch[1], head);
287ad30f8e7SGabor Kovesdan wc = (wchar_t)ch;
288ad30f8e7SGabor Kovesdan done:
289ad30f8e7SGabor Kovesdan psenc->chlen = head;
290ad30f8e7SGabor Kovesdan if (pwc != NULL)
291ad30f8e7SGabor Kovesdan *pwc = wc;
292ad30f8e7SGabor Kovesdan *nresult = (size_t)((wc == 0) ? 0 : (s0 - *s));
293ad30f8e7SGabor Kovesdan *s = s0;
294ad30f8e7SGabor Kovesdan
295ad30f8e7SGabor Kovesdan return (0);
296ad30f8e7SGabor Kovesdan }
297ad30f8e7SGabor Kovesdan
298ad30f8e7SGabor Kovesdan static int
_citrus_UES_wcrtomb_priv(_UESEncodingInfo * __restrict ei,char * __restrict s,size_t n,wchar_t wc,_UESState * __restrict psenc,size_t * __restrict nresult)299ad30f8e7SGabor Kovesdan _citrus_UES_wcrtomb_priv(_UESEncodingInfo * __restrict ei,
300ad30f8e7SGabor Kovesdan char * __restrict s, size_t n, wchar_t wc,
301ad30f8e7SGabor Kovesdan _UESState * __restrict psenc, size_t * __restrict nresult)
302ad30f8e7SGabor Kovesdan {
303ad30f8e7SGabor Kovesdan wchar_t hi, lo;
304ad30f8e7SGabor Kovesdan
305ad30f8e7SGabor Kovesdan if (psenc->chlen != 0)
306ad30f8e7SGabor Kovesdan return (EINVAL);
307ad30f8e7SGabor Kovesdan
308ad30f8e7SGabor Kovesdan if ((ei->mode & MODE_C99) ? is_basic(wc) : (uint32_t)wc <= 0x7F) {
309ad30f8e7SGabor Kovesdan if (n-- < 1)
310ad30f8e7SGabor Kovesdan goto e2big;
311ad30f8e7SGabor Kovesdan psenc->ch[psenc->chlen++] = (char)wc;
312ad30f8e7SGabor Kovesdan } else if ((uint32_t)wc <= BMP_MAX) {
313ad30f8e7SGabor Kovesdan if (n < 6)
314ad30f8e7SGabor Kovesdan goto e2big;
315ad30f8e7SGabor Kovesdan psenc->chlen = to_str(&psenc->ch[0], wc, UCS2_BIT);
316ad30f8e7SGabor Kovesdan } else if ((ei->mode & MODE_C99) == 0 && (uint32_t)wc <= UCS2_MAX) {
317ad30f8e7SGabor Kovesdan if (n < 12)
318ad30f8e7SGabor Kovesdan goto e2big;
319ad30f8e7SGabor Kovesdan ucs_to_surrogate(wc, &hi, &lo);
320ad30f8e7SGabor Kovesdan psenc->chlen += to_str(&psenc->ch[0], hi, UCS2_BIT);
321ad30f8e7SGabor Kovesdan psenc->chlen += to_str(&psenc->ch[6], lo, UCS2_BIT);
322ad30f8e7SGabor Kovesdan } else if ((ei->mode & MODE_C99) && (uint32_t)wc <= UCS4_MAX) {
323ad30f8e7SGabor Kovesdan if (n < 10)
324ad30f8e7SGabor Kovesdan goto e2big;
325ad30f8e7SGabor Kovesdan psenc->chlen = to_str(&psenc->ch[0], wc, UCS4_BIT);
326ad30f8e7SGabor Kovesdan } else {
327ad30f8e7SGabor Kovesdan *nresult = (size_t)-1;
328ad30f8e7SGabor Kovesdan return (EILSEQ);
329ad30f8e7SGabor Kovesdan }
330ad30f8e7SGabor Kovesdan memcpy(s, psenc->ch, psenc->chlen);
331ad30f8e7SGabor Kovesdan *nresult = psenc->chlen;
332ad30f8e7SGabor Kovesdan psenc->chlen = 0;
333ad30f8e7SGabor Kovesdan
334ad30f8e7SGabor Kovesdan return (0);
335ad30f8e7SGabor Kovesdan
336ad30f8e7SGabor Kovesdan e2big:
337ad30f8e7SGabor Kovesdan *nresult = (size_t)-1;
338ad30f8e7SGabor Kovesdan return (E2BIG);
339ad30f8e7SGabor Kovesdan }
340ad30f8e7SGabor Kovesdan
341ad30f8e7SGabor Kovesdan /*ARGSUSED*/
342ad30f8e7SGabor Kovesdan static int
_citrus_UES_stdenc_wctocs(_UESEncodingInfo * __restrict ei __unused,_csid_t * __restrict csid,_index_t * __restrict idx,wchar_t wc)343ad30f8e7SGabor Kovesdan _citrus_UES_stdenc_wctocs(_UESEncodingInfo * __restrict ei __unused,
344ad30f8e7SGabor Kovesdan _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
345ad30f8e7SGabor Kovesdan {
346ad30f8e7SGabor Kovesdan
347ad30f8e7SGabor Kovesdan *csid = 0;
348ad30f8e7SGabor Kovesdan *idx = (_index_t)wc;
349ad30f8e7SGabor Kovesdan
350ad30f8e7SGabor Kovesdan return (0);
351ad30f8e7SGabor Kovesdan }
352ad30f8e7SGabor Kovesdan
353ad30f8e7SGabor Kovesdan static __inline int
354ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_UES_stdenc_cstowc(_UESEncodingInfo * __restrict ei __unused,wchar_t * __restrict wc,_csid_t csid,_index_t idx)355ad30f8e7SGabor Kovesdan _citrus_UES_stdenc_cstowc(_UESEncodingInfo * __restrict ei __unused,
356ad30f8e7SGabor Kovesdan wchar_t * __restrict wc, _csid_t csid, _index_t idx)
357ad30f8e7SGabor Kovesdan {
358ad30f8e7SGabor Kovesdan
359ad30f8e7SGabor Kovesdan if (csid != 0)
360ad30f8e7SGabor Kovesdan return (EILSEQ);
361ad30f8e7SGabor Kovesdan *wc = (wchar_t)idx;
362ad30f8e7SGabor Kovesdan
363ad30f8e7SGabor Kovesdan return (0);
364ad30f8e7SGabor Kovesdan }
365ad30f8e7SGabor Kovesdan
366ad30f8e7SGabor Kovesdan static __inline int
367ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_UES_stdenc_get_state_desc_generic(_UESEncodingInfo * __restrict ei __unused,_UESState * __restrict psenc,int * __restrict rstate)368ad30f8e7SGabor Kovesdan _citrus_UES_stdenc_get_state_desc_generic(_UESEncodingInfo * __restrict ei __unused,
369ad30f8e7SGabor Kovesdan _UESState * __restrict psenc, int * __restrict rstate)
370ad30f8e7SGabor Kovesdan {
371ad30f8e7SGabor Kovesdan
372ad30f8e7SGabor Kovesdan *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
373ad30f8e7SGabor Kovesdan _STDENC_SDGEN_INCOMPLETE_CHAR;
374ad30f8e7SGabor Kovesdan return (0);
375ad30f8e7SGabor Kovesdan }
376ad30f8e7SGabor Kovesdan
377ad30f8e7SGabor Kovesdan static void
378ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_UES_encoding_module_uninit(_UESEncodingInfo * ei __unused)379ad30f8e7SGabor Kovesdan _citrus_UES_encoding_module_uninit(_UESEncodingInfo *ei __unused)
380ad30f8e7SGabor Kovesdan {
381ad30f8e7SGabor Kovesdan
382ad30f8e7SGabor Kovesdan /* ei seems to be unused */
383ad30f8e7SGabor Kovesdan }
384ad30f8e7SGabor Kovesdan
385ad30f8e7SGabor Kovesdan static int
386ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_UES_encoding_module_init(_UESEncodingInfo * __restrict ei,const void * __restrict var,size_t lenvar)387ad30f8e7SGabor Kovesdan _citrus_UES_encoding_module_init(_UESEncodingInfo * __restrict ei,
388ad30f8e7SGabor Kovesdan const void * __restrict var, size_t lenvar)
389ad30f8e7SGabor Kovesdan {
390ad30f8e7SGabor Kovesdan const char *p;
391ad30f8e7SGabor Kovesdan
392ad30f8e7SGabor Kovesdan p = var;
393ad30f8e7SGabor Kovesdan memset((void *)ei, 0, sizeof(*ei));
394ad30f8e7SGabor Kovesdan while (lenvar > 0) {
395ad30f8e7SGabor Kovesdan switch (_bcs_toupper(*p)) {
396ad30f8e7SGabor Kovesdan case 'C':
397ad30f8e7SGabor Kovesdan MATCH(C99, ei->mode |= MODE_C99);
398ad30f8e7SGabor Kovesdan break;
399ad30f8e7SGabor Kovesdan }
400ad30f8e7SGabor Kovesdan ++p;
401ad30f8e7SGabor Kovesdan --lenvar;
402ad30f8e7SGabor Kovesdan }
403ad30f8e7SGabor Kovesdan ei->mb_cur_max = (ei->mode & MODE_C99) ? 10 : 12;
404ad30f8e7SGabor Kovesdan
405ad30f8e7SGabor Kovesdan return (0);
406ad30f8e7SGabor Kovesdan }
407ad30f8e7SGabor Kovesdan
408ad30f8e7SGabor Kovesdan /* ----------------------------------------------------------------------
409ad30f8e7SGabor Kovesdan * public interface for stdenc
410ad30f8e7SGabor Kovesdan */
411ad30f8e7SGabor Kovesdan
412ad30f8e7SGabor Kovesdan _CITRUS_STDENC_DECLS(UES);
413ad30f8e7SGabor Kovesdan _CITRUS_STDENC_DEF_OPS(UES);
414ad30f8e7SGabor Kovesdan
415ad30f8e7SGabor Kovesdan #include "citrus_stdenc_template.h"
416