1 | #include <wctype.h>
|
---|
2 | #include <wchar.h>
|
---|
3 | #include <stdio.h>
|
---|
4 | #include <locale.h>
|
---|
5 | #include <string.h>
|
---|
6 | #include <errno.h>
|
---|
7 | #include <limits.h>
|
---|
8 | #include <stdlib.h>
|
---|
9 |
|
---|
10 |
|
---|
11 | static int testSingleChar1(const char *pszMBCS, size_t cbMBCS, const wchar_t *pwcsFacit, size_t cwcFacit, const char *pszTest)
|
---|
12 | {
|
---|
13 | int i;
|
---|
14 | int rc = 0;
|
---|
15 | mbstate_t mbs;
|
---|
16 | mbstate_t mbsLen1;
|
---|
17 | size_t cbLeft = cbMBCS;
|
---|
18 | memset(&mbs, 0, sizeof(mbs));
|
---|
19 | memset(&mbsLen1, 0, sizeof(mbsLen1));
|
---|
20 |
|
---|
21 | for (i = 0; i < cwcFacit; i++)
|
---|
22 | {
|
---|
23 | size_t cbLen1;
|
---|
24 | size_t cbLen2;
|
---|
25 |
|
---|
26 | /* convert */
|
---|
27 | wchar_t wc = 0xfffe;
|
---|
28 | size_t cb = mbrtowc(&wc, pszMBCS, cbLeft, &mbs);
|
---|
29 | if ((int)cb < 0)
|
---|
30 | {
|
---|
31 | printf("error: Pos %d on test %s. mbrtowc -> %d errno=%d\n", i, pszTest, cb, errno);
|
---|
32 | return rc + 1;
|
---|
33 | }
|
---|
34 | if (cb == 0 && i + 1 != cwcFacit)
|
---|
35 | {
|
---|
36 | printf("error: Pos %d on test %s. Early end!\n", i, pszTest);
|
---|
37 | return rc + 1;
|
---|
38 | }
|
---|
39 |
|
---|
40 | /* check */
|
---|
41 | if (wc != *pwcsFacit)
|
---|
42 | {
|
---|
43 | printf("error: Pos %d on test %s. 0x%04x != 0x%04x\n", i, pszTest, wc, *pwcsFacit);
|
---|
44 | rc++;
|
---|
45 | }
|
---|
46 |
|
---|
47 | /* check length */
|
---|
48 | cbLen1 = mbrlen(pszMBCS, cbLeft, NULL);
|
---|
49 | if (cb != cbLen1)
|
---|
50 | {
|
---|
51 | printf("error: Pos %d on test %s. cb=%d mbrlen=%d (1)\n", i, pszTest, cb, cbLen1);
|
---|
52 | rc++;
|
---|
53 | }
|
---|
54 | cbLen2 = mbrlen(pszMBCS, cbLeft, &mbsLen1);
|
---|
55 | if (cb != cbLen2)
|
---|
56 | {
|
---|
57 | printf("error: Pos %d on test %s. cb=%d mbrlen=%d (2)\n", i, pszTest, cb, cbLen2);
|
---|
58 | rc++;
|
---|
59 | }
|
---|
60 |
|
---|
61 | /* advance */
|
---|
62 | pwcsFacit++;
|
---|
63 | pszMBCS += cb;
|
---|
64 | cbLeft -= cb;
|
---|
65 | }
|
---|
66 |
|
---|
67 | return rc;
|
---|
68 | }
|
---|
69 |
|
---|
70 |
|
---|
71 | static int testSingleChar2(const char *pszMBCS, size_t cbMBCS, const wchar_t *pwcsFacit, size_t cwcFacit, const char *pszTest)
|
---|
72 | {
|
---|
73 | int i;
|
---|
74 | int rc = 0;
|
---|
75 | mbstate_t mbs;
|
---|
76 | size_t cbLeft = cbMBCS;
|
---|
77 | memset(&mbs, 0, sizeof(mbs));
|
---|
78 |
|
---|
79 | for (i = 0; i < cwcFacit; i++)
|
---|
80 | {
|
---|
81 | /* convert */
|
---|
82 | char ach[MB_LEN_MAX];
|
---|
83 | size_t cb = wcrtomb(ach, *pwcsFacit, &mbs);
|
---|
84 | if ((int)cb <= 0)
|
---|
85 | {
|
---|
86 | printf("error: Pos %d on test %s. wcrtomb -> %d errno=%d\n", i, pszTest, cb, errno);
|
---|
87 | return rc + 1;
|
---|
88 | }
|
---|
89 |
|
---|
90 | /* check */
|
---|
91 | if (memcmp(ach, pszMBCS, cb))
|
---|
92 | {
|
---|
93 | printf("error: Pos %d on test %s. Mismatch! wc=0x%04x\n", i, pszTest, *pwcsFacit);
|
---|
94 | rc++;
|
---|
95 | }
|
---|
96 |
|
---|
97 | /* advance */
|
---|
98 | pwcsFacit++;
|
---|
99 | pszMBCS += cb;
|
---|
100 | cbLeft -= cb;
|
---|
101 | }
|
---|
102 |
|
---|
103 | return rc;
|
---|
104 | }
|
---|
105 |
|
---|
106 |
|
---|
107 | static int testString1(const char *pszMBCS, size_t cbMBCS, const wchar_t *pwcsFacit, size_t cwcFacit, const char *pszTest)
|
---|
108 | {
|
---|
109 | int rc = 0;
|
---|
110 | mbstate_t mbs;
|
---|
111 | mbstate_t mbsLen1;
|
---|
112 | size_t cb;
|
---|
113 | size_t cbLen1;
|
---|
114 | size_t cbLen2;
|
---|
115 | wchar_t *pwcsOut = alloca((cwcFacit + 4) * sizeof(wchar_t));
|
---|
116 | const char *pszIn = pszMBCS;
|
---|
117 | memset(&mbs, 0, sizeof(mbs));
|
---|
118 | memset(&mbsLen1, 0, sizeof(mbsLen1));
|
---|
119 |
|
---|
120 | /* convert it as a full string. */
|
---|
121 | pwcsOut[cwcFacit + 1] = 0xfffe;
|
---|
122 | pwcsOut[cwcFacit + 0] = 0x3432;
|
---|
123 | pwcsOut[cwcFacit + 1] = 0x3031;
|
---|
124 | cb = mbsrtowcs(pwcsOut, &pszIn, cbMBCS, &mbs);
|
---|
125 | if ((int)cb <= 0)
|
---|
126 | {
|
---|
127 | printf("error: String conversion (to wc) failed, testcase %s. cb=%d errno=%d\n", pszTest, cb, errno);
|
---|
128 | return 1;
|
---|
129 | }
|
---|
130 | if (cb + 1 != cbMBCS)
|
---|
131 | {
|
---|
132 | printf("error: String conversion (to wc) testcase %s, length mismatch cb=%d cbMBCS=%d\n", pszTest, cb, cbMBCS);
|
---|
133 | return 1;
|
---|
134 | }
|
---|
135 | if (pszIn)
|
---|
136 | {
|
---|
137 | printf("error: String conversion (to wc) testcase %s, incorrect stop pointer. pszIn=%p expected=NULL\n", pszTest, (void *)pszIn);
|
---|
138 | return 1;
|
---|
139 | }
|
---|
140 | if (memcmp(pwcsOut, pwcsFacit, cwcFacit * sizeof(wchar_t)))
|
---|
141 | {
|
---|
142 | printf("error: String conversion (to wc) testcase %s, failed. Incorrect output!\n", pszTest);
|
---|
143 | return 1;
|
---|
144 | }
|
---|
145 | if ( pwcsOut[cwcFacit + 0] != 0x3432
|
---|
146 | || pwcsOut[cwcFacit + 1] != 0x3031)
|
---|
147 | {
|
---|
148 | printf("error: String conversion (to wc) testcase %s, failed. Wrote to much.\n", pszTest);
|
---|
149 | return 1;
|
---|
150 | }
|
---|
151 | if (pwcsOut[cwcFacit - 1])
|
---|
152 | {
|
---|
153 | printf("error: String conversion (to wc) testcase %s, failed. not terminated.\n", pszTest);
|
---|
154 | return 1;
|
---|
155 | }
|
---|
156 |
|
---|
157 | /* lengths */
|
---|
158 | pszIn = pszMBCS;
|
---|
159 | cbLen1 = mbsrtowcs(NULL, &pszIn, cbMBCS, NULL);
|
---|
160 | if (cbLen1 != cb)
|
---|
161 | {
|
---|
162 | printf("error: String length 1 mismatched for testcase %s. cbLen1=%d cb=%d\n", pszTest, cbLen1, cb);
|
---|
163 | rc++;
|
---|
164 | }
|
---|
165 |
|
---|
166 | pszIn = pszMBCS;
|
---|
167 | cbLen2 = mbsrtowcs(NULL, &pszIn, cbMBCS, &mbsLen1);
|
---|
168 | if (cbLen2 != cb)
|
---|
169 | {
|
---|
170 | printf("error: String length 2 mismatched for testcase %s. cbLen2=%d cb=%d\n", pszTest, cbLen2, cb);
|
---|
171 | rc++;
|
---|
172 | }
|
---|
173 |
|
---|
174 | return rc;
|
---|
175 | }
|
---|
176 |
|
---|
177 | static int testString2(const char *pszMBCS, size_t cbMBCS, const wchar_t *pwcsFacit, size_t cwcFacit, const char *pszTest)
|
---|
178 | {
|
---|
179 | int rc = 0;
|
---|
180 | mbstate_t mbs;
|
---|
181 | mbstate_t mbsLen1;
|
---|
182 | size_t cb;
|
---|
183 | size_t cbLen1;
|
---|
184 | size_t cbLen2;
|
---|
185 | const wchar_t *pwcsIn = pwcsFacit;
|
---|
186 | char *pszOut = (char *)alloca(cbMBCS + 4);
|
---|
187 | memset(&mbs, 0, sizeof(mbs));
|
---|
188 | memset(&mbsLen1, 0, sizeof(mbsLen1));
|
---|
189 |
|
---|
190 | /* convert it as a full string. */
|
---|
191 | pszOut[cbMBCS - 1] = 0x7e;
|
---|
192 | pszOut[cbMBCS + 0] = 0x34;
|
---|
193 | pszOut[cbMBCS + 1] = 0x32;
|
---|
194 | cb = wcsrtombs(pszOut, &pwcsIn, cbMBCS, &mbs);
|
---|
195 | if ((int)cb <= 0)
|
---|
196 | {
|
---|
197 | printf("error: String conversion (to mb) failed, testcase %s. cb=%d errno=%d\n", pszTest, cb, errno);
|
---|
198 | return 1;
|
---|
199 | }
|
---|
200 | if (cb + 1 != cbMBCS)
|
---|
201 | {
|
---|
202 | printf("error: String conversion (to mb) testcase %s, length mismatch cb=%d cbMBCS=%d\n", pszTest, cb, cbMBCS);
|
---|
203 | return 1;
|
---|
204 | }
|
---|
205 | if (pwcsIn)
|
---|
206 | {
|
---|
207 | printf("error: String conversion (to mb) testcase %s, incorrect stop pointer. pwcsIn=%p expected=NULL\n", pszTest, (void *)pwcsIn);
|
---|
208 | return 1;
|
---|
209 | }
|
---|
210 | if (memcmp(pszOut, pszMBCS, cbMBCS))
|
---|
211 | {
|
---|
212 | printf("error: String conversion (to mb) testcase %s, failed. Incorrect output!\n", pszTest);
|
---|
213 | return 1;
|
---|
214 | }
|
---|
215 | if ( pszOut[cbMBCS + 0] != 0x34
|
---|
216 | || pszOut[cbMBCS + 1] != 0x32)
|
---|
217 | {
|
---|
218 | printf("error: String conversion (to mb) testcase %s, failed. Wrote to much.\n", pszTest);
|
---|
219 | return 1;
|
---|
220 | }
|
---|
221 | if (pszOut[cbMBCS - 1])
|
---|
222 | {
|
---|
223 | printf("error: String conversion (to mb) testcase %s, failed. Not terminated.\n", pszTest);
|
---|
224 | return 1;
|
---|
225 | }
|
---|
226 |
|
---|
227 | /* lengths */
|
---|
228 | pwcsIn = pwcsFacit;
|
---|
229 | cbLen1 = wcsrtombs(NULL, &pwcsIn, cbMBCS, NULL);
|
---|
230 | if (cbLen1 != cb)
|
---|
231 | {
|
---|
232 | printf("error: String length 1 mismatched for testcase %s. cbLen1=%d cb=%d\n", pszTest, cbLen1, cb);
|
---|
233 | rc++;
|
---|
234 | }
|
---|
235 |
|
---|
236 | pwcsIn = pwcsFacit;
|
---|
237 | cbLen2 = wcsrtombs(NULL, &pwcsIn, cbMBCS, &mbsLen1);
|
---|
238 | if (cbLen2 != cb)
|
---|
239 | {
|
---|
240 | printf("error: String length 2 mismatched for testcase %s. cbLen2=%d cb=%d\n", pszTest, cbLen2, cb);
|
---|
241 | rc++;
|
---|
242 | }
|
---|
243 |
|
---|
244 | return rc;
|
---|
245 | }
|
---|
246 |
|
---|
247 |
|
---|
248 |
|
---|
249 | static int test(const unsigned char *pszMBCS, size_t cbMBCS, const wchar_t *pwcsFacit, size_t cwcFacit, const char *pszTest)
|
---|
250 | {
|
---|
251 | int rc = testSingleChar1((const char *)pszMBCS, cbMBCS, pwcsFacit, cwcFacit, pszTest);
|
---|
252 | rc += testSingleChar2((const char *)pszMBCS, cbMBCS, pwcsFacit, cwcFacit, pszTest);
|
---|
253 | rc += testString1((const char *)pszMBCS, cbMBCS, pwcsFacit, cwcFacit, pszTest);
|
---|
254 | rc += testString2((const char *)pszMBCS, cbMBCS, pwcsFacit, cwcFacit, pszTest);
|
---|
255 | return rc;
|
---|
256 | }
|
---|
257 |
|
---|
258 |
|
---|
259 | int main(void)
|
---|
260 | {
|
---|
261 | /* -- ASSUMES wchar is unicode. */
|
---|
262 | static const wchar_t wcsTestUCS2[14] = { 0x00E6, 0x00F8, 0x00E5, 0x0a,
|
---|
263 | 0x00C6, 0x00D8, 0x00C5, 0x0a,
|
---|
264 | 0x00E4, 0x00C4, 0x00F6, 0x00D6, 0x0a, 0};
|
---|
265 | static const unsigned char szTest850[14] = { 0x91, 0x9b, 0x86, 0x0a,
|
---|
266 | 0x92, 0x9d, 0x8f, 0x0a,
|
---|
267 | 0x84, 0x8e, 0x94, 0x99, 0x0a, 0 }; /* "\n\n\n" */
|
---|
268 | static const unsigned char szTest8859_1[14] = { 0xe6, 0xf8, 0xe5, 0x0a,
|
---|
269 | 0xc6, 0xd8, 0xc5, 0x0a,
|
---|
270 | 0xe4, 0xc4, 0xf6, 0xd6, 0x0a, 0 }; /* "æøå\nÆØÅ\näÄöÖ\n" */
|
---|
271 | static const unsigned char szTestUTF_8[] = { 0xc3, 0xa6, 0xc3, 0xb8, 0xc3, 0xa5, 0x0a,
|
---|
272 | 0xc3, 0x86, 0xc3, 0x98, 0xc3, 0x85, 0x0a,
|
---|
273 | 0xc3, 0xa4, 0xc3, 0x84, 0xc3, 0xb6, 0xc3, 0x96, 0x0a, 0 };
|
---|
274 | int rc = 0;
|
---|
275 | printf("mbstuff-1: TESTING\n");
|
---|
276 |
|
---|
277 |
|
---|
278 | /*
|
---|
279 | * The tests.
|
---|
280 | */
|
---|
281 | if ( setlocale(LC_CTYPE, "no_NO.IBM-850")
|
---|
282 | || setlocale(LC_CTYPE, "no_NO.IBM850")
|
---|
283 | || setlocale(LC_CTYPE, "no_NO.CP850")
|
---|
284 | || setlocale(LC_CTYPE, "de_DE.CP850"))
|
---|
285 | {
|
---|
286 | rc += test(&szTest850[0], sizeof(szTest850), &wcsTestUCS2[0], sizeof(wcsTestUCS2) / sizeof(wcsTestUCS2[0]), "IBM-850");
|
---|
287 | }
|
---|
288 | else
|
---|
289 | printf("warning! Couldn't set LC_CTYPE to any IBM-850 base locale. :/\n");
|
---|
290 |
|
---|
291 | if ( setlocale(LC_CTYPE, "en_US.ISO8859-1")
|
---|
292 | || setlocale(LC_CTYPE, "en_US.ISO-8859-1")
|
---|
293 | || setlocale(LC_CTYPE, "en_US.IBM-819")
|
---|
294 | || setlocale(LC_CTYPE, "en_US.IBM-819"))
|
---|
295 | {
|
---|
296 | rc += test(&szTest8859_1[0], sizeof(szTest8859_1), &wcsTestUCS2[0], sizeof(wcsTestUCS2) / sizeof(wcsTestUCS2[0]), "ISO8859-1");
|
---|
297 | }
|
---|
298 | else
|
---|
299 | printf("warning! Couldn't set LC_CTYPE to any ISO-8859-1 based locale. :/\n");
|
---|
300 |
|
---|
301 | if ( setlocale(LC_CTYPE, "en_US.UTF-8")
|
---|
302 | || setlocale(LC_CTYPE, "en_US.UTF8")
|
---|
303 | || setlocale(LC_CTYPE, "en_US.IBM1208")
|
---|
304 | || setlocale(LC_CTYPE, "en_US.IBM-1208")
|
---|
305 | || setlocale(LC_CTYPE, "ja_JP.UTF-8")
|
---|
306 | || setlocale(LC_CTYPE, "ja_JP.UTF8"))
|
---|
307 | {
|
---|
308 | rc += test(&szTestUTF_8[0], sizeof(szTestUTF_8), &wcsTestUCS2[0], sizeof(wcsTestUCS2) / sizeof(wcsTestUCS2[0]), "UTF-8");
|
---|
309 | }
|
---|
310 | else
|
---|
311 | printf("warning! Couldn't set LC_CTYPE to any UTF-8 based locale. :/\n");
|
---|
312 |
|
---|
313 | /* test summary. */
|
---|
314 | if (rc)
|
---|
315 | printf("mbstuff-1: FAILURE. %d errors\n", rc);
|
---|
316 | else
|
---|
317 | printf("mbstuff-1: SUCCESS\n");
|
---|
318 | return rc;
|
---|
319 | }
|
---|