Boost.Locale
message.hpp
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 #ifndef BOOST_LOCALE_MESSAGE_HPP_INCLUDED
9 #define BOOST_LOCALE_MESSAGE_HPP_INCLUDED
10 
11 #include <boost/locale/config.hpp>
12 #ifdef BOOST_MSVC
13 # pragma warning(push)
14 # pragma warning(disable : 4275 4251 4231 4660)
15 #endif
16 #include <locale>
17 #include <string>
18 #include <vector>
19 #include <set>
20 #include <memory>
21 #include <boost/locale/formatting.hpp>
22 
23 
24 namespace boost {
25  namespace locale {
33 
35 
36  template<typename CharType>
37  struct base_message_format: public std::locale::facet
38  {
39  };
40 
42 
46  template<typename CharType>
47  class message_format : public base_message_format<CharType>
48  {
49  public:
50 
54  typedef CharType char_type;
58  typedef std::basic_string<CharType> string_type;
59 
63  message_format(size_t refs = 0) :
64  base_message_format<CharType>(refs)
65  {
66  }
67 
78  virtual char_type const *get(int domain_id,char_type const *context,char_type const *id) const = 0;
92  virtual char_type const *get(int domain_id,char_type const *context,char_type const *single_id,int n) const = 0;
93 
97  virtual int domain(std::string const &domain) const = 0;
98 
107  virtual char_type const *convert(char_type const *msg,string_type &buffer) const = 0;
108 
109 #if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
110  std::locale::id& __get_id (void) const { return id; }
111 #endif
112  protected:
113  virtual ~message_format()
114  {
115  }
116 
117  };
118 
120 
121  namespace details {
122  inline bool is_us_ascii_char(char c)
123  {
124  // works for null terminated strings regardless char "signness"
125  return 0<c && c<0x7F;
126  }
127  inline bool is_us_ascii_string(char const *msg)
128  {
129  while(*msg) {
130  if(!is_us_ascii_char(*msg++))
131  return false;
132  }
133  return true;
134  }
135 
136  template<typename CharType>
137  struct string_cast_traits {
138  static CharType const *cast(CharType const *msg,std::basic_string<CharType> &/*unused*/)
139  {
140  return msg;
141  }
142  };
143 
144  template<>
145  struct string_cast_traits<char> {
146  static char const *cast(char const *msg,std::string &buffer)
147  {
148  if(is_us_ascii_string(msg))
149  return msg;
150  buffer.reserve(strlen(msg));
151  char c;
152  while((c=*msg++)!=0) {
153  if(is_us_ascii_char(c))
154  buffer+=c;
155  }
156  return buffer.c_str();
157  }
158  };
159  } // details
160 
162 
170  template<typename CharType>
172  public:
173 
174  typedef CharType char_type;
175  typedef std::basic_string<char_type> string_type;
177 
182  n_(0),
183  c_id_(0),
184  c_context_(0),
185  c_plural_(0)
186  {
187  }
188 
193  explicit basic_message(char_type const *id) :
194  n_(0),
195  c_id_(id),
196  c_context_(0),
197  c_plural_(0)
198  {
199  }
200 
207  explicit basic_message(char_type const *single,char_type const *plural,int n) :
208  n_(n),
209  c_id_(single),
210  c_context_(0),
211  c_plural_(plural)
212  {
213  }
214 
220  explicit basic_message(char_type const *context,char_type const *id) :
221  n_(0),
222  c_id_(id),
223  c_context_(context),
224  c_plural_(0)
225  {
226  }
227 
234  explicit basic_message(char_type const *context,char_type const *single,char_type const *plural,int n) :
235  n_(n),
236  c_id_(single),
237  c_context_(context),
238  c_plural_(plural)
239  {
240  }
241 
242 
246  explicit basic_message(string_type const &id) :
247  n_(0),
248  c_id_(0),
249  c_context_(0),
250  c_plural_(0),
251  id_(id)
252  {
253  }
254 
260  explicit basic_message(string_type const &single,string_type const &plural,int number) :
261  n_(number),
262  c_id_(0),
263  c_context_(0),
264  c_plural_(0),
265  id_(single),
266  plural_(plural)
267  {
268  }
269 
273  explicit basic_message(string_type const &context,string_type const &id) :
274  n_(0),
275  c_id_(0),
276  c_context_(0),
277  c_plural_(0),
278  id_(id),
279  context_(context)
280  {
281  }
282 
288  explicit basic_message(string_type const &context,string_type const &single,string_type const &plural,int number) :
289  n_(number),
290  c_id_(0),
291  c_context_(0),
292  c_plural_(0),
293  id_(single),
294  context_(context),
295  plural_(plural)
296  {
297  }
298 
302  basic_message(basic_message const &other) :
303  n_(other.n_),
304  c_id_(other.c_id_),
305  c_context_(other.c_context_),
306  c_plural_(other.c_plural_),
307  id_(other.id_),
308  context_(other.context_),
309  plural_(other.plural_)
310  {
311  }
312 
316  basic_message const &operator=(basic_message const &other)
317  {
318  if(this==&other) {
319  return *this;
320  }
321  basic_message tmp(other);
322  swap(tmp);
323  return *this;
324  }
325 
329  void swap(basic_message &other)
330  {
331  std::swap(n_,other.n_);
332  std::swap(c_id_,other.c_id_);
333  std::swap(c_context_,other.c_context_);
334  std::swap(c_plural_,other.c_plural_);
335 
336  id_.swap(other.id_);
337  context_.swap(other.context_);
338  plural_.swap(other.plural_);
339  }
340 
344 
345  operator string_type () const
346  {
347  return str();
348  }
349 
353  string_type str() const
354  {
355  std::locale loc;
356  return str(loc,0);
357  }
358 
362  string_type str(std::locale const &locale) const
363  {
364  return str(locale,0);
365  }
366 
370  string_type str(std::locale const &locale,std::string const &domain_id) const
371  {
372  int id=0;
373  if(std::has_facet<facet_type>(locale))
374  id=std::use_facet<facet_type>(locale).domain(domain_id);
375  return str(locale,id);
376  }
377 
381  string_type str(std::string const &domain_id) const
382  {
383  int id=0;
384  std::locale loc;
385  if(std::has_facet<facet_type>(loc))
386  id=std::use_facet<facet_type>(loc).domain(domain_id);
387  return str(loc,id);
388  }
389 
390 
394  string_type str(std::locale const &loc,int id) const
395  {
396  string_type buffer;
397  char_type const *ptr = write(loc,id,buffer);
398  if(ptr == buffer.c_str())
399  return buffer;
400  else
401  buffer = ptr;
402  return buffer;
403  }
404 
405 
410  void write(std::basic_ostream<char_type> &out) const
411  {
412  std::locale const &loc = out.getloc();
413  int id = ios_info::get(out).domain_id();
414  string_type buffer;
415  out << write(loc,id,buffer);
416  }
417 
418  private:
419  char_type const *plural() const
420  {
421  if(c_plural_)
422  return c_plural_;
423  if(plural_.empty())
424  return 0;
425  return plural_.c_str();
426  }
427  char_type const *context() const
428  {
429  if(c_context_)
430  return c_context_;
431  if(context_.empty())
432  return 0;
433  return context_.c_str();
434  }
435 
436  char_type const *id() const
437  {
438  return c_id_ ? c_id_ : id_.c_str();
439  }
440 
441  char_type const *write(std::locale const &loc,int domain_id,string_type &buffer) const
442  {
443  char_type const *translated = 0;
444  static const char_type empty_string[1] = {0};
445 
446  char_type const *id = this->id();
447  char_type const *context = this->context();
448  char_type const *plural = this->plural();
449 
450  if(*id == 0)
451  return empty_string;
452 
453  facet_type const *facet = 0;
454  if(std::has_facet<facet_type>(loc))
455  facet = &std::use_facet<facet_type>(loc);
456 
457  if(facet) {
458  if(!plural) {
459  translated = facet->get(domain_id,context,id);
460  }
461  else {
462  translated = facet->get(domain_id,context,id,n_);
463  }
464  }
465 
466  if(!translated) {
467  char_type const *msg = plural ? ( n_ == 1 ? id : plural) : id;
468 
469  if(facet) {
470  translated = facet->convert(msg,buffer);
471  }
472  else {
473  translated = details::string_cast_traits<char_type>::cast(msg,buffer);
474  }
475  }
476  return translated;
477  }
478 
480 
481  int n_;
482  char_type const *c_id_;
483  char_type const *c_context_;
484  char_type const *c_plural_;
485  string_type id_;
486  string_type context_;
487  string_type plural_;
488  };
489 
490 
499  #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
504  #endif
505  #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
510  #endif
511 
515  template<typename CharType>
516  std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_message<CharType> const &msg)
517  {
518  msg.write(out);
519  return out;
520  }
521 
525 
529  template<typename CharType>
530  inline basic_message<CharType> translate(CharType const *msg)
531  {
532  return basic_message<CharType>(msg);
533  }
537  template<typename CharType>
538  inline basic_message<CharType> translate( CharType const *context,
539  CharType const *msg)
540  {
541  return basic_message<CharType>(context,msg);
542  }
546  template<typename CharType>
547  inline basic_message<CharType> translate( CharType const *single,
548  CharType const *plural,
549  int n)
550  {
551  return basic_message<CharType>(single,plural,n);
552  }
556  template<typename CharType>
557  inline basic_message<CharType> translate( CharType const *context,
558  CharType const *single,
559  CharType const *plural,
560  int n)
561  {
562  return basic_message<CharType>(context,single,plural,n);
563  }
564 
568  template<typename CharType>
569  inline basic_message<CharType> translate(std::basic_string<CharType> const &msg)
570  {
571  return basic_message<CharType>(msg);
572  }
573 
577  template<typename CharType>
578  inline basic_message<CharType> translate( std::basic_string<CharType> const &context,
579  std::basic_string<CharType> const &msg)
580  {
581  return basic_message<CharType>(context,msg);
582  }
586  template<typename CharType>
587  inline basic_message<CharType> translate( std::basic_string<CharType> const &context,
588  std::basic_string<CharType> const &single,
589  std::basic_string<CharType> const &plural,
590  int n)
591  {
592  return basic_message<CharType>(context,single,plural,n);
593  }
594 
598 
599  template<typename CharType>
600  inline basic_message<CharType> translate( std::basic_string<CharType> const &single,
601  std::basic_string<CharType> const &plural,
602  int n)
603  {
604  return basic_message<CharType>(single,plural,n);
605  }
606 
608 
612 
616  template<typename CharType>
617  std::basic_string<CharType> gettext(CharType const *id,
618  std::locale const &loc=std::locale())
619  {
620  return basic_message<CharType>(id).str(loc);
621  }
625  template<typename CharType>
626  std::basic_string<CharType> ngettext( CharType const *s,
627  CharType const *p,
628  int n,
629  std::locale const &loc=std::locale())
630  {
631  return basic_message<CharType>(s,p,n).str(loc);
632  }
636  template<typename CharType>
637  std::basic_string<CharType> dgettext( char const *domain,
638  CharType const *id,
639  std::locale const &loc=std::locale())
640  {
641  return basic_message<CharType>(id).str(loc,domain);
642  }
643 
647  template<typename CharType>
648  std::basic_string<CharType> dngettext( char const *domain,
649  CharType const *s,
650  CharType const *p,
651  int n,
652  std::locale const &loc=std::locale())
653  {
654  return basic_message<CharType>(s,p,n).str(loc,domain);
655  }
659  template<typename CharType>
660  std::basic_string<CharType> pgettext( CharType const *context,
661  CharType const *id,
662  std::locale const &loc=std::locale())
663  {
664  return basic_message<CharType>(context,id).str(loc);
665  }
669  template<typename CharType>
670  std::basic_string<CharType> npgettext( CharType const *context,
671  CharType const *s,
672  CharType const *p,
673  int n,
674  std::locale const &loc=std::locale())
675  {
676  return basic_message<CharType>(context,s,p,n).str(loc);
677  }
681  template<typename CharType>
682  std::basic_string<CharType> dpgettext( char const *domain,
683  CharType const *context,
684  CharType const *id,
685  std::locale const &loc=std::locale())
686  {
687  return basic_message<CharType>(context,id).str(loc,domain);
688  }
692  template<typename CharType>
693  std::basic_string<CharType> dnpgettext(char const *domain,
694  CharType const *context,
695  CharType const *s,
696  CharType const *p,
697  int n,
698  std::locale const &loc=std::locale())
699  {
700  return basic_message<CharType>(context,s,p,n).str(loc,domain);
701  }
702 
706 
707  template<>
708  struct BOOST_LOCALE_DECL base_message_format<char> : public std::locale::facet
709  {
710  base_message_format(size_t refs = 0) : std::locale::facet(refs)
711  {
712  }
713  static std::locale::id id;
714  };
715 
716  template<>
717  struct BOOST_LOCALE_DECL base_message_format<wchar_t> : public std::locale::facet
718  {
719  base_message_format(size_t refs = 0) : std::locale::facet(refs)
720  {
721  }
722  static std::locale::id id;
723  };
724 
725  #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
726 
727  template<>
728  struct BOOST_LOCALE_DECL base_message_format<char16_t> : public std::locale::facet
729  {
730  base_message_format(size_t refs = 0) : std::locale::facet(refs)
731  {
732  }
733  static std::locale::id id;
734  };
735 
736  #endif
737 
738  #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
739 
740  template<>
741  struct BOOST_LOCALE_DECL base_message_format<char32_t> : public std::locale::facet
742  {
743  base_message_format(size_t refs = 0) : std::locale::facet(refs)
744  {
745  }
746  static std::locale::id id;
747  };
748 
749  #endif
750 
752 
756 
757  namespace as {
759  namespace details {
760  struct set_domain {
761  std::string domain_id;
762  };
763  template<typename CharType>
764  std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out, set_domain const &dom)
765  {
766  int id = std::use_facet<message_format<CharType> >(out.getloc()).domain(dom.domain_id);
767  ios_info::get(out).domain_id(id);
768  return out;
769  }
770  } // details
772 
777 
783  inline
784  #ifdef BOOST_LOCALE_DOXYGEN
785  unspecified_type
786  #else
787  details::set_domain
788  #endif
789  domain(std::string const &id)
790  {
791  details::set_domain tmp = { id };
792  return tmp;
793  }
795  } // as
796  } // locale
797 } // boost
798 
799 #ifdef BOOST_MSVC
800 #pragma warning(pop)
801 #endif
802 
803 
804 #endif
805 
806 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
807 
std::basic_string< CharType > ngettext(CharType const *s, CharType const *p, int n, std::locale const &loc=std::locale())
Definition: message.hpp:626
message_format(size_t refs=0)
Definition: message.hpp:63
basic_message(char_type const *context, char_type const *id)
Definition: message.hpp:220
void write(std::basic_ostream< char_type > &out) const
Definition: message.hpp:410
basic_message(string_type const &id)
Definition: message.hpp:246
CharType char_type
The character this message object is used with.
Definition: message.hpp:174
basic_message(string_type const &context, string_type const &id)
Definition: message.hpp:273
std::basic_string< char_type > string_type
The string type this object can be used with.
Definition: message.hpp:175
void swap(basic_message &other)
Definition: message.hpp:329
string_type str(std::string const &domain_id) const
Definition: message.hpp:381
basic_message(char_type const *id)
Definition: message.hpp:193
string_type str() const
Definition: message.hpp:353
basic_message< wchar_t > wmessage
Definition: message.hpp:498
This class represents a message that can be converted to a specific locale message.
Definition: message.hpp:171
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:670
basic_message< char32_t > u32message
Definition: message.hpp:509
basic_message const & operator=(basic_message const &other)
Definition: message.hpp:316
This facet provides message formatting abilities.
Definition: message.hpp:47
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:693
std::ios_base & number(std::ios_base &ios)
Definition: formatting.hpp:292
string_type str(std::locale const &locale, std::string const &domain_id) const
Definition: message.hpp:370
CharType char_type
Definition: message.hpp:54
basic_message< char > message
Definition: message.hpp:494
basic_message(string_type const &single, string_type const &plural, int number)
Definition: message.hpp:260
string_type str(std::locale const &locale) const
Definition: message.hpp:362
static ios_info & get(std::ios_base &ios)
basic_message()
Definition: message.hpp:181
std::basic_string< CharType > dgettext(char const *domain, CharType const *id, std::locale const &loc=std::locale())
Definition: message.hpp:637
basic_message< CharType > translate(CharType const *msg)
Translate a message, msg is not copied.
Definition: message.hpp:530
unspecified_type domain(std::string const &id)
Definition: message.hpp:789
std::basic_string< CharType > pgettext(CharType const *context, CharType const *id, std::locale const &loc=std::locale())
Definition: message.hpp:660
basic_message(string_type const &context, string_type const &single, string_type const &plural, int number)
Definition: message.hpp:288
std::basic_string< CharType > dpgettext(char const *domain, CharType const *context, CharType const *id, std::locale const &loc=std::locale())
Definition: message.hpp:682
virtual int domain(std::string const &domain) const =0
basic_message< char16_t > u16message
Definition: message.hpp:503
std::basic_string< CharType > gettext(CharType const *id, std::locale const &loc=std::locale())
Definition: message.hpp:617
basic_message(char_type const *single, char_type const *plural, int n)
Definition: message.hpp:207
basic_message(char_type const *context, char_type const *single, char_type const *plural, int n)
Definition: message.hpp:234
std::basic_string< CharType > string_type
Definition: message.hpp:58
message_format< char_type > facet_type
The type of the facet the messages are fetched with.
Definition: message.hpp:176
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:648
string_type str(std::locale const &loc, int id) const
Definition: message.hpp:394
virtual char_type const * convert(char_type const *msg, string_type &buffer) const =0
basic_message(basic_message const &other)
Definition: message.hpp:302