1//
2// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3// Copyright (c) 2022-2023 Alexander Grund
4//
5// Distributed under the Boost Software License, Version 1.0.
6// https://www.boost.org/LICENSE_1_0.txt
7
8#include <boost/locale/encoding.hpp>
9#include "boost/locale/util/make_std_unique.hpp"
10
11#if BOOST_LOCALE_USE_WIN32_API
12# define BOOST_LOCALE_WITH_WCONV
13#endif
14#ifdef BOOST_LOCALE_WITH_ICONV
15# include "boost/locale/encoding/iconv_converter.hpp"
16#endif
17#ifdef BOOST_LOCALE_WITH_ICU
18# include "boost/locale/encoding/uconv_converter.hpp"
19#endif
20#ifdef BOOST_LOCALE_WITH_WCONV
21# include "boost/locale/encoding/wconv_converter.hpp"
22#endif
23
24namespace boost { namespace locale { namespace conv {
25
26 std::string between(const char* begin,
27 const char* end,
28 const std::string& to_charset,
29 const std::string& from_charset,
30 method_type how)
31 {
32#ifdef BOOST_LOCALE_WITH_ICONV
33 {
34 impl::iconv_between cvt;
35 if(cvt.open(to_charset, from_charset, how))
36 return cvt.convert(begin, end);
37 }
38#endif
39#ifdef BOOST_LOCALE_WITH_ICU
40 {
41 impl::uconv_between cvt;
42 if(cvt.open(to_charset, from_charset, how))
43 return cvt.convert(begin, end);
44 }
45#endif
46#ifdef BOOST_LOCALE_WITH_WCONV
47 {
48 impl::wconv_between cvt;
49 if(cvt.open(to_charset, from_charset, how))
50 return cvt.convert(begin, end);
51 }
52#endif
53 throw invalid_charset_error(std::string(to_charset) + " or " + from_charset);
54 }
55
56 template<typename CharType>
57 std::basic_string<CharType> to_utf(const char* begin, const char* end, const std::string& charset, method_type how)
58 {
59#ifdef BOOST_LOCALE_WITH_ICONV
60 {
61 impl::iconv_to_utf<CharType> cvt;
62 if(cvt.open(charset, how))
63 return cvt.convert(begin, end);
64 }
65#endif
66#ifdef BOOST_LOCALE_WITH_ICU
67 {
68 impl::uconv_to_utf<CharType> cvt;
69 if(cvt.open(charset, how))
70 return cvt.convert(begin, end);
71 }
72#endif
73#ifdef BOOST_LOCALE_WITH_WCONV
74 {
75 impl::wconv_to_utf<CharType> cvt;
76 if(cvt.open(charset, how))
77 return cvt.convert(begin, end);
78 }
79#endif
80 throw invalid_charset_error(charset);
81 }
82
83 template<typename CharType>
84 std::string from_utf(const CharType* begin, const CharType* end, const std::string& charset, method_type how)
85 {
86#ifdef BOOST_LOCALE_WITH_ICONV
87 {
88 impl::iconv_from_utf<CharType> cvt;
89 if(cvt.open(charset, how))
90 return cvt.convert(begin, end);
91 }
92#endif
93#ifdef BOOST_LOCALE_WITH_ICU
94 {
95 impl::uconv_from_utf<CharType> cvt;
96 if(cvt.open(charset, how))
97 return cvt.convert(begin, end);
98 }
99#endif
100#ifdef BOOST_LOCALE_WITH_WCONV
101 {
102 impl::wconv_from_utf<CharType> cvt;
103 if(cvt.open(charset, how))
104 return cvt.convert(begin, end);
105 }
106#endif
107 throw invalid_charset_error(charset);
108 }
109
110 namespace detail {
111 template<class T>
112 static std::unique_ptr<T> move_to_ptr(T& c)
113 {
114 return make_std_unique<T>(std::move(c));
115 }
116
117 template<typename Char>
118 std::unique_ptr<utf_encoder<Char>>
119 make_utf_encoder(const std::string& charset, method_type how, conv_backend impl)
120 {
121#ifdef BOOST_LOCALE_WITH_ICONV
122 if(impl == conv_backend::Default || impl == conv_backend::IConv) {
123 impl::iconv_to_utf<Char> cvt;
124 if(cvt.open(charset, how))
125 return move_to_ptr(cvt);
126 }
127#endif
128#ifdef BOOST_LOCALE_WITH_ICU
129 if(impl == conv_backend::Default || impl == conv_backend::ICU) {
130 impl::uconv_to_utf<Char> cvt;
131 if(cvt.open(charset, how))
132 return move_to_ptr(cvt);
133 }
134#endif
135#ifdef BOOST_LOCALE_WITH_WCONV
136 if(impl == conv_backend::Default || impl == conv_backend::WinAPI) {
137 impl::wconv_to_utf<Char> cvt;
138 if(cvt.open(charset, how))
139 return move_to_ptr(cvt);
140 }
141#endif
142 throw invalid_charset_error(charset);
143 }
144
145 template<typename Char>
146 std::unique_ptr<utf_decoder<Char>>
147 make_utf_decoder(const std::string& charset, method_type how, conv_backend impl)
148 {
149#ifdef BOOST_LOCALE_WITH_ICONV
150 if(impl == conv_backend::Default || impl == conv_backend::IConv) {
151 impl::iconv_from_utf<Char> cvt;
152 if(cvt.open(charset, how))
153 return move_to_ptr(cvt);
154 }
155#endif
156#ifdef BOOST_LOCALE_WITH_ICU
157 if(impl == conv_backend::Default || impl == conv_backend::ICU) {
158 impl::uconv_from_utf<Char> cvt;
159 if(cvt.open(charset, how))
160 return move_to_ptr(cvt);
161 }
162#endif
163#ifdef BOOST_LOCALE_WITH_WCONV
164 if(impl == conv_backend::Default || impl == conv_backend::WinAPI) {
165 impl::wconv_from_utf<Char> cvt;
166 if(cvt.open(charset, how))
167 return move_to_ptr(cvt);
168 }
169#endif
170 throw invalid_charset_error(charset);
171 }
172 std::unique_ptr<narrow_converter> make_narrow_converter(const std::string& src_encoding,
173 const std::string& target_encoding,
174 method_type how,
175 conv_backend impl)
176 {
177#ifdef BOOST_LOCALE_WITH_ICONV
178 if(impl == conv_backend::Default || impl == conv_backend::IConv) {
179 impl::iconv_between cvt;
180 if(cvt.open(to_charset: target_encoding, from_charset: src_encoding, how))
181 return move_to_ptr(c&: cvt);
182 }
183#endif
184#ifdef BOOST_LOCALE_WITH_ICU
185 if(impl == conv_backend::Default || impl == conv_backend::ICU) {
186 impl::uconv_between cvt;
187 if(cvt.open(to_charset: target_encoding, from_charset: src_encoding, how))
188 return move_to_ptr(c&: cvt);
189 }
190#endif
191#ifdef BOOST_LOCALE_WITH_WCONV
192 if(impl == conv_backend::Default || impl == conv_backend::WinAPI) {
193 impl::wconv_between cvt;
194 if(cvt.open(target_encoding, src_encoding, how))
195 return move_to_ptr(cvt);
196 }
197#endif
198 throw invalid_charset_error(std::string(src_encoding) + " or " + target_encoding);
199 }
200 } // namespace detail
201
202#define BOOST_LOCALE_INSTANTIATE(CHARTYPE) \
203 namespace detail { \
204 template class charset_converter<char, CHARTYPE>; \
205 template BOOST_LOCALE_DECL std::unique_ptr<utf_encoder<CHARTYPE>> \
206 make_utf_encoder(const std::string& charset, method_type how, conv_backend impl); \
207 template BOOST_LOCALE_DECL std::unique_ptr<utf_decoder<CHARTYPE>> \
208 make_utf_decoder(const std::string& charset, method_type how, conv_backend impl); \
209 } \
210 template BOOST_LOCALE_DECL std::basic_string<CHARTYPE> to_utf<CHARTYPE>(const char* begin, \
211 const char* end, \
212 const std::string& charset, \
213 method_type how); \
214 template BOOST_LOCALE_DECL std::string from_utf<CHARTYPE>(const CHARTYPE* begin, \
215 const CHARTYPE* end, \
216 const std::string& charset, \
217 method_type how)
218#define BOOST_LOCALE_INSTANTIATE_NO_CHAR(CHARTYPE) \
219 BOOST_LOCALE_INSTANTIATE(CHARTYPE); \
220 namespace detail { \
221 template class charset_converter<CHARTYPE, char>; \
222 }
223
224 BOOST_LOCALE_INSTANTIATE(char);
225 BOOST_LOCALE_INSTANTIATE_NO_CHAR(wchar_t);
226
227#ifndef BOOST_LOCALE_NO_CXX20_STRING8
228 BOOST_LOCALE_INSTANTIATE_NO_CHAR(char8_t);
229#endif
230
231#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
232 BOOST_LOCALE_INSTANTIATE_NO_CHAR(char16_t);
233#endif
234
235#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
236 BOOST_LOCALE_INSTANTIATE_NO_CHAR(char32_t);
237#endif
238
239}}} // namespace boost::locale::conv
240

source code of boost/libs/locale/src/boost/locale/encoding/codepage.cpp