Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/locale/format.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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_FORMAT_HPP_INCLUDED | |
9 #define BOOST_LOCALE_FORMAT_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 <boost/locale/message.hpp> | |
17 #include <boost/locale/formatting.hpp> | |
18 | |
19 #include <sstream> | |
20 | |
21 | |
22 namespace boost { | |
23 namespace locale { | |
24 | |
25 /// | |
26 /// \defgroup format Format | |
27 /// | |
28 /// This module provides printf like functionality integrated into iostreams and suitable for localization | |
29 /// | |
30 /// @{ | |
31 /// | |
32 | |
33 /// \cond INTERNAL | |
34 namespace details { | |
35 | |
36 template<typename CharType> | |
37 struct formattible { | |
38 typedef std::basic_ostream<CharType> stream_type; | |
39 typedef void (*writer_type)(stream_type &output,void const *ptr); | |
40 | |
41 formattible() : | |
42 pointer_(0), | |
43 writer_(&formattible::void_write) | |
44 { | |
45 } | |
46 | |
47 formattible(formattible const &other) : | |
48 pointer_(other.pointer_), | |
49 writer_(other.writer_) | |
50 { | |
51 } | |
52 | |
53 formattible const &operator=(formattible const &other) | |
54 { | |
55 if(this != &other) { | |
56 pointer_=other.pointer_; | |
57 writer_=other.writer_; | |
58 } | |
59 return *this; | |
60 } | |
61 | |
62 template<typename Type> | |
63 formattible(Type const &value) | |
64 { | |
65 pointer_ = static_cast<void const *>(&value); | |
66 writer_ = &write<Type>; | |
67 } | |
68 | |
69 template<typename Type> | |
70 formattible const &operator=(Type const &other) | |
71 { | |
72 *this = formattible(other); | |
73 return *this; | |
74 } | |
75 | |
76 friend stream_type &operator<<(stream_type &out,formattible const &fmt) | |
77 { | |
78 fmt.writer_(out,fmt.pointer_); | |
79 return out; | |
80 } | |
81 | |
82 private: | |
83 static void void_write(stream_type &output,void const * /*ptr*/) | |
84 { | |
85 CharType empty_string[1]={0}; | |
86 output<<empty_string; | |
87 } | |
88 | |
89 template<typename Type> | |
90 static void write(stream_type &output,void const *ptr) | |
91 { | |
92 output << *static_cast<Type const *>(ptr); | |
93 } | |
94 | |
95 void const *pointer_; | |
96 writer_type writer_; | |
97 }; // formattible | |
98 | |
99 class BOOST_LOCALE_DECL format_parser { | |
100 public: | |
101 format_parser(std::ios_base &ios,void *,void (*imbuer)(void *,std::locale const &)); | |
102 ~format_parser(); | |
103 | |
104 unsigned get_position(); | |
105 | |
106 void set_one_flag(std::string const &key,std::string const &value); | |
107 | |
108 template<typename CharType> | |
109 void set_flag_with_str(std::string const &key,std::basic_string<CharType> const &value) | |
110 { | |
111 if(key=="ftime" || key=="strftime") { | |
112 as::strftime(ios_); | |
113 ios_info::get(ios_).date_time_pattern(value); | |
114 } | |
115 } | |
116 void restore(); | |
117 private: | |
118 void imbue(std::locale const &); | |
119 format_parser(format_parser const &); | |
120 void operator=(format_parser const &); | |
121 | |
122 std::ios_base &ios_; | |
123 struct data; | |
124 std::auto_ptr<data> d; | |
125 }; | |
126 | |
127 } | |
128 | |
129 /// \endcond | |
130 | |
131 /// | |
132 /// \brief a printf like class that allows type-safe and locale aware message formatting | |
133 /// | |
134 /// This class creates a formatted message similar to printf or boost::format and receives | |
135 /// formatted entries via operator %. | |
136 /// | |
137 /// For example | |
138 /// \code | |
139 /// cout << format("Hello {1}, you are {2} years old") % name % age << endl; | |
140 /// \endcode | |
141 /// | |
142 /// Formatting is enclosed between curly brackets \c { \c } and defined by a comma separated list of flags in the format key[=value] | |
143 /// value may also be text included between single quotes \c ' that is used for special purposes where inclusion of non-ASCII | |
144 /// text is allowed | |
145 /// | |
146 /// Including of literal \c { and \c } is possible by specifying double brackets \c {{ and \c }} accordingly. | |
147 /// | |
148 /// | |
149 /// For example: | |
150 /// | |
151 /// \code | |
152 /// cout << format("The height of water at {1,time} is {2,num=fixed,precision=3}") % time % height; | |
153 /// \endcode | |
154 /// | |
155 /// The special key -- a number without a value defines the position of an input parameter. | |
156 /// List of keys: | |
157 /// - \c [0-9]+ -- digits, the index of a formatted parameter -- mandatory key. | |
158 /// - \c num or \c number -- format a number. Optional values are: | |
159 /// - \c hex -- display hexadecimal number | |
160 /// - \c oct -- display in octal format | |
161 /// - \c sci or \c scientific -- display in scientific format | |
162 /// - \c fix or \c fixed -- display in fixed format | |
163 /// . | |
164 /// For example \c number=sci | |
165 /// - \c cur or \c currency -- format currency. Optional values are: | |
166 /// | |
167 /// - \c iso -- display using ISO currency symbol. | |
168 /// - \c nat or \c national -- display using national currency symbol. | |
169 /// . | |
170 /// - \c per or \c percent -- format percent value. | |
171 /// - \c date, \c time , \c datetime or \c dt -- format date, time or date and time. Optional values are: | |
172 /// - \c s or \c short -- display in short format | |
173 /// - \c m or \c medium -- display in medium format. | |
174 /// - \c l or \c long -- display in long format. | |
175 /// - \c f or \c full -- display in full format. | |
176 /// . | |
177 /// - \c ftime with string (quoted) parameter -- display as with \c strftime see, \c as::ftime manipulator | |
178 /// - \c spell or \c spellout -- spell the number. | |
179 /// - \c ord or \c ordinal -- format ordinal number (1st, 2nd... etc) | |
180 /// - \c left or \c < -- align to left. | |
181 /// - \c right or \c > -- align to right. | |
182 /// - \c width or \c w -- set field width (requires parameter). | |
183 /// - \c precision or \c p -- set precision (requires parameter). | |
184 /// - \c locale -- with parameter -- switch locale for current operation. This command generates locale | |
185 /// with formatting facets giving more fine grained control of formatting. For example: | |
186 /// \code | |
187 /// cout << format("Today {1,date} ({1,date,locale=he_IL.UTF-8@calendar=hebrew,date} Hebrew Date)") % date; | |
188 /// \endcode | |
189 /// - \c timezone or \c tz -- the name of the timezone to display the time in. For example:\n | |
190 /// \code | |
191 /// cout << format("Time is: Local {1,time}, ({1,time,tz=EET} Eastern European Time)") % date; | |
192 /// \endcode | |
193 /// - \c local - display the time in local time | |
194 /// - \c gmt - display the time in UTC time scale | |
195 /// \code | |
196 /// cout << format("Local time is: {1,time,local}, universal time is {1,time,gmt}") % time; | |
197 /// \endcode | |
198 /// | |
199 /// | |
200 /// Invalid formatting strings are slightly ignored. This would prevent from translator | |
201 /// to crash the program in unexpected location. | |
202 /// | |
203 template<typename CharType> | |
204 class basic_format { | |
205 public: | |
206 typedef CharType char_type; ///< Underlying character type | |
207 typedef basic_message<char_type> message_type; ///< The translation message type | |
208 /// \cond INTERNAL | |
209 typedef details::formattible<CharType> formattible_type; | |
210 /// \endcond | |
211 | |
212 typedef std::basic_string<CharType> string_type; ///< string type for this type of character | |
213 typedef std::basic_ostream<CharType> stream_type; ///< output stream type for this type of character | |
214 | |
215 | |
216 /// | |
217 /// Create a format class for \a format_string | |
218 /// | |
219 basic_format(string_type format_string) : | |
220 format_(format_string), | |
221 translate_(false), | |
222 parameters_count_(0) | |
223 { | |
224 } | |
225 /// | |
226 /// Create a format class using message \a trans. The message if translated first according | |
227 /// to the rules of target locale and then interpreted as format string | |
228 /// | |
229 basic_format(message_type const &trans) : | |
230 message_(trans), | |
231 translate_(true), | |
232 parameters_count_(0) | |
233 { | |
234 } | |
235 | |
236 /// | |
237 /// Add new parameter to format list. The object should be a type | |
238 /// with defined expression out << object where \c out is \c std::basic_ostream. | |
239 /// | |
240 template<typename Formattible> | |
241 basic_format &operator % (Formattible const &object) | |
242 { | |
243 add(formattible_type(object)); | |
244 return *this; | |
245 } | |
246 | |
247 /// | |
248 /// Format a string using a locale \a loc | |
249 /// | |
250 string_type str(std::locale const &loc = std::locale()) const | |
251 { | |
252 std::basic_ostringstream<CharType> buffer; | |
253 buffer.imbue(loc); | |
254 write(buffer); | |
255 return buffer.str(); | |
256 } | |
257 | |
258 /// | |
259 /// write a formatted string to output stream \a out using out's locale | |
260 /// | |
261 void write(stream_type &out) const | |
262 { | |
263 string_type format; | |
264 if(translate_) | |
265 format = message_.str(out.getloc(),ios_info::get(out).domain_id()); | |
266 else | |
267 format = format_; | |
268 | |
269 format_output(out,format); | |
270 | |
271 } | |
272 | |
273 | |
274 private: | |
275 | |
276 class format_guard { | |
277 public: | |
278 format_guard(details::format_parser &fmt) : | |
279 fmt_(&fmt), | |
280 restored_(false) | |
281 { | |
282 } | |
283 void restore() | |
284 { | |
285 if(restored_) | |
286 return; | |
287 fmt_->restore(); | |
288 restored_ = true; | |
289 } | |
290 ~format_guard() | |
291 { | |
292 try { | |
293 restore(); | |
294 } | |
295 catch(...) { | |
296 } | |
297 } | |
298 private: | |
299 details::format_parser *fmt_; | |
300 bool restored_; | |
301 }; | |
302 | |
303 void format_output(stream_type &out,string_type const &sformat) const | |
304 { | |
305 char_type obrk='{'; | |
306 char_type cbrk='}'; | |
307 char_type eq='='; | |
308 char_type comma=','; | |
309 char_type quote='\''; | |
310 | |
311 size_t pos = 0; | |
312 size_t size=sformat.size(); | |
313 CharType const *format=sformat.c_str(); | |
314 while(format[pos]!=0) { | |
315 if(format[pos] != obrk) { | |
316 if(format[pos]==cbrk && format[pos+1]==cbrk) { | |
317 out << cbrk; | |
318 pos+=2; | |
319 } | |
320 else { | |
321 out<<format[pos]; | |
322 pos++; | |
323 } | |
324 continue; | |
325 } | |
326 | |
327 if(pos+1 < size && format[pos+1]==obrk) { | |
328 out << obrk; | |
329 pos+=2; | |
330 continue; | |
331 } | |
332 pos++; | |
333 | |
334 details::format_parser fmt(out,static_cast<void *>(&out),&basic_format::imbue_locale); | |
335 | |
336 format_guard guard(fmt); | |
337 | |
338 while(pos < size) { | |
339 std::string key; | |
340 std::string svalue; | |
341 string_type value; | |
342 bool use_svalue = true; | |
343 for(;format[pos];pos++) { | |
344 char_type c=format[pos]; | |
345 if(c==comma || c==eq || c==cbrk) | |
346 break; | |
347 else { | |
348 key+=static_cast<char>(c); | |
349 } | |
350 } | |
351 | |
352 if(format[pos]==eq) { | |
353 pos++; | |
354 if(format[pos]==quote) { | |
355 pos++; | |
356 use_svalue = false; | |
357 while(format[pos]) { | |
358 if(format[pos]==quote) { | |
359 if(format[pos+1]==quote) { | |
360 value+=quote; | |
361 pos+=2; | |
362 } | |
363 else { | |
364 pos++; | |
365 break; | |
366 } | |
367 } | |
368 else { | |
369 value+=format[pos]; | |
370 pos++; | |
371 } | |
372 } | |
373 } | |
374 else { | |
375 char_type c; | |
376 while((c=format[pos])!=0 && c!=comma && c!=cbrk) { | |
377 svalue+=static_cast<char>(c); | |
378 pos++; | |
379 } | |
380 } | |
381 } | |
382 | |
383 if(use_svalue) { | |
384 fmt.set_one_flag(key,svalue); | |
385 } | |
386 else | |
387 fmt.set_flag_with_str(key,value); | |
388 | |
389 if(format[pos]==comma) { | |
390 pos++; | |
391 continue; | |
392 } | |
393 else if(format[pos]==cbrk) { | |
394 unsigned position = fmt.get_position(); | |
395 out << get(position); | |
396 guard.restore(); | |
397 pos++; | |
398 break; | |
399 } | |
400 else { | |
401 guard.restore(); | |
402 break; | |
403 } | |
404 } | |
405 } | |
406 } | |
407 | |
408 | |
409 // | |
410 // Non-copyable | |
411 // | |
412 basic_format(basic_format const &other); | |
413 void operator=(basic_format const &other); | |
414 | |
415 void add(formattible_type const ¶m) | |
416 { | |
417 if(parameters_count_ >= base_params_) | |
418 ext_params_.push_back(param); | |
419 else | |
420 parameters_[parameters_count_] = param; | |
421 parameters_count_++; | |
422 } | |
423 | |
424 formattible_type get(unsigned id) const | |
425 { | |
426 if(id >= parameters_count_) | |
427 return formattible_type(); | |
428 else if(id >= base_params_) | |
429 return ext_params_[id - base_params_]; | |
430 else | |
431 return parameters_[id]; | |
432 } | |
433 | |
434 static void imbue_locale(void *ptr,std::locale const &l) | |
435 { | |
436 reinterpret_cast<stream_type *>(ptr)->imbue(l); | |
437 } | |
438 | |
439 | |
440 | |
441 static unsigned const base_params_ = 8; | |
442 | |
443 message_type message_; | |
444 string_type format_; | |
445 bool translate_; | |
446 | |
447 | |
448 formattible_type parameters_[base_params_]; | |
449 unsigned parameters_count_; | |
450 std::vector<formattible_type> ext_params_; | |
451 }; | |
452 | |
453 /// | |
454 /// Write formatted message to stream. | |
455 /// | |
456 /// This operator actually causes actual text formatting. It uses the locale of \a out stream | |
457 /// | |
458 template<typename CharType> | |
459 std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_format<CharType> const &fmt) | |
460 { | |
461 fmt.write(out); | |
462 return out; | |
463 } | |
464 | |
465 | |
466 /// | |
467 /// Definition of char based format | |
468 /// | |
469 typedef basic_format<char> format; | |
470 | |
471 /// | |
472 /// Definition of wchar_t based format | |
473 /// | |
474 typedef basic_format<wchar_t> wformat; | |
475 | |
476 #ifdef BOOST_HAS_CHAR16_T | |
477 /// | |
478 /// Definition of char16_t based format | |
479 /// | |
480 typedef basic_format<char16_t> u16format; | |
481 #endif | |
482 | |
483 #ifdef BOOST_HAS_CHAR32_T | |
484 /// | |
485 /// Definition of char32_t based format | |
486 /// | |
487 typedef basic_format<char32_t> u32format; | |
488 #endif | |
489 | |
490 /// | |
491 /// @} | |
492 /// | |
493 | |
494 } | |
495 } | |
496 | |
497 #ifdef BOOST_MSVC | |
498 #pragma warning(pop) | |
499 #endif | |
500 | |
501 #endif | |
502 | |
503 /// | |
504 /// \example hello.cpp | |
505 /// | |
506 /// Basic example of using various functions provided by this library | |
507 /// | |
508 /// \example whello.cpp | |
509 /// | |
510 /// Basic example of using various functions with wide strings provided by this library | |
511 /// | |
512 /// | |
513 | |
514 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 | |
515 |