fmtio.h
Go to the documentation of this file.00001 #ifndef format_h_header_included_p
00002 #define format_h_header_included_p
00003
00011
00012 #include <portable_io.h>
00013
00014 #include <iostream>
00015 #include <string>
00016 #include <sstream>
00017 #include <iomanip>
00018
00019
00020
00021 namespace fmtio
00025 {
00026
00027
00028
00029 namespace printableType
00042 {
00043
00044
00045
00046
00047
00048
00049
00050
00051 struct Integral {};
00052 struct String {};
00053 struct StlString {};
00054 struct Float {};
00055 struct DoubleFloat {};
00056 struct UserDefined {};
00057 struct Unsigned {};
00058 struct Char {};
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 template<class T> struct devolify { typedef T type; };
00071 template<class T> struct devolify<T volatile> { typedef T type; };
00072
00073 template<class T> struct deconstify { typedef typename devolify<T>::type type; };
00074 template<class T> struct deconstify<T const> { typedef typename devolify<T>::type type; };
00075
00076
00077
00078 template<int N> struct typeDetector;
00089
00090 template<> struct typeDetector<1> { typedef UserDefined type; };
00091 template<> struct typeDetector<0> { typedef Integral type; };
00092
00093 template<class Type>
00094 struct isClassType
00099 {
00100
00101 template <typename ClassType>
00102 static short fun(void (ClassType::*)());
00103
00104 template <typename NonClassType>
00105 static char fun(...);
00106
00107 enum { value = sizeof(fun<Type>(0)) == sizeof(short) };
00108 };
00109
00110
00111
00112 template<class T>
00113 struct classification
00122 {
00123 typedef typename typeDetector< isClassType< typename deconstify<T>::type >::value >::type printableClass;
00124 };
00125
00126
00127
00128
00129
00130
00131 template<class T>
00132 typename classification< typename deconstify<T>::type >::printableClass
00133 classifier(T const &t)
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 {
00145 return typename classification< typename deconstify<T>::type >::printableClass();
00146 }
00147
00148
00149
00150 template<class T> struct classification<T *> { typedef Integral printableClass; };
00156
00157
00158
00159
00160 template<> struct classification<int> { typedef Integral printableClass; };
00161 template<> struct classification<short> { typedef Integral printableClass; };
00162 template<> struct classification<long> { typedef Integral printableClass; };
00163 template<> struct classification<long long> { typedef Integral printableClass; };
00164
00165 template<> struct classification<unsigned int> { typedef Unsigned printableClass; };
00166 template<> struct classification<unsigned short> { typedef Unsigned printableClass; };
00167 template<> struct classification<unsigned long> { typedef Unsigned printableClass; };
00168 template<> struct classification<unsigned long long> { typedef Unsigned printableClass; };
00169
00170
00171
00172
00173 template<> struct classification<char> { typedef Char printableClass; };
00174 template<> struct classification<unsigned char> { typedef Char printableClass; };
00175
00176
00177
00178 template<> struct classification<float> { typedef Float printableClass; };
00179 template<> struct classification<double> { typedef DoubleFloat printableClass; };
00180
00181
00182
00183
00184
00185
00186
00187 template<> struct classification<char*> { typedef String printableClass; };
00188 template<> struct classification<unsigned char*> { typedef String printableClass; };
00189 template<> struct classification<unsigned char const *>{ typedef String printableClass; };
00190 template<> struct classification<std::string> { typedef StlString printableClass; };
00191
00192
00193
00194 struct Exception
00196 {
00197 char expectedFormat_;
00198
00199 char const *foundType_;
00200
00201 Exception(char e, char const *found)
00202 : expectedFormat_(e)
00203 , foundType_(found)
00204 {
00205 }
00206
00207 };
00208 };
00209
00210
00211
00212 class cs
00322 {
00323
00324
00325 mutable char expectedFormat_;
00326
00327 mutable char const *cs_;
00328
00329 mutable std::string buffer_;
00330
00331 mutable int fieldWidth_;
00332 mutable int fillChar_;
00333 mutable int precision_;
00334 mutable int left_;
00335
00336
00337
00338 void reset() const
00340 {
00341 left_ = 0;
00342 fieldWidth_ = 0;
00343 fillChar_ = 0;
00344 precision_ = 0;
00345 }
00346
00347
00348 public:
00349
00350
00351
00352 operator std::string const &() const { return buffer_; }
00353
00354
00355
00356 cs(char const *cs)
00368 : expectedFormat_(*cs)
00369 , cs_(cs)
00370 {
00371 advanceFormat();
00372 }
00373
00374 ~cs()
00375 {
00376 if(expectedFormat_ != '?' )
00377 {
00378
00379
00380 throw printableType::Exception(expectedFormat_, "<EXPECTED END OF FORMAT STRING>");
00381
00382 }
00383 }
00384
00385 private:
00386
00387
00388
00389 void advanceFormat() const
00396 {
00397 reset();
00398
00399
00400
00401 while(*cs_)
00402 {
00403
00404 while(*cs_ && *cs_ != '%')
00405 buffer_ += *cs_++;
00406
00407 if(*cs_ == '%')
00408 ++cs_;
00409
00410 if(*cs_ == '%')
00411 {
00412 buffer_ += '%';
00413 ++cs_;
00414 }
00415 else
00416 break;
00417 }
00418
00419
00420
00421 expectedFormat_ = '?';
00422
00423
00424
00425 if(*cs_ == '-')
00426 {
00427 left_ = 1;
00428 ++cs_;
00429 }
00430
00431 if(*cs_ == '0')
00432 {
00433 fillChar_ = '0';
00434 ++cs_;
00435 }
00436
00437 if(*cs_ >= '0' && *cs_ <='9')
00438 {
00439 fieldWidth_ = 0;
00440
00441 while(*cs_ >= '0' && *cs_ <= '9')
00442 {
00443 fieldWidth_ *= 10;
00444 fieldWidth_ += *cs_++ -'0';
00445 }
00446 }
00447
00448 if(*cs_ == '.')
00449 {
00450 ++cs_;
00451
00452 precision_ = 0;
00453
00454 while(*cs_ >= '0' && *cs_ <= '9')
00455 {
00456 precision_ *= 10;
00457 precision_ += *cs_++ -'0';
00458 }
00459
00460 }
00461
00462
00463
00464 if(*cs_)
00465 {
00466 expectedFormat_ = *cs_++;
00467 }
00468
00469 }
00470
00471
00472
00473 void outputIntegral( long long t ) const
00477 {
00478 char b[100];
00479
00480 char cs[40];
00481
00482 char *scan = &cs[0];
00483
00484 {
00485
00486 *scan++ = '%';
00487
00488 if(left_)
00489 *scan++ = '-';
00490
00491 if(fillChar_ == '0')
00492 *scan++ = '0';
00493
00494 if(fieldWidth_)
00495 {
00496 char buffer[40];
00497
00498 snprintf(buffer, 40, "%d", fieldWidth_);
00499
00500 char *input = &buffer[0];
00501
00502 while(*input)
00503 *scan++ = *input++;
00504
00505 }
00506
00507 if(precision_)
00508 {
00509 *scan++ = '.';
00510
00511 char buffer[40];
00512
00513 snprintf(buffer, 40, "%d", precision_);
00514
00515 char *input = &buffer[0];
00516
00517 while(*input)
00518 *scan++ = *input++;
00519
00520 }
00521 }
00522
00523 *scan++ = 'l';
00524 *scan++ = 'l';
00525 *scan++ = expectedFormat_;
00526 *scan++ = 0;
00527
00528
00529 snprintf(b, sizeof(b), cs, (long long)t);
00530
00531 buffer_ += b;
00532
00533 }
00534
00535
00536 bool isIntegralFormat() const
00540 {
00541 return expectedFormat_ == 'd'
00542 || expectedFormat_ == 'u'
00543 || expectedFormat_ == 'o'
00544 || expectedFormat_ == 'x'
00545 ;
00546 }
00547
00548
00549 template<class T> void output(T const &t, printableType::Integral) const
00553
00554 {
00555 if( !isIntegralFormat() )
00556 {
00557 throw printableType::Exception(expectedFormat_, "Integral");
00558 }
00559
00560 outputIntegral((long long)t);
00561
00562 }
00563
00564
00565 template<class T> void output(T const &t, printableType::Unsigned) const
00569 {
00570 if( !isIntegralFormat() )
00571 {
00572 throw printableType::Exception(expectedFormat_, "Unsigned");
00573 }
00574
00575 outputIntegral((long long)t);
00576
00577 }
00578
00579
00580 template<class T> void output(T const &t, printableType::Char) const
00584 {
00585 if(expectedFormat_ == 'c')
00586 {
00587 buffer_ += (t);
00588 }
00589 else
00590 if( !isIntegralFormat() )
00591 {
00592 throw printableType::Exception(expectedFormat_, "Char");
00593 }
00594 else
00595 outputIntegral(t);
00596 }
00597
00598
00599
00600 template<class T> void output(T const &t, printableType::String) const
00604 {
00605 if( expectedFormat_ != 's'
00606 )
00607 {
00608 throw printableType::Exception(expectedFormat_, "String");
00609 }
00610
00611
00612 buffer_ += (char const *)(t);
00613 }
00614
00615
00616 template<class T> void output(T const &t, printableType::StlString) const
00620 {
00621 if( expectedFormat_ != 's'
00622 )
00623 {
00624 throw printableType::Exception(expectedFormat_, "std::string");
00625 }
00626
00627
00628 buffer_ += t;
00629
00630 }
00631
00632
00633 void outputFloat(double d) const
00637 {
00638 std::stringstream tmp;
00639
00640 if(left_)
00641 {
00642 tmp << std::left;
00643 }
00644
00645 if(fillChar_)
00646 {
00647 tmp << std::setfill(char(fillChar_));
00648 }
00649
00650 if(fieldWidth_)
00651 {
00652 tmp << std::setw(fieldWidth_);
00653 }
00654
00655 if(precision_)
00656 {
00657 tmp << std::setprecision(precision_);
00658 }
00659
00660 tmp << d;
00661
00662 buffer_ +=tmp.str();
00663 }
00664
00665
00666 template<class T> void output(T const &t, printableType::Float) const
00670 {
00671 if( expectedFormat_ != 'f'
00672 )
00673 {
00674 throw printableType::Exception(expectedFormat_, "Float");
00675 }
00676
00677 outputFloat(t);
00678
00679 }
00680
00681
00682 template<class T> void output(T const &t, printableType::DoubleFloat) const
00686 {
00687 if( expectedFormat_ != 'f'
00688 )
00689 {
00690 throw printableType::Exception(expectedFormat_, "DoubleFloat");
00691 }
00692
00693 outputFloat(t);
00694
00695 }
00696
00697
00698 template<class T> void output(T const &t, printableType::UserDefined) const
00702 {
00703 if( expectedFormat_ != 'U'
00704 )
00705 {
00706 throw printableType::Exception(expectedFormat_, "UserDefined");
00707 }
00708
00709 std::stringstream tmp;
00710
00711 if(left_)
00712 {
00713 tmp << std::left;
00714 }
00715
00716 if(fillChar_)
00717 {
00718 tmp << std::setfill(char(fillChar_));
00719 }
00720
00721 tmp << std::setw(fieldWidth_) << std::setprecision(precision_) << t;
00722
00723 buffer_ += tmp.str();
00724 }
00725
00726 public:
00727
00728
00729 template< class T >
00730 cs const &operator% ( T const &rhs ) const
00743
00744 {
00745 output(rhs, printableType::classifier(rhs));
00746
00747 advanceFormat();
00748
00749 return *this;
00750 }
00751
00752
00753 cs const &operator% ( char const *rhs ) const
00766
00767 {
00768 output(rhs, printableType::String() );
00769
00770 advanceFormat();
00771
00772 return *this;
00773 }
00774
00775
00776 template<class T, int N>
00777 cs const &operator% ( T const (&rhs)[N] ) const
00792
00793 {
00794 output(rhs, printableType::Integral() );
00795
00796 advanceFormat();
00797
00798 return *this;
00799 }
00800
00801
00802 size_t size() const { return buffer_.size(); }
00803
00804 private:
00805
00806
00807
00808 cs(cs const &);
00809
00810
00811
00812
00813
00814
00815
00816
00817 template< class T > void operator<< ( T & ) const;
00818
00819 };
00820
00821
00822
00823 inline std::ostream &operator<< (std::ostream &s, cs const &fmt)
00824 {
00825 if(s.good())
00826 {
00827
00828 s << (std::string const &) fmt;
00829
00830 }
00831
00832 return s;
00833 }
00834
00835
00836
00837
00838 }
00839 #endif