diff --git a/src/common/Format.h b/src/common/Format.h new file mode 100644 index 000000000..1cec0408e --- /dev/null +++ b/src/common/Format.h @@ -0,0 +1,90 @@ +#pragma once + +#include +#include + +#include "common/String.h" + +template class FormatProxy +{ + T const &value; + inline FormatProxy(T const &_value): value(_value) {} +public: + inline void Write(StringBuilder &b) { b << value; } +}; + +class Format +{ + std::function writer; +public: + template inline Format(T const &value, Ts... args): + writer([value, args...](StringBuilder &b) { FormatProxy(value, args...).Write(b); }) + {} + + friend StringBuilder &operator<<(StringBuilder &, Format const &); + + enum Base { Dec, Oct, Hex }; + enum Float { Default, Fixed, Scientific }; +}; + +inline StringBuilder &operator<<(StringBuilder &b, Format const &f) +{ + f.writer(b); + return b; +} + +template class IntegralFormatProxy +{ + T value; + Format::Base base; + size_t width; +public: + inline IntegralFormatProxy(T _value, Format::Base _base = Format::Dec, size_t _width = 0): value(_value), base(_base), width(_width) {} + inline void Write(StringBuilder &b) + { + std::ios_base::fmtflags oldflags = b.flags; + b.flags &= ~std::ios_base::basefield; + b.flags |= base == Format::Hex ? std::ios_base::hex : base == Format::Oct ? std::ios_base::oct : std::ios_base::dec; + size_t oldwidth = b.width; + b.width = width; + b << value; + b.flags = oldflags; + b.width = oldwidth; + } +}; + +template<> class FormatProxy: public IntegralFormatProxy { using IntegralFormatProxy::IntegralFormatProxy; }; +template<> class FormatProxy: public IntegralFormatProxy { using IntegralFormatProxy::IntegralFormatProxy; }; +template<> class FormatProxy: public IntegralFormatProxy { using IntegralFormatProxy::IntegralFormatProxy; }; +template<> class FormatProxy: public IntegralFormatProxy { using IntegralFormatProxy::IntegralFormatProxy; }; +template<> class FormatProxy: public IntegralFormatProxy { using IntegralFormatProxy::IntegralFormatProxy; }; +template<> class FormatProxy: public IntegralFormatProxy { using IntegralFormatProxy::IntegralFormatProxy; }; +template<> class FormatProxy: public IntegralFormatProxy { using IntegralFormatProxy::IntegralFormatProxy; }; +template<> class FormatProxy: public IntegralFormatProxy { using IntegralFormatProxy::IntegralFormatProxy; }; + +template class FloatingFormatProxy +{ + T value; + size_t precision; + Format::Float style; + size_t width; +public: + inline FloatingFormatProxy(T _value, size_t _precision, Format::Float _style = Format::Default, size_t _width = 0): value(_value), precision(_precision), style(_style), width(_width) {} + inline void Write(StringBuilder &b) + { + std::ios_base::fmtflags oldflags = b.flags; + b.flags &= ~std::ios_base::floatfield; + b.flags |= style == Format::Fixed ? std::ios_base::fixed : style == Format::Scientific ? std::ios_base::scientific : std::ios_base::fmtflags(); + size_t oldwidth = b.width; + b.width = width; + size_t oldprecision = b.precision; + b.precision = precision; + b << value; + b.flags = oldflags; + b.width = oldwidth; + b.precision = oldprecision; + } +}; + +template<> class FormatProxy: public FloatingFormatProxy { using FloatingFormatProxy::FloatingFormatProxy; }; +template<> class FormatProxy: public FloatingFormatProxy { using FloatingFormatProxy::FloatingFormatProxy; }; diff --git a/src/common/String.h b/src/common/String.h index 9b6eb2696..1f6011b47 100644 --- a/src/common/String.h +++ b/src/common/String.h @@ -1,5 +1,4 @@ -#ifndef TPT_STRING -#define TPT_STRING +#pragma once #include #include @@ -285,4 +284,4 @@ StringBuilder &operator<<(StringBuilder &, float); StringBuilder &operator<<(StringBuilder &, double); template StringBuilder &operator<<(StringBuilder &b, ByteString::value_type const (&data)[N]) { return b << ByteString(data).FromUtf8(); } -#endif +#include "common/Format.h"