1//
2// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3//
4// Distributed under the Boost Software License, Version 1.0.
5// https://www.boost.org/LICENSE_1_0.txt
6
7#include <boost/locale/conversion.hpp>
8#include <boost/locale/encoding.hpp>
9#include <boost/locale/generator.hpp>
10#include <locale>
11#include <stdexcept>
12#include <vector>
13
14#include "boost/locale/std/all_generator.hpp"
15
16namespace boost { namespace locale { namespace impl_std {
17
18 template<typename CharType>
19 class std_converter : public converter<CharType> {
20 public:
21 typedef std::basic_string<CharType> string_type;
22 typedef std::ctype<CharType> ctype_type;
23
24 std_converter(const std::string& locale_name) :
25 base_(std::locale::classic(), new std::ctype_byname<CharType>(locale_name))
26 {}
27 string_type convert(converter_base::conversion_type how,
28 const CharType* begin,
29 const CharType* end,
30 int /*flags*/ = 0) const override
31 {
32 switch(how) {
33 case converter_base::upper_case:
34 case converter_base::lower_case:
35 case converter_base::case_folding: {
36 const ctype_type& ct = std::use_facet<ctype_type>(base_);
37 size_t len = end - begin;
38 std::vector<CharType> res(len + 1, 0);
39 CharType* lbegin = res.data();
40 std::copy(begin, end, lbegin);
41 if(how == converter_base::upper_case)
42 ct.toupper(lbegin, lbegin + len);
43 else
44 ct.tolower(lbegin, lbegin + len);
45 return string_type(lbegin, len);
46 }
47 case converter_base::normalization:
48 case converter_base::title_case: break;
49 }
50 return string_type(begin, end - begin);
51 }
52
53 private:
54 std::locale base_;
55 };
56
57 template<typename U8Char>
58 class utf8_converter : public converter<U8Char> {
59 public:
60 typedef std::basic_string<U8Char> string_type;
61 typedef std::ctype<wchar_t> wctype_type;
62
63 utf8_converter(const std::string& locale_name) :
64 base_(std::locale::classic(), new std::ctype_byname<wchar_t>(locale_name))
65 {}
66 string_type convert(converter_base::conversion_type how,
67 const U8Char* begin,
68 const U8Char* end,
69 int /*flags*/ = 0) const override
70 {
71 using conversion_type = converter_base::conversion_type;
72 switch(how) {
73 case conversion_type::upper_case:
74 case conversion_type::lower_case:
75 case conversion_type::case_folding: {
76 std::wstring tmp = conv::utf_to_utf<wchar_t>(begin, end);
77 const wctype_type& ct = std::use_facet<wctype_type>(loc: base_);
78 wchar_t* lbegin = &tmp.front();
79 const size_t len = tmp.size();
80 if(how == conversion_type::upper_case)
81 ct.toupper(lo: lbegin, hi: lbegin + len);
82 else
83 ct.tolower(lo: lbegin, hi: lbegin + len);
84 return conv::utf_to_utf<U8Char>(lbegin, lbegin + len);
85 }
86 case conversion_type::title_case:
87 case conversion_type::normalization: break;
88 }
89 return string_type(begin, end - begin);
90 }
91
92 private:
93 std::locale base_;
94 };
95
96 std::locale
97 create_convert(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf)
98 {
99 switch(type) {
100 case char_facet_t::nochar: break;
101 case char_facet_t::char_f:
102 if(utf != utf8_support::none)
103 return std::locale(in, new utf8_converter<char>(locale_name));
104 else
105 return std::locale(in, new std_converter<char>(locale_name));
106 case char_facet_t::wchar_f: return std::locale(in, new std_converter<wchar_t>(locale_name));
107#ifndef BOOST_LOCALE_NO_CXX20_STRING8
108 case char_facet_t::char8_f: return std::locale(in, new utf8_converter<char8_t>(locale_name));
109#elif defined(__cpp_char8_t)
110 case char_facet_t::char8_f: break;
111#endif
112#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
113 case char_facet_t::char16_f: return std::locale(in, new std_converter<char16_t>(locale_name));
114#endif
115#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
116 case char_facet_t::char32_f: return std::locale(in, new std_converter<char32_t>(locale_name));
117#endif
118 }
119 return in;
120 }
121
122}}} // namespace boost::locale::impl_std
123

source code of boost/libs/locale/src/boost/locale/std/converter.cpp