2 * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: head/lib/libc/locale/mbrtocXX_iconv.h 281550 2015-04-15 09:09:20Z tijl $
29 #include <sys/queue.h>
38 #include "../citrus/citrus_hash.h"
39 #include "../citrus/citrus_module.h"
40 #include "../citrus/citrus_iconv.h"
41 #include "xlocale_private.h"
45 struct _citrus_iconv iconv
;
46 char srcbuf
[MB_LEN_MAX
];
49 charXX_t widechar
[DSTBUF_LEN
];
50 char bytes
[sizeof(charXX_t
) * DSTBUF_LEN
];
54 _Static_assert(sizeof(_ConversionState
) <= sizeof(mbstate_t),
55 "Size of _ConversionState must not exceed mbstate_t's size.");
58 mbrtocXX_l(charXX_t
* __restrict pc
, const char * __restrict s
, size_t n
,
59 mbstate_t * __restrict ps
, locale_t locale
)
62 struct _citrus_iconv
*handle
;
68 ps
= &locale
->mbrtocXX
;
69 cs
= (_ConversionState
*)ps
;
72 /* Reinitialize mbstate_t. */
73 if (s
== NULL
|| !cs
->initialized
) {
74 if (_citrus_iconv_open(&handle
,
75 nl_langinfo_l(CODESET
, locale
), UTF_XX_INTERNAL
) != 0) {
76 cs
->initialized
= false;
80 handle
->cv_shared
->ci_discard_ilseq
= true;
81 handle
->cv_shared
->ci_hooks
= NULL
;
82 cs
->srcbuf_len
= cs
->dstbuf_len
= 0;
83 cs
->initialized
= true;
88 /* See if we still have characters left from the previous invocation. */
89 if (cs
->dstbuf_len
> 0) {
94 /* Fill up the read buffer as far as possible. */
95 if (n
> sizeof(cs
->srcbuf
) - cs
->srcbuf_len
)
96 n
= sizeof(cs
->srcbuf
) - cs
->srcbuf_len
;
97 memcpy(cs
->srcbuf
+ cs
->srcbuf_len
, s
, n
);
99 /* Convert as few characters to the dst buffer as possible. */
102 size_t srcleft
, dstleft
, invlen
;
106 srcleft
= cs
->srcbuf_len
+ n
;
107 dst
= cs
->dstbuf
.bytes
;
108 dstleft
= i
* sizeof(charXX_t
);
109 assert(srcleft
<= sizeof(cs
->srcbuf
) &&
110 dstleft
<= sizeof(cs
->dstbuf
.bytes
));
111 err
= _citrus_iconv_convert(handle
, &src
, &srcleft
,
112 &dst
, &dstleft
, 0, &invlen
);
113 cs
->dstbuf_len
= (dst
- cs
->dstbuf
.bytes
) / sizeof(charXX_t
);
115 /* Got new character(s). Return the first. */
116 if (cs
->dstbuf_len
> 0) {
117 assert(src
- cs
->srcbuf
> cs
->srcbuf_len
);
118 retval
= src
- cs
->srcbuf
- cs
->srcbuf_len
;
123 /* Increase dst buffer size, to obtain the surrogate pair. */
127 /* Illegal sequence. */
134 /* Save unprocessed remainder for the next invocation. */
135 memmove(cs
->srcbuf
, src
, srcleft
);
136 cs
->srcbuf_len
= srcleft
;
141 retchar
= cs
->dstbuf
.widechar
[0];
142 memmove(&cs
->dstbuf
.widechar
[0], &cs
->dstbuf
.widechar
[1],
143 --cs
->dstbuf_len
* sizeof(charXX_t
));
152 mbrtocXX(charXX_t
* __restrict pc
, const char * __restrict s
, size_t n
,
153 mbstate_t * __restrict ps
)
156 return (mbrtocXX_l(pc
, s
, n
, ps
, __get_locale()));