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 #if defined(__FreeBSD__)
11 #include <xlocale.h>
12 #endif
13 #include <locale>
14 #include <stdexcept>
15 #include <boost/locale/generator.hpp>
16 #include <boost/locale/conversion.hpp>
17 #include <boost/locale/encoding.hpp>
18 #include <boost/shared_ptr.hpp>
19 #include <vector>
20 #include <string.h>
21 #include <wctype.h>
22 #include <ctype.h>
23 #include <langinfo.h>
24 #include "all_generator.hpp"
25
26 namespace boost {
27 namespace locale {
28 namespace impl_posix {
29
30 template<typename CharType>
31 struct case_traits;
32
33 template<>
34 struct case_traits<char> {
lowerboost::locale::impl_posix::case_traits35 static char lower(char c,locale_t lc)
36 {
37 return tolower_l(c,lc);
38 }
upperboost::locale::impl_posix::case_traits39 static char upper(char c,locale_t lc)
40 {
41 return toupper_l(c,lc);
42 }
43 };
44
45 template<>
46 struct case_traits<wchar_t> {
lowerboost::locale::impl_posix::case_traits47 static wchar_t lower(wchar_t c,locale_t lc)
48 {
49 return towlower_l(c,lc);
50 }
upperboost::locale::impl_posix::case_traits51 static wchar_t upper(wchar_t c,locale_t lc)
52 {
53 return towupper_l(c,lc);
54 }
55 };
56
57
58 template<typename CharType>
59 class std_converter : public converter<CharType>
60 {
61 public:
62 typedef CharType char_type;
63 typedef std::basic_string<char_type> string_type;
64 typedef std::ctype<char_type> ctype_type;
std_converter(boost::shared_ptr<locale_t> lc,size_t refs=0)65 std_converter(boost::shared_ptr<locale_t> lc,size_t refs = 0) :
66 converter<CharType>(refs),
67 lc_(lc)
68 {
69 }
convert(converter_base::conversion_type how,char_type const * begin,char_type const * end,int=0) const70 virtual string_type convert(converter_base::conversion_type how,char_type const *begin,char_type const *end,int /*flags*/ = 0) const
71 {
72 switch(how) {
73 case converter_base::upper_case:
74 {
75 string_type res;
76 res.reserve(end-begin);
77 while(begin!=end) {
78 res+=case_traits<char_type>::upper(*begin++,*lc_);
79 }
80 return res;
81 }
82 case converter_base::lower_case:
83 case converter_base::case_folding:
84 {
85 string_type res;
86 res.reserve(end-begin);
87 while(begin!=end) {
88 res+=case_traits<char_type>::lower(*begin++,*lc_);
89 }
90 return res;
91 }
92 default:
93 return string_type(begin,end-begin);
94 }
95 }
96 private:
97 boost::shared_ptr<locale_t> lc_;
98 };
99
100 class utf8_converter : public converter<char> {
101 public:
utf8_converter(boost::shared_ptr<locale_t> lc,size_t refs=0)102 utf8_converter(boost::shared_ptr<locale_t> lc,size_t refs = 0) :
103 converter<char>(refs),
104 lc_(lc)
105 {
106 }
convert(converter_base::conversion_type how,char const * begin,char const * end,int=0) const107 virtual std::string convert(converter_base::conversion_type how,char const *begin,char const *end,int /*flags*/ = 0) const
108 {
109 switch(how) {
110 case upper_case:
111 {
112 std::wstring tmp = conv::to_utf<wchar_t>(begin,end,"UTF-8");
113 std::wstring wres;
114 wres.reserve(tmp.size());
115 for(unsigned i=0;i<tmp.size();i++)
116 wres+=towupper_l(tmp[i],*lc_);
117 return conv::from_utf<wchar_t>(wres,"UTF-8");
118 }
119
120 case lower_case:
121 case case_folding:
122 {
123 std::wstring tmp = conv::to_utf<wchar_t>(begin,end,"UTF-8");
124 std::wstring wres;
125 wres.reserve(tmp.size());
126 for(unsigned i=0;i<tmp.size();i++)
127 wres+=towlower_l(tmp[i],*lc_);
128 return conv::from_utf<wchar_t>(wres,"UTF-8");
129 }
130 default:
131 return std::string(begin,end-begin);
132 }
133 }
134 private:
135 boost::shared_ptr<locale_t> lc_;
136 };
137
create_convert(std::locale const & in,boost::shared_ptr<locale_t> lc,character_facet_type type)138 std::locale create_convert( std::locale const &in,
139 boost::shared_ptr<locale_t> lc,
140 character_facet_type type)
141 {
142 switch(type) {
143 case char_facet:
144 {
145 std::string encoding = nl_langinfo_l(CODESET,*lc);
146 for(unsigned i=0;i<encoding.size();i++)
147 if('A'<=encoding[i] && encoding[i]<='Z')
148 encoding[i]=encoding[i]-'A'+'a';
149 if(encoding=="utf-8" || encoding=="utf8" || encoding=="utf_8") {
150 return std::locale(in,new utf8_converter(lc));
151 }
152 return std::locale(in,new std_converter<char>(lc));
153 }
154 case wchar_t_facet:
155 return std::locale(in,new std_converter<wchar_t>(lc));
156 default:
157 return in;
158 }
159 }
160
161
162 } // namespace impl_std
163 } // locale
164 } // boost
165 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
166