Boost.Locale: boost/locale/format.hpp Source File

| Boost.Locale

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Examples

- File List

boost/locale/format.hpp

    00001 //
    00002 //  Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
    00003 //
    00004 //  Distributed under the Boost Software License, Version 1.0. (See
    00005 //  accompanying file LICENSE_1_0.txt or copy at
    00006 //  http://www.boost.org/LICENSE_1_0.txt)
    00007 //
    00008 #ifndef BOOST_LOCALE_FORMAT_HPP_INCLUDED
    00009 #define BOOST_LOCALE_FORMAT_HPP_INCLUDED
    00010
    00011 #include <boost/locale/config.hpp>
    00012 #ifdef BOOST_MSVC
    00013 #  pragma warning(push)
    00014 #  pragma warning(disable : 4275 4251 4231 4660)
    00015 #endif
    00016 #include <boost/locale/message.hpp>
    00017 #include <boost/locale/formatting.hpp>
    00018
    00019 #include <sstream>
    00020
    00021
    00022 namespace boost {
    00023     namespace locale {
    00024
    00032
    00034         namespace details {
    00035
    00036             template<typename CharType>
    00037             struct formattible {
    00038                 typedef std::basic_ostream<CharType> stream_type;
    00039                 typedef void (*writer_type)(stream_type &output,void const *ptr);
    00040
    00041                 formattible() :
    00042                     pointer_(0),
    00043                     writer_(&formattible::void_write)
    00044                 {
    00045                 }
    00046
    00047                 formattible(formattible const &other) :
    00048                     pointer_(other.pointer_),
    00049                     writer_(other.writer_)
    00050                 {
    00051                 }
    00052
    00053                 formattible const &operator=(formattible const &other)
    00054                 {
    00055                     if(this != &other) {
    00056                         pointer_=other.pointer_;
    00057                         writer_=other.writer_;
    00058                     }
    00059                     return *this;
    00060                 }
    00061
    00062                 template<typename Type>
    00063                 formattible(Type const &value)
    00064                 {
    00065                     pointer_ = static_cast<void const *>(&value);
    00066                     writer_ = &write<Type>;
    00067                 }
    00068
    00069                 template<typename Type>
    00070                 formattible const &operator=(Type const &other)
    00071                 {
    00072                     *this = formattible(other);
    00073                     return *this;
    00074                 }
    00075
    00076                 friend stream_type &operator<<(stream_type &out,formattible const &fmt)
    00077                 {
    00078                     fmt.writer_(out,fmt.pointer_);
    00079                     return out;
    00080                 }
    00081
    00082             private:
    00083                 static void void_write(stream_type &output,void const * /*ptr*/)
    00084                 {
    00085                     CharType empty_string[1]={0};
    00086                     output<<empty_string;
    00087                 }
    00088
    00089                 template<typename Type>
    00090                 static void write(stream_type &output,void const *ptr)
    00091                 {
    00092                     output << *static_cast<Type const *>(ptr);
    00093                 }
    00094
    00095                 void const *pointer_;
    00096                 writer_type writer_;
    00097             }; // formattible
    00098
    00099             class BOOST_LOCALE_DECL format_parser  {
    00100             public:
    00101                 format_parser(std::ios_base &ios,void *,void (*imbuer)(void *,std::locale const &));
    00102                 ~format_parser();
    00103
    00104                 unsigned get_position();
    00105
    00106                 void set_one_flag(std::string const &key,std::string const &value);
    00107
    00108                 template<typename CharType>
    00109                 void set_flag_with_str(std::string const &key,std::basic_string<CharType> const &value)
    00110                 {
    00111                     if(key=="ftime" || key=="strftime") {
    00112                         as::strftime(ios_);
    00113                         ios_info::get(ios_).date_time_pattern(value);
    00114                     }
    00115                 }
    00116                 void restore();
    00117             private:
    00118                 void imbue(std::locale const &);
    00119                 format_parser(format_parser const &);
    00120                 void operator=(format_parser const &);
    00121
    00122                 std::ios_base &ios_;
    00123                 struct data;
    00124                 std::auto_ptr<data> d;
    00125             };
    00126
    00127         }
    00128
    00130
    00203         template<typename CharType>
    00204         class basic_format {
    00205         public:
    00206             typedef CharType char_type;
    00207             typedef basic_message<char_type> message_type;
    00208
    00209             typedef details::formattible<CharType> formattible_type;
    00211
    00212             typedef std::basic_string<CharType> string_type;
    00213             typedef std::basic_ostream<CharType> stream_type;
    00214
    00215
    00219             basic_format(string_type format_string) :
    00220                 format_(format_string),
    00221                 translate_(false),
    00222                 parameters_count_(0)
    00223             {
    00224             }
    00229             basic_format(message_type const &trans) :
    00230                 message_(trans),
    00231                 translate_(true),
    00232                 parameters_count_(0)
    00233             {
    00234             }
    00235
    00240             template<typename Formattible>
    00241             basic_format &operator % (Formattible const &object)
    00242             {
    00243                 add(formattible_type(object));
    00244                 return *this;
    00245             }
    00246
    00250             string_type str(std::locale const &loc = std::locale()) const
    00251             {
    00252                 std::basic_ostringstream<CharType> buffer;
    00253                 buffer.imbue(loc);
    00254                 write(buffer);
    00255                 return buffer.str();
    00256             }
    00257
    00261             void write(stream_type &out) const
    00262             {
    00263                 string_type format;
    00264                 if(translate_)
    00265                     format = message_.str(out.getloc(),ios_info::get(out).domain_id());
    00266                 else
    00267                     format = format_;
    00268
    00269                 format_output(out,format);
    00270
    00271             }
    00272
    00273
    00274         private:
    00275
    00276             class format_guard {
    00277             public:
    00278                 format_guard(details::format_parser &fmt) :
    00279                     fmt_(&fmt),
    00280                     restored_(false)
    00281                 {
    00282                 }
    00283                 void restore()
    00284                 {
    00285                     if(restored_)
    00286                         return;
    00287                     fmt_->restore();
    00288                     restored_ = true;
    00289                 }
    00290                 ~format_guard()
    00291                 {
    00292                     try {
    00293                         restore();
    00294                     }
    00295                     catch(...) {
    00296                     }
    00297                 }
    00298             private:
    00299                 details::format_parser *fmt_;
    00300                 bool restored_;
    00301             };
    00302
    00303             void format_output(stream_type &out,string_type const &sformat) const
    00304             {
    00305                 char_type obrk='{';
    00306                 char_type cbrk='}';
    00307                 char_type eq='=';
    00308                 char_type comma=',';
    00309                 char_type quote='\'';
    00310
    00311                 size_t pos = 0;
    00312                 size_t size=sformat.size();
    00313                 CharType const *format=sformat.c_str();
    00314                 while(format[pos]!=0) {
    00315                     if(format[pos] != obrk) {
    00316                         if(format[pos]==cbrk && format[pos+1]==cbrk) {
    00317                             out << cbrk;
    00318                             pos+=2;
    00319                         }
    00320                         else {
    00321                             out<<format[pos];
    00322                             pos++;
    00323                         }
    00324                         continue;
    00325                     }
    00326
    00327                     if(pos+1 < size && format[pos+1]==obrk) {
    00328                         out << obrk;
    00329                         pos+=2;
    00330                         continue;
    00331                     }
    00332                     pos++;
    00333
    00334                     details::format_parser fmt(out,static_cast<void *>(&out),&basic_format::imbue_locale);
    00335
    00336                     format_guard guard(fmt);
    00337
    00338                     while(pos < size) {
    00339                         std::string key;
    00340                         std::string svalue;
    00341                         string_type value;
    00342                         bool use_svalue = true;
    00343                         for(;format[pos];pos++) {
    00344                             char_type c=format[pos];
    00345                             if(c==comma || c==eq || c==cbrk)
    00346                                 break;
    00347                             else {
    00348                                 key+=static_cast<char>(c);
    00349                             }
    00350                         }
    00351
    00352                         if(format[pos]==eq) {
    00353                             pos++;
    00354                             if(format[pos]==quote) {
    00355                                 pos++;
    00356                                 use_svalue = false;
    00357                                 while(format[pos]) {
    00358                                     if(format[pos]==quote) {
    00359                                         if(format[pos+1]==quote) {
    00360                                             value+=quote;
    00361                                             pos+=2;
    00362                                         }
    00363                                         else {
    00364                                             pos++;
    00365                                             break;
    00366                                         }
    00367                                     }
    00368                                     else {
    00369                                         value+=format[pos];
    00370                                         pos++;
    00371                                     }
    00372                                 }
    00373                             }
    00374                             else {
    00375                                 char_type c;
    00376                                 while((c=format[pos])!=0 && c!=comma && c!=cbrk) {
    00377                                     svalue+=static_cast<char>(c);
    00378                                     pos++;
    00379                                 }
    00380                             }
    00381                         }
    00382
    00383                         if(use_svalue) {
    00384                             fmt.set_one_flag(key,svalue);
    00385                         }
    00386                         else
    00387                             fmt.set_flag_with_str(key,value);
    00388
    00389                         if(format[pos]==comma) {
    00390                             pos++;
    00391                             continue;
    00392                         }
    00393                         else if(format[pos]==cbrk)  {
    00394                             unsigned position = fmt.get_position();
    00395                             out << get(position);
    00396                             guard.restore();
    00397                             pos++;
    00398                             break;
    00399                         }
    00400                         else {
    00401                             guard.restore();
    00402                             break;
    00403                         }
    00404                     }
    00405                 }
    00406             }
    00407
    00408
    00409             //
    00410             // Non-copyable
    00411             //
    00412             basic_format(basic_format const &other);
    00413             void operator=(basic_format const &other);
    00414
    00415             void add(formattible_type const &param)
    00416             {
    00417                 if(parameters_count_ >= base_params_)
    00418                     ext_params_.push_back(param);
    00419                 else
    00420                     parameters_[parameters_count_] = param;
    00421                 parameters_count_++;
    00422             }
    00423
    00424             formattible_type get(unsigned id) const
    00425             {
    00426                 if(id >= parameters_count_)
    00427                     return formattible_type();
    00428                 else if(id >= base_params_)
    00429                     return ext_params_[id - base_params_];
    00430                 else
    00431                     return parameters_[id];
    00432             }
    00433
    00434             static void imbue_locale(void *ptr,std::locale const &l)
    00435             {
    00436                 reinterpret_cast<stream_type *>(ptr)->imbue(l);
    00437             }
    00438
    00439
    00440
    00441             static unsigned const base_params_ = 8;
    00442
    00443             message_type message_;
    00444             string_type format_;
    00445             bool translate_;
    00446
    00447
    00448             formattible_type parameters_[base_params_];
    00449             unsigned parameters_count_;
    00450             std::vector<formattible_type> ext_params_;
    00451         };
    00452
    00458         template<typename CharType>
    00459         std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_format<CharType> const &fmt)
    00460         {
    00461             fmt.write(out);
    00462             return out;
    00463         }
    00464
    00465
    00469         typedef basic_format<char> format;
    00470
    00474         typedef basic_format<wchar_t> wformat;
    00475
    00476         #ifdef BOOST_HAS_CHAR16_T
    00477
    00478
    00479
    00480         typedef basic_format<char16_t> u16format;
    00481         #endif
    00482
    00483         #ifdef BOOST_HAS_CHAR32_T
    00484
    00485
    00486
    00487         typedef basic_format<char32_t> u32format;
    00488         #endif
    00489
    00493
    00494     }
    00495 }
    00496
    00497 #ifdef BOOST_MSVC
    00498 #pragma warning(pop)
    00499 #endif
    00500
    00501 #endif
    00502
    00513
    00514 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
    00515