|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include <functional> |
| 4 | +#include <ios> |
| 5 | + |
| 6 | +#include "common/String.h" |
| 7 | + |
| 8 | +template<typename T> class FormatProxy |
| 9 | +{ |
| 10 | + T const &value; |
| 11 | + inline FormatProxy(T const &_value): value(_value) {} |
| 12 | +public: |
| 13 | + inline void Write(StringBuilder &b) { b << value; } |
| 14 | +}; |
| 15 | + |
| 16 | +class Format |
| 17 | +{ |
| 18 | + std::function<void(StringBuilder &)> writer; |
| 19 | +public: |
| 20 | + template<typename T, typename... Ts> inline Format(T const &value, Ts... args): |
| 21 | + writer([value, args...](StringBuilder &b) { FormatProxy<T>(value, args...).Write(b); }) |
| 22 | + {} |
| 23 | + |
| 24 | + friend StringBuilder &operator<<(StringBuilder &, Format const &); |
| 25 | + |
| 26 | + enum Base { Dec, Oct, Hex }; |
| 27 | + enum Float { Default, Fixed, Scientific }; |
| 28 | +}; |
| 29 | + |
| 30 | +inline StringBuilder &operator<<(StringBuilder &b, Format const &f) |
| 31 | +{ |
| 32 | + f.writer(b); |
| 33 | + return b; |
| 34 | +} |
| 35 | + |
| 36 | +template<typename T> class IntegralFormatProxy |
| 37 | +{ |
| 38 | + T value; |
| 39 | + Format::Base base; |
| 40 | + size_t width; |
| 41 | +public: |
| 42 | + inline IntegralFormatProxy(T _value, Format::Base _base = Format::Dec, size_t _width = 0): value(_value), base(_base), width(_width) {} |
| 43 | + inline void Write(StringBuilder &b) |
| 44 | + { |
| 45 | + std::ios_base::fmtflags oldflags = b.flags; |
| 46 | + b.flags &= ~std::ios_base::basefield; |
| 47 | + b.flags |= base == Format::Hex ? std::ios_base::hex : base == Format::Oct ? std::ios_base::oct : std::ios_base::dec; |
| 48 | + size_t oldwidth = b.width; |
| 49 | + b.width = width; |
| 50 | + b << value; |
| 51 | + b.flags = oldflags; |
| 52 | + b.width = oldwidth; |
| 53 | + } |
| 54 | +}; |
| 55 | + |
| 56 | +template<> class FormatProxy<short int>: public IntegralFormatProxy<short int> { using IntegralFormatProxy::IntegralFormatProxy; }; |
| 57 | +template<> class FormatProxy<int>: public IntegralFormatProxy<int> { using IntegralFormatProxy::IntegralFormatProxy; }; |
| 58 | +template<> class FormatProxy<long int>: public IntegralFormatProxy<long int> { using IntegralFormatProxy::IntegralFormatProxy; }; |
| 59 | +template<> class FormatProxy<long long int>: public IntegralFormatProxy<long long int> { using IntegralFormatProxy::IntegralFormatProxy; }; |
| 60 | +template<> class FormatProxy<unsigned short int>: public IntegralFormatProxy<unsigned short int> { using IntegralFormatProxy::IntegralFormatProxy; }; |
| 61 | +template<> class FormatProxy<unsigned int>: public IntegralFormatProxy<unsigned int> { using IntegralFormatProxy::IntegralFormatProxy; }; |
| 62 | +template<> class FormatProxy<unsigned long int>: public IntegralFormatProxy<unsigned long int> { using IntegralFormatProxy::IntegralFormatProxy; }; |
| 63 | +template<> class FormatProxy<unsigned long long int>: public IntegralFormatProxy<unsigned long long int> { using IntegralFormatProxy::IntegralFormatProxy; }; |
| 64 | + |
| 65 | +template<typename T> class FloatingFormatProxy |
| 66 | +{ |
| 67 | + T value; |
| 68 | + size_t precision; |
| 69 | + Format::Float style; |
| 70 | + size_t width; |
| 71 | +public: |
| 72 | + inline FloatingFormatProxy(T _value, size_t _precision, Format::Float _style = Format::Default, size_t _width = 0): value(_value), precision(_precision), style(_style), width(_width) {} |
| 73 | + inline void Write(StringBuilder &b) |
| 74 | + { |
| 75 | + std::ios_base::fmtflags oldflags = b.flags; |
| 76 | + b.flags &= ~std::ios_base::floatfield; |
| 77 | + b.flags |= style == Format::Fixed ? std::ios_base::fixed : style == Format::Scientific ? std::ios_base::scientific : std::ios_base::fmtflags(); |
| 78 | + size_t oldwidth = b.width; |
| 79 | + b.width = width; |
| 80 | + size_t oldprecision = b.precision; |
| 81 | + b.precision = precision; |
| 82 | + b << value; |
| 83 | + b.flags = oldflags; |
| 84 | + b.width = oldwidth; |
| 85 | + b.precision = oldprecision; |
| 86 | + } |
| 87 | +}; |
| 88 | + |
| 89 | +template<> class FormatProxy<float>: public FloatingFormatProxy<float> { using FloatingFormatProxy::FloatingFormatProxy; }; |
| 90 | +template<> class FormatProxy<double>: public FloatingFormatProxy<double> { using FloatingFormatProxy::FloatingFormatProxy; }; |
0 commit comments