1 /**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6 #ifndef WIN32_LEAN_AND_MEAN
7 #define WIN32_LEAN_AND_MEAN
8 #endif
9 #include "mb_wc_common.h"
10 #include <wchar.h>
11 #include <stdlib.h>
12 #include <errno.h>
13 #include <windows.h>
14
15 static int __MINGW_ATTRIB_NONNULL(1) __MINGW_ATTRIB_NONNULL(4)
__mbrtowc_cp(wchar_t * __restrict__ pwc,const char * __restrict__ s,size_t n,mbstate_t * __restrict__ ps,const unsigned int cp,const unsigned int mb_max)16 __mbrtowc_cp (wchar_t * __restrict__ pwc, const char * __restrict__ s,
17 size_t n, mbstate_t* __restrict__ ps,
18 const unsigned int cp, const unsigned int mb_max)
19 {
20 union {
21 mbstate_t val;
22 char mbcs[4];
23 } shift_state;
24
25 /* Do the prelim checks */
26 if (s == NULL)
27 return 0;
28
29 if (n == 0)
30 /* The standard doesn't mention this case explicitly. Tell
31 caller that the conversion from a non-null s is incomplete. */
32 return -2;
33
34 /* Save the current shift state, in case we need it in DBCS case. */
35 shift_state.val = *ps;
36 *ps = 0;
37
38 if (!*s)
39 {
40 *pwc = 0;
41 return 0;
42 }
43
44 if (mb_max > 1)
45 {
46 if (shift_state.mbcs[0] != 0)
47 {
48 /* Complete the mb char with the trailing byte. */
49 shift_state.mbcs[1] = *s; /* the second byte */
50 if (MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS,
51 shift_state.mbcs, 2, pwc, 1)
52 == 0)
53 {
54 /* An invalid trailing byte */
55 errno = EILSEQ;
56 return -1;
57 }
58 return 2;
59 }
60 else if (IsDBCSLeadByteEx (cp, *s))
61 {
62 /* If told to translate one byte, just save the leadbyte
63 in *ps. */
64 if (n < 2)
65 {
66 ((char*) ps)[0] = *s;
67 return -2;
68 }
69 /* Else translate the first two bytes */
70 else if (MultiByteToWideChar (cp, MB_ERR_INVALID_CHARS,
71 s, 2, pwc, 1)
72 == 0)
73 {
74 errno = EILSEQ;
75 return -1;
76 }
77 return 2;
78 }
79 }
80
81 /* Fall through to single byte char */
82 if (cp == 0)
83 *pwc = (wchar_t)(unsigned char)*s;
84
85 else if (MultiByteToWideChar (cp, MB_ERR_INVALID_CHARS, s, 1, pwc, 1)
86 == 0)
87 {
88 errno = EILSEQ;
89 return -1;
90 }
91
92 return 1;
93 }
94
95 size_t
mbrtowc(wchar_t * __restrict__ pwc,const char * __restrict__ s,size_t n,mbstate_t * __restrict__ ps)96 mbrtowc (wchar_t * __restrict__ pwc, const char * __restrict__ s,
97 size_t n, mbstate_t* __restrict__ ps)
98 {
99 static mbstate_t internal_mbstate = 0;
100 wchar_t byte_bucket = 0;
101 wchar_t* dst = pwc ? pwc : &byte_bucket;
102
103 return (size_t) __mbrtowc_cp (dst, s, n, ps ? ps : &internal_mbstate,
104 ___lc_codepage_func(), MB_CUR_MAX);
105 }
106
107
108 size_t
mbsrtowcs(wchar_t * __restrict__ dst,const char ** __restrict__ src,size_t len,mbstate_t * __restrict__ ps)109 mbsrtowcs (wchar_t* __restrict__ dst, const char ** __restrict__ src,
110 size_t len, mbstate_t* __restrict__ ps)
111 {
112 int ret =0 ;
113 size_t n = 0;
114 static mbstate_t internal_mbstate = 0;
115 mbstate_t* internal_ps = ps ? ps : &internal_mbstate;
116 const unsigned int cp = ___lc_codepage_func();
117 const unsigned int mb_max = MB_CUR_MAX;
118
119 if (src == NULL || *src == NULL) /* undefined behavior */
120 return 0;
121
122 if (dst != NULL)
123 {
124 while (n < len
125 && (ret = __mbrtowc_cp(dst, *src, len - n,
126 internal_ps, cp, mb_max))
127 > 0)
128 {
129 ++dst;
130 *src += ret;
131 n += ret;
132 }
133
134 if (n < len && ret == 0)
135 *src = (char *)NULL;
136 }
137 else
138 {
139 wchar_t byte_bucket = 0;
140 while ((ret = __mbrtowc_cp (&byte_bucket, *src + n, mb_max,
141 internal_ps, cp, mb_max))
142 > 0)
143 n += ret;
144 }
145 return n;
146 }
147
148 size_t
mbrlen(const char * __restrict__ s,size_t n,mbstate_t * __restrict__ ps)149 mbrlen (const char * __restrict__ s, size_t n,
150 mbstate_t * __restrict__ ps)
151 {
152 static mbstate_t s_mbstate = 0;
153 wchar_t byte_bucket = 0;
154 return __mbrtowc_cp (&byte_bucket, s, n, (ps) ? ps : &s_mbstate,
155 ___lc_codepage_func(), MB_CUR_MAX);
156 }
157