text: //
  //  Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
  //
  //  Distributed under the Boost Software License, Version 1.0. (See
  //  accompanying file LICENSE_1_0.txt or copy at
  //  http://www.boost.org/LICENSE_1_0.txt)
  //
  #define BOOST_LOCALE_SOURCE
  #include <boost/locale/generator.hpp>
  #include <boost/locale/encoding.hpp>
  #include <boost/locale/localization_backend.hpp>
  #include <map>
  #include <vector>
  #include <algorithm>
  #include <boost/shared_ptr.hpp>
  #include <boost/thread/mutex.hpp>
  
  namespace boost {
      namespace locale {
          struct generator::data {
              data(localization_backend_manager const &mgr)  :
                  cats(all_categories),
                  chars(all_characters),
                  caching_enabled(false),
                  use_ansi_encoding(false),
                  backend_manager(mgr)
              {
              }
  
              typedef std::map<std::string,std::locale> cached_type;
              mutable cached_type cached;
              mutable boost::mutex cached_lock;
  
              locale_category_type cats;
              character_facet_type chars;
  
              bool caching_enabled;
              bool use_ansi_encoding;
  
              std::vector<std::string> paths;
              std::vector<std::string> domains;
  
              std::map<std::string,std::vector<std::string> > options;
  
              localization_backend_manager backend_manager;
  
          };
  
          generator::generator(localization_backend_manager const &mgr) :
              d(new generator::data(mgr))
          {
          }
          generator::generator() :
              d(new generator::data(localization_backend_manager::global()))
          {
          }
          generator::~generator()
          {
          }
  
          locale_category_type generator::categories() const
          {
              return d->cats;
          }
          void generator::categories(locale_category_type t)
          {
              d->cats=t;
          }
  
          void generator::characters(character_facet_type t)
          {
              d->chars=t;
          }
          
          character_facet_type generator::characters() const
          {
              return d->chars;
          }
  
          void generator::add_messages_domain(std::string const &domain)
          {
              if(std::find(d->domains.begin(),d->domains.end(),domain) == d->domains.end())
                  d->domains.push_back(domain);
          }
          
          void generator::set_default_messages_domain(std::string const &domain)
          {
              std::vector<std::string>::iterator p;
              if((p=std::find(d->domains.begin(),d->domains.end(),domain)) == d->domains.end()) {
                  d->domains.erase(p);
              }
              d->domains.insert(d->domains.begin(),domain);
          }
  
          void generator::clear_domains()
          {
              d->domains.clear();
          }
          void generator::add_messages_path(std::string const &path)
          {
              d->paths.push_back(path);
          }
          void generator::clear_paths()
          {
              d->paths.clear();
          }
          void generator::clear_cache()
          {
              d->cached.clear();
          }
  
          std::locale generator::generate(std::string const &id) const
          {
              std::locale base=std::locale::classic();
  
              return generate(base,id);
          }
  
          std::locale generator::generate(std::locale const &base,std::string const &id) const
          {
              if(d->caching_enabled) {
                  boost::unique_lock<boost::mutex> guard(d->cached_lock);
                  data::cached_type::const_iterator p = d->cached.find(id);
                  if(p!=d->cached.end()) {
                      return p->second;
                  }
              }
              shared_ptr<localization_backend> backend(d->backend_manager.get());
              set_all_options(backend,id);
  
              std::locale result = base;
              locale_category_type facets = d->cats;
              character_facet_type chars = d->chars;
  
              for(locale_category_type facet = per_character_facet_first; facet <= per_character_facet_last && facet!=0; facet <<=1) {
                  if(!(facets & facet))
                      continue;
                  for(character_facet_type ch = character_first_facet ; ch<=character_last_facet;ch <<=1) {
                      if(!(ch & chars))
                          continue;
                      result = backend->install(result,facet,ch);
                  }
              }
              for(locale_category_type facet = non_character_facet_first; facet <= non_character_facet_last && facet!=0; facet <<=1) {
                  if(!(facets & facet))
                      continue;
                  result = backend->install(result,facet);
              }
              if(d->caching_enabled) {
                  boost::unique_lock<boost::mutex> guard(d->cached_lock);
                  data::cached_type::const_iterator p = d->cached.find(id);
                  if(p==d->cached.end()) {
                      d->cached[id] = result;
                  }
              }
              return result;
          }
  
          bool generator::use_ansi_encoding() const
          {
              return d->use_ansi_encoding;
          }
  
          void generator::use_ansi_encoding(bool v)
          {
              d->use_ansi_encoding = v;
          }
  
          bool generator::locale_cache_enabled() const
          {
              return d->caching_enabled;
          }
          void generator::locale_cache_enabled(bool enabled) 
          {
              d->caching_enabled = enabled;
          }
          
          void generator::set_all_options(shared_ptr<localization_backend> backend,std::string const &id) const
          {
              backend->set_option("locale",id);
              if(d->use_ansi_encoding)
                  backend->set_option("use_ansi_encoding","true");
              for(size_t i=0;i<d->domains.size();i++)
                  backend->set_option("message_application",d->domains[i]);
              for(size_t i=0;i<d->paths.size();i++)
                  backend->set_option("message_path",d->paths[i]);
          }
          
      } // locale
  } // boost
  // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 
  