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/generator.hpp> 10 #include <boost/locale/encoding.hpp> 11 #include <boost/locale/localization_backend.hpp> 12 #include <map> 13 #include <vector> 14 #include <algorithm> 15 #include <boost/shared_ptr.hpp> 16 #include <boost/thread/mutex.hpp> 17 18 namespace boost { 19 namespace locale { 20 struct generator::data { databoost::locale::generator::data21 data(localization_backend_manager const &mgr) : 22 cats(all_categories), 23 chars(all_characters), 24 caching_enabled(false), 25 use_ansi_encoding(false), 26 backend_manager(mgr) 27 { 28 } 29 30 typedef std::map<std::string,std::locale> cached_type; 31 mutable cached_type cached; 32 mutable boost::mutex cached_lock; 33 34 locale_category_type cats; 35 character_facet_type chars; 36 37 bool caching_enabled; 38 bool use_ansi_encoding; 39 40 std::vector<std::string> paths; 41 std::vector<std::string> domains; 42 43 std::map<std::string,std::vector<std::string> > options; 44 45 localization_backend_manager backend_manager; 46 47 }; 48 generator(localization_backend_manager const & mgr)49 generator::generator(localization_backend_manager const &mgr) : 50 d(new generator::data(mgr)) 51 { 52 } generator()53 generator::generator() : 54 d(new generator::data(localization_backend_manager::global())) 55 { 56 } ~generator()57 generator::~generator() 58 { 59 } 60 categories() const61 locale_category_type generator::categories() const 62 { 63 return d->cats; 64 } categories(locale_category_type t)65 void generator::categories(locale_category_type t) 66 { 67 d->cats=t; 68 } 69 characters(character_facet_type t)70 void generator::characters(character_facet_type t) 71 { 72 d->chars=t; 73 } 74 characters() const75 character_facet_type generator::characters() const 76 { 77 return d->chars; 78 } 79 add_messages_domain(std::string const & domain)80 void generator::add_messages_domain(std::string const &domain) 81 { 82 if(std::find(d->domains.begin(),d->domains.end(),domain) == d->domains.end()) 83 d->domains.push_back(domain); 84 } 85 set_default_messages_domain(std::string const & domain)86 void generator::set_default_messages_domain(std::string const &domain) 87 { 88 std::vector<std::string>::iterator p; 89 if((p=std::find(d->domains.begin(),d->domains.end(),domain)) == d->domains.end()) { 90 d->domains.erase(p); 91 } 92 d->domains.insert(d->domains.begin(),domain); 93 } 94 clear_domains()95 void generator::clear_domains() 96 { 97 d->domains.clear(); 98 } add_messages_path(std::string const & path)99 void generator::add_messages_path(std::string const &path) 100 { 101 d->paths.push_back(path); 102 } clear_paths()103 void generator::clear_paths() 104 { 105 d->paths.clear(); 106 } clear_cache()107 void generator::clear_cache() 108 { 109 d->cached.clear(); 110 } 111 generate(std::string const & id) const112 std::locale generator::generate(std::string const &id) const 113 { 114 std::locale base=std::locale::classic(); 115 116 return generate(base,id); 117 } 118 generate(std::locale const & base,std::string const & id) const119 std::locale generator::generate(std::locale const &base,std::string const &id) const 120 { 121 if(d->caching_enabled) { 122 boost::unique_lock<boost::mutex> guard(d->cached_lock); 123 data::cached_type::const_iterator p = d->cached.find(id); 124 if(p!=d->cached.end()) { 125 return p->second; 126 } 127 } 128 shared_ptr<localization_backend> backend(d->backend_manager.get()); 129 set_all_options(backend,id); 130 131 std::locale result = base; 132 locale_category_type facets = d->cats; 133 character_facet_type chars = d->chars; 134 135 for(locale_category_type facet = per_character_facet_first; facet <= per_character_facet_last && facet!=0; facet <<=1) { 136 if(!(facets & facet)) 137 continue; 138 for(character_facet_type ch = character_first_facet ; ch<=character_last_facet;ch <<=1) { 139 if(!(ch & chars)) 140 continue; 141 result = backend->install(result,facet,ch); 142 } 143 } 144 for(locale_category_type facet = non_character_facet_first; facet <= non_character_facet_last && facet!=0; facet <<=1) { 145 if(!(facets & facet)) 146 continue; 147 result = backend->install(result,facet); 148 } 149 if(d->caching_enabled) { 150 boost::unique_lock<boost::mutex> guard(d->cached_lock); 151 data::cached_type::const_iterator p = d->cached.find(id); 152 if(p==d->cached.end()) { 153 d->cached[id] = result; 154 } 155 } 156 return result; 157 } 158 use_ansi_encoding() const159 bool generator::use_ansi_encoding() const 160 { 161 return d->use_ansi_encoding; 162 } 163 use_ansi_encoding(bool v)164 void generator::use_ansi_encoding(bool v) 165 { 166 d->use_ansi_encoding = v; 167 } 168 locale_cache_enabled() const169 bool generator::locale_cache_enabled() const 170 { 171 return d->caching_enabled; 172 } locale_cache_enabled(bool enabled)173 void generator::locale_cache_enabled(bool enabled) 174 { 175 d->caching_enabled = enabled; 176 } 177 set_all_options(shared_ptr<localization_backend> backend,std::string const & id) const178 void generator::set_all_options(shared_ptr<localization_backend> backend,std::string const &id) const 179 { 180 backend->set_option("locale",id); 181 if(d->use_ansi_encoding) 182 backend->set_option("use_ansi_encoding","true"); 183 for(size_t i=0;i<d->domains.size();i++) 184 backend->set_option("message_application",d->domains[i]); 185 for(size_t i=0;i<d->paths.size();i++) 186 backend->set_option("message_path",d->paths[i]); 187 } 188 189 } // locale 190 } // boost 191 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 192