Boost.Locale
message.hpp
1 //
2 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // https://www.boost.org/LICENSE_1_0.txt
6 
7 #ifndef BOOST_LOCALE_MESSAGE_HPP_INCLUDED
8 #define BOOST_LOCALE_MESSAGE_HPP_INCLUDED
9 
10 #include <boost/locale/formatting.hpp>
11 #include <locale>
12 #include <memory>
13 #include <set>
14 #include <string>
15 
16 #ifdef BOOST_MSVC
17 # pragma warning(push)
18 # pragma warning(disable : 4275 4251 4231 4660)
19 #endif
20 
21 // glibc < 2.3.4 declares those as macros if compiled with optimization turned on
22 #ifdef gettext
23 # undef gettext
24 # undef ngettext
25 # undef dgettext
26 # undef dngettext
27 #endif
28 
29 namespace boost {
30  namespace locale {
38 
40 
41  template<typename CharType>
42  struct base_message_format;
43 
45 
49  template<typename CharType>
50  class BOOST_SYMBOL_VISIBLE message_format : public base_message_format<CharType>
51  {
52  public:
53 
57  typedef CharType char_type;
61  typedef std::basic_string<CharType> string_type;
62 
66  message_format(size_t refs = 0) : base_message_format<CharType>(refs)
67  {
68  }
69 
80  virtual char_type const *get(int domain_id,char_type const *context,char_type const *id) const = 0;
94  virtual char_type const *get(int domain_id,char_type const *context,char_type const *single_id,int n) const = 0;
95 
99  virtual int domain(std::string const &domain) const = 0;
100 
109  virtual char_type const *convert(char_type const *msg,string_type &buffer) const = 0;
110 
111 #if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
112  std::locale::id& __get_id (void) const { return id; }
113 #endif
114  protected:
115  virtual ~message_format() {}
116  };
117 
119 
120  namespace details {
121  inline bool is_us_ascii_char(char c)
122  {
123  // works for null terminated strings regardless char "signness"
124  return 0<c && c<0x7F;
125  }
126  inline bool is_us_ascii_string(char const *msg)
127  {
128  while(*msg) {
129  if(!is_us_ascii_char(*msg++))
130  return false;
131  }
132  return true;
133  }
134 
135  template<typename CharType>
136  struct string_cast_traits {
137  static CharType const *cast(CharType const *msg,std::basic_string<CharType> &/*unused*/)
138  {
139  return msg;
140  }
141  };
142 
143  template<>
144  struct string_cast_traits<char> {
145  static char const *cast(char const *msg,std::string &buffer)
146  {
147  if(is_us_ascii_string(msg))
148  return msg;
149  buffer.reserve(strlen(msg));
150  char c;
151  while((c=*msg++)!=0) {
152  if(is_us_ascii_char(c))
153  buffer+=c;
154  }
155  return buffer.c_str();
156  }
157  };
158  } // details
159 
161 
169  template<typename CharType>
171  public:
172 
173  typedef CharType char_type;
174  typedef std::basic_string<char_type> string_type;
176 
181  n_(0),
182  c_id_(0),
183  c_context_(0),
184  c_plural_(0)
185  {
186  }
187 
192  explicit basic_message(char_type const *id) :
193  n_(0),
194  c_id_(id),
195  c_context_(0),
196  c_plural_(0)
197  {
198  }
199 
206  explicit basic_message(char_type const *single,char_type const *plural,int n) :
207  n_(n),
208  c_id_(single),
209  c_context_(0),
210  c_plural_(plural)
211  {
212  }
213 
219  explicit basic_message(char_type const *context,char_type const *id) :
220  n_(0),
221  c_id_(id),
222  c_context_(context),
223  c_plural_(0)
224  {
225  }
226 
233  explicit basic_message(char_type const *context,char_type const *single,char_type const *plural,int n) :
234  n_(n),
235  c_id_(single),
236  c_context_(context),
237  c_plural_(plural)
238  {
239  }
240 
241 
245  explicit basic_message(string_type const &id) :
246  n_(0),
247  c_id_(0),
248  c_context_(0),
249  c_plural_(0),
250  id_(id)
251  {
252  }
253 
259  explicit basic_message(string_type const &single,string_type const &plural,int number) :
260  n_(number),
261  c_id_(0),
262  c_context_(0),
263  c_plural_(0),
264  id_(single),
265  plural_(plural)
266  {
267  }
268 
272  explicit basic_message(string_type const &context,string_type const &id) :
273  n_(0),
274  c_id_(0),
275  c_context_(0),
276  c_plural_(0),
277  id_(id),
278  context_(context)
279  {
280  }
281 
287  explicit basic_message(string_type const &context,string_type const &single,string_type const &plural,int number) :
288  n_(number),
289  c_id_(0),
290  c_context_(0),
291  c_plural_(0),
292  id_(single),
293  context_(context),
294  plural_(plural)
295  {
296  }
297 
301  basic_message(basic_message const &other) :
302  n_(other.n_),
303  c_id_(other.c_id_),
304  c_context_(other.c_context_),
305  c_plural_(other.c_plural_),
306  id_(other.id_),
307  context_(other.context_),
308  plural_(other.plural_)
309  {
310  }
311 
315  basic_message const &operator=(basic_message const &other)
316  {
317  if(this==&other) {
318  return *this;
319  }
320  basic_message tmp(other);
321  swap(tmp);
322  return *this;
323  }
324 
328  void swap(basic_message &other)
329  {
330  std::swap(n_,other.n_);
331  std::swap(c_id_,other.c_id_);
332  std::swap(c_context_,other.c_context_);
333  std::swap(c_plural_,other.c_plural_);
334 
335  id_.swap(other.id_);
336  context_.swap(other.context_);
337  plural_.swap(other.plural_);
338  }
339 
343 
344  operator string_type () const
345  {
346  return str();
347  }
348 
352  string_type str() const
353  {
354  std::locale loc;
355  return str(loc,0);
356  }
357 
361  string_type str(std::locale const &locale) const
362  {
363  return str(locale,0);
364  }
365 
369  string_type str(std::locale const &locale,std::string const &domain_id) const
370  {
371  int id=0;
372  if(std::has_facet<facet_type>(locale))
373  id=std::use_facet<facet_type>(locale).domain(domain_id);
374  return str(locale,id);
375  }
376 
380  string_type str(std::string const &domain_id) const
381  {
382  int id=0;
383  std::locale loc;
384  if(std::has_facet<facet_type>(loc))
385  id=std::use_facet<facet_type>(loc).domain(domain_id);
386  return str(loc,id);
387  }
388 
389 
393  string_type str(std::locale const &loc,int id) const
394  {
395  string_type buffer;
396  char_type const *ptr = write(loc,id,buffer);
397  if(ptr == buffer.c_str())
398  return buffer;
399  else
400  buffer = ptr;
401  return buffer;
402  }
403 
404 
409  void write(std::basic_ostream<char_type> &out) const
410  {
411  std::locale const &loc = out.getloc();
412  int id = ios_info::get(out).domain_id();
413  string_type buffer;
414  out << write(loc,id,buffer);
415  }
416 
417  private:
418  char_type const *plural() const
419  {
420  if(c_plural_)
421  return c_plural_;
422  if(plural_.empty())
423  return 0;
424  return plural_.c_str();
425  }
426  char_type const *context() const
427  {
428  if(c_context_)
429  return c_context_;
430  if(context_.empty())
431  return 0;
432  return context_.c_str();
433  }
434 
435  char_type const *id() const
436  {
437  return c_id_ ? c_id_ : id_.c_str();
438  }
439 
440  char_type const *write(std::locale const &loc,int domain_id,string_type &buffer) const
441  {
442  char_type const *translated = 0;
443  static const char_type empty_string[1] = {0};
444 
445  char_type const *id = this->id();
446  char_type const *context = this->context();
447  char_type const *plural = this->plural();
448 
449  if(*id == 0)
450  return empty_string;
451 
452  facet_type const *facet = 0;
453  if(std::has_facet<facet_type>(loc))
454  facet = &std::use_facet<facet_type>(loc);
455 
456  if(facet) {
457  if(!plural) {
458  translated = facet->get(domain_id,context,id);
459  }
460  else {
461  translated = facet->get(domain_id,context,id,n_);
462  }
463  }
464 
465  if(!translated) {
466  char_type const *msg = plural ? ( n_ == 1 ? id : plural) : id;
467 
468  if(facet) {
469  translated = facet->convert(msg,buffer);
470  }
471  else {
472  translated = details::string_cast_traits<char_type>::cast(msg,buffer);
473  }
474  }
475  return translated;
476  }
477 
479 
480  int n_;
481  char_type const *c_id_;
482  char_type const *c_context_;
483  char_type const *c_plural_;
484  string_type id_;
485  string_type context_;
486  string_type plural_;
487  };
488 
489 
498  #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
503  #endif
504  #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
509  #endif
510 
514  template<typename CharType>
515  std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_message<CharType> const &msg)
516  {
517  msg.write(out);
518  return out;
519  }
520 
524 
528  template<typename CharType>
529  inline basic_message<CharType> translate(CharType const *msg)
530  {
531  return basic_message<CharType>(msg);
532  }
536  template<typename CharType>
537  inline basic_message<CharType> translate( CharType const *context,
538  CharType const *msg)
539  {
540  return basic_message<CharType>(context,msg);
541  }
545  template<typename CharType>
546  inline basic_message<CharType> translate( CharType const *single,
547  CharType const *plural,
548  int n)
549  {
550  return basic_message<CharType>(single,plural,n);
551  }
555  template<typename CharType>
556  inline basic_message<CharType> translate( CharType const *context,
557  CharType const *single,
558  CharType const *plural,
559  int n)
560  {
561  return basic_message<CharType>(context,single,plural,n);
562  }
563 
567  template<typename CharType>
568  inline basic_message<CharType> translate(std::basic_string<CharType> const &msg)
569  {
570  return basic_message<CharType>(msg);
571  }
572 
576  template<typename CharType>
577  inline basic_message<CharType> translate( std::basic_string<CharType> const &context,
578  std::basic_string<CharType> const &msg)
579  {
580  return basic_message<CharType>(context,msg);
581  }
585  template<typename CharType>
586  inline basic_message<CharType> translate( std::basic_string<CharType> const &context,
587  std::basic_string<CharType> const &single,
588  std::basic_string<CharType> const &plural,
589  int n)
590  {
591  return basic_message<CharType>(context,single,plural,n);
592  }
593 
597 
598  template<typename CharType>
599  inline basic_message<CharType> translate( std::basic_string<CharType> const &single,
600  std::basic_string<CharType> const &plural,
601  int n)
602  {
603  return basic_message<CharType>(single,plural,n);
604  }
605 
607 
611 
615  template<typename CharType>
616  std::basic_string<CharType> gettext(CharType const *id,
617  std::locale const &loc=std::locale())
618  {
619  return basic_message<CharType>(id).str(loc);
620  }
624  template<typename CharType>
625  std::basic_string<CharType> ngettext( CharType const *s,
626  CharType const *p,
627  int n,
628  std::locale const &loc=std::locale())
629  {
630  return basic_message<CharType>(s,p,n).str(loc);
631  }
635  template<typename CharType>
636  std::basic_string<CharType> dgettext( char const *domain,
637  CharType const *id,
638  std::locale const &loc=std::locale())
639  {
640  return basic_message<CharType>(id).str(loc,domain);
641  }
642 
646  template<typename CharType>
647  std::basic_string<CharType> dngettext( char const *domain,
648  CharType const *s,
649  CharType const *p,
650  int n,
651  std::locale const &loc=std::locale())
652  {
653  return basic_message<CharType>(s,p,n).str(loc,domain);
654  }
658  template<typename CharType>
659  std::basic_string<CharType> pgettext( CharType const *context,
660  CharType const *id,
661  std::locale const &loc=std::locale())
662  {
663  return basic_message<CharType>(context,id).str(loc);
664  }
668  template<typename CharType>
669  std::basic_string<CharType> npgettext( CharType const *context,
670  CharType const *s,
671  CharType const *p,
672  int n,
673  std::locale const &loc=std::locale())
674  {
675  return basic_message<CharType>(context,s,p,n).str(loc);
676  }
680  template<typename CharType>
681  std::basic_string<CharType> dpgettext( char const *domain,
682  CharType const *context,
683  CharType const *id,
684  std::locale const &loc=std::locale())
685  {
686  return basic_message<CharType>(context,id).str(loc,domain);
687  }
691  template<typename CharType>
692  std::basic_string<CharType> dnpgettext(char const *domain,
693  CharType const *context,
694  CharType const *s,
695  CharType const *p,
696  int n,
697  std::locale const &loc=std::locale())
698  {
699  return basic_message<CharType>(context,s,p,n).str(loc,domain);
700  }
701 
705 
706  template<>
707  struct BOOST_LOCALE_DECL base_message_format<char> : public std::locale::facet
708  {
709  base_message_format(size_t refs = 0) : std::locale::facet(refs)
710  {
711  }
712  static std::locale::id id;
713  };
714 
715  template<>
716  struct BOOST_LOCALE_DECL base_message_format<wchar_t> : public std::locale::facet
717  {
718  base_message_format(size_t refs = 0) : std::locale::facet(refs)
719  {
720  }
721  static std::locale::id id;
722  };
723 
724  #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
725 
726  template<>
727  struct BOOST_LOCALE_DECL base_message_format<char16_t> : public std::locale::facet
728  {
729  base_message_format(size_t refs = 0) : std::locale::facet(refs)
730  {
731  }
732  static std::locale::id id;
733  };
734 
735  #endif
736 
737  #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
738 
739  template<>
740  struct BOOST_LOCALE_DECL base_message_format<char32_t> : public std::locale::facet
741  {
742  base_message_format(size_t refs = 0) : std::locale::facet(refs)
743  {
744  }
745  static std::locale::id id;
746  };
747 
748  #endif
749 
751 
755 
756  namespace as {
758  namespace details {
759  struct set_domain {
760  std::string domain_id;
761  };
762  template<typename CharType>
763  std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out, set_domain const &dom)
764  {
765  int id = std::use_facet<message_format<CharType> >(out.getloc()).domain(dom.domain_id);
766  ios_info::get(out).domain_id(id);
767  return out;
768  }
769  } // details
771 
776 
782  inline
783  #ifdef BOOST_LOCALE_DOXYGEN
784  unspecified_type
785  #else
786  details::set_domain
787  #endif
788  domain(std::string const &id)
789  {
790  details::set_domain tmp = { id };
791  return tmp;
792  }
794  } // as
795  } // locale
796 } // boost
797 
798 #ifdef BOOST_MSVC
799 #pragma warning(pop)
800 #endif
801 
802 
803 #endif
804 
805 
std::basic_string< CharType > ngettext(CharType const *s, CharType const *p, int n, std::locale const &loc=std::locale())
Definition: message.hpp:625
message_format(size_t refs=0)
Definition: message.hpp:66
basic_message(char_type const *context, char_type const *id)
Definition: message.hpp:219
string_type str(std::string const &domain_id) const
Definition: message.hpp:380
basic_message(string_type const &id)
Definition: message.hpp:245
CharType char_type
The character this message object is used with.
Definition: message.hpp:173
basic_message(string_type const &context, string_type const &id)
Definition: message.hpp:272
std::basic_string< char_type > string_type
The string type this object can be used with.
Definition: message.hpp:174
void swap(basic_message &other)
Definition: message.hpp:328
basic_message(char_type const *id)
Definition: message.hpp:192
basic_message< wchar_t > wmessage
Definition: message.hpp:497
This class represents a message that can be converted to a specific locale message.
Definition: message.hpp:170
std::basic_string< CharType > npgettext(CharType const *context, CharType const *s, CharType const *p, int n, std::locale const &loc=std::locale())
Definition: message.hpp:669
basic_message< char32_t > u32message
Definition: message.hpp:508
string_type str() const
Definition: message.hpp:352
basic_message const & operator=(basic_message const &other)
Definition: message.hpp:315
This facet provides message formatting abilities.
Definition: message.hpp:50
string_type str(std::locale const &loc, int id) const
Definition: message.hpp:393
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.hpp:692
std::ios_base & number(std::ios_base &ios)
Definition: formatting.hpp:292
CharType char_type
Definition: message.hpp:57
basic_message< char > message
Definition: message.hpp:493
basic_message(string_type const &single, string_type const &plural, int number)
Definition: message.hpp:259
static ios_info & get(std::ios_base &ios)
basic_message()
Definition: message.hpp:180
std::basic_string< CharType > dgettext(char const *domain, CharType const *id, std::locale const &loc=std::locale())
Definition: message.hpp:636
basic_message< CharType > translate(CharType const *msg)
Translate a message, msg is not copied.
Definition: message.hpp:529
unspecified_type domain(std::string const &id)
Definition: message.hpp:788
std::basic_string< CharType > pgettext(CharType const *context, CharType const *id, std::locale const &loc=std::locale())
Definition: message.hpp:659
basic_message(string_type const &context, string_type const &single, string_type const &plural, int number)
Definition: message.hpp:287
std::basic_string< CharType > dpgettext(char const *domain, CharType const *context, CharType const *id, std::locale const &loc=std::locale())
Definition: message.hpp:681
string_type str(std::locale const &locale, std::string const &domain_id) const
Definition: message.hpp:369
void write(std::basic_ostream< char_type > &out) const
Definition: message.hpp:409
basic_message< char16_t > u16message
Definition: message.hpp:502
std::basic_string< CharType > gettext(CharType const *id, std::locale const &loc=std::locale())
Definition: message.hpp:616
basic_message(char_type const *single, char_type const *plural, int n)
Definition: message.hpp:206
std::basic_ostream< CharType > & operator<<(std::basic_ostream< CharType > &out, date_time const &t)
Definition: date_time.hpp:871
basic_message(char_type const *context, char_type const *single, char_type const *plural, int n)
Definition: message.hpp:233
std::basic_string< CharType > string_type
Definition: message.hpp:61
string_type str(std::locale const &locale) const
Definition: message.hpp:361
message_format< char_type > facet_type
The type of the facet the messages are fetched with.
Definition: message.hpp:175
std::basic_string< CharType > dngettext(char const *domain, CharType const *s, CharType const *p, int n, std::locale const &loc=std::locale())
Definition: message.hpp:647
Domain code - for message formatting.
Definition: formatting.hpp:86
basic_message(basic_message const &other)
Definition: message.hpp:301