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