1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <codecvt>
10 
11 // template <class Elem, unsigned long Maxcode = 0x10ffff,
12 //           codecvt_mode Mode = (codecvt_mode)0>
13 // class codecvt_utf16
14 //     : public codecvt<Elem, char, mbstate_t>
15 // {
16 //     // unspecified
17 // };
18 
19 // result
20 // out(stateT& state,
21 //     const internT* from, const internT* from_end, const internT*& from_next,
22 //     externT* to, externT* to_end, externT*& to_next) const;
23 
24 #include <codecvt>
25 #include <cassert>
26 
27 #include "test_macros.h"
28 
29 template <class CharT, size_t = sizeof(CharT)>
30 struct TestHelper;
31 template <class CharT>
32 struct TestHelper<CharT, 2> {
33   static void test();
34 };
35 template <class CharT>
36 struct TestHelper<CharT, 4> {
37   static void test();
38 };
39 
40 template <class CharT>
41 void TestHelper<CharT, 2>::test() {
42   // Nothing to do, the conversion in unsupported
43 }
44 
45 template <class CharT>
46 void TestHelper<CharT, 4>::test() {
47   {
48     typedef std::codecvt_utf16<CharT> C;
49     C c;
50     CharT w = 0x40003;
51     char n[4] = {0};
52     const CharT* wp = nullptr;
53     std::mbstate_t m;
54     char* np = nullptr;
55     std::codecvt_base::result r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
56     assert(r == std::codecvt_base::ok);
57     assert(wp == &w + 1);
58     assert(np == n + 4);
59     assert(n[0] == char(0xD8));
60     assert(n[1] == char(0xC0));
61     assert(n[2] == char(0xDC));
62     assert(n[3] == char(0x03));
63 
64     w = 0x1005;
65     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
66     assert(r == std::codecvt_base::ok);
67     assert(wp == &w + 1);
68     assert(np == n + 2);
69     assert(n[0] == char(0x10));
70     assert(n[1] == char(0x05));
71     assert(n[2] == char(0xDC));
72     assert(n[3] == char(0x03));
73 
74     w = 0x453;
75     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
76     assert(r == std::codecvt_base::ok);
77     assert(wp == &w + 1);
78     assert(np == n + 2);
79     assert(n[0] == char(0x04));
80     assert(n[1] == char(0x53));
81     assert(n[2] == char(0xDC));
82     assert(n[3] == char(0x03));
83 
84     w = 0x56;
85     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
86     assert(r == std::codecvt_base::ok);
87     assert(wp == &w + 1);
88     assert(np == n + 2);
89     assert(n[0] == char(0x00));
90     assert(n[1] == char(0x56));
91     assert(n[2] == char(0xDC));
92     assert(n[3] == char(0x03));
93   }
94   {
95     typedef std::codecvt_utf16<CharT, 0x1000> C;
96     C c;
97     CharT w = 0x40003;
98     char n[4] = {0};
99     const CharT* wp = nullptr;
100     std::mbstate_t m;
101     char* np = nullptr;
102     std::codecvt_base::result r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
103     assert(r == std::codecvt_base::error);
104     assert(wp == &w);
105     assert(np == n);
106     assert(n[0] == char(0));
107     assert(n[1] == char(0));
108     assert(n[2] == char(0));
109     assert(n[3] == char(0));
110 
111     w = 0x1005;
112     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
113     assert(r == std::codecvt_base::error);
114     assert(wp == &w);
115     assert(np == n);
116     assert(n[0] == char(0));
117     assert(n[1] == char(0));
118     assert(n[2] == char(0));
119     assert(n[3] == char(0));
120 
121     w = 0x453;
122     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
123     assert(r == std::codecvt_base::ok);
124     assert(wp == &w + 1);
125     assert(np == n + 2);
126     assert(n[0] == char(0x04));
127     assert(n[1] == char(0x53));
128     assert(n[2] == char(0));
129     assert(n[3] == char(0));
130 
131     w = 0x56;
132     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
133     assert(r == std::codecvt_base::ok);
134     assert(wp == &w + 1);
135     assert(np == n + 2);
136     assert(n[0] == char(0x00));
137     assert(n[1] == char(0x56));
138     assert(n[2] == char(0));
139     assert(n[3] == char(0));
140   }
141   {
142     typedef std::codecvt_utf16<CharT, 0x10ffff, std::generate_header> C;
143     C c;
144     CharT w = 0x40003;
145     char n[6] = {0};
146     const CharT* wp = nullptr;
147     std::mbstate_t m;
148     char* np = nullptr;
149     std::codecvt_base::result r = c.out(m, &w, &w + 1, wp, n, n + 6, np);
150     assert(r == std::codecvt_base::ok);
151     assert(wp == &w + 1);
152     assert(np == n + 6);
153     assert(n[0] == char(0xFE));
154     assert(n[1] == char(0xFF));
155     assert(n[2] == char(0xD8));
156     assert(n[3] == char(0xC0));
157     assert(n[4] == char(0xDC));
158     assert(n[5] == char(0x03));
159 
160     w = 0x1005;
161     r = c.out(m, &w, &w + 1, wp, n, n + 6, np);
162     assert(r == std::codecvt_base::ok);
163     assert(wp == &w + 1);
164     assert(np == n + 4);
165     assert(n[0] == char(0xFE));
166     assert(n[1] == char(0xFF));
167     assert(n[2] == char(0x10));
168     assert(n[3] == char(0x05));
169     assert(n[4] == char(0xDC));
170     assert(n[5] == char(0x03));
171 
172     w = 0x453;
173     r = c.out(m, &w, &w + 1, wp, n, n + 6, np);
174     assert(r == std::codecvt_base::ok);
175     assert(wp == &w + 1);
176     assert(np == n + 4);
177     assert(n[0] == char(0xFE));
178     assert(n[1] == char(0xFF));
179     assert(n[2] == char(0x04));
180     assert(n[3] == char(0x53));
181     assert(n[4] == char(0xDC));
182     assert(n[5] == char(0x03));
183 
184     w = 0x56;
185     r = c.out(m, &w, &w + 1, wp, n, n + 6, np);
186     assert(r == std::codecvt_base::ok);
187     assert(wp == &w + 1);
188     assert(np == n + 4);
189     assert(n[0] == char(0xFE));
190     assert(n[1] == char(0xFF));
191     assert(n[2] == char(0x00));
192     assert(n[3] == char(0x56));
193     assert(n[4] == char(0xDC));
194     assert(n[5] == char(0x03));
195   }
196 
197   {
198     typedef std::codecvt_utf16<CharT, 0x10FFFF, std::little_endian> C;
199     C c;
200     CharT w = 0x40003;
201     char n[4] = {0};
202     const CharT* wp = nullptr;
203     std::mbstate_t m;
204     char* np = nullptr;
205     std::codecvt_base::result r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
206     assert(r == std::codecvt_base::ok);
207     assert(wp == &w + 1);
208     assert(np == n + 4);
209     assert(n[1] == char(0xD8));
210     assert(n[0] == char(0xC0));
211     assert(n[3] == char(0xDC));
212     assert(n[2] == char(0x03));
213 
214     w = 0x1005;
215     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
216     assert(r == std::codecvt_base::ok);
217     assert(wp == &w + 1);
218     assert(np == n + 2);
219     assert(n[1] == char(0x10));
220     assert(n[0] == char(0x05));
221     assert(n[3] == char(0xDC));
222     assert(n[2] == char(0x03));
223 
224     w = 0x453;
225     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
226     assert(r == std::codecvt_base::ok);
227     assert(wp == &w + 1);
228     assert(np == n + 2);
229     assert(n[1] == char(0x04));
230     assert(n[0] == char(0x53));
231     assert(n[3] == char(0xDC));
232     assert(n[2] == char(0x03));
233 
234     w = 0x56;
235     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
236     assert(r == std::codecvt_base::ok);
237     assert(wp == &w + 1);
238     assert(np == n + 2);
239     assert(n[1] == char(0x00));
240     assert(n[0] == char(0x56));
241     assert(n[3] == char(0xDC));
242     assert(n[2] == char(0x03));
243   }
244   {
245     typedef std::codecvt_utf16<CharT, 0x1000, std::little_endian> C;
246     C c;
247     CharT w = 0x40003;
248     char n[4] = {0};
249     const CharT* wp = nullptr;
250     std::mbstate_t m;
251     char* np = nullptr;
252     std::codecvt_base::result r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
253     assert(r == std::codecvt_base::error);
254     assert(wp == &w);
255     assert(np == n);
256     assert(n[1] == char(0));
257     assert(n[0] == char(0));
258     assert(n[3] == char(0));
259     assert(n[2] == char(0));
260 
261     w = 0x1005;
262     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
263     assert(r == std::codecvt_base::error);
264     assert(wp == &w);
265     assert(np == n);
266     assert(n[1] == char(0));
267     assert(n[0] == char(0));
268     assert(n[3] == char(0));
269     assert(n[2] == char(0));
270 
271     w = 0x453;
272     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
273     assert(r == std::codecvt_base::ok);
274     assert(wp == &w + 1);
275     assert(np == n + 2);
276     assert(n[1] == char(0x04));
277     assert(n[0] == char(0x53));
278     assert(n[3] == char(0));
279     assert(n[2] == char(0));
280 
281     w = 0x56;
282     r = c.out(m, &w, &w + 1, wp, n, n + 4, np);
283     assert(r == std::codecvt_base::ok);
284     assert(wp == &w + 1);
285     assert(np == n + 2);
286     assert(n[1] == char(0x00));
287     assert(n[0] == char(0x56));
288     assert(n[3] == char(0));
289     assert(n[2] == char(0));
290   }
291   {
292     typedef std::codecvt_utf16<CharT, 0x10ffff,
293                                std::codecvt_mode(std::generate_header |
294                                                  std::little_endian)>
295         C;
296     C c;
297     CharT w = 0x40003;
298     char n[6] = {0};
299     const CharT* wp = nullptr;
300     std::mbstate_t m;
301     char* np = nullptr;
302     std::codecvt_base::result r = c.out(m, &w, &w + 1, wp, n, n + 6, np);
303     assert(r == std::codecvt_base::ok);
304     assert(wp == &w + 1);
305     assert(np == n + 6);
306     assert(n[1] == char(0xFE));
307     assert(n[0] == char(0xFF));
308     assert(n[3] == char(0xD8));
309     assert(n[2] == char(0xC0));
310     assert(n[5] == char(0xDC));
311     assert(n[4] == char(0x03));
312 
313     w = 0x1005;
314     r = c.out(m, &w, &w + 1, wp, n, n + 6, np);
315     assert(r == std::codecvt_base::ok);
316     assert(wp == &w + 1);
317     assert(np == n + 4);
318     assert(n[1] == char(0xFE));
319     assert(n[0] == char(0xFF));
320     assert(n[3] == char(0x10));
321     assert(n[2] == char(0x05));
322     assert(n[5] == char(0xDC));
323     assert(n[4] == char(0x03));
324 
325     w = 0x453;
326     r = c.out(m, &w, &w + 1, wp, n, n + 6, np);
327     assert(r == std::codecvt_base::ok);
328     assert(wp == &w + 1);
329     assert(np == n + 4);
330     assert(n[1] == char(0xFE));
331     assert(n[0] == char(0xFF));
332     assert(n[3] == char(0x04));
333     assert(n[2] == char(0x53));
334     assert(n[5] == char(0xDC));
335     assert(n[4] == char(0x03));
336 
337     w = 0x56;
338     r = c.out(m, &w, &w + 1, wp, n, n + 6, np);
339     assert(r == std::codecvt_base::ok);
340     assert(wp == &w + 1);
341     assert(np == n + 4);
342     assert(n[1] == char(0xFE));
343     assert(n[0] == char(0xFF));
344     assert(n[3] == char(0x00));
345     assert(n[2] == char(0x56));
346     assert(n[5] == char(0xDC));
347     assert(n[4] == char(0x03));
348   }
349 }
350 
351 int main(int, char**) {
352   TestHelper<char32_t>::test();
353 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
354   TestHelper<wchar_t>::test();
355 #endif
356 
357   return 0;
358 }
359