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_utf8_utf16
14 //     : public codecvt<Elem, char, mbstate_t>
15 // {
16 //     // unspecified
17 // };
18 
19 // result
20 //     in(stateT& state,
21 //        const externT* from, const externT* from_end, const externT*& from_next,
22 //        internT* to, internT* to_end, internT*& 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   {
43     typedef std::codecvt_utf8_utf16<CharT, 0x1000> C;
44     C c;
45     CharT w[2] = {0};
46     char n[4] = {char(0xF1), char(0x80), char(0x80), char(0x83)};
47     CharT* wp = nullptr;
48     std::mbstate_t m;
49     const char* np = nullptr;
50     std::codecvt_base::result r = c.in(m, n, n + 4, np, w, w + 2, wp);
51     assert(r == std::codecvt_base::error);
52     assert(wp == w);
53     assert(np == n);
54 
55     n[0] = char(0xE1);
56     n[1] = char(0x80);
57     n[2] = char(0x85);
58     r = c.in(m, n, n + 3, np, w, w + 2, wp);
59     assert(r == std::codecvt_base::error);
60     assert(wp == w);
61     assert(np == n);
62 
63     n[0] = char(0xD1);
64     n[1] = char(0x93);
65     r = c.in(m, n, n + 2, np, w, w + 2, wp);
66     assert(r == std::codecvt_base::ok);
67     assert(wp == w + 1);
68     assert(np == n + 2);
69     assert(w[0] == 0x0453);
70 
71     n[0] = char(0x56);
72     r = c.in(m, n, n + 1, np, w, w + 2, wp);
73     assert(r == std::codecvt_base::ok);
74     assert(wp == w + 1);
75     assert(np == n + 1);
76     assert(w[0] == 0x0056);
77   }
78   {
79     typedef std::codecvt_utf8_utf16<CharT, 0x10ffff, std::consume_header> C;
80     C c;
81     CharT w[2] = {0};
82     char n[7] = {char(0xEF), char(0xBB), char(0xBF), char(0xF1),
83                  char(0x80), char(0x80), char(0x83)};
84     CharT* wp = nullptr;
85     std::mbstate_t m;
86     const char* np = nullptr;
87     std::codecvt_base::result r = c.in(m, n, n + 7, np, w, w + 2, wp);
88     assert(r == std::codecvt_base::ok);
89     assert(wp == w + 2);
90     assert(np == n + 7);
91     assert(w[0] == 0xD8C0);
92     assert(w[1] == 0xDC03);
93 
94     n[0] = char(0xE1);
95     n[1] = char(0x80);
96     n[2] = char(0x85);
97     r = c.in(m, n, n + 3, np, w, w + 2, wp);
98     assert(r == std::codecvt_base::ok);
99     assert(wp == w + 1);
100     assert(np == n + 3);
101     assert(w[0] == 0x1005);
102 
103     n[0] = char(0xD1);
104     n[1] = char(0x93);
105     r = c.in(m, n, n + 2, np, w, w + 2, wp);
106     assert(r == std::codecvt_base::ok);
107     assert(wp == w + 1);
108     assert(np == n + 2);
109     assert(w[0] == 0x0453);
110 
111     n[0] = char(0x56);
112     r = c.in(m, n, n + 1, np, w, w + 2, wp);
113     assert(r == std::codecvt_base::ok);
114     assert(wp == w + 1);
115     assert(np == n + 1);
116     assert(w[0] == 0x0056);
117   }
118 }
119 
120 template <class CharT>
121 void TestHelper<CharT, 4>::test() {
122   {
123     typedef std::codecvt_utf8_utf16<CharT> C;
124     C c;
125     CharT w[2] = {0};
126     char n[4] = {char(0xF1), char(0x80), char(0x80), char(0x83)};
127     CharT* wp = nullptr;
128     std::mbstate_t m;
129     const char* np = nullptr;
130     std::codecvt_base::result r = c.in(m, n, n + 4, np, w, w + 2, wp);
131     assert(r == std::codecvt_base::ok);
132     assert(wp == w + 2);
133     assert(np == n + 4);
134     assert(w[0] == 0xD8C0);
135     assert(w[1] == 0xDC03);
136 
137     n[0] = char(0xE1);
138     n[1] = char(0x80);
139     n[2] = char(0x85);
140     r = c.in(m, n, n + 3, np, w, w + 2, wp);
141     assert(r == std::codecvt_base::ok);
142     assert(wp == w + 1);
143     assert(np == n + 3);
144     assert(w[0] == 0x1005);
145 
146     n[0] = char(0xD1);
147     n[1] = char(0x93);
148     r = c.in(m, n, n + 2, np, w, w + 2, wp);
149     assert(r == std::codecvt_base::ok);
150     assert(wp == w + 1);
151     assert(np == n + 2);
152     assert(w[0] == 0x0453);
153 
154     n[0] = char(0x56);
155     r = c.in(m, n, n + 1, np, w, w + 2, wp);
156     assert(r == std::codecvt_base::ok);
157     assert(wp == w + 1);
158     assert(np == n + 1);
159     assert(w[0] == 0x0056);
160   }
161   {
162     typedef std::codecvt_utf8_utf16<CharT, 0x1000> C;
163     C c;
164     CharT w[2] = {0};
165     char n[4] = {char(0xF1), char(0x80), char(0x80), char(0x83)};
166     CharT* wp = nullptr;
167     std::mbstate_t m;
168     const char* np = nullptr;
169     std::codecvt_base::result r = c.in(m, n, n + 4, np, w, w + 2, wp);
170     assert(r == std::codecvt_base::error);
171     assert(wp == w);
172     assert(np == n);
173 
174     n[0] = char(0xE1);
175     n[1] = char(0x80);
176     n[2] = char(0x85);
177     r = c.in(m, n, n + 3, np, w, w + 2, wp);
178     assert(r == std::codecvt_base::error);
179     assert(wp == w);
180     assert(np == n);
181 
182     n[0] = char(0xD1);
183     n[1] = char(0x93);
184     r = c.in(m, n, n + 2, np, w, w + 2, wp);
185     assert(r == std::codecvt_base::ok);
186     assert(wp == w + 1);
187     assert(np == n + 2);
188     assert(w[0] == 0x0453);
189 
190     n[0] = char(0x56);
191     r = c.in(m, n, n + 1, np, w, w + 2, wp);
192     assert(r == std::codecvt_base::ok);
193     assert(wp == w + 1);
194     assert(np == n + 1);
195     assert(w[0] == 0x0056);
196   }
197   {
198     typedef std::codecvt_utf8_utf16<CharT, 0x10ffff, std::consume_header> C;
199     C c;
200     CharT w[2] = {0};
201     char n[7] = {char(0xEF), char(0xBB), char(0xBF), char(0xF1),
202                  char(0x80), char(0x80), char(0x83)};
203     CharT* wp = nullptr;
204     std::mbstate_t m;
205     const char* np = nullptr;
206     std::codecvt_base::result r = c.in(m, n, n + 7, np, w, w + 2, wp);
207     assert(r == std::codecvt_base::ok);
208     assert(wp == w + 2);
209     assert(np == n + 7);
210     assert(w[0] == 0xD8C0);
211     assert(w[1] == 0xDC03);
212 
213     n[0] = char(0xE1);
214     n[1] = char(0x80);
215     n[2] = char(0x85);
216     r = c.in(m, n, n + 3, np, w, w + 2, wp);
217     assert(r == std::codecvt_base::ok);
218     assert(wp == w + 1);
219     assert(np == n + 3);
220     assert(w[0] == 0x1005);
221 
222     n[0] = char(0xD1);
223     n[1] = char(0x93);
224     r = c.in(m, n, n + 2, np, w, w + 2, wp);
225     assert(r == std::codecvt_base::ok);
226     assert(wp == w + 1);
227     assert(np == n + 2);
228     assert(w[0] == 0x0453);
229 
230     n[0] = char(0x56);
231     r = c.in(m, n, n + 1, np, w, w + 2, wp);
232     assert(r == std::codecvt_base::ok);
233     assert(wp == w + 1);
234     assert(np == n + 1);
235     assert(w[0] == 0x0056);
236   }
237 }
238 
239 int main(int, char**) {
240 #if !defined(_WIN32) && !defined(TEST_HAS_NO_WIDE_CHARACTERS)
241   TestHelper<wchar_t>::test();
242 #endif
243   TestHelper<char32_t>::test();
244   TestHelper<char16_t>::test();
245 
246   return 0;
247 }
248