CppCMS

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

format.h
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 BOOSTER_LOCALE_FORMAT_H_INCLUDED
9 #define BOOSTER_LOCALE_FORMAT_H_INCLUDED
10
11 #include <booster/config.h>
12 #ifdef BOOSTER_MSVC
13 # pragma warning(push)
14 # pragma warning(disable : 4275 4251 4231 4660)
15 #endif
16 #include <booster/locale/message.h>
17 #include <booster/locale/formatting.h>
18
19 #include <sstream>
20
21
22 namespace booster {
23 namespace locale {
24
32
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 BOOSTER_API 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
130
203 template<typename CharType>
204 class basic_format {
205 public:
206 typedef CharType char_type;
207 typedef basic_message<char_type> message_type;
208 typedef details::formattible<CharType> formattible_type;
211
212 typedef std::basic_string<CharType> string_type;
213 typedef std::basic_ostream<CharType> stream_type;
214
215
219 basic_format(string_type format_string) :
220 format_(format_string),
221 translate_(false),
222 parameters_count_(0)
223 {
224 }
229 basic_format(message_type const &trans) :
230 message_(trans),
231 translate_(true),
232 parameters_count_(0)
233 {
234 }
235
240 template<typename Formattible>
241 basic_format &operator % (Formattible const &object)
242 {
243 add(formattible_type(object));
244 return *this;
245 }
246
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
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 &param)
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
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
469 typedef basic_format<char> format;
470
474 typedef basic_format<wchar_t> wformat;
475
476 #ifdef BOOSTER_HAS_CHAR16_T
477 typedef basic_format<char16_t> u16format;
481 #endif
482
483 #ifdef BOOSTER_HAS_CHAR32_T
484 typedef basic_format<char32_t> u32format;
488 #endif
489
493
494 }
495 }
496
497 #ifdef BOOSTER_MSVC
498 #pragma warning(pop)
499 #endif
500
501 #endif
502
513
514 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
515
booster::locale::basic_format::char_type
CharType char_type
Underlying character type.
Definition: format.h:206
booster::locale::basic_format::string_type
std::basic_string< CharType > string_type
string type for this type of character
Definition: format.h:212
booster::locale::ios_info::domain_id
void domain_id(int)
booster::locale::basic_format::basic_format
basic_format(string_type format_string)
Definition: format.h:219
booster::locale::operator<<
std::basic_ostream< CharType > & operator<<(std::basic_ostream< CharType > &out, date_time const &t)
Definition: date_time.h:874
booster::locale::basic_format::stream_type
std::basic_ostream< CharType > stream_type
output stream type for this type of character
Definition: format.h:213
booster::locale::basic_format::basic_format
basic_format(message_type const &trans)
Definition: format.h:229
booster::locale::ios_info::get
static ios_info & get(std::ios_base &ios)
booster::locale::wformat
basic_format< wchar_t > wformat
Definition: format.h:474
booster::locale::basic_format::str
string_type str(std::locale const &loc=std::locale()) const
Definition: format.h:250
booster::locale
This is the main namespace that encloses all localization classes.
Definition: locale_fwd.h:14
booster::locale::basic_format::message_type
basic_message< char_type > message_type
Definition: format.h:207
booster::locale::ios_info::date_time_pattern
void date_time_pattern(std::basic_string< CharType > const &str)
Definition: formatting.h:155
booster::locale::format
basic_format< char > format
Definition: format.h:469
booster::locale::basic_message< char_type >
booster::locale::as::strftime
std::ios_base & strftime(std::ios_base &ios)
Definition: formatting.h:347
booster::locale::basic_format
a printf like class that allows type-safe and locale aware message formatting
Definition: format.h:204
booster
Booster library namespace. The library that implements Boost Like API in ABI backward compatible way...
Definition: application.h:23
booster::locale::basic_format::write
void write(stream_type &out) const
Definition: format.h:261