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 // This test relies on P0482 being fixed, which isn't in
10 // older Apple dylibs
11 //
12 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
13 
14 // This test runs in C++20, but we have deprecated codecvt<char(16|32), char, mbstate_t> in C++20.
15 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
16 
17 // <locale>
18 
19 // template <> class codecvt<char32_t, char, mbstate_t>
20 // template <> class codecvt<char16_t, char, mbstate_t>
21 // template <> class codecvt<char32_t, char8_t, mbstate_t> // C++20
22 // template <> class codecvt<char16_t, char8_t, mbstate_t> // C++20
23 // template <> class codecvt<char32_t, char16_t, mbstate_t>  // extension
24 
25 // sanity check
26 
27 #include <locale>
28 #include <codecvt>
29 #include <cassert>
30 
31 #include <stdio.h>
32 
33 #include "test_macros.h"
34 
main(int,char **)35 int main(int, char**) {
36   typedef std::codecvt<char32_t, char, std::mbstate_t> F32_8;
37   typedef std::codecvt<char16_t, char, std::mbstate_t> F16_8;
38   typedef std::codecvt_utf16<char32_t> F32_16;
39   std::locale l = std::locale(std::locale::classic(), new F32_16);
40   const F32_8& f32_8 = std::use_facet<F32_8>(std::locale::classic());
41   const F32_16& f32_16 = std::use_facet<F32_16>(l);
42   const F16_8& f16_8 = std::use_facet<F16_8>(std::locale::classic());
43   std::mbstate_t mbs32_8 = {};
44   std::mbstate_t mbs16_8 = {};
45   std::mbstate_t mbs32_16 = {};
46   F32_8::intern_type* c32p;
47   F16_8::intern_type* c16p;
48   F32_8::extern_type* c8p;
49   const F32_8::intern_type* c_c32p;
50   const F16_8::intern_type* c_c16p;
51   const F32_8::extern_type* c_c8p;
52   F32_8::intern_type c32;
53   F16_8::intern_type c16[2];
54   char c16c[4];
55   char* c16cp;
56   F32_8::extern_type c8[4];
57 
58 #if TEST_STD_VER > 17
59   typedef std::codecvt<char32_t, char8_t, std::mbstate_t> F32_8T;
60   typedef std::codecvt<char16_t, char8_t, std::mbstate_t> F16_8T;
61   const F32_8T& f32_8t = std::use_facet<F32_8T>(std::locale::classic());
62   const F16_8T& f16_8t = std::use_facet<F16_8T>(std::locale::classic());
63   std::mbstate_t mbs32_8t = {};
64   std::mbstate_t mbs16_8t = {};
65   F32_8T::extern_type* c8tp;
66   const F32_8T::extern_type* c_c8tp;
67   F32_8T::extern_type c8t[4];
68 #endif
69 
70   for (F32_8::intern_type c32x = 0; c32x < 0x110003; ++c32x) {
71     if ((0xD800 <= c32x && c32x < 0xE000) || c32x >= 0x110000) {
72 #ifndef _MSVC_STL_VERSION // Don't ask; eldritch horrors.
73       assert(f32_16.out(mbs32_16, &c32x, &c32x + 1, c_c32p, c16c + 0, c16c + 4,
74                         c16cp) == F32_8::error);
75       assert(f32_8.out(mbs32_8, &c32x, &c32x + 1, c_c32p, c8, c8 + 4, c8p) ==
76              F32_8::error);
77 #endif
78 
79 #if TEST_STD_VER > 17
80       assert(f32_8t.out(mbs32_8t, &c32x, &c32x + 1, c_c32p, c8t, c8t + 4,
81                         c8tp) == F32_8T::error);
82 #endif
83     } else {
84       assert(f32_16.out(mbs32_16, &c32x, &c32x + 1, c_c32p, c16c, c16c + 4,
85                         c16cp) == F32_8::ok);
86       assert(c_c32p - &c32x == 1);
87       if (c32x < 0x10000)
88         assert(c16cp - c16c == 2);
89       else
90         assert(c16cp - c16c == 4);
91       for (int i = 0; i < (c16cp - c16c) / 2; ++i)
92         c16[i] = (char16_t)((unsigned char)c16c[2 * i] << 8 |
93                             (unsigned char)c16c[2 * i + 1]);
94       c_c16p = c16 + (c16cp - c16c) / 2;
95       assert(f16_8.out(mbs16_8, c16, c_c16p, c_c16p, c8, c8 + 4, c8p) ==
96              F32_8::ok);
97       if (c32x < 0x10000)
98         assert(c_c16p - c16 == 1);
99       else
100         assert(c_c16p - c16 == 2);
101       if (c32x < 0x80)
102         assert(c8p - c8 == 1);
103       else if (c32x < 0x800)
104         assert(c8p - c8 == 2);
105       else if (c32x < 0x10000)
106         assert(c8p - c8 == 3);
107       else
108         assert(c8p - c8 == 4);
109       c_c8p = c8p;
110       assert(f32_8.in(mbs32_8, c8, c_c8p, c_c8p, &c32, &c32 + 1, c32p) ==
111              F32_8::ok);
112       if (c32x < 0x80)
113         assert(c_c8p - c8 == 1);
114       else if (c32x < 0x800)
115         assert(c_c8p - c8 == 2);
116       else if (c32x < 0x10000)
117         assert(c_c8p - c8 == 3);
118       else
119         assert(c_c8p - c8 == 4);
120       assert(c32p - &c32 == 1);
121       assert(c32 == c32x);
122       assert(f32_8.out(mbs32_8, &c32x, &c32x + 1, c_c32p, c8, c8 + 4, c8p) ==
123              F32_8::ok);
124       assert(c_c32p - &c32x == 1);
125       if (c32x < 0x80)
126         assert(c8p - c8 == 1);
127       else if (c32x < 0x800)
128         assert(c8p - c8 == 2);
129       else if (c32x < 0x10000)
130         assert(c8p - c8 == 3);
131       else
132         assert(c8p - c8 == 4);
133       c_c8p = c8p;
134       assert(f16_8.in(mbs16_8, c8, c_c8p, c_c8p, c16, c16 + 2, c16p) ==
135              F32_8::ok);
136       if (c32x < 0x80)
137         assert(c_c8p - c8 == 1);
138       else if (c32x < 0x800)
139         assert(c_c8p - c8 == 2);
140       else if (c32x < 0x10000)
141         assert(c_c8p - c8 == 3);
142       else
143         assert(c_c8p - c8 == 4);
144       if (c32x < 0x10000)
145         assert(c16p - c16 == 1);
146       else
147         assert(c16p - c16 == 2);
148       for (int i = 0; i < c16p - c16; ++i) {
149         c16c[2 * i] = static_cast<char>(c16[i] >> 8);
150         c16c[2 * i + 1] = static_cast<char>(c16[i]);
151       }
152       const char* c_c16cp = c16c + (c16p - c16) * 2;
153       assert(f32_16.in(mbs32_16, c16c, c_c16cp, c_c16cp, &c32, &c32 + 1,
154                        c32p) == F32_8::ok);
155       if (c32x < 0x10000)
156         assert(c_c16cp - c16c == 2);
157       else
158         assert(c_c16cp - c16c == 4);
159       assert(c32p - &c32 == 1);
160       assert(c32 == c32x);
161 
162 #if TEST_STD_VER > 17
163       assert(f32_8t.out(mbs32_8t, &c32x, &c32x + 1, c_c32p, c8t, c8t + 4,
164                         c8tp) == F32_8T::ok);
165       assert(c_c32p - &c32x == 1);
166       if (c32x < 0x80)
167         assert(c8tp - c8t == 1);
168       else if (c32x < 0x800)
169         assert(c8tp - c8t == 2);
170       else if (c32x < 0x10000)
171         assert(c8tp - c8t == 3);
172       else
173         assert(c8tp - c8t == 4);
174       c_c8tp = c8tp;
175       assert(f16_8t.in(mbs16_8t, c8t, c_c8tp, c_c8tp, c16, c16 + 2, c16p) ==
176              F16_8T::ok);
177       if (c32x < 0x80)
178         assert(c_c8tp - c8t == 1);
179       else if (c32x < 0x800)
180         assert(c_c8tp - c8t == 2);
181       else if (c32x < 0x10000)
182         assert(c_c8tp - c8t == 3);
183       else
184         assert(c_c8tp - c8t == 4);
185       if (c32x < 0x10000)
186         assert(c16p - c16 == 1);
187       else
188         assert(c16p - c16 == 2);
189       c_c16p = c16p;
190       assert(f16_8t.out(mbs16_8t, c16, c_c16p, c_c16p, c8t, c8t + 4, c8tp) ==
191              F16_8T::ok);
192       if (c32x < 0x10000)
193         assert(c_c16p - c16 == 1);
194       else
195         assert(c_c16p - c16 == 2);
196       if (c32x < 0x80)
197         assert(c8tp - c8t == 1);
198       else if (c32x < 0x800)
199         assert(c8tp - c8t == 2);
200       else if (c32x < 0x10000)
201         assert(c8tp - c8t == 3);
202       else
203         assert(c8tp - c8t == 4);
204       c_c8tp = c8tp;
205       assert(f32_8t.in(mbs32_8t, c8t, c_c8tp, c_c8tp, &c32, &c32 + 1, c32p) ==
206              F32_8T::ok);
207       if (c32x < 0x80)
208         assert(c_c8tp - c8t == 1);
209       else if (c32x < 0x800)
210         assert(c_c8tp - c8t == 2);
211       else if (c32x < 0x10000)
212         assert(c_c8tp - c8t == 3);
213       else
214         assert(c_c8tp - c8t == 4);
215       assert(c32p - &c32 == 1);
216       assert(c32 == c32x);
217 #endif
218     }
219   }
220 
221   return 0;
222 }
223