• 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 #if defined(__FreeBSD__)
10 #include <xlocale.h>
11 #endif
12 #include <boost/locale/localization_backend.hpp>
13 #include <boost/locale/gnu_gettext.hpp>
14 #include <boost/locale/info.hpp>
15 #include "all_generator.hpp"
16 #include "posix_backend.hpp"
17 
18 #include "../util/locale_data.hpp"
19 #include "../util/gregorian.hpp"
20 #include <boost/locale/util.hpp>
21 #include <algorithm>
22 #include <iterator>
23 
24 #include <langinfo.h>
25 
26 namespace boost {
27 namespace locale {
28 namespace impl_posix {
29 
30     class posix_localization_backend : public localization_backend {
31     public:
posix_localization_backend()32         posix_localization_backend() :
33             invalid_(true)
34         {
35         }
posix_localization_backend(posix_localization_backend const & other)36         posix_localization_backend(posix_localization_backend const &other) :
37             localization_backend(),
38             paths_(other.paths_),
39             domains_(other.domains_),
40             locale_id_(other.locale_id_),
41             invalid_(true)
42         {
43         }
clone() const44         virtual posix_localization_backend *clone() const
45         {
46             return new posix_localization_backend(*this);
47         }
48 
set_option(std::string const & name,std::string const & value)49         void set_option(std::string const &name,std::string const &value)
50         {
51             invalid_ = true;
52             if(name=="locale")
53                 locale_id_ = value;
54             else if(name=="message_path")
55                 paths_.push_back(value);
56             else if(name=="message_application")
57                 domains_.push_back(value);
58 
59         }
clear_options()60         void clear_options()
61         {
62             invalid_ = true;
63             locale_id_.clear();
64             paths_.clear();
65             domains_.clear();
66         }
67 
free_locale_by_ptr(locale_t * lc)68         static void free_locale_by_ptr(locale_t *lc)
69         {
70             freelocale(*lc);
71             delete lc;
72         }
73 
prepare_data()74         void prepare_data()
75         {
76             if(!invalid_)
77                 return;
78             invalid_ = false;
79             lc_.reset();
80             real_id_ = locale_id_;
81             if(real_id_.empty())
82                 real_id_ = util::get_system_locale();
83 
84             locale_t tmp = newlocale(LC_ALL_MASK,real_id_.c_str(),0);
85 
86             if(!tmp) {
87                 tmp=newlocale(LC_ALL_MASK,"C",0);
88             }
89             if(!tmp) {
90                 throw std::runtime_error("newlocale failed");
91             }
92 
93             locale_t *tmp_p = 0;
94 
95             try {
96                 tmp_p = new locale_t();
97             }
98             catch(...) {
99                 freelocale(tmp);
100                 throw;
101             }
102 
103             *tmp_p = tmp;
104             lc_ = boost::shared_ptr<locale_t>(tmp_p,free_locale_by_ptr);
105         }
106 
install(std::locale const & base,locale_category_type category,character_facet_type type=nochar_facet)107         virtual std::locale install(std::locale const &base,
108                                     locale_category_type category,
109                                     character_facet_type type = nochar_facet)
110         {
111             prepare_data();
112 
113             switch(category) {
114             case convert_facet:
115                 return create_convert(base,lc_,type);
116             case collation_facet:
117                 return create_collate(base,lc_,type);
118             case formatting_facet:
119                 return create_formatting(base,lc_,type);
120             case parsing_facet:
121                 return create_parsing(base,lc_,type);
122             case codepage_facet:
123                 return create_codecvt(base,nl_langinfo_l(CODESET,*lc_),type);
124             case calendar_facet:
125                 {
126                     util::locale_data inf;
127                     inf.parse(real_id_);
128                     return util::install_gregorian_calendar(base,inf.country);
129                 }
130             case message_facet:
131                 {
132                     gnu_gettext::messages_info minf;
133                     util::locale_data inf;
134                     inf.parse(real_id_);
135                     minf.language = inf.language;
136                     minf.country = inf.country;
137                     minf.variant = inf.variant;
138                     minf.encoding = inf.encoding;
139                     std::copy(domains_.begin(),domains_.end(),std::back_inserter<gnu_gettext::messages_info::domains_type>(minf.domains));
140                     minf.paths = paths_;
141                     switch(type) {
142                     case char_facet:
143                         return std::locale(base,gnu_gettext::create_messages_facet<char>(minf));
144                     case wchar_t_facet:
145                         return std::locale(base,gnu_gettext::create_messages_facet<wchar_t>(minf));
146                     #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
147                     case char16_t_facet:
148                         return std::locale(base,gnu_gettext::create_messages_facet<char16_t>(minf));
149                     #endif
150                     #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
151                     case char32_t_facet:
152                         return std::locale(base,gnu_gettext::create_messages_facet<char32_t>(minf));
153                     #endif
154                     default:
155                         return base;
156                     }
157                 }
158             case information_facet:
159                 return util::create_info(base,real_id_);
160             default:
161                 return base;
162             }
163         }
164 
165     private:
166 
167         std::vector<std::string> paths_;
168         std::vector<std::string> domains_;
169         std::string locale_id_;
170         std::string real_id_;
171 
172         bool invalid_;
173         boost::shared_ptr<locale_t> lc_;
174     };
175 
create_localization_backend()176     localization_backend *create_localization_backend()
177     {
178         return new posix_localization_backend();
179     }
180 
181 }  // impl posix
182 }  // locale
183 }  // boost
184 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
185