00001 #ifndef CXX_fmtd_header_included_p
00002 #define CXX_fmtd_header_included_p
00003
00004 #include <iostream>
00005 #include <portable_io.h>
00006 #include <cxxtls/classTraits.h>
00007
00008 namespace cxxtls
00009 {
00010
00015
00016
00017 namespace fmtdalgo
00022 {
00023
00024
00025
00026
00027 inline void int2ascii(char *&scan, int d)
00034 {
00035 char buffer[26];
00036
00037 char *end = &buffer[25];
00038
00039 *end = 0;
00040
00041 char *ptr = end;
00042
00043 while(d)
00044 {
00045 *(--ptr) = '0' + (d%10);
00046 d /= 10;
00047 }
00048
00049 while(ptr != end)
00050 *scan++ = *ptr++;
00051
00052
00053 }
00054
00055
00056 inline void setup(char *&scan,
00057 int fieldWidth,
00058 int precision,
00059 bool lJust,
00060 bool padding,
00061 char pad
00062 )
00066 {
00067 *scan++ = '%';
00068
00069 if(lJust && fieldWidth != 0)
00070 *scan++ = '-';
00071
00072 if(!lJust && pad == '0')
00073 *scan++ = '0';
00074
00075 if(fieldWidth)
00076 int2ascii(scan, fieldWidth);
00077
00078 if(precision)
00079 {
00080 *scan++ = '.';
00081 int2ascii(scan, precision);
00082 }
00083 }
00084
00085
00086 template<class T, int fieldWidth, int precision, int lJust, int padding, int pad, int base, int errchr>
00087 struct StringFormatter
00095 {
00096
00097 size_t operator()(std::string const &v,
00098 char *buffer,
00099 int buffsize
00100 )
00101 {
00102 return (*this)(v.c_str(), buffer, buffsize);
00103 }
00104
00105
00106 size_t operator() (char const *v,
00107 char *buffer,
00108 int buffsize
00109 )
00117 {
00118 char cs[100];
00119
00120 char *scan = &cs[0];
00121
00122 setup(scan,
00123 fieldWidth,
00124 precision,
00125 lJust,
00126 padding,
00127 pad
00128 );
00129
00130
00131 *scan++ = 's';
00132
00133 *scan++ = 0;
00134
00135 size_t bytesWritten = snprintf(buffer, buffsize, cs, v);
00136
00137 size_t errorThreshold = buffsize;
00138
00139 if(fieldWidth)
00140 errorThreshold = fieldWidth;
00141
00142 if( bytesWritten > errorThreshold)
00143 {
00144 std::fill_n(buffer, fieldWidth, errchr);
00145 buffer[fieldWidth] = 0;
00146
00147 bytesWritten = fieldWidth;
00148 }
00149
00150 return bytesWritten;
00151
00152 }
00153
00154 };
00155
00156
00157
00158
00159 template<class T, int fieldWidth, int precision, int lJust, int padding, int pad, int base, int errchr>
00160 struct FloatFormatter
00165 {
00166 size_t operator() (T const &v,
00167 char *buffer,
00168 int buffsize
00169 )
00177 {
00178 char cs[100];
00179
00180 char *scan = &cs[0];
00181
00182 setup(scan,
00183 fieldWidth,
00184 precision,
00185 lJust,
00186 padding,
00187 pad
00188 );
00189
00190
00191 *scan++ = 'L';
00192
00193 if(!lJust && precision)
00194 *scan++ = 'f';
00195 else
00196 *scan++ = 'g';
00197
00198 *scan++ = 0;
00199
00200 long double x = v;
00201
00202 size_t bytesWritten = snprintf(buffer, buffsize, cs, x);
00203
00204 size_t errorThreshold = buffsize;
00205
00206 if(fieldWidth)
00207 errorThreshold = fieldWidth;
00208
00209 if( bytesWritten > errorThreshold)
00210 {
00211 std::fill_n(buffer, fieldWidth, errchr);
00212 buffer[fieldWidth] = 0;
00213
00214 bytesWritten = fieldWidth;
00215 }
00216
00217 return bytesWritten;
00218
00219 }
00220
00221 };
00222
00223
00224 template<class T, int fieldWidth, int precision, int lJust, int padding, int pad, int base, int errchr>
00225 struct IntFormatter
00230 {
00231 size_t operator() (T const &v,
00232 char *buffer,
00233 int buffsize
00234 )
00242 {
00243 char cs[100];
00244
00245 char *scan = &cs[0];
00246
00247 setup(scan,
00248 fieldWidth,
00249 precision,
00250 lJust,
00251 padding,
00252 pad
00253 );
00254
00255
00256 *scan++ = 'l';
00257 *scan++ = 'l';
00258
00259 if(base == 16)
00260 *scan++ = 'x';
00261 else
00262 if(base == 8)
00263 *scan++ = 'o';
00264 else
00265 if(isUnsignedType<T>::value)
00266 *scan++ = 'u';
00267 else
00268 *scan++ = 'd';
00269
00270 *scan++ = 0;
00271
00272 long long x = v;
00273
00274 size_t errorThreshold = buffsize;
00275
00276 if(fieldWidth)
00277 errorThreshold = fieldWidth;
00278
00279 size_t rv;
00280
00281 if( (rv = snprintf(buffer, buffsize, cs, x) ) > errorThreshold)
00282 {
00283 std::fill_n(buffer, fieldWidth, errchr);
00284 buffer[fieldWidth] = 0;
00285 rv = fieldWidth;
00286 }
00287
00288 return rv;
00289 }
00290 };
00291
00292
00293 template<int N,
00294 class T,
00295 int fieldWidth,
00296 int precision,
00297 int lJust,
00298 int padding,
00299 int pad,
00300 int base,
00301 int errchr
00302 >
00303 struct algo;
00307
00308
00309
00310 template<class T,
00311 int fieldWidth,
00312 int precision,
00313 int lJust,
00314 int padding,
00315 int pad,
00316 int base,
00317 int errchr
00318 >
00319 struct algo<bctIntegralType,
00320 T,
00321 fieldWidth,
00322 precision,
00323 lJust,
00324 padding,
00325 pad,
00326 base,
00327 errchr
00328 >
00332 {
00333 typedef IntFormatter<T,
00334 fieldWidth,
00335 precision,
00336 lJust,
00337 padding,
00338 pad,
00339 base,
00340 errchr
00341 >
00342 type;
00343 };
00344
00345
00346 template<class T,
00347 int fieldWidth,
00348 int precision,
00349 int lJust,
00350 int padding,
00351 int pad,
00352 int base,
00353 int errchr
00354 >
00355 struct algo<bctFloatType,
00356 T,
00357 fieldWidth,
00358 precision,
00359 lJust,
00360 padding,
00361 pad,
00362 base,
00363 errchr
00364 >
00368 {
00369 typedef FloatFormatter<T,
00370 fieldWidth,
00371 precision,
00372 lJust,
00373 padding,
00374 pad,
00375 base,
00376 errchr
00377 > type;
00378 };
00379
00380
00381 template<
00382 int fieldWidth,
00383 int precision,
00384 int lJust,
00385 int padding,
00386 int pad,
00387 int base,
00388 int errchr
00389 >
00390 struct algo<bctClassType,
00391 char const *,
00392 fieldWidth,
00393 precision,
00394 lJust,
00395 padding,
00396 pad,
00397 base,
00398 errchr
00399 >
00403 {
00404 typedef StringFormatter<std::string,
00405 fieldWidth,
00406 precision,
00407 lJust,
00408 padding,
00409 pad,
00410 base,
00411 errchr
00412 > type;
00413 };
00414
00415
00416
00417 };
00418
00419
00420 template<int WIDTH=0, int PRECISION=0, int PAD=' ', int BASE=10, int ERRCHR='@'>
00421 struct fmtd
00492 {
00493
00494
00495
00496 enum constants { MIN_WIDTH = 25,
00497 BUFF_SAFETY = 10,
00498 POS_WIDTH = (WIDTH < 0) ? -WIDTH : WIDTH,
00499 FIELD_WIDTH = (PRECISION > POS_WIDTH ? PRECISION : ( (POS_WIDTH == 0) ? 0 : POS_WIDTH ) ),
00500 BUFF_SIZE = FIELD_WIDTH + BUFF_SAFETY,
00501 PADDING = (POS_WIDTH != 0) || (PRECISION != 0),
00502 LJUST = (WIDTH< 1),
00503 };
00504
00505 private:
00506
00507 char buffer_[ BUFF_SIZE ];
00508
00509 size_t size_;
00510
00511 public:
00512
00513
00514
00515 template<class T>
00516 fmtd(T const &v)
00517 {
00518 using namespace fmtdalgo;
00519
00520 typename algo< basicClassType<T>::value, T, FIELD_WIDTH, PRECISION, LJUST, PADDING, PAD, BASE, ERRCHR>::type doit;
00521
00522
00523
00524
00525
00526
00527
00528
00529 size_ = doit(v,buffer_,BUFF_SIZE);
00530 }
00531
00532
00533
00534 fmtd(char const *s)
00535 {
00536 using namespace fmtdalgo;
00537
00538 typename algo< bctClassType, char const *, FIELD_WIDTH, PRECISION, LJUST, PADDING, PAD, BASE, ERRCHR>::type doit;
00539
00540 size_ = doit(s,buffer_,BUFF_SIZE);
00541 }
00542
00543
00544
00545 fmtd(std::string const &s)
00546 {
00547 using namespace fmtdalgo;
00548
00549 typename algo< bctClassType, char const *, FIELD_WIDTH, PRECISION, LJUST, PADDING, PAD, BASE, ERRCHR>::type doit;
00550
00551 size_ = doit(s.c_str(),buffer_,BUFF_SIZE);
00552 }
00553
00554
00555
00556
00557
00558 operator char const *() const { return buffer_; }
00559
00560
00561
00562 size_t size() const { return size_; }
00563
00564
00565
00566
00567 friend std::ostream &operator<< ( std::ostream &s, fmtd const &f)
00568 {
00569 s << f.buffer_;
00570 return s;
00571 }
00572
00573
00574 };
00575
00576 }
00577 #endif