• 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 #include <boost/locale/localization_backend.hpp>
10 #include <boost/shared_ptr.hpp>
11 #include <boost/thread/locks.hpp>
12 #include <boost/thread/mutex.hpp>
13 #include <boost/locale/hold_ptr.hpp>
14 #include <vector>
15 
16 #ifdef BOOST_LOCALE_WITH_ICU
17 #include "../icu/icu_backend.hpp"
18 #endif
19 
20 #ifndef BOOST_LOCALE_NO_POSIX_BACKEND
21 #include "../posix/posix_backend.hpp"
22 #endif
23 
24 #ifndef BOOST_LOCALE_NO_STD_BACKEND
25 #include "../std/std_backend.hpp"
26 #endif
27 
28 #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND
29 #include "../win32/win_backend.hpp"
30 #endif
31 
32 namespace boost {
33     namespace locale {
34         class localization_backend_manager::impl {
35             void operator = (impl const &);
36         public:
impl(impl const & other)37             impl(impl const &other) :
38                 default_backends_(other.default_backends_)
39             {
40                 for(all_backends_type::const_iterator p=other.all_backends_.begin();p!=other.all_backends_.end();++p) {
41                     all_backends_type::value_type v;
42                     v.first=p->first;
43                     v.second.reset(p->second->clone());
44                     all_backends_.push_back(v);
45                 }
46             }
impl()47             impl() :
48                 default_backends_(32,-1)
49             {
50             }
51 
create() const52             localization_backend *create() const
53             {
54                 std::vector<boost::shared_ptr<localization_backend> > backends;
55                 for(unsigned i=0;i<all_backends_.size();i++)
56                     backends.push_back(all_backends_[i].second);
57                 return new actual_backend(backends,default_backends_);
58             }
adopt_backend(std::string const & name,localization_backend * backend_ptr)59             void adopt_backend(std::string const &name,localization_backend *backend_ptr)
60             {
61                 boost::shared_ptr<localization_backend> sptr(backend_ptr);
62                 if(all_backends_.empty()) {
63                     all_backends_.push_back(std::make_pair(name,sptr));
64                     for(unsigned i=0;i<default_backends_.size();i++)
65                         default_backends_[i]=0;
66                 }
67                 else {
68                     for(unsigned i=0;i<all_backends_.size();i++)
69                         if(all_backends_[i].first == name)
70                             return;
71                     all_backends_.push_back(std::make_pair(name,sptr));
72                 }
73             }
74 
select(std::string const & backend_name,locale_category_type category=all_categories)75             void select(std::string const &backend_name,locale_category_type category = all_categories)
76             {
77                 unsigned id;
78                 for(id=0;id<all_backends_.size();id++) {
79                     if(all_backends_[id].first == backend_name)
80                         break;
81                 }
82                 if(id==all_backends_.size())
83                     return;
84                 for(unsigned flag = 1,i=0;i<default_backends_.size();flag <<=1,i++) {
85                     if(category & flag) {
86                         default_backends_[i]=id;
87                     }
88                 }
89             }
90 
remove_all_backends()91             void remove_all_backends()
92             {
93                 all_backends_.clear();
94                 for(unsigned i=0;i<default_backends_.size();i++) {
95                     default_backends_[i]=-1;
96                 }
97             }
get_all_backends() const98             std::vector<std::string> get_all_backends() const
99             {
100                 std::vector<std::string> res;
101                 all_backends_type::const_iterator  p;
102                 for(p=all_backends_.begin();p!=all_backends_.end();++p) {
103                     res.push_back(p->first);
104                 }
105                 return res;
106             }
107 
108         private:
109             class actual_backend : public localization_backend {
110             public:
actual_backend(std::vector<boost::shared_ptr<localization_backend>> const & backends,std::vector<int> const & index)111                 actual_backend(std::vector<boost::shared_ptr<localization_backend> > const &backends,std::vector<int> const &index):
112                     index_(index)
113                 {
114                     backends_.resize(backends.size());
115                     for(unsigned i=0;i<backends.size();i++) {
116                         backends_[i].reset(backends[i]->clone());
117                     }
118                 }
clone() const119                 virtual actual_backend *clone() const
120                 {
121                     return new actual_backend(backends_,index_);
122                 }
set_option(std::string const & name,std::string const & value)123                 virtual void set_option(std::string const &name,std::string const &value)
124                 {
125                     for(unsigned i=0;i<backends_.size();i++)
126                         backends_[i]->set_option(name,value);
127                 }
clear_options()128                 virtual void clear_options()
129                 {
130                     for(unsigned i=0;i<backends_.size();i++)
131                         backends_[i]->clear_options();
132                 }
install(std::locale const & l,locale_category_type category,character_facet_type type=nochar_facet)133                 virtual std::locale install(std::locale const &l,locale_category_type category,character_facet_type type = nochar_facet)
134                 {
135                     int id;
136                     unsigned v;
137                     for(v=1,id=0;v!=0;v<<=1,id++) {
138                         if(category == v)
139                             break;
140                     }
141                     if(v==0)
142                         return l;
143                     if(unsigned(id) >= index_.size())
144                         return l;
145                     if(index_[id]==-1)
146                         return l;
147                     return backends_[index_[id]]->install(l,category,type);
148                 }
149             private:
150                 std::vector<boost::shared_ptr<localization_backend> > backends_;
151                 std::vector<int> index_;
152             };
153 
154             typedef std::vector<std::pair<std::string,boost::shared_ptr<localization_backend> > > all_backends_type;
155             all_backends_type all_backends_;
156             std::vector<int> default_backends_;
157         };
158 
159 
160 
localization_backend_manager()161         localization_backend_manager::localization_backend_manager() :
162             pimpl_(new impl())
163         {
164         }
165 
~localization_backend_manager()166         localization_backend_manager::~localization_backend_manager()
167         {
168         }
169 
localization_backend_manager(localization_backend_manager const & other)170         localization_backend_manager::localization_backend_manager(localization_backend_manager const &other) :
171             pimpl_(new impl(*other.pimpl_))
172         {
173         }
174 
operator =(localization_backend_manager const & other)175         localization_backend_manager const &localization_backend_manager::operator = (localization_backend_manager const &other)
176         {
177             if(this!=&other) {
178                 pimpl_.reset(new impl(*other.pimpl_));
179             }
180             return *this;
181         }
182 
183 
184         #if !defined(BOOST_LOCALE_HIDE_AUTO_PTR) && !defined(BOOST_NO_AUTO_PTR)
get() const185         std::auto_ptr<localization_backend> localization_backend_manager::get() const
186         {
187             std::auto_ptr<localization_backend> r(pimpl_->create());
188             return r;
189         }
add_backend(std::string const & name,std::auto_ptr<localization_backend> backend)190         void localization_backend_manager::add_backend(std::string const &name,std::auto_ptr<localization_backend> backend)
191         {
192             pimpl_->adopt_backend(name,backend.release());
193         }
194         #endif
195         #ifndef BOOST_NO_CXX11_SMART_PTR
get_unique_ptr() const196         std::unique_ptr<localization_backend> localization_backend_manager::get_unique_ptr() const
197         {
198             std::unique_ptr<localization_backend> r(pimpl_->create());
199             return r;
200         }
add_backend(std::string const & name,std::unique_ptr<localization_backend> backend)201         void localization_backend_manager::add_backend(std::string const &name,std::unique_ptr<localization_backend> backend)
202         {
203             pimpl_->adopt_backend(name,backend.release());
204         }
205         #endif
create() const206         localization_backend *localization_backend_manager::create() const
207         {
208             return pimpl_->create();
209         }
adopt_backend(std::string const & name,localization_backend * backend)210         void localization_backend_manager::adopt_backend(std::string const &name,localization_backend *backend)
211         {
212             pimpl_->adopt_backend(name,backend);
213         }
214 
215 
remove_all_backends()216         void localization_backend_manager::remove_all_backends()
217         {
218             pimpl_->remove_all_backends();
219         }
get_all_backends() const220         std::vector<std::string> localization_backend_manager::get_all_backends() const
221         {
222             return pimpl_->get_all_backends();
223         }
select(std::string const & backend_name,locale_category_type category)224         void localization_backend_manager::select(std::string const &backend_name,locale_category_type category)
225         {
226             pimpl_->select(backend_name,category);
227         }
228 
229         namespace {
230             // prevent initialization order fiasco
localization_backend_manager_mutex()231             boost::mutex &localization_backend_manager_mutex()
232             {
233                 static boost::mutex the_mutex;
234                 return the_mutex;
235             }
236             // prevent initialization order fiasco
localization_backend_manager_global()237             localization_backend_manager &localization_backend_manager_global()
238             {
239                 static localization_backend_manager the_manager;
240                 return the_manager;
241             }
242 
243             struct init {
initboost::locale::__anone33ae5700111::init244                 init() {
245                     localization_backend_manager mgr;
246                     #ifdef BOOST_LOCALE_WITH_ICU
247                     mgr.adopt_backend("icu",impl_icu::create_localization_backend());
248                     #endif
249 
250                     #ifndef BOOST_LOCALE_NO_POSIX_BACKEND
251                     mgr.adopt_backend("posix",impl_posix::create_localization_backend());
252                     #endif
253 
254                     #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND
255                     mgr.adopt_backend("winapi",impl_win::create_localization_backend());
256                     #endif
257 
258                     #ifndef BOOST_LOCALE_NO_STD_BACKEND
259                     mgr.adopt_backend("std",impl_std::create_localization_backend());
260                     #endif
261 
262                     localization_backend_manager::global(mgr);
263                 }
264             } do_init;
265         }
266 
global()267         localization_backend_manager localization_backend_manager::global()
268         {
269             boost::unique_lock<boost::mutex> lock(localization_backend_manager_mutex());
270             localization_backend_manager mgr = localization_backend_manager_global();
271             return mgr;
272         }
global(localization_backend_manager const & in)273         localization_backend_manager localization_backend_manager::global(localization_backend_manager const &in)
274         {
275             boost::unique_lock<boost::mutex> lock(localization_backend_manager_mutex());
276             localization_backend_manager mgr = localization_backend_manager_global();
277             localization_backend_manager_global() = in;
278             return mgr;
279         }
280 
281 
282 
283     } // locale
284 } // boost
285 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
286