00001
00002
00003
00004
00005
00006
00007
00008 #ifndef BOOST_LOCALE_FORMAT_HPP_INCLUDED
00009 #define BOOST_LOCALE_FORMAT_HPP_INCLUDED
00010
00011 #include <boost/locale/config.hpp>
00012 #ifdef BOOST_MSVC
00013 # pragma warning(push)
00014 # pragma warning(disable : 4275 4251 4231 4660)
00015 #endif
00016 #include <boost/locale/message.hpp>
00017 #include <boost/locale/formatting.hpp>
00018
00019 #include <sstream>
00020 #include <iostream>
00021
00022
00023 namespace boost {
00024 namespace locale {
00025
00033
00035 namespace details {
00036
00037 template<typename CharType>
00038 struct formattible {
00039 typedef std::basic_ostream<CharType> stream_type;
00040 typedef void (*writer_type)(stream_type &output,void const *ptr);
00041
00042 formattible() :
00043 pointer_(0),
00044 writer_(&formattible::void_write)
00045 {
00046 }
00047
00048 formattible(formattible const &other) :
00049 pointer_(other.pointer_),
00050 writer_(other.writer_)
00051 {
00052 }
00053
00054 formattible const &operator=(formattible const &other)
00055 {
00056 if(this != &other) {
00057 pointer_=other.pointer_;
00058 writer_=other.writer_;
00059 }
00060 return *this;
00061 }
00062
00063 template<typename Type>
00064 formattible(Type const &value)
00065 {
00066 pointer_ = reinterpret_cast<void const *>(&value);
00067 writer_ = &write<Type>;
00068 }
00069
00070 template<typename Type>
00071 formattible const &operator=(Type const &other)
00072 {
00073 *this = formattible(other);
00074 return *this;
00075 }
00076
00077 friend stream_type &operator<<(stream_type &out,formattible const &fmt)
00078 {
00079 fmt.writer_(out,fmt.pointer_);
00080 return out;
00081 }
00082
00083 private:
00084 static void void_write(stream_type &output,void const *ptr)
00085 {
00086 CharType empty_string[1]={0};
00087 output<<empty_string;
00088 }
00089
00090 template<typename Type>
00091 static void write(stream_type &output,void const *ptr)
00092 {
00093 output << *reinterpret_cast<Type const *>(ptr);
00094 }
00095
00096 void const *pointer_;
00097 writer_type writer_;
00098 };
00099
00100 class BOOST_LOCALE_DECL format_parser {
00101 public:
00102 format_parser(std::ios_base &ios);
00103 ~format_parser();
00104
00105 unsigned get_posision();
00106
00107 void set_one_flag(std::string const &key,std::string const &value);
00108
00109 template<typename CharType>
00110 void set_flag_with_str(std::string const &key,std::basic_string<CharType> const &value)
00111 {
00112 if(key=="ftime" || key=="strftime") {
00113 as::strftime(ios_);
00114 ext_pattern(ios_,flags::datetime_pattern,value);
00115 }
00116 }
00117 void restore();
00118 private:
00119 format_parser(format_parser const &);
00120 void operator=(format_parser const &);
00121
00122 std::ios_base &ios_;
00123 struct data;
00124 std::auto_ptr<data> d;
00125 };
00126
00127 }
00128
00130
00186 template<typename CharType>
00187 class basic_format {
00188 public:
00189 typedef CharType char_type;
00190
00191 typedef details::formattible<CharType> formattible_type;
00193
00194 typedef std::basic_string<CharType> string_type;
00195 typedef std::basic_ostream<CharType> stream_type;
00196
00197
00201 basic_format(string_type format_string) :
00202 format_(format_string),
00203 translate_(false),
00204 parameters_count_(0)
00205 {
00206 }
00211 basic_format(message const &trans) :
00212 message_(trans),
00213 translate_(true),
00214 parameters_count_(0)
00215 {
00216 }
00217
00221 template<typename Formattible>
00222 basic_format &operator % (Formattible const &object)
00223 {
00224 add(formattible_type(object));
00225 return *this;
00226 }
00227
00231 string_type str(std::locale const &loc = std::locale()) const
00232 {
00233 std::basic_ostringstream<CharType> buffer;
00234 buffer.imbue(loc);
00235 write(buffer,false);
00236 return buffer.str();
00237 }
00238
00242 void write(stream_type &out) const
00243 {
00244 string_type format;
00245 if(translate_)
00246 format = message_.str<CharType>(out.getloc(),ext_value(out,flags::domain_id));
00247 else
00248 format = format_;
00249
00250 format_output(out,format);
00251
00252 }
00253
00254
00255 private:
00256
00257 void format_output(stream_type &out,string_type const &sformat) const
00258 {
00259 char_type obrk='{';
00260 char_type cbrk='}';
00261 char_type eq='=';
00262 char_type comma=',';
00263 char_type quote='\'';
00264
00265 size_t pos = 0;
00266 size_t size=sformat.size();
00267 CharType const *format=sformat.c_str();
00268 while(format[pos]!=0) {
00269 if(format[pos] != obrk) {
00270 if(format[pos]==cbrk && format[pos+1]==cbrk) {
00271 out << cbrk;
00272 pos+=2;
00273 }
00274 else {
00275 out<<format[pos];
00276 pos++;
00277 }
00278 continue;
00279 }
00280
00281 if(pos+1 < size && format[pos+1]==obrk) {
00282 out << obrk;
00283 pos+=2;
00284 continue;
00285 }
00286 pos++;
00287
00288
00289 details::format_parser fmt(out);
00290
00291 while(pos < size) {
00292 std::string key;
00293 std::string svalue;
00294 string_type value;
00295 bool use_svalue = true;
00296 for(;format[pos];pos++) {
00297 char_type c=format[pos];
00298 if(c==comma || c==eq || c==cbrk)
00299 break;
00300 else {
00301 key+=static_cast<char>(c);
00302 }
00303 }
00304
00305 if(format[pos]==eq) {
00306 pos++;
00307 if(format[pos]==quote) {
00308 pos++;
00309 use_svalue = false;
00310 while(format[pos]) {
00311 if(format[pos]==quote) {
00312 if(format[pos+1]==quote) {
00313 value+=quote;
00314 pos+=2;
00315 }
00316 else {
00317 pos++;
00318 break;
00319 }
00320 }
00321 else {
00322 value+=format[pos];
00323 pos++;
00324 }
00325 }
00326 }
00327 else {
00328 char_type c;
00329 while((c=format[pos])!=0 && c!=comma && c!=cbrk) {
00330 svalue+=static_cast<char>(c);
00331 pos++;
00332 }
00333 }
00334 }
00335
00336 if(use_svalue)
00337 fmt.set_one_flag(key,svalue);
00338 else
00339 fmt.set_flag_with_str(key,value);
00340
00341 if(format[pos]==',') {
00342 pos++;
00343 continue;
00344 }
00345 else if(format[pos]=='}') {
00346 unsigned position = fmt.get_posision();
00347 out << get(position);
00348 fmt.restore();
00349 pos++;
00350 break;
00351 }
00352 else {
00353 fmt.restore();
00354 break;
00355 }
00356 }
00357 }
00358 }
00359
00360
00361
00362
00363
00364 basic_format(basic_format const &other);
00365 void operator=(basic_format const &other);
00366
00367 void add(formattible_type const ¶m)
00368 {
00369 if(parameters_count_ >= base_params_)
00370 ext_params_.push_back(param);
00371 else
00372 parameters_[parameters_count_] = param;
00373 parameters_count_++;
00374 }
00375
00376 formattible_type get(unsigned id) const
00377 {
00378 if(id >= parameters_count_)
00379 return formattible_type();
00380 else if(id >= base_params_)
00381 return ext_params_[id - base_params_];
00382 else
00383 return parameters_[id];
00384 }
00385
00386
00387
00388 static unsigned const base_params_ = 8;
00389
00390 message message_;
00391 string_type format_;
00392 bool translate_;
00393
00394
00395 formattible_type parameters_[base_params_];
00396 unsigned parameters_count_;
00397 std::vector<formattible_type> ext_params_;
00398 };
00399
00405 template<typename CharType>
00406 std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_format<CharType> const &fmt)
00407 {
00408 fmt.write(out);
00409 return out;
00410 }
00411
00412
00416 typedef basic_format<char> format;
00417
00418 #ifndef BOOST_NO_STD_WSTRING
00422 typedef basic_format<wchar_t> wformat;
00423 #endif
00424
00425 #ifdef BOOST_HAS_CHAR16_T
00429 typedef basic_format<char16_t> u16format;
00430 #endif
00431
00432 #ifdef BOOST_HAS_CHAR32_T
00436 typedef basic_format<char32_t> u32format;
00437 #endif
00438
00442
00443 }
00444 }
00445
00446 #ifdef BOOST_MSVC
00447 #pragma warning(pop)
00448 #endif
00449
00450 #endif
00451
00462
00463
00464