CppCMS
booster/locale/formatting.h
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 BOOSTER_LOCALE_FORMATTING_H_INCLUDED
00009 #define BOOSTER_LOCALE_FORMATTING_H_INCLUDED
00010 
00011 #include <booster/config.h>
00012 #ifdef BOOSTER_MSVC
00013 #  pragma warning(push)
00014 #  pragma warning(disable : 4275 4251 4231 4660)
00015 #endif
00016 #include <booster/cstdint.h>
00017 #include <booster/locale/time_zone.h>
00018 #include <ostream>
00019 #include <istream>
00020 #include <string>
00021 #include <string.h>
00022 #include <typeinfo>
00023 
00024 namespace booster {
00025     namespace locale {
00030         namespace flags {
00035             typedef enum {
00036                 posix               = 0,
00037                 number              = 1,
00038                 currency            = 2,
00039                 percent             = 3,
00040                 date                = 4,
00041                 time                = 5,
00042                 datetime            = 6,
00043                 strftime            = 7,
00044                 spellout            = 8,
00045                 ordinal             = 9,
00046 
00047                 display_flags_mask  = 31,
00048 
00049                 currency_default    = 0 << 5,
00050                 currency_iso        = 1 << 5,
00051                 currency_national   = 2 << 5,
00052 
00053                 currency_flags_mask = 3 << 5,
00054 
00055                 time_default        = 0 << 7,
00056                 time_short          = 1 << 7,
00057                 time_medium         = 2 << 7,
00058                 time_long           = 3 << 7,
00059                 time_full           = 4 << 7,
00060                 time_flags_mask     = 7 << 7,
00061 
00062                 date_default        = 0 << 10,
00063                 date_short          = 1 << 10,
00064                 date_medium         = 2 << 10,
00065                 date_long           = 3 << 10,
00066                 date_full           = 4 << 10,
00067                 date_flags_mask     = 7 << 10,
00068 
00069                 datetime_flags_mask = date_flags_mask | time_flags_mask
00070 
00071             } display_flags_type;
00072 
00077             typedef enum {
00078                 datetime_pattern,   
00079                 time_zone_id        
00080             } pattern_type;
00081 
00085             typedef enum {
00086                 domain_id           
00087             } value_type;
00088 
00089             
00090         } // flags
00091 
00098         class BOOSTER_API ios_info {
00099         public:
00100 
00102 
00103             ios_info();
00104             ios_info(ios_info const &);
00105             ios_info const &operator=(ios_info const &);
00106             ~ios_info();
00107 
00109 
00113             static ios_info &get(std::ios_base &ios);
00114 
00118             void display_flags(uint64_t flags);
00119             
00123             void currency_flags(uint64_t flags);
00124             
00128             void date_flags(uint64_t flags);
00129             
00133             void time_flags(uint64_t flags);
00134             
00138             void datetime_flags(uint64_t flags);
00139             
00143             void domain_id(int);
00144             
00148             void time_zone(std::string const &);
00149             
00150 
00154             template<typename CharType>
00155             void date_time_pattern(std::basic_string<CharType> const &str)
00156             {
00157                 string_set &s = date_time_pattern_set();
00158                 s.set<CharType>(str.c_str());
00159             }
00160 
00161 
00165             uint64_t display_flags() const;
00166             
00170             uint64_t currency_flags() const;
00171 
00172             
00176             uint64_t date_flags() const;
00177             
00181             uint64_t time_flags() const;
00182 
00186             uint64_t datetime_flags() const;
00187             
00191             int domain_id() const;
00192             
00196             std::string time_zone() const;
00197             
00201             template<typename CharType>
00202             std::basic_string<CharType> date_time_pattern() const
00203             {
00204                 string_set const &s = date_time_pattern_set();
00205                 return s.get<CharType>();
00206             }
00207             
00209             void on_imbue();
00211             
00212         private:
00213 
00214             class string_set;
00215 
00216             string_set const &date_time_pattern_set() const;
00217             string_set &date_time_pattern_set();
00218             
00219             class BOOSTER_API string_set {
00220             public:
00221                 string_set(); 
00222                 ~string_set();
00223                 string_set(string_set const &other);
00224                 string_set const &operator=(string_set const &other);
00225                 void swap(string_set &other);
00226                 
00227                 template<typename Char>
00228                 void set(Char const *s)
00229                 {
00230                     delete [] ptr;
00231                     ptr = 0;
00232                     type=&typeid(Char);
00233                     Char const *end = s;
00234                     while(*end!=0) end++;
00235                     // if ptr = 0 it does not matter what is value of size
00236                     size = sizeof(Char)*(end - s+1);
00237                     ptr = new char[size];
00238                     memcpy(ptr,s,size);
00239                 }
00240 
00241                 template<typename Char>
00242                 std::basic_string<Char> get() const
00243                 {
00244                     if(type==0 || *type!=typeid(Char))
00245                         throw std::bad_cast();
00246                     std::basic_string<Char> result = reinterpret_cast<Char const *>(ptr);
00247                     return result;
00248                 }
00249 
00250             private:
00251                 std::type_info const *type;
00252                 size_t size;
00253                 char *ptr;
00254             };
00255 
00256             uint64_t flags_;
00257             int domain_id_;
00258             std::string time_zone_;
00259             string_set datetime_;
00260 
00261             struct data;
00262             data *d;
00263 
00264         };
00265 
00266 
00270         namespace as {
00276 
00281             
00282             inline std::ios_base & posix(std::ios_base & ios)
00283             {
00284                 ios_info::get(ios).display_flags(flags::posix);
00285                 return ios;
00286             }
00287 
00292             inline std::ios_base & number(std::ios_base & ios)
00293             {
00294                 ios_info::get(ios).display_flags(flags::number);
00295                 return ios;
00296             }
00297             
00301             inline std::ios_base & currency(std::ios_base & ios)
00302             {
00303                 ios_info::get(ios).display_flags(flags::currency);
00304                 return ios;
00305             }
00306             
00310             inline std::ios_base & percent(std::ios_base & ios)
00311             {
00312                 ios_info::get(ios).display_flags(flags::percent);
00313                 return ios;
00314             }
00315             
00319             inline std::ios_base & date(std::ios_base & ios)
00320             {
00321                 ios_info::get(ios).display_flags(flags::date);
00322                 return ios;
00323             }
00324 
00328             inline std::ios_base & time(std::ios_base & ios)
00329             {
00330                 ios_info::get(ios).display_flags(flags::time);
00331                 return ios;
00332             }
00333 
00337             inline std::ios_base & datetime(std::ios_base & ios)
00338             {
00339                 ios_info::get(ios).display_flags(flags::datetime);
00340                 return ios;
00341             }
00342 
00347             inline std::ios_base & strftime(std::ios_base & ios)
00348             {
00349                 ios_info::get(ios).display_flags(flags::strftime);
00350                 return ios;
00351             }
00352             
00356             inline std::ios_base & spellout(std::ios_base & ios)
00357             {
00358                 ios_info::get(ios).display_flags(flags::spellout);
00359                 return ios;
00360             }
00361             
00365             inline std::ios_base & ordinal(std::ios_base & ios)
00366             {
00367                 ios_info::get(ios).display_flags(flags::ordinal);
00368                 return ios;
00369             }
00370 
00374             inline std::ios_base & currency_default(std::ios_base & ios)
00375             {
00376                 ios_info::get(ios).currency_flags(flags::currency_default);
00377                 return ios;
00378             }
00379 
00383             inline std::ios_base & currency_iso(std::ios_base & ios)
00384             {
00385                 ios_info::get(ios).currency_flags(flags::currency_iso);
00386                 return ios;
00387             }
00388 
00392             inline std::ios_base & currency_national(std::ios_base & ios)
00393             {
00394                 ios_info::get(ios).currency_flags(flags::currency_national);
00395                 return ios;
00396             }
00397 
00401             inline std::ios_base & time_default(std::ios_base & ios)
00402             {
00403                 ios_info::get(ios).time_flags(flags::time_default);
00404                 return ios;
00405             }
00406 
00410             inline std::ios_base & time_short(std::ios_base & ios)
00411             {
00412                 ios_info::get(ios).time_flags(flags::time_short);
00413                 return ios;
00414             }
00415 
00419             inline std::ios_base & time_medium(std::ios_base & ios)
00420             {
00421                 ios_info::get(ios).time_flags(flags::time_medium);
00422                 return ios;
00423             }
00424 
00428             inline std::ios_base & time_long(std::ios_base & ios)
00429             {
00430                 ios_info::get(ios).time_flags(flags::time_long);
00431                 return ios;
00432             }
00433 
00437             inline std::ios_base & time_full(std::ios_base & ios)
00438             {
00439                 ios_info::get(ios).time_flags(flags::time_full);
00440                 return ios;
00441             }
00442 
00446             inline std::ios_base & date_default(std::ios_base & ios)
00447             {
00448                 ios_info::get(ios).date_flags(flags::date_default);
00449                 return ios;
00450             }
00451 
00455             inline std::ios_base & date_short(std::ios_base & ios)
00456             {
00457                 ios_info::get(ios).date_flags(flags::date_short);
00458                 return ios;
00459             }
00460 
00464             inline std::ios_base & date_medium(std::ios_base & ios)
00465             {
00466                 ios_info::get(ios).date_flags(flags::date_medium);
00467                 return ios;
00468             }
00469 
00473             inline std::ios_base & date_long(std::ios_base & ios)
00474             {
00475                 ios_info::get(ios).date_flags(flags::date_long);
00476                 return ios;
00477             }
00478 
00482             inline std::ios_base & date_full(std::ios_base & ios)
00483             {
00484                 ios_info::get(ios).date_flags(flags::date_full);
00485                 return ios;
00486             }            
00487             
00488             
00490             namespace details {
00491                 template<typename CharType>
00492                 struct add_ftime {
00493 
00494                     std::basic_string<CharType> ftime;
00495 
00496                     void apply(std::basic_ios<CharType> &ios) const
00497                     {
00498                         ios_info::get(ios).date_time_pattern(ftime);
00499                         as::strftime(ios);
00500                     }
00501 
00502                 };
00503 
00504                 template<typename CharType>
00505                 std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,add_ftime<CharType> const &fmt)
00506                 {
00507                     fmt.apply(out);
00508                     return out;
00509                 }
00510                 
00511                 template<typename CharType>
00512                 std::basic_istream<CharType> &operator>>(std::basic_istream<CharType> &in,add_ftime<CharType> const &fmt)
00513                 {
00514                     fmt.apply(in);
00515                     return in;
00516                 }
00517 
00518             }
00520 
00555 
00556 
00557             template<typename CharType>
00558             #ifdef BOOSTER_LOCALE_DOXYGEN
00559             unspecified_type
00560             #else
00561             details::add_ftime<CharType> 
00562             #endif
00563             ftime(std::basic_string<CharType> const &format)
00564             {
00565                 details::add_ftime<CharType> fmt;
00566                 fmt.ftime=format;
00567                 return fmt;
00568             }
00569 
00573             template<typename CharType>
00574             #ifdef BOOSTER_LOCALE_DOXYGEN
00575             unspecified_type
00576             #else
00577             details::add_ftime<CharType> 
00578             #endif
00579             ftime(CharType const *format)
00580             {
00581                 details::add_ftime<CharType> fmt;
00582                 fmt.ftime=format;
00583                 return fmt;
00584             }
00585 
00587             namespace details {
00588                 struct set_timezone {
00589                     std::string id;
00590                 };
00591                 template<typename CharType>
00592                 std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,set_timezone const &fmt)
00593                 {
00594                     ios_info::get(out).time_zone(fmt.id);
00595                     return out;
00596                 }
00597                 
00598                 template<typename CharType>
00599                 std::basic_istream<CharType> &operator>>(std::basic_istream<CharType> &in,set_timezone const &fmt)
00600                 {
00601                     ios_info::get(in).time_zone(fmt.id);
00602                     return in;
00603                 }
00604             }
00606             
00610             inline std::ios_base &gmt(std::ios_base &ios)
00611             {
00612                 ios_info::get(ios).time_zone("GMT");
00613                 return ios;
00614             }
00615 
00619             inline std::ios_base &local_time(std::ios_base &ios)
00620             {
00621                 ios_info::get(ios).time_zone(time_zone::global());
00622                 return ios;
00623             }
00624 
00628             inline 
00629             #ifdef BOOSTER_LOCALE_DOXYGEN
00630             unspecified_type
00631             #else
00632             details::set_timezone 
00633             #endif
00634             time_zone(char const *id) 
00635             {
00636                 details::set_timezone tz;
00637                 tz.id=id;
00638                 return tz;
00639             }
00640 
00644             inline 
00645             #ifdef BOOSTER_LOCALE_DOXYGEN
00646             unspecified_type
00647             #else
00648             details::set_timezone 
00649             #endif            
00650             time_zone(std::string const &id) 
00651             {
00652                 details::set_timezone tz;
00653                 tz.id=id;
00654                 return tz;
00655             }
00656 
00657 
00661 
00662         } // as manipulators
00663         
00664     } // locale
00665 } // boost
00666 
00667 #ifdef BOOSTER_MSVC
00668 #pragma warning(pop)
00669 #endif
00670 
00671 
00672 #endif
00673 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4