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 // glibc < 2.3.4 declares those as macros if compiled with optimization turned on
24 #ifdef gettext
25 #  undef gettext
26 #  undef ngettext
27 #  undef dgettext
28 #  undef dngettext
29 #endif
30 
31 namespace boost {
32     namespace locale {
33         ///
34         /// \defgroup message Message Formatting (translation)
35         ///
36         ///This module provides message translation functionality, i.e. allow your application to speak native language
37         ///
38         /// @{
39         ///
40 
41         /// \cond INTERNAL
42 
43         template<typename CharType>
44         struct base_message_format: public std::locale::facet
45         {
46         };
47 
48         /// \endcond
49 
50         ///
51         /// \brief This facet provides message formatting abilities
52         ///
53         template<typename CharType>
54         class message_format : public base_message_format<CharType>
55         {
56         public:
57 
58             ///
59             /// Character type
60             ///
61             typedef CharType char_type;
62             ///
63             /// String type
64             ///
65             typedef std::basic_string<CharType> string_type;
66 
67             ///
68             /// Default constructor
69             ///
message_format(size_t refs=0)70             message_format(size_t refs = 0) :
71                 base_message_format<CharType>(refs)
72             {
73             }
74 
75             ///
76             /// This function returns a pointer to the string for a message defined by a \a context
77             /// and identification string \a id. Both create a single key for message lookup in
78             /// a domain defined by \a domain_id.
79             ///
80             /// If \a context is NULL it is not considered to be a part of the key
81             ///
82             /// If a translated string is found, it is returned, otherwise NULL is returned
83             ///
84             ///
85             virtual char_type const *get(int domain_id,char_type const *context,char_type const *id) const = 0;
86             ///
87             /// This function returns a pointer to the string for a plural message defined by a \a context
88             /// and identification string \a single_id.
89             ///
90             /// If \a context is NULL it is not considered to be a part of the key
91             ///
92             /// Both create a single key for message lookup in
93             /// a domain defined \a domain_id. \a n is used to pick the correct translation string for a specific
94             /// number.
95             ///
96             /// If a translated string is found, it is returned, otherwise NULL is returned
97             ///
98             ///
99             virtual char_type const *get(int domain_id,char_type const *context,char_type const *single_id,int n) const = 0;
100 
101             ///
102             /// Convert a string that defines \a domain to the integer id used by \a get functions
103             ///
104             virtual int domain(std::string const &domain) const = 0;
105 
106             ///
107             /// Convert the string \a msg to target locale's encoding. If \a msg is already
108             /// in target encoding it would be returned otherwise the converted
109             /// string is stored in temporary \a buffer and buffer.c_str() is returned.
110             ///
111             /// Note: for char_type that is char16_t, char32_t and wchar_t it is no-op, returns
112             /// msg
113             ///
114             virtual char_type const *convert(char_type const *msg,string_type &buffer) const = 0;
115 
116 #if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
__get_id(void) const117             std::locale::id& __get_id (void) const { return id; }
118 #endif
119         protected:
~message_format()120             virtual ~message_format()
121             {
122             }
123 
124         };
125 
126         /// \cond INTERNAL
127 
128         namespace details {
is_us_ascii_char(char c)129             inline bool is_us_ascii_char(char c)
130             {
131                 // works for null terminated strings regardless char "signness"
132                 return 0<c && c<0x7F;
133             }
is_us_ascii_string(char const * msg)134             inline bool is_us_ascii_string(char const *msg)
135             {
136                 while(*msg) {
137                     if(!is_us_ascii_char(*msg++))
138                         return false;
139                 }
140                 return true;
141             }
142 
143             template<typename CharType>
144             struct string_cast_traits {
castboost::locale::details::string_cast_traits145                 static CharType const *cast(CharType const *msg,std::basic_string<CharType> &/*unused*/)
146                 {
147                     return msg;
148                 }
149             };
150 
151             template<>
152             struct string_cast_traits<char> {
castboost::locale::details::string_cast_traits153                 static char const *cast(char const *msg,std::string &buffer)
154                 {
155                     if(is_us_ascii_string(msg))
156                         return msg;
157                     buffer.reserve(strlen(msg));
158                     char c;
159                     while((c=*msg++)!=0) {
160                         if(is_us_ascii_char(c))
161                             buffer+=c;
162                     }
163                     return buffer.c_str();
164                 }
165             };
166         } // details
167 
168         /// \endcond
169 
170         ///
171         /// \brief This class represents a message that can be converted to a specific locale message
172         ///
173         /// It holds the original ASCII string that is queried in the dictionary when converting to the output string.
174         /// The created string may be UTF-8, UTF-16, UTF-32 or other 8-bit encoded string according to the target
175         /// character type and locale encoding.
176         ///
177         template<typename CharType>
178         class basic_message {
179         public:
180 
181             typedef CharType char_type; ///< The character this message object is used with
182             typedef std::basic_string<char_type> string_type;   ///< The string type this object can be used with
183             typedef message_format<char_type> facet_type;   ///< The type of the facet the messages are fetched with
184 
185             ///
186             /// Create default empty message
187             ///
basic_message()188             basic_message() :
189                 n_(0),
190                 c_id_(0),
191                 c_context_(0),
192                 c_plural_(0)
193             {
194             }
195 
196             ///
197             /// Create a simple message from 0 terminated string. The string should exist
198             /// until the message is destroyed. Generally useful with static constant strings
199             ///
basic_message(char_type const * id)200             explicit basic_message(char_type const *id) :
201                 n_(0),
202                 c_id_(id),
203                 c_context_(0),
204                 c_plural_(0)
205             {
206             }
207 
208             ///
209             /// Create a simple plural form message from 0 terminated strings. The strings should exist
210             /// until the message is destroyed. Generally useful with static constant strings.
211             ///
212             /// \a n is the number, \a single and \a plural are singular and plural forms of the message
213             ///
basic_message(char_type const * single,char_type const * plural,int n)214             explicit basic_message(char_type const *single,char_type const *plural,int n) :
215                 n_(n),
216                 c_id_(single),
217                 c_context_(0),
218                 c_plural_(plural)
219             {
220             }
221 
222             ///
223             /// Create a simple message from 0 terminated strings, with context
224             /// information. The string should exist
225             /// until the message is destroyed. Generally useful with static constant strings
226             ///
basic_message(char_type const * context,char_type const * id)227             explicit basic_message(char_type const *context,char_type const *id) :
228                 n_(0),
229                 c_id_(id),
230                 c_context_(context),
231                 c_plural_(0)
232             {
233             }
234 
235             ///
236             /// Create a simple plural form message from 0 terminated strings, with context. The strings should exist
237             /// until the message is destroyed. Generally useful with static constant strings.
238             ///
239             /// \a n is the number, \a single and \a plural are singular and plural forms of the message
240             ///
basic_message(char_type const * context,char_type const * single,char_type const * plural,int n)241             explicit basic_message(char_type const *context,char_type const *single,char_type const *plural,int n) :
242                 n_(n),
243                 c_id_(single),
244                 c_context_(context),
245                 c_plural_(plural)
246             {
247             }
248 
249 
250             ///
251             /// Create a simple message from a string.
252             ///
basic_message(string_type const & id)253             explicit basic_message(string_type const &id) :
254                 n_(0),
255                 c_id_(0),
256                 c_context_(0),
257                 c_plural_(0),
258                 id_(id)
259             {
260             }
261 
262             ///
263             /// Create a simple plural form message from strings.
264             ///
265             /// \a n is the number, \a single and \a plural are single and plural forms of the message
266             ///
basic_message(string_type const & single,string_type const & plural,int number)267             explicit basic_message(string_type const &single,string_type const &plural,int number) :
268                 n_(number),
269                 c_id_(0),
270                 c_context_(0),
271                 c_plural_(0),
272                 id_(single),
273                 plural_(plural)
274             {
275             }
276 
277             ///
278             /// Create a simple message from a string with context.
279             ///
basic_message(string_type const & context,string_type const & id)280             explicit basic_message(string_type const &context,string_type const &id) :
281                 n_(0),
282                 c_id_(0),
283                 c_context_(0),
284                 c_plural_(0),
285                 id_(id),
286                 context_(context)
287             {
288             }
289 
290             ///
291             /// Create a simple plural form message from strings.
292             ///
293             /// \a n is the number, \a single and \a plural are single and plural forms of the message
294             ///
basic_message(string_type const & context,string_type const & single,string_type const & plural,int number)295             explicit basic_message(string_type const &context,string_type const &single,string_type const &plural,int number) :
296                 n_(number),
297                 c_id_(0),
298                 c_context_(0),
299                 c_plural_(0),
300                 id_(single),
301                 context_(context),
302                 plural_(plural)
303             {
304             }
305 
306             ///
307             /// Copy an object
308             ///
basic_message(basic_message const & other)309             basic_message(basic_message const &other) :
310                 n_(other.n_),
311                 c_id_(other.c_id_),
312                 c_context_(other.c_context_),
313                 c_plural_(other.c_plural_),
314                 id_(other.id_),
315                 context_(other.context_),
316                 plural_(other.plural_)
317             {
318             }
319 
320             ///
321             /// Assign other message object to this one
322             ///
operator =(basic_message const & other)323             basic_message const &operator=(basic_message const &other)
324             {
325                 if(this==&other) {
326                     return *this;
327                 }
328                 basic_message tmp(other);
329                 swap(tmp);
330                 return *this;
331             }
332 
333             ///
334             /// Swap two message objects
335             ///
swap(basic_message & other)336             void swap(basic_message &other)
337             {
338                 std::swap(n_,other.n_);
339                 std::swap(c_id_,other.c_id_);
340                 std::swap(c_context_,other.c_context_);
341                 std::swap(c_plural_,other.c_plural_);
342 
343                 id_.swap(other.id_);
344                 context_.swap(other.context_);
345                 plural_.swap(other.plural_);
346             }
347 
348             ///
349             /// Message class can be explicitly converted to string class
350             ///
351 
operator string_type() const352             operator string_type () const
353             {
354                 return str();
355             }
356 
357             ///
358             /// Translate message to a string in the default global locale, using default domain
359             ///
str() const360             string_type str() const
361             {
362                 std::locale loc;
363                 return str(loc,0);
364             }
365 
366             ///
367             /// Translate message to a string in the locale \a locale, using default domain
368             ///
str(std::locale const & locale) const369             string_type str(std::locale const &locale) const
370             {
371                 return str(locale,0);
372             }
373 
374             ///
375             /// Translate message to a string using locale \a locale and message domain  \a domain_id
376             ///
str(std::locale const & locale,std::string const & domain_id) const377             string_type str(std::locale const &locale,std::string const &domain_id) const
378             {
379                 int id=0;
380                 if(std::has_facet<facet_type>(locale))
381                     id=std::use_facet<facet_type>(locale).domain(domain_id);
382                 return str(locale,id);
383             }
384 
385             ///
386             /// Translate message to a string using the default locale and message domain  \a domain_id
387             ///
str(std::string const & domain_id) const388             string_type str(std::string const &domain_id) const
389             {
390                 int id=0;
391                 std::locale loc;
392                 if(std::has_facet<facet_type>(loc))
393                     id=std::use_facet<facet_type>(loc).domain(domain_id);
394                 return str(loc,id);
395             }
396 
397 
398             ///
399             /// Translate message to a string using locale \a loc and message domain index  \a id
400             ///
str(std::locale const & loc,int id) const401             string_type str(std::locale const &loc,int id) const
402             {
403                 string_type buffer;
404                 char_type const *ptr = write(loc,id,buffer);
405                 if(ptr == buffer.c_str())
406                     return buffer;
407                 else
408                     buffer = ptr;
409                 return buffer;
410             }
411 
412 
413             ///
414             /// Translate message and write to stream \a out, using imbued locale and domain set to the
415             /// stream
416             ///
write(std::basic_ostream<char_type> & out) const417             void write(std::basic_ostream<char_type> &out) const
418             {
419                 std::locale const &loc = out.getloc();
420                 int id = ios_info::get(out).domain_id();
421                 string_type buffer;
422                 out << write(loc,id,buffer);
423             }
424 
425         private:
plural() const426             char_type const *plural() const
427             {
428                 if(c_plural_)
429                     return c_plural_;
430                 if(plural_.empty())
431                     return 0;
432                 return plural_.c_str();
433             }
context() const434             char_type const *context() const
435             {
436                 if(c_context_)
437                     return c_context_;
438                 if(context_.empty())
439                     return 0;
440                 return context_.c_str();
441             }
442 
id() const443             char_type const *id() const
444             {
445                 return c_id_ ? c_id_ : id_.c_str();
446             }
447 
write(std::locale const & loc,int domain_id,string_type & buffer) const448             char_type const *write(std::locale const &loc,int domain_id,string_type &buffer) const
449             {
450                 char_type const *translated = 0;
451                 static const char_type empty_string[1] = {0};
452 
453                 char_type const *id = this->id();
454                 char_type const *context = this->context();
455                 char_type const *plural = this->plural();
456 
457                 if(*id == 0)
458                     return empty_string;
459 
460                 facet_type const *facet = 0;
461                 if(std::has_facet<facet_type>(loc))
462                     facet = &std::use_facet<facet_type>(loc);
463 
464                 if(facet) {
465                     if(!plural) {
466                         translated = facet->get(domain_id,context,id);
467                     }
468                     else {
469                         translated = facet->get(domain_id,context,id,n_);
470                     }
471                 }
472 
473                 if(!translated) {
474                     char_type const *msg = plural ? ( n_ == 1 ? id : plural) : id;
475 
476                     if(facet) {
477                         translated = facet->convert(msg,buffer);
478                     }
479                     else {
480                         translated = details::string_cast_traits<char_type>::cast(msg,buffer);
481                     }
482                 }
483                 return translated;
484             }
485 
486             /// members
487 
488             int n_;
489             char_type const *c_id_;
490             char_type const *c_context_;
491             char_type const *c_plural_;
492             string_type id_;
493             string_type context_;
494             string_type plural_;
495         };
496 
497 
498         ///
499         /// Convenience typedef for char
500         ///
501         typedef basic_message<char> message;
502         ///
503         /// Convenience typedef for wchar_t
504         ///
505         typedef basic_message<wchar_t> wmessage;
506         #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
507         ///
508         /// Convenience typedef for char16_t
509         ///
510         typedef basic_message<char16_t> u16message;
511         #endif
512         #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
513         ///
514         /// Convenience typedef for char32_t
515         ///
516         typedef basic_message<char32_t> u32message;
517         #endif
518 
519         ///
520         /// Translate message \a msg and write it to stream
521         ///
522         template<typename CharType>
operator <<(std::basic_ostream<CharType> & out,basic_message<CharType> const & msg)523         std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_message<CharType> const &msg)
524         {
525             msg.write(out);
526             return out;
527         }
528 
529         ///
530         /// \anchor boost_locale_translate_family \name Indirect message translation function family
531         /// @{
532 
533         ///
534         /// \brief Translate a message, \a msg is not copied
535         ///
536         template<typename CharType>
translate(CharType const * msg)537         inline basic_message<CharType> translate(CharType const *msg)
538         {
539             return basic_message<CharType>(msg);
540         }
541         ///
542         /// \brief Translate a message in context, \a msg and \a context are not copied
543         ///
544         template<typename CharType>
translate(CharType const * context,CharType const * msg)545         inline basic_message<CharType> translate(   CharType const *context,
546                                                     CharType const *msg)
547         {
548             return basic_message<CharType>(context,msg);
549         }
550         ///
551         /// \brief Translate a plural message form, \a single and \a plural are not copied
552         ///
553         template<typename CharType>
translate(CharType const * single,CharType const * plural,int n)554         inline basic_message<CharType> translate(   CharType const *single,
555                                                     CharType const *plural,
556                                                     int n)
557         {
558             return basic_message<CharType>(single,plural,n);
559         }
560         ///
561         /// \brief Translate a plural message from in constext, \a context, \a single and \a plural are not copied
562         ///
563         template<typename CharType>
translate(CharType const * context,CharType const * single,CharType const * plural,int n)564         inline basic_message<CharType> translate(   CharType const *context,
565                                                     CharType const *single,
566                                                     CharType const *plural,
567                                                     int n)
568         {
569             return basic_message<CharType>(context,single,plural,n);
570         }
571 
572         ///
573         /// \brief Translate a message, \a msg is copied
574         ///
575         template<typename CharType>
translate(std::basic_string<CharType> const & msg)576         inline basic_message<CharType> translate(std::basic_string<CharType> const &msg)
577         {
578             return basic_message<CharType>(msg);
579         }
580 
581         ///
582         /// \brief Translate a message in context,\a context and \a msg is copied
583         ///
584         template<typename CharType>
translate(std::basic_string<CharType> const & context,std::basic_string<CharType> const & msg)585         inline basic_message<CharType> translate(   std::basic_string<CharType> const &context,
586                                                     std::basic_string<CharType> const &msg)
587         {
588             return basic_message<CharType>(context,msg);
589         }
590         ///
591         /// \brief Translate a plural message form in constext, \a context, \a single and \a plural are copied
592         ///
593         template<typename CharType>
translate(std::basic_string<CharType> const & context,std::basic_string<CharType> const & single,std::basic_string<CharType> const & plural,int n)594         inline basic_message<CharType> translate(   std::basic_string<CharType> const &context,
595                                                     std::basic_string<CharType> const &single,
596                                                     std::basic_string<CharType> const &plural,
597                                                     int n)
598         {
599             return basic_message<CharType>(context,single,plural,n);
600         }
601 
602         ///
603         /// \brief Translate a plural message form, \a single and \a plural are copied
604         ///
605 
606         template<typename CharType>
translate(std::basic_string<CharType> const & single,std::basic_string<CharType> const & plural,int n)607         inline basic_message<CharType> translate(   std::basic_string<CharType> const &single,
608                                                     std::basic_string<CharType> const &plural,
609                                                     int n)
610         {
611             return basic_message<CharType>(single,plural,n);
612         }
613 
614         /// @}
615 
616         ///
617         /// \anchor boost_locale_gettext_family \name Direct message translation functions family
618         ///
619 
620         ///
621         /// Translate message \a id according to locale \a loc
622         ///
623         template<typename CharType>
gettext(CharType const * id,std::locale const & loc=std::locale ())624         std::basic_string<CharType> gettext(CharType const *id,
625                                             std::locale const &loc=std::locale())
626         {
627             return basic_message<CharType>(id).str(loc);
628         }
629         ///
630         /// Translate plural form according to locale \a loc
631         ///
632         template<typename CharType>
ngettext(CharType const * s,CharType const * p,int n,std::locale const & loc=std::locale ())633         std::basic_string<CharType> ngettext(   CharType const *s,
634                                                 CharType const *p,
635                                                 int n,
636                                                 std::locale const &loc=std::locale())
637         {
638             return basic_message<CharType>(s,p,n).str(loc);
639         }
640         ///
641         /// Translate message \a id according to locale \a loc in domain \a domain
642         ///
643         template<typename CharType>
dgettext(char const * domain,CharType const * id,std::locale const & loc=std::locale ())644         std::basic_string<CharType>  dgettext(  char const *domain,
645                                                 CharType const *id,
646                                                 std::locale const &loc=std::locale())
647         {
648             return basic_message<CharType>(id).str(loc,domain);
649         }
650 
651         ///
652         /// Translate plural form according to locale \a loc in domain \a domain
653         ///
654         template<typename CharType>
dngettext(char const * domain,CharType const * s,CharType const * p,int n,std::locale const & loc=std::locale ())655         std::basic_string<CharType>  dngettext( char const *domain,
656                                                 CharType const *s,
657                                                 CharType const *p,
658                                                 int n,
659                                                 std::locale const &loc=std::locale())
660         {
661             return basic_message<CharType>(s,p,n).str(loc,domain);
662         }
663         ///
664         /// Translate message \a id according to locale \a loc in context \a context
665         ///
666         template<typename CharType>
pgettext(CharType const * context,CharType const * id,std::locale const & loc=std::locale ())667         std::basic_string<CharType>  pgettext(  CharType const *context,
668                                                 CharType const *id,
669                                                 std::locale const &loc=std::locale())
670         {
671             return basic_message<CharType>(context,id).str(loc);
672         }
673         ///
674         /// Translate plural form according to locale \a loc in context \a context
675         ///
676         template<typename CharType>
npgettext(CharType const * context,CharType const * s,CharType const * p,int n,std::locale const & loc=std::locale ())677         std::basic_string<CharType>  npgettext( CharType const *context,
678                                                 CharType const *s,
679                                                 CharType const *p,
680                                                 int n,
681                                                 std::locale const &loc=std::locale())
682         {
683             return basic_message<CharType>(context,s,p,n).str(loc);
684         }
685         ///
686         /// Translate message \a id according to locale \a loc in domain \a domain in context \a context
687         ///
688         template<typename CharType>
dpgettext(char const * domain,CharType const * context,CharType const * id,std::locale const & loc=std::locale ())689         std::basic_string<CharType>  dpgettext( char const *domain,
690                                                 CharType const *context,
691                                                 CharType const *id,
692                                                 std::locale const &loc=std::locale())
693         {
694             return basic_message<CharType>(context,id).str(loc,domain);
695         }
696         ///
697         /// Translate plural form according to locale \a loc in domain \a domain in context \a context
698         ///
699         template<typename CharType>
dnpgettext(char const * domain,CharType const * context,CharType const * s,CharType const * p,int n,std::locale const & loc=std::locale ())700         std::basic_string<CharType>  dnpgettext(char const *domain,
701                                                 CharType const *context,
702                                                 CharType const *s,
703                                                 CharType const *p,
704                                                 int n,
705                                                 std::locale const &loc=std::locale())
706         {
707             return basic_message<CharType>(context,s,p,n).str(loc,domain);
708         }
709 
710         ///
711         /// \cond INTERNAL
712         ///
713 
714         template<>
715         struct BOOST_LOCALE_DECL base_message_format<char> : public std::locale::facet
716         {
base_message_formatboost::locale::base_message_format717             base_message_format(size_t refs = 0) : std::locale::facet(refs)
718             {
719             }
720             static std::locale::id id;
721         };
722 
723         template<>
724         struct BOOST_LOCALE_DECL base_message_format<wchar_t> : public std::locale::facet
725         {
base_message_formatboost::locale::base_message_format726             base_message_format(size_t refs = 0) : std::locale::facet(refs)
727             {
728             }
729             static std::locale::id id;
730         };
731 
732         #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
733 
734         template<>
735         struct BOOST_LOCALE_DECL base_message_format<char16_t> : public std::locale::facet
736         {
base_message_formatboost::locale::base_message_format737             base_message_format(size_t refs = 0) : std::locale::facet(refs)
738             {
739             }
740             static std::locale::id id;
741         };
742 
743         #endif
744 
745         #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
746 
747         template<>
748         struct BOOST_LOCALE_DECL base_message_format<char32_t> : public std::locale::facet
749         {
base_message_formatboost::locale::base_message_format750             base_message_format(size_t refs = 0) : std::locale::facet(refs)
751             {
752             }
753             static std::locale::id id;
754         };
755 
756         #endif
757 
758         /// \endcond
759 
760         ///
761         /// @}
762         ///
763 
764         namespace as {
765             /// \cond INTERNAL
766             namespace details {
767                 struct set_domain {
768                     std::string domain_id;
769                 };
770                 template<typename CharType>
operator <<(std::basic_ostream<CharType> & out,set_domain const & dom)771                 std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out, set_domain const &dom)
772                 {
773                     int id = std::use_facet<message_format<CharType> >(out.getloc()).domain(dom.domain_id);
774                     ios_info::get(out).domain_id(id);
775                     return out;
776                 }
777             } // details
778             /// \endcond
779 
780             ///
781             /// \addtogroup manipulators
782             ///
783             /// @{
784 
785             ///
786             /// Manipulator for switching message domain in ostream,
787             ///
788             /// \note The returned object throws std::bad_cast if the I/O stream does not have \ref message_format facet installed
789             ///
790             inline
791             #ifdef BOOST_LOCALE_DOXYGEN
792             unspecified_type
793             #else
794             details::set_domain
795             #endif
domain(std::string const & id)796             domain(std::string const &id)
797             {
798                 details::set_domain tmp = { id };
799                 return tmp;
800             }
801             /// @}
802         } // as
803     } // locale
804 } // boost
805 
806 #ifdef BOOST_MSVC
807 #pragma warning(pop)
808 #endif
809 
810 
811 #endif
812 
813 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
814 
815