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