• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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