diff --git a/src/common/Format.h b/src/common/Format.h index 1cec0408e9..1c7fdf9753 100644 --- a/src/common/Format.h +++ b/src/common/Format.h @@ -13,78 +13,106 @@ template class FormatProxy inline void Write(StringBuilder &b) { b << value; } }; -class Format +namespace Format { - std::function writer; -public: - template inline Format(T const &value, Ts... args): - writer([value, args...](StringBuilder &b) { FormatProxy(value, args...).Write(b); }) - {} + template struct FlagsOverride + { + T value; + inline FlagsOverride(T _value): value(_value) {} + }; + template struct FlagsOverride + { + inline FlagsOverride() {} + }; + + template struct WidthOverride + { + T value; + size_t width; + inline WidthOverride(T _value, size_t _width): value(_value), width(_width) {} + }; + template<> struct WidthOverride + { + size_t width; + inline WidthOverride(size_t _width): width(_width) {} + }; + + template struct PrecisionOverride + { + T value; + size_t precision; + inline PrecisionOverride(T _value, size_t _precision): value(_value), precision(_precision) {} + }; + template<> struct PrecisionOverride + { + size_t precision; + inline PrecisionOverride(size_t _precision): precision(_precision) {} + }; + + template inline FlagsOverride Oct(T value) { return FlagsOverride(value); } + template inline FlagsOverride Dec(T value) { return FlagsOverride(value); } + template inline FlagsOverride Hex(T value) { return FlagsOverride(value); } + inline FlagsOverride Oct() { return FlagsOverride(); } + inline FlagsOverride Dec() { return FlagsOverride(); } + inline FlagsOverride Hex() { return FlagsOverride(); } - friend StringBuilder &operator<<(StringBuilder &, Format const &); + template inline FlagsOverride Fixed(T value) { return FlagsOverride(value); } + template inline FlagsOverride Scientific(T value) { return FlagsOverride(value); } + template inline FlagsOverride FloatDefault(T value) { return FlagsOverride(value); } + inline FlagsOverride Fixed() { return FlagsOverride(); } + inline FlagsOverride Scientific() { return FlagsOverride(); } + inline FlagsOverride FloatDefault() { return FlagsOverride(); } - enum Base { Dec, Oct, Hex }; - enum Float { Default, Fixed, Scientific }; + template inline WidthOverride Width(T value, size_t width) { return WidthOverride(value, width); } + template inline PrecisionOverride Precision(T value, size_t precision) { return PrecisionOverride(value, precision); } + inline WidthOverride Width(size_t width) { return WidthOverride(width); } + inline PrecisionOverride Precision(size_t precision) { return PrecisionOverride(precision); } }; -inline StringBuilder &operator<<(StringBuilder &b, Format const &f) +template inline StringBuilder &operator<<(StringBuilder &b, Format::FlagsOverride data) { - f.writer(b); + std::ios_base::fmtflags oldflags = b.flags; + b.flags = (b.flags & ~reset) | set; + b << data.value; + b.flags = oldflags; return b; } - -template class IntegralFormatProxy +template inline StringBuilder &operator<<(StringBuilder &b, Format::FlagsOverride data) { - 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; }; + b.flags = (b.flags & ~reset) | set; + return b; +} -template class FloatingFormatProxy +template inline StringBuilder &operator<<(StringBuilder &b, Format::WidthOverride data) { - 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; - } -}; + size_t oldwidth = b.width; + b.width = data.width; + b << data.value; + b.width = oldwidth; + return b; +} +inline StringBuilder &operator<<(StringBuilder &b, Format::WidthOverride data) +{ + b.width = data.width; + return b; +} -template<> class FormatProxy: public FloatingFormatProxy { using FloatingFormatProxy::FloatingFormatProxy; }; -template<> class FormatProxy: public FloatingFormatProxy { using FloatingFormatProxy::FloatingFormatProxy; }; +template inline StringBuilder &operator<<(StringBuilder &b, Format::PrecisionOverride data) +{ + std::ios_base::fmtflags oldflags = b.flags; + if(!(oldflags & std::ios_base::floatfield)) + b.flags |= std::ios_base::fixed; + size_t oldprecision = b.precision; + b.precision = data.precision; + b << data.value; + b.precision = oldprecision; + b.flags = oldflags; + return b; +} +inline StringBuilder &operator<<(StringBuilder &b, Format::PrecisionOverride data) +{ + if(!(b.flags & std::ios_base::floatfield)) + b.flags |= std::ios_base::fixed; + b.precision = data.precision; + return b; +} diff --git a/src/common/String.h b/src/common/String.h index 1f6011b475..79eb3d1457 100644 --- a/src/common/String.h +++ b/src/common/String.h @@ -194,6 +194,7 @@ class String : public std::basic_string ByteString ToUtf8() const; ByteString ToAscii() const; + template static String Build(Ts&&... args); using Stream = std::basic_stringstream; }; @@ -284,4 +285,11 @@ StringBuilder &operator<<(StringBuilder &, float); StringBuilder &operator<<(StringBuilder &, double); template StringBuilder &operator<<(StringBuilder &b, ByteString::value_type const (&data)[N]) { return b << ByteString(data).FromUtf8(); } +template String String::Build(Ts&&... args) +{ + StringBuilder b; + b.Add(std::forward(args)...); + return b.Build(); +} + #include "common/Format.h"