]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/locale/src/util/numeric.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / locale / src / util / numeric.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_IMPL_UTIL_NUMERIC_HPP
9 #define BOOST_LOCALE_IMPL_UTIL_NUMERIC_HPP
10 #include <locale>
11 #include <string>
12 #include <ios>
13 #include <boost/locale/formatting.hpp>
14 #include <boost/locale/info.hpp>
15 #include <sstream>
16 #include <vector>
17 #include <ctime>
18 #include <stdlib.h>
19
20 #include "timezone.hpp"
21
22 // This is internal header so disable crappy "unsecure functions" for all
23 #ifdef BOOST_MSVC
24 # pragma warning(disable : 4996)
25 #endif
26
27
28 namespace boost {
29 namespace locale {
30 namespace util {
31
32 template<typename CharType>
33 struct formatting_size_traits {
34 static size_t size(std::basic_string<CharType> const &s,std::locale const &/*l*/)
35 {
36 return s.size();
37 }
38 };
39
40 template<>
41 struct formatting_size_traits<char> {
42 static size_t size(std::string const &s,std::locale const &l)
43 {
44 if(!std::has_facet<info>(l))
45 return s.size();
46 if(!std::use_facet<info>(l).utf8())
47 return s.size();
48 // count code points, poor man's text size
49 size_t res = 0;
50 for(size_t i=0;i<s.size();i++) {
51 unsigned char c = s[i];
52 if(c <= 127)
53 res ++;
54 else if ((c & 0xC0) == 0xC0) { // first UTF-8 byte
55 res ++;
56 }
57 }
58 return res;
59 }
60 };
61
62
63
64 template<typename CharType>
65 class base_num_format : public std::num_put<CharType>
66 {
67 public:
68 typedef typename std::num_put<CharType>::iter_type iter_type;
69 typedef std::basic_string<CharType> string_type;
70 typedef CharType char_type;
71
72 base_num_format(size_t refs = 0) :
73 std::num_put<CharType>(refs)
74 {
75 }
76 protected:
77
78
79 virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, long val) const
80 {
81 return do_real_put(out,ios,fill,val);
82 }
83 virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, unsigned long val) const
84 {
85 return do_real_put(out,ios,fill,val);
86 }
87 virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, double val) const
88 {
89 return do_real_put(out,ios,fill,val);
90 }
91 virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, long double val) const
92 {
93 return do_real_put(out,ios,fill,val);
94 }
95
96 #ifndef BOOST_NO_LONG_LONG
97 virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, long long val) const
98 {
99 return do_real_put(out,ios,fill,val);
100 }
101 virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, unsigned long long val) const
102 {
103 return do_real_put(out,ios,fill,val);
104 }
105 #endif
106
107
108 private:
109
110
111
112 template<typename ValueType>
113 iter_type do_real_put (iter_type out, std::ios_base &ios, char_type fill, ValueType val) const
114 {
115 typedef std::num_put<char_type> super;
116
117 ios_info &info=ios_info::get(ios);
118
119 switch(info.display_flags()) {
120 case flags::posix:
121 {
122 typedef std::basic_ostringstream<char_type> sstream_type;
123 sstream_type ss;
124 ss.imbue(std::locale::classic());
125 ss.flags(ios.flags());
126 ss.precision(ios.precision());
127 ss.width(ios.width());
128 iter_type ret_ptr = super::do_put(out,ss,fill,val);
129 ios.width(0);
130 return ret_ptr;
131 }
132 case flags::date:
133 return format_time(out,ios,fill,static_cast<std::time_t>(val),'x');
134 case flags::time:
135 return format_time(out,ios,fill,static_cast<std::time_t>(val),'X');
136 case flags::datetime:
137 return format_time(out,ios,fill,static_cast<std::time_t>(val),'c');
138 case flags::strftime:
139 return format_time(out,ios,fill,static_cast<std::time_t>(val),info.date_time_pattern<char_type>());
140 case flags::currency:
141 {
142 bool nat = info.currency_flags()==flags::currency_default
143 || info.currency_flags() == flags::currency_national;
144 bool intl = !nat;
145 return do_format_currency(intl,out,ios,fill,static_cast<long double>(val));
146 }
147
148 case flags::number:
149 case flags::percent:
150 case flags::spellout:
151 case flags::ordinal:
152 default:
153 return super::do_put(out,ios,fill,val);
154 }
155 }
156
157 virtual iter_type do_format_currency(bool intl,iter_type out,std::ios_base &ios,char_type fill,long double val) const
158 {
159 if(intl)
160 return format_currency<true>(out,ios,fill,val);
161 else
162 return format_currency<false>(out,ios,fill,val);
163 }
164
165 template<bool intl>
166 iter_type format_currency(iter_type out,std::ios_base &ios,char_type fill,long double val) const
167 {
168 std::locale loc = ios.getloc();
169 int digits = std::use_facet<std::moneypunct<char_type,intl> >(loc).frac_digits();
170 while(digits > 0) {
171 val*=10;
172 digits --;
173 }
174 std::ios_base::fmtflags f=ios.flags();
175 ios.flags(f | std::ios_base::showbase);
176 out = std::use_facet<std::money_put<char_type> >(loc).put(out,intl,ios,fill,val);
177 ios.flags(f);
178 return out;
179 }
180
181 iter_type format_time(iter_type out,std::ios_base &ios,char_type fill,std::time_t time,char c) const
182 {
183 string_type fmt;
184 fmt+=char_type('%');
185 fmt+=char_type(c);
186 return format_time(out,ios,fill,time,fmt);
187 }
188
189 iter_type format_time(iter_type out,std::ios_base &ios,char_type fill,std::time_t time,string_type const &format) const
190 {
191 std::string tz = ios_info::get(ios).time_zone();
192 std::tm tm;
193 #if defined(__linux) || defined(__FreeBSD__) || defined(__APPLE__)
194 std::vector<char> tmp_buf(tz.c_str(),tz.c_str()+tz.size()+1);
195 #endif
196 if(tz.empty()) {
197 #ifdef BOOST_WINDOWS
198 /// Windows uses TLS
199 tm = *localtime(&time);
200 #else
201 localtime_r(&time,&tm);
202 #endif
203 }
204 else {
205 int gmtoff = parse_tz(tz);
206 time+=gmtoff;
207 #ifdef BOOST_WINDOWS
208 /// Windows uses TLS
209 tm = *gmtime(&time);
210 #else
211 gmtime_r(&time,&tm);
212 #endif
213
214 #if defined(__linux) || defined(__FreeBSD__) || defined(__APPLE__)
215 // These have extra fields to specify timezone
216 if(gmtoff!=0) {
217 // bsd and apple want tm_zone be non-const
218 tm.tm_zone=&tmp_buf.front();
219 tm.tm_gmtoff = gmtoff;
220 }
221 #endif
222 }
223 std::basic_ostringstream<char_type> tmp_out;
224 std::use_facet<std::time_put<char_type> >(ios.getloc()).put(tmp_out,tmp_out,fill,&tm,format.c_str(),format.c_str()+format.size());
225 string_type str = tmp_out.str();
226 std::streamsize on_left=0,on_right = 0;
227 std::streamsize points =
228 formatting_size_traits<char_type>::size(str,ios.getloc());
229 if(points < ios.width()) {
230 std::streamsize n = ios.width() - points;
231
232 std::ios_base::fmtflags flags = ios.flags() & std::ios_base::adjustfield;
233
234 //
235 // we do not really know internal point, so we assume that it does not
236 // exist. so according to the standard field should be right aligned
237 //
238 if(flags != std::ios_base::left)
239 on_left = n;
240 on_right = n - on_left;
241 }
242 while(on_left > 0) {
243 *out++ = fill;
244 on_left--;
245 }
246 std::copy(str.begin(),str.end(),out);
247 while(on_right > 0) {
248 *out++ = fill;
249 on_right--;
250 }
251 ios.width(0);
252 return out;
253 }
254
255 }; /// num_format
256
257
258 template<typename CharType>
259 class base_num_parse : public std::num_get<CharType>
260 {
261 public:
262 base_num_parse(size_t refs = 0) :
263 std::num_get<CharType>(refs)
264 {
265 }
266 protected:
267 typedef typename std::num_get<CharType>::iter_type iter_type;
268 typedef std::basic_string<CharType> string_type;
269 typedef CharType char_type;
270
271 virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,long &val) const
272 {
273 return do_real_get(in,end,ios,err,val);
274 }
275
276 virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned short &val) const
277 {
278 return do_real_get(in,end,ios,err,val);
279 }
280
281 virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned int &val) const
282 {
283 return do_real_get(in,end,ios,err,val);
284 }
285
286 virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned long &val) const
287 {
288 return do_real_get(in,end,ios,err,val);
289 }
290
291 virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,float &val) const
292 {
293 return do_real_get(in,end,ios,err,val);
294 }
295
296 virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,double &val) const
297 {
298 return do_real_get(in,end,ios,err,val);
299 }
300
301 virtual iter_type do_get (iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,long double &val) const
302 {
303 return do_real_get(in,end,ios,err,val);
304 }
305
306 #ifndef BOOST_NO_LONG_LONG
307 virtual iter_type do_get (iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,long long &val) const
308 {
309 return do_real_get(in,end,ios,err,val);
310 }
311
312 virtual iter_type do_get (iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned long long &val) const
313 {
314 return do_real_get(in,end,ios,err,val);
315 }
316
317 #endif
318
319 private:
320
321 template<typename ValueType>
322 iter_type do_real_get(iter_type in,iter_type end,std::ios_base &ios,std::ios_base::iostate &err,ValueType &val) const
323 {
324 typedef std::num_get<char_type> super;
325
326 ios_info &info=ios_info::get(ios);
327
328 switch(info.display_flags()) {
329 case flags::posix:
330 {
331 std::stringstream ss;
332 ss.imbue(std::locale::classic());
333 ss.flags(ios.flags());
334 ss.precision(ios.precision());
335 return super::do_get(in,end,ss,err,val);
336 }
337 case flags::currency:
338 {
339 long double ret_val = 0;
340 if(info.currency_flags()==flags::currency_default || info.currency_flags() == flags::currency_national)
341 in = parse_currency<false>(in,end,ios,err,ret_val);
342 else
343 in = parse_currency<true>(in,end,ios,err,ret_val);
344 if(!(err & std::ios_base::failbit))
345 val = static_cast<ValueType>(ret_val);
346 return in;
347 }
348
349 // date-time parsing is not supported
350 // due to buggy standard
351 case flags::date:
352 case flags::time:
353 case flags::datetime:
354 case flags::strftime:
355
356 case flags::number:
357 case flags::percent:
358 case flags::spellout:
359 case flags::ordinal:
360 default:
361 return super::do_get(in,end,ios,err,val);
362 }
363 }
364
365 template<bool intl>
366 iter_type parse_currency(iter_type in,iter_type end,std::ios_base &ios,std::ios_base::iostate &err,long double &val) const
367 {
368 std::locale loc = ios.getloc();
369 int digits = std::use_facet<std::moneypunct<char_type,intl> >(loc).frac_digits();
370 long double rval;
371 in = std::use_facet<std::money_get<char_type> >(loc).get(in,end,intl,ios,err,rval);
372 if(!(err & std::ios::failbit)) {
373 while(digits > 0) {
374 rval/=10;
375 digits --;
376 }
377 val = rval;
378 }
379 return in;
380 }
381
382
383 };
384
385 } // util
386 } // locale
387 } //boost
388
389
390
391
392 #endif
393 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4