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 #if defined(__FreeBSD__) 10 #include <xlocale.h> 11 #endif 12 #include <boost/locale/localization_backend.hpp> 13 #include <boost/locale/gnu_gettext.hpp> 14 #include <boost/locale/info.hpp> 15 #include "all_generator.hpp" 16 #include "posix_backend.hpp" 17 18 #include "../util/locale_data.hpp" 19 #include "../util/gregorian.hpp" 20 #include <boost/locale/util.hpp> 21 #include <algorithm> 22 #include <iterator> 23 24 #include <langinfo.h> 25 26 namespace boost { 27 namespace locale { 28 namespace impl_posix { 29 30 class posix_localization_backend : public localization_backend { 31 public: posix_localization_backend()32 posix_localization_backend() : 33 invalid_(true) 34 { 35 } posix_localization_backend(posix_localization_backend const & other)36 posix_localization_backend(posix_localization_backend const &other) : 37 localization_backend(), 38 paths_(other.paths_), 39 domains_(other.domains_), 40 locale_id_(other.locale_id_), 41 invalid_(true) 42 { 43 } clone() const44 virtual posix_localization_backend *clone() const 45 { 46 return new posix_localization_backend(*this); 47 } 48 set_option(std::string const & name,std::string const & value)49 void set_option(std::string const &name,std::string const &value) 50 { 51 invalid_ = true; 52 if(name=="locale") 53 locale_id_ = value; 54 else if(name=="message_path") 55 paths_.push_back(value); 56 else if(name=="message_application") 57 domains_.push_back(value); 58 59 } clear_options()60 void clear_options() 61 { 62 invalid_ = true; 63 locale_id_.clear(); 64 paths_.clear(); 65 domains_.clear(); 66 } 67 free_locale_by_ptr(locale_t * lc)68 static void free_locale_by_ptr(locale_t *lc) 69 { 70 freelocale(*lc); 71 delete lc; 72 } 73 prepare_data()74 void prepare_data() 75 { 76 if(!invalid_) 77 return; 78 invalid_ = false; 79 lc_.reset(); 80 real_id_ = locale_id_; 81 if(real_id_.empty()) 82 real_id_ = util::get_system_locale(); 83 84 locale_t tmp = newlocale(LC_ALL_MASK,real_id_.c_str(),0); 85 86 if(!tmp) { 87 tmp=newlocale(LC_ALL_MASK,"C",0); 88 } 89 if(!tmp) { 90 throw std::runtime_error("newlocale failed"); 91 } 92 93 locale_t *tmp_p = 0; 94 95 try { 96 tmp_p = new locale_t(); 97 } 98 catch(...) { 99 freelocale(tmp); 100 throw; 101 } 102 103 *tmp_p = tmp; 104 lc_ = boost::shared_ptr<locale_t>(tmp_p,free_locale_by_ptr); 105 } 106 install(std::locale const & base,locale_category_type category,character_facet_type type=nochar_facet)107 virtual std::locale install(std::locale const &base, 108 locale_category_type category, 109 character_facet_type type = nochar_facet) 110 { 111 prepare_data(); 112 113 switch(category) { 114 case convert_facet: 115 return create_convert(base,lc_,type); 116 case collation_facet: 117 return create_collate(base,lc_,type); 118 case formatting_facet: 119 return create_formatting(base,lc_,type); 120 case parsing_facet: 121 return create_parsing(base,lc_,type); 122 case codepage_facet: 123 return create_codecvt(base,nl_langinfo_l(CODESET,*lc_),type); 124 case calendar_facet: 125 { 126 util::locale_data inf; 127 inf.parse(real_id_); 128 return util::install_gregorian_calendar(base,inf.country); 129 } 130 case message_facet: 131 { 132 gnu_gettext::messages_info minf; 133 util::locale_data inf; 134 inf.parse(real_id_); 135 minf.language = inf.language; 136 minf.country = inf.country; 137 minf.variant = inf.variant; 138 minf.encoding = inf.encoding; 139 std::copy(domains_.begin(),domains_.end(),std::back_inserter<gnu_gettext::messages_info::domains_type>(minf.domains)); 140 minf.paths = paths_; 141 switch(type) { 142 case char_facet: 143 return std::locale(base,gnu_gettext::create_messages_facet<char>(minf)); 144 case wchar_t_facet: 145 return std::locale(base,gnu_gettext::create_messages_facet<wchar_t>(minf)); 146 #ifdef BOOST_LOCALE_ENABLE_CHAR16_T 147 case char16_t_facet: 148 return std::locale(base,gnu_gettext::create_messages_facet<char16_t>(minf)); 149 #endif 150 #ifdef BOOST_LOCALE_ENABLE_CHAR32_T 151 case char32_t_facet: 152 return std::locale(base,gnu_gettext::create_messages_facet<char32_t>(minf)); 153 #endif 154 default: 155 return base; 156 } 157 } 158 case information_facet: 159 return util::create_info(base,real_id_); 160 default: 161 return base; 162 } 163 } 164 165 private: 166 167 std::vector<std::string> paths_; 168 std::vector<std::string> domains_; 169 std::string locale_id_; 170 std::string real_id_; 171 172 bool invalid_; 173 boost::shared_ptr<locale_t> lc_; 174 }; 175 create_localization_backend()176 localization_backend *create_localization_backend() 177 { 178 return new posix_localization_backend(); 179 } 180 181 } // impl posix 182 } // locale 183 } // boost 184 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 185