summaryrefslogtreecommitdiffstats
path: root/lib/libc/locale/gb18030.c
diff options
context:
space:
mode:
authortjr <tjr@FreeBSD.org>2004-04-07 10:48:19 +0000
committertjr <tjr@FreeBSD.org>2004-04-07 10:48:19 +0000
commit54a18fa1d63375b790f3bf3157f6b64b294e5d16 (patch)
tree44e2a3f83138ea23f4b4f68cbea18e4f60c8745e /lib/libc/locale/gb18030.c
parenta6980b04fc41a4c6dc314dc3aa00de7e7834ba7b (diff)
downloadFreeBSD-src-54a18fa1d63375b790f3bf3157f6b64b294e5d16.zip
FreeBSD-src-54a18fa1d63375b790f3bf3157f6b64b294e5d16.tar.gz
Allow partial multibyte characters to accumulate in conversion state
objects passed to mbrtowc(), mbsrtowcs(), and mbrlen(), as required by C99.
Diffstat (limited to 'lib/libc/locale/gb18030.c')
-rw-r--r--lib/libc/locale/gb18030.c50
1 files changed, 40 insertions, 10 deletions
diff --git a/lib/libc/locale/gb18030.c b/lib/libc/locale/gb18030.c
index dca718f..817602b 100644
--- a/lib/libc/locale/gb18030.c
+++ b/lib/libc/locale/gb18030.c
@@ -29,22 +29,30 @@
* See gb18030(5) for details.
*/
-#include <sys/cdefs.h>
+#include <sys/param.h>
__FBSDID("$FreeBSD$");
#include <errno.h>
#include <runetype.h>
#include <stdlib.h>
+#include <string.h>
#include <wchar.h>
extern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict,
size_t, mbstate_t * __restrict);
+extern int (*__mbsinit)(const mbstate_t *);
extern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict);
int _GB18030_init(_RuneLocale *);
-size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
+size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t,
mbstate_t * __restrict);
-size_t _GB18030_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+int _GB18030_mbsinit(const mbstate_t *);
+size_t _GB18030_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict);
+
+typedef struct {
+ int count;
+ u_char bytes[4];
+} _GB18030State;
int
_GB18030_init(_RuneLocale *rl)
@@ -52,22 +60,44 @@ _GB18030_init(_RuneLocale *rl)
__mbrtowc = _GB18030_mbrtowc;
__wcrtomb = _GB18030_wcrtomb;
+ __mbsinit = _GB18030_mbsinit;
_CurrentRuneLocale = rl;
__mb_cur_max = 4;
return (0);
}
+int
+_GB18030_mbsinit(const mbstate_t *ps)
+{
+
+ return (ps == NULL || ((_GB18030State *)ps)->count == 0);
+}
+
size_t
_GB18030_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
- size_t n, mbstate_t * __restrict ps __unused)
+ size_t n, mbstate_t * __restrict ps)
{
+ _GB18030State *gs;
wchar_t wch;
- int ch, len;
+ int ch, len, ocount;
+ size_t ncopy;
+
+ gs = (_GB18030State *)ps;
+
+ if (s == NULL) {
+ s = "";
+ n = 1;
+ pwc = NULL;
+ }
+
+ ncopy = MIN(MIN(n, MB_CUR_MAX), sizeof(gs->bytes) - gs->count);
+ memcpy(gs->bytes + gs->count, s, ncopy);
+ ocount = gs->count;
+ gs->count += ncopy;
+ s = (char *)gs->bytes;
+ n = gs->count;
- if (s == NULL)
- /* Reset to initial shift state (no-op) */
- return (0);
if (n == 0)
/* Incomplete multibyte sequence */
return ((size_t)-2);
@@ -116,7 +146,8 @@ _GB18030_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
if (pwc != NULL)
*pwc = wch;
- return (wch == L'\0' ? 0 : len);
+ gs->count = 0;
+ return (wch == L'\0' ? 0 : len - ocount);
ilseq:
errno = EILSEQ;
return ((size_t)-1);
@@ -132,7 +163,6 @@ _GB18030_wcrtomb(char * __restrict s, wchar_t wc,
if (s == NULL)
/* Reset to initial shift state (no-op) */
return (1);
-
if ((wc & ~0x7fffffff) != 0)
goto ilseq;
if (wc & 0x7f000000) {
OpenPOWER on IntegriCloud