message.h
//
// 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)
//
#ifndef BOOSTER_LOCALE_MESSAGE_H_INCLUDED
#define BOOSTER_LOCALE_MESSAGE_H_INCLUDED
#include <booster/config.h>
#ifdef BOOSTER_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <locale>
#include <string>
#include <vector>
#include <set>
#include <memory>
#include <booster/locale/formatting.h>
namespace booster {
namespace locale {
template<typename CharType>
struct base_message_format: public std::locale::facet
{
};
template<typename CharType>
class message_format : public base_message_format<CharType>
{
public:
typedef CharType char_type;
typedef std::basic_string<CharType> string_type;
message_format(size_t refs = 0) :
base_message_format<CharType>(refs)
{
}
virtual char_type const *get(int domain_id,char_type const *context,char_type const *id) const = 0;
virtual char_type const *get(int domain_id,char_type const *context,char_type const *single_id,int n) const = 0;
virtual int domain(std::string const &domain) const = 0;
virtual char_type const *convert(char_type const *msg,string_type &buffer) const = 0;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
protected:
virtual ~message_format()
{
}
};
namespace details {
inline bool is_us_ascii_char(char c)
{
// works for null terminated strings regardless char "signness"
return 0<c && c<0x7F;
}
inline bool is_us_ascii_string(char const *msg)
{
while(*msg) {
if(!is_us_ascii_char(*msg++))
return false;
}
return true;
}
template<typename CharType>
struct string_cast_traits {
static CharType const *cast(CharType const *msg,std::basic_string<CharType> &/*unused*/)
{
return msg;
}
};
template<>
struct string_cast_traits<char> {
static char const *cast(char const *msg,std::string &buffer)
{
if(is_us_ascii_string(msg))
return msg;
buffer.reserve(strlen(msg));
char c;
while((c=*msg++)!=0) {
if(is_us_ascii_char(c))
buffer+=c;
}
return buffer.c_str();
}
};
} // details
template<typename CharType>
class basic_message {
public:
typedef CharType char_type;
typedef std::basic_string<char_type> string_type;
typedef message_format<char_type> facet_type;
basic_message() :
n_(0),
c_id_(0),
c_context_(0),
c_plural_(0)
{
}
explicit basic_message(char_type const *id) :
n_(0),
c_id_(id),
c_context_(0),
c_plural_(0)
{
}
explicit basic_message(char_type const *single,char_type const *plural,int n) :
n_(n),
c_id_(single),
c_context_(0),
c_plural_(plural)
{
}
explicit basic_message(char_type const *context,char_type const *id) :
n_(0),
c_id_(id),
c_context_(context),
c_plural_(0)
{
}
explicit basic_message(char_type const *context,char_type const *single,char_type const *plural,int n) :
n_(n),
c_id_(single),
c_context_(context),
c_plural_(plural)
{
}
explicit basic_message(string_type const &id) :
n_(0),
c_id_(0),
c_context_(0),
c_plural_(0),
id_(id)
{
}
explicit basic_message(string_type const &single,string_type const &plural,int number) :
n_(number),
c_id_(0),
c_context_(0),
c_plural_(0),
id_(single),
plural_(plural)
{
}
explicit basic_message(string_type const &context,string_type const &id) :
n_(0),
c_id_(0),
c_context_(0),
c_plural_(0),
id_(id),
context_(context)
{
}
explicit basic_message(string_type const &context,string_type const &single,string_type const &plural,int number) :
n_(number),
c_id_(0),
c_context_(0),
c_plural_(0),
id_(single),
context_(context),
plural_(plural)
{
}
basic_message(basic_message const &other) :
n_(other.n_),
c_id_(other.c_id_),
c_context_(other.c_context_),
c_plural_(other.c_plural_),
id_(other.id_),
context_(other.context_),
plural_(other.plural_)
{
}
basic_message const &operator=(basic_message const &other)
{
if(this==&other) {
return *this;
}
basic_message tmp(other);
swap(tmp);
return *this;
}
void swap(basic_message &other)
{
std::swap(n_,other.n_);
std::swap(c_id_,other.c_id_);
std::swap(c_context_,other.c_context_);
std::swap(c_plural_,other.c_plural_);
id_.swap(other.id_);
context_.swap(other.context_);
plural_.swap(other.plural_);
}
operator string_type () const
{
return str();
}
string_type str() const
{
std::locale loc;
return str(loc,0);
}
string_type str(std::locale const &locale) const
{
return str(locale,0);
}
string_type str(std::locale const &locale,std::string const &domain_id) const
{
int id=0;
if(std::has_facet<facet_type>(locale))
id=std::use_facet<facet_type>(locale).domain(domain_id);
return str(locale,id);
}
string_type str(std::string const &domain_id) const
{
int id=0;
std::locale loc;
if(std::has_facet<facet_type>(loc))
id=std::use_facet<facet_type>(loc).domain(domain_id);
return str(loc,id);
}
string_type str(std::locale const &loc,int id) const
{
string_type buffer;
char_type const *ptr = write(loc,id,buffer);
if(ptr == buffer.c_str())
return buffer;
else
buffer = ptr;
return buffer;
}
void write(std::basic_ostream<char_type> &out) const
{
std::locale const &loc = out.getloc();
int id = ios_info::get(out).domain_id();
string_type buffer;
out << write(loc,id,buffer);
}
private:
char_type const *plural() const
{
if(c_plural_)
return c_plural_;
if(plural_.empty())
return 0;
return plural_.c_str();
}
char_type const *context() const
{
if(c_context_)
return c_context_;
if(context_.empty())
return 0;
return context_.c_str();
}
char_type const *id() const
{
return c_id_ ? c_id_ : id_.c_str();
}
char_type const *write(std::locale const &loc,int domain_id,string_type &buffer) const
{
char_type const *translated = 0;
static const char_type empty_string[1] = {0};
char_type const *id = this->id();
char_type const *context = this->context();
char_type const *plural = this->plural();
if(*id == 0)
return empty_string;
facet_type const *facet = 0;
if(std::has_facet<facet_type>(loc))
facet = &std::use_facet<facet_type>(loc);
if(facet) {
if(!plural) {
translated = facet->get(domain_id,context,id);
}
else {
translated = facet->get(domain_id,context,id,n_);
}
}
if(!translated) {
char_type const *msg = plural ? ( n_ == 1 ? id : plural) : id;
if(facet) {
translated = facet->convert(msg,buffer);
}
else {
translated = details::string_cast_traits<char_type>::cast(msg,buffer);
}
}
return translated;
}
int n_;
char_type const *c_id_;
char_type const *c_context_;
char_type const *c_plural_;
string_type id_;
string_type context_;
string_type plural_;
};
typedef basic_message<char> message;
typedef basic_message<wchar_t> wmessage;
#ifdef BOOSTER_HAS_CHAR16_T
typedef basic_message<char16_t> u16message;
#endif
#ifdef BOOSTER_HAS_CHAR32_T
typedef basic_message<char32_t> u32message;
#endif
template<typename CharType>
std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_message<CharType> const &msg)
{
msg.write(out);
return out;
}
template<typename CharType>
inline basic_message<CharType> translate(CharType const *msg)
{
return basic_message<CharType>(msg);
}
template<typename CharType>
inline basic_message<CharType> translate( CharType const *context,
CharType const *msg)
{
return basic_message<CharType>(context,msg);
}
template<typename CharType>
inline basic_message<CharType> translate( CharType const *single,
CharType const *plural,
int n)
{
return basic_message<CharType>(single,plural,n);
}
template<typename CharType>
inline basic_message<CharType> translate( CharType const *context,
CharType const *single,
CharType const *plural,
int n)
{
return basic_message<CharType>(context,single,plural,n);
}
template<typename CharType>
inline basic_message<CharType> translate(std::basic_string<CharType> const &msg)
{
return basic_message<CharType>(msg);
}
template<typename CharType>
inline basic_message<CharType> translate( std::basic_string<CharType> const &context,
std::basic_string<CharType> const &msg)
{
return basic_message<CharType>(context,msg);
}
template<typename CharType>
inline basic_message<CharType> translate( std::basic_string<CharType> const &context,
std::basic_string<CharType> const &single,
std::basic_string<CharType> const &plural,
int n)
{
return basic_message<CharType>(context,single,plural,n);
}
template<typename CharType>
inline basic_message<CharType> translate( std::basic_string<CharType> const &single,
std::basic_string<CharType> const &plural,
int n)
{
return basic_message<CharType>(single,plural,n);
}
template<typename CharType>
std::basic_string<CharType> gettext(CharType const *id,
std::locale const &loc=std::locale())
{
return basic_message<CharType>(id).str(loc);
}
template<typename CharType>
std::basic_string<CharType> ngettext( CharType const *s,
CharType const *p,
int n,
std::locale const &loc=std::locale())
{
return basic_message<CharType>(s,p,n).str(loc);
}
template<typename CharType>
std::basic_string<CharType> dgettext( char const *domain,
CharType const *id,
std::locale const &loc=std::locale())
{
return basic_message<CharType>(id).str(loc,domain);
}
template<typename CharType>
std::basic_string<CharType> dngettext( char const *domain,
CharType const *s,
CharType const *p,
int n,
std::locale const &loc=std::locale())
{
return basic_message<CharType>(s,p,n).str(loc,domain);
}
template<typename CharType>
std::basic_string<CharType> pgettext( CharType const *context,
CharType const *id,
std::locale const &loc=std::locale())
{
return basic_message<CharType>(context,id).str(loc);
}
template<typename CharType>
std::basic_string<CharType> npgettext( CharType const *context,
CharType const *s,
CharType const *p,
int n,
std::locale const &loc=std::locale())
{
return basic_message<CharType>(context,s,p,n).str(loc);
}
template<typename CharType>
std::basic_string<CharType> dpgettext( char const *domain,
CharType const *context,
CharType const *id,
std::locale const &loc=std::locale())
{
return basic_message<CharType>(context,id).str(loc,domain);
}
template<typename CharType>
std::basic_string<CharType> dnpgettext(char const *domain,
CharType const *context,
CharType const *s,
CharType const *p,
int n,
std::locale const &loc=std::locale())
{
return basic_message<CharType>(context,s,p,n).str(loc,domain);
}
template<>
struct BOOSTER_API base_message_format<char> : public std::locale::facet
{
base_message_format(size_t refs = 0) : std::locale::facet(refs)
{
}
static std::locale::id id;
};
template<>
struct BOOSTER_API base_message_format<wchar_t> : public std::locale::facet
{
base_message_format(size_t refs = 0) : std::locale::facet(refs)
{
}
static std::locale::id id;
};
#ifdef BOOSTER_HAS_CHAR16_T
template<>
struct BOOSTER_API base_message_format<char16_t> : public std::locale::facet
{
base_message_format(size_t refs = 0) : std::locale::facet(refs)
{
}
static std::locale::id id;
};
#endif
#ifdef BOOSTER_HAS_CHAR32_T
template<>
struct BOOSTER_API base_message_format<char32_t> : public std::locale::facet
{
base_message_format(size_t refs = 0) : std::locale::facet(refs)
{
}
static std::locale::id id;
};
#endif
namespace as {
namespace details {
struct set_domain {
std::string domain_id;
};
template<typename CharType>
std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out, set_domain const &dom)
{
int id = std::use_facet<message_format<CharType> >(out.getloc()).domain(dom.domain_id);
ios_info::get(out).domain_id(id);
return out;
}
} // details
inline
#ifdef BOOSTER_LOCALE_DOXYGEN
unspecified_type
#else
details::set_domain
#endif
domain(std::string const &id)
{
details::set_domain tmp = { id };
return tmp;
}
} // as
} // locale
} // boost
#ifdef BOOSTER_MSVC
#pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
booster::locale::basic_message::swap
void swap(basic_message &other)
Definition: message.h:329
booster::locale::basic_message::basic_message
basic_message(basic_message const &other)
Definition: message.h:302
booster::locale::ios_info::domain_id
void domain_id(int)
booster::locale::dgettext
std::basic_string< CharType > dgettext(char const *domain, CharType const *id, std::locale const &loc=std::locale())
Definition: message.h:637
booster::locale::message_format::message_format
message_format(size_t refs=0)
Definition: message.h:63
booster::locale::basic_message::str
string_type str(std::string const &domain_id) const
Definition: message.h:381
booster::locale::basic_message::basic_message
basic_message()
Definition: message.h:181
booster::locale::basic_message::char_type
CharType char_type
The character this message object is used with.
Definition: message.h:174
booster::locale::basic_message::basic_message
basic_message(string_type const &context, string_type const &single, string_type const &plural, int number)
Definition: message.h:288
booster::locale::as::domain
details::set_domain domain(std::string const &id)
Definition: message.h:789
booster::locale::message_format::domain
virtual int domain(std::string const &domain) const =0
booster::locale::message_format
This facet provides message formatting abilities.
Definition: message.h:47
booster::locale::dpgettext
std::basic_string< CharType > dpgettext(char const *domain, CharType const *context, CharType const *id, std::locale const &loc=std::locale())
Definition: message.h:682
booster::locale::pgettext
std::basic_string< CharType > pgettext(CharType const *context, CharType const *id, std::locale const &loc=std::locale())
Definition: message.h:660
booster::locale::basic_message::facet_type
message_format< char_type > facet_type
The type of the facet the messages are fetched with.
Definition: message.h:176
booster::locale::message_format::char_type
CharType char_type
Definition: message.h:54
booster::locale::translate
basic_message< CharType > translate(CharType const *msg)
Translate a message, msg is not copied.
Definition: message.h:530
booster::locale::basic_message::write
void write(std::basic_ostream< char_type > &out) const
Definition: message.h:410
booster::locale::ios_info::get
static ios_info & get(std::ios_base &ios)
booster::locale::gettext
std::basic_string< CharType > gettext(CharType const *id, std::locale const &loc=std::locale())
Definition: message.h:617
booster::locale::basic_message::str
string_type str(std::locale const &locale, std::string const &domain_id) const
Definition: message.h:370
booster::locale::dngettext
std::basic_string< CharType > dngettext(char const *domain, CharType const *s, CharType const *p, int n, std::locale const &loc=std::locale())
Definition: message.h:648
booster::locale::basic_message::str
string_type str(std::locale const &loc, int id) const
Definition: message.h:394
booster::locale::ngettext
std::basic_string< CharType > ngettext(CharType const *s, CharType const *p, int n, std::locale const &loc=std::locale())
Definition: message.h:626
booster::locale::basic_message::str
string_type str(std::locale const &locale) const
Definition: message.h:362
booster::locale::basic_message::basic_message
basic_message(char_type const *context, char_type const *single, char_type const *plural, int n)
Definition: message.h:234
booster::locale::message_format::convert
virtual char_type const * convert(char_type const *msg, string_type &buffer) const =0
booster::locale::basic_message::operator=
basic_message const & operator=(basic_message const &other)
Definition: message.h:316
booster::locale::basic_message::basic_message
basic_message(string_type const &single, string_type const &plural, int number)
Definition: message.h:260
booster::locale::basic_message::basic_message
basic_message(char_type const *id)
Definition: message.h:193
booster::locale::wmessage
basic_message< wchar_t > wmessage
Definition: message.h:498
booster::locale::dnpgettext
std::basic_string< CharType > dnpgettext(char const *domain, CharType const *context, CharType const *s, CharType const *p, int n, std::locale const &loc=std::locale())
Definition: message.h:693
booster::locale::message
basic_message< char > message
Definition: message.h:494
booster::locale::as::number
std::ios_base & number(std::ios_base &ios)
Definition: formatting.h:292
booster::locale::basic_message::basic_message
basic_message(string_type const &id)
Definition: message.h:246
booster::locale::basic_message
This class represents a message that can be converted to a specific locale message.
Definition: message.h:171
booster::locale::basic_message::basic_message
basic_message(char_type const *context, char_type const *id)
Definition: message.h:220
booster::locale::basic_message::basic_message
basic_message(string_type const &context, string_type const &id)
Definition: message.h:273
booster::locale::basic_message::string_type
std::basic_string< char_type > string_type
The string type this object can be used with.
Definition: message.h:175
booster::locale::message_format::string_type
std::basic_string< CharType > string_type
Definition: message.h:58
booster::locale::npgettext
std::basic_string< CharType > npgettext(CharType const *context, CharType const *s, CharType const *p, int n, std::locale const &loc=std::locale())
Definition: message.h:670
booster::locale::basic_message::str
string_type str() const
Definition: message.h:353
booster::locale::basic_message::basic_message
basic_message(char_type const *single, char_type const *plural, int n)
Definition: message.h:207