1 //
2 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 #define BOOST_LOCALE_SOURCE
9
10 #include <boost/config.hpp>
11 #ifdef BOOST_MSVC
12 # pragma warning(disable : 4996)
13 #endif
14
15 #include <locale>
16 #include <stdexcept>
17 #include <boost/locale/generator.hpp>
18 #include <boost/locale/conversion.hpp>
19 #include <boost/locale/encoding.hpp>
20 #include <vector>
21
22
23
24 #include "all_generator.hpp"
25
26 namespace boost {
27 namespace locale {
28 namespace impl_std {
29
30
31 template<typename CharType>
32 class std_converter : public converter<CharType>
33 {
34 public:
35 typedef CharType char_type;
36 typedef std::basic_string<char_type> string_type;
37 typedef std::ctype<char_type> ctype_type;
std_converter(std::locale const & base,size_t refs=0)38 std_converter(std::locale const &base,size_t refs = 0) :
39 converter<CharType>(refs),
40 base_(base)
41 {
42 }
convert(converter_base::conversion_type how,char_type const * begin,char_type const * end,int=0) const43 virtual string_type convert(converter_base::conversion_type how,char_type const *begin,char_type const *end,int /*flags*/ = 0) const
44 {
45 switch(how) {
46 case converter_base::upper_case:
47 case converter_base::lower_case:
48 case converter_base::case_folding:
49 {
50 ctype_type const &ct=std::use_facet<ctype_type>(base_);
51 size_t len = end - begin;
52 std::vector<char_type> res(len+1,0);
53 char_type *lbegin = &res[0];
54 std::copy(begin,end,lbegin);
55 if(how == converter_base::upper_case)
56 ct.toupper(lbegin,lbegin+len);
57 else
58 ct.tolower(lbegin,lbegin+len);
59 return string_type(lbegin,len);
60 }
61 default:
62 return string_type(begin,end-begin);
63 }
64 }
65 private:
66 std::locale base_;
67 };
68
69 class utf8_converter : public converter<char> {
70 public:
71 typedef std::ctype<char> ctype_type;
72 typedef std::ctype<wchar_t> wctype_type;
utf8_converter(std::locale const & base,size_t refs=0)73 utf8_converter(std::locale const &base,size_t refs = 0) :
74 converter<char>(refs),
75 base_(base)
76 {
77 }
convert(converter_base::conversion_type how,char const * begin,char const * end,int=0) const78 virtual std::string convert(converter_base::conversion_type how,char const *begin,char const *end,int /*flags*/ = 0) const
79 {
80 switch(how) {
81 case upper_case:
82 case lower_case:
83 case case_folding:
84 {
85 std::wstring tmp = conv::to_utf<wchar_t>(begin,end,"UTF-8");
86 wctype_type const &ct=std::use_facet<wctype_type>(base_);
87 size_t len = tmp.size();
88 std::vector<wchar_t> res(len+1,0);
89 wchar_t *lbegin = &res[0];
90 std::copy(tmp.c_str(),tmp.c_str()+len,lbegin);
91 if(how == upper_case)
92 ct.toupper(lbegin,lbegin+len);
93 else
94 ct.tolower(lbegin,lbegin+len);
95 return conv::from_utf<wchar_t>(lbegin,lbegin+len,"UTF-8");
96 }
97 default:
98 return std::string(begin,end-begin);
99 }
100 }
101 private:
102 std::locale base_;
103 };
104
create_convert(std::locale const & in,std::string const & locale_name,character_facet_type type,utf8_support utf)105 std::locale create_convert( std::locale const &in,
106 std::string const &locale_name,
107 character_facet_type type,
108 utf8_support utf)
109 {
110 switch(type) {
111 case char_facet:
112 {
113 if(utf == utf8_native_with_wide || utf == utf8_from_wide) {
114 std::locale base(std::locale::classic(),new std::ctype_byname<wchar_t>(locale_name.c_str()));
115 return std::locale(in,new utf8_converter(base));
116 }
117 std::locale base(std::locale::classic(),new std::ctype_byname<char>(locale_name.c_str()));
118 return std::locale(in,new std_converter<char>(base));
119 }
120 case wchar_t_facet:
121 {
122 std::locale base(std::locale::classic(),new std::ctype_byname<wchar_t>(locale_name.c_str()));
123 return std::locale(in,new std_converter<wchar_t>(base));
124 }
125 #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
126 case char16_t_facet:
127 {
128 std::locale base(std::locale::classic(),new std::ctype_byname<char16_t>(locale_name.c_str()));
129 return std::locale(in,new std_converter<char16_t>(base));
130 }
131 #endif
132 #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
133 case char32_t_facet:
134 {
135 std::locale base(std::locale::classic(),new std::ctype_byname<char32_t>(locale_name.c_str()));
136 return std::locale(in,new std_converter<char32_t>(base));
137 }
138 #endif
139 default:
140 return in;
141 }
142 }
143
144
145 } // namespace impl_std
146 } // locale
147 } // boost
148 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
149