blob: a642fa00972568a2c7204783ef46819ec8f34203 [file] [log] [blame]
//
// 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/localization_backend.hpp>
#include <boost/locale/gnu_gettext.hpp>
#include <boost/locale/info.hpp>
#include "all_generator.hpp"
#include "posix_backend.hpp"
#include "../util/locale_data.hpp"
#include "../util/gregorian.hpp"
#include <boost/locale/util.hpp>
#include <algorithm>
#include <iterator>
#include <langinfo.h>
namespace boost {
namespace locale {
namespace impl_posix {
class posix_localization_backend : public localization_backend {
public:
posix_localization_backend() :
invalid_(true)
{
}
posix_localization_backend(posix_localization_backend const &other) :
localization_backend(),
paths_(other.paths_),
domains_(other.domains_),
locale_id_(other.locale_id_),
invalid_(true)
{
}
virtual posix_localization_backend *clone() const
{
return new posix_localization_backend(*this);
}
void set_option(std::string const &name,std::string const &value)
{
invalid_ = true;
if(name=="locale")
locale_id_ = value;
else if(name=="message_path")
paths_.push_back(value);
else if(name=="message_application")
domains_.push_back(value);
}
void clear_options()
{
invalid_ = true;
locale_id_.clear();
paths_.clear();
domains_.clear();
}
static void free_locale_by_ptr(locale_t *lc)
{
freelocale(*lc);
delete lc;
}
void prepare_data()
{
if(!invalid_)
return;
invalid_ = false;
lc_.reset();
real_id_ = locale_id_;
if(real_id_.empty())
real_id_ = util::get_system_locale();
locale_t tmp = newlocale(LC_ALL_MASK,real_id_.c_str(),0);
if(!tmp) {
tmp=newlocale(LC_ALL_MASK,"C",0);
}
if(!tmp) {
throw std::runtime_error("newlocale failed");
}
locale_t *tmp_p = 0;
try {
tmp_p = new locale_t();
}
catch(...) {
freelocale(tmp);
throw;
}
*tmp_p = tmp;
lc_ = boost::shared_ptr<locale_t>(tmp_p,free_locale_by_ptr);
}
virtual std::locale install(std::locale const &base,
locale_category_type category,
character_facet_type type = nochar_facet)
{
prepare_data();
switch(category) {
case convert_facet:
return create_convert(base,lc_,type);
case collation_facet:
return create_collate(base,lc_,type);
case formatting_facet:
return create_formatting(base,lc_,type);
case parsing_facet:
return create_parsing(base,lc_,type);
case codepage_facet:
return create_codecvt(base,nl_langinfo_l(CODESET,*lc_),type);
case calendar_facet:
{
util::locale_data inf;
inf.parse(real_id_);
return util::install_gregorian_calendar(base,inf.country);
}
case message_facet:
{
gnu_gettext::messages_info minf;
util::locale_data inf;
inf.parse(real_id_);
minf.language = inf.language;
minf.country = inf.country;
minf.variant = inf.variant;
minf.encoding = inf.encoding;
std::copy(domains_.begin(),domains_.end(),std::back_inserter<gnu_gettext::messages_info::domains_type>(minf.domains));
minf.paths = paths_;
switch(type) {
case char_facet:
return std::locale(base,gnu_gettext::create_messages_facet<char>(minf));
case wchar_t_facet:
return std::locale(base,gnu_gettext::create_messages_facet<wchar_t>(minf));
#ifdef BOOST_HAS_CHAR16_T
case char16_t_facet:
return std::locale(base,gnu_gettext::create_messages_facet<char16_t>(minf));
#endif
#ifdef BOOST_HAS_CHAR32_T
case char32_t_facet:
return std::locale(base,gnu_gettext::create_messages_facet<char32_t>(minf));
#endif
default:
return base;
}
}
case information_facet:
return util::create_info(base,real_id_);
default:
return base;
}
}
private:
std::vector<std::string> paths_;
std::vector<std::string> domains_;
std::string locale_id_;
std::string real_id_;
bool invalid_;
boost::shared_ptr<locale_t> lc_;
};
localization_backend *create_localization_backend()
{
return new posix_localization_backend();
}
} // impl posix
} // locale
} // boost
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4