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 #define BOOST_LOCALE_SOURCE
9 #include <boost/locale/format.hpp>
10 #include <boost/locale/generator.hpp>
11 #include <boost/locale/info.hpp>
12 #include <limits>
13 #include <stdlib.h>
14 
15 #include <iostream>
16 
17 namespace boost {
18     namespace locale {
19         namespace details {
20             struct format_parser::data {
21                 unsigned position;
22                 std::streamsize precision;
23                 std::ios_base::fmtflags flags;
24                 ios_info info;
25                 std::locale saved_locale;
26                 bool restore_locale;
27                 void *cookie;
28                 void (*imbuer)(void *,std::locale const &);
29             };
30 
format_parser(std::ios_base & ios,void * cookie,void (* imbuer)(void *,std::locale const &))31             format_parser::format_parser(std::ios_base &ios,void *cookie,void (*imbuer)(void *,std::locale const &)) :
32                 ios_(ios),
33                 d(new data)
34             {
35                 d->position=std::numeric_limits<unsigned>::max();
36                 d->precision=ios.precision();
37                 d->flags = ios.flags();
38                 d->info=ios_info::get(ios);
39                 d->saved_locale = ios.getloc();
40                 d->restore_locale=false;
41                 d->cookie = cookie;
42                 d->imbuer = imbuer;
43             }
44 
imbue(std::locale const & l)45             void format_parser::imbue(std::locale const &l)
46             {
47                 d->imbuer(d->cookie,l);
48             }
49 
~format_parser()50             format_parser::~format_parser()
51             {
52             }
53 
restore()54             void format_parser::restore()
55             {
56                 ios_info::get(ios_) = d->info;
57                 ios_.width(0);
58                 ios_.flags(d->flags);
59                 if(d->restore_locale)
60                     imbue(d->saved_locale);
61             }
62 
get_position()63             unsigned format_parser::get_position()
64             {
65                 return d->position;
66             }
67 
set_one_flag(std::string const & key,std::string const & value)68             void format_parser::set_one_flag(std::string const &key,std::string const &value)
69             {
70                 if(key.empty())
71                     return;
72                 unsigned i;
73                 for(i=0;i<key.size();i++) {
74                     if(key[i] < '0' || '9'< key[i])
75                         break;
76                 }
77                 if(i==key.size()) {
78                     d->position=atoi(key.c_str()) - 1;
79                     return;
80                 }
81 
82                 if(key=="num" || key=="number") {
83                     as::number(ios_);
84 
85                     if(value=="hex")
86                         ios_.setf(std::ios_base::hex,std::ios_base::basefield);
87                     else if(value=="oct")
88                         ios_.setf(std::ios_base::oct,std::ios_base::basefield);
89                     else if(value=="sci" || value=="scientific")
90                         ios_.setf(std::ios_base::scientific,std::ios_base::floatfield);
91                     else if(value=="fix" || value=="fixed")
92                         ios_.setf(std::ios_base::fixed,std::ios_base::floatfield);
93                 }
94                 else if(key=="cur" || key=="currency") {
95                     as::currency(ios_);
96                     if(value=="iso")
97                         as::currency_iso(ios_);
98                     else if(value=="nat" || value=="national")
99                         as::currency_national(ios_);
100                 }
101                 else if(key=="per" || key=="percent") {
102                     as::percent(ios_);
103                 }
104                 else if(key=="date") {
105                     as::date(ios_);
106                     if(value=="s" || value=="short")
107                         as::date_short(ios_);
108                     else if(value=="m" || value=="medium")
109                         as::date_medium(ios_);
110                     else if(value=="l" || value=="long")
111                         as::date_long(ios_);
112                     else if(value=="f" || value=="full")
113                         as::date_full(ios_);
114                 }
115                 else if(key=="time") {
116                     as::time(ios_);
117                     if(value=="s" || value=="short")
118                         as::time_short(ios_);
119                     else if(value=="m" || value=="medium")
120                         as::time_medium(ios_);
121                     else if(value=="l" || value=="long")
122                         as::time_long(ios_);
123                     else if(value=="f" || value=="full")
124                         as::time_full(ios_);
125                 }
126                 else if(key=="dt" || key=="datetime") {
127                     as::datetime(ios_);
128                     if(value=="s" || value=="short") {
129                         as::date_short(ios_);
130                         as::time_short(ios_);
131                     }
132                     else if(value=="m" || value=="medium") {
133                         as::date_medium(ios_);
134                         as::time_medium(ios_);
135                     }
136                     else if(value=="l" || value=="long") {
137                         as::date_long(ios_);
138                         as::time_long(ios_);
139                     }
140                     else if(value=="f" || value=="full") {
141                         as::date_full(ios_);
142                         as::time_full(ios_);
143                     }
144                 }
145                 else if(key=="spell" || key=="spellout") {
146                     as::spellout(ios_);
147                 }
148                 else if(key=="ord" || key=="ordinal") {
149                     as::ordinal(ios_);
150                 }
151                 else if(key=="left" || key=="<")
152                     ios_.setf(std::ios_base::left,std::ios_base::adjustfield);
153                 else if(key=="right" || key==">")
154                     ios_.setf(std::ios_base::right,std::ios_base::adjustfield);
155                 else if(key=="gmt")
156                     as::gmt(ios_);
157                 else if(key=="local")
158                     as::local_time(ios_);
159                 else if(key=="timezone" || key=="tz")
160                     ios_info::get(ios_).time_zone(value);
161                 else if(key=="w" || key=="width")
162                     ios_.width(atoi(value.c_str()));
163                 else if(key=="p" || key=="precision")
164                     ios_.precision(atoi(value.c_str()));
165                 else if(key=="locale") {
166                     if(!d->restore_locale) {
167                         d->saved_locale=ios_.getloc();
168                         d->restore_locale=true;
169                     }
170 
171                     std::string encoding=std::use_facet<info>(d->saved_locale).encoding();
172                     generator gen;
173                     gen.categories(formatting_facet);
174 
175                     std::locale new_loc;
176                     if(value.find('.')==std::string::npos)
177                         new_loc = gen(value + "." +  encoding);
178                     else
179                         new_loc = gen(value);
180 
181                     imbue(new_loc);
182                 }
183 
184             }
185         }
186     }
187 }
188 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
189