From 90f1278043ae90ad69bf40a9ef014c78d6d7f158 Mon Sep 17 00:00:00 2001 From: syntheticpp Date: Thu, 5 Jan 2006 20:41:47 +0000 Subject: [PATCH] move Printf/SPrintf into the Loki namespace git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@433 7ec92016-0320-0410-acc4-a06ded1c099a --- include/loki/SafeFormat.h | 931 +++++++++++++++++++------------------- 1 file changed, 468 insertions(+), 463 deletions(-) diff --git a/include/loki/SafeFormat.h b/include/loki/SafeFormat.h index 1520768..88bf5c7 100755 --- a/include/loki/SafeFormat.h +++ b/include/loki/SafeFormat.h @@ -25,490 +25,495 @@ #include #include -// Crude writing method: writes straight to the file, unbuffered -// Must be combined with a buffer to work properly (and efficiently) +namespace Loki +{ -void write(std::FILE* f, const char* from, const char* to) { - assert(from <= to); - fwrite(from, 1, to - from, f); -} + // Crude writing method: writes straight to the file, unbuffered + // Must be combined with a buffer to work properly (and efficiently) -// Write to a string + void write(std::FILE* f, const char* from, const char* to) { + assert(from <= to); + fwrite(from, 1, to - from, f); + } -void write(std::string& s, const char* from, const char* to) { - assert(from <= to); - s.append(from, to); -} + // Write to a string -// Write to a fixed-size buffer + void write(std::string& s, const char* from, const char* to) { + assert(from <= to); + s.append(from, to); + } -template -void write(std::pair& s, const Char* from, const Char* to) { - assert(from <= to); - if (from + s.second > to) throw std::overflow_error(""); - s.first = copy(from, to, s.first); - s.second -= to - from; -} + // Write to a fixed-size buffer -//////////////////////////////////////////////////////////////////////////////// -// PrintfState class template -// Holds the formatting state, and implements operator() to format stuff -// Todo: make sure errors are handled properly -//////////////////////////////////////////////////////////////////////////////// + template + void write(std::pair& s, const Char* from, const Char* to) { + assert(from <= to); + if (from + s.second > to) throw std::overflow_error(""); + s.first = copy(from, to, s.first); + s.second -= to - from; + } -template -struct PrintfState { - PrintfState(Device dev, const Char * format) - : device_(dev) - , format_(format) - , result_(0) { - Advance(); - } - - ~PrintfState() { - } + //////////////////////////////////////////////////////////////////////////////// + // PrintfState class template + // Holds the formatting state, and implements operator() to format stuff + // Todo: make sure errors are handled properly + //////////////////////////////////////////////////////////////////////////////// - #define LOKI_PRINTF_STATE_FORWARD(type) \ - PrintfState& operator()(type par) {\ - return (*this)(static_cast< unsigned long >(par)); \ - } + template + struct PrintfState { + PrintfState(Device dev, const Char * format) + : device_(dev) + , format_(format) + , result_(0) { + Advance(); + } + + ~PrintfState() { + } - LOKI_PRINTF_STATE_FORWARD(bool) - LOKI_PRINTF_STATE_FORWARD(char) - LOKI_PRINTF_STATE_FORWARD(signed char) - LOKI_PRINTF_STATE_FORWARD(unsigned char) - LOKI_PRINTF_STATE_FORWARD(short) - LOKI_PRINTF_STATE_FORWARD(unsigned short) - LOKI_PRINTF_STATE_FORWARD(int) - LOKI_PRINTF_STATE_FORWARD(unsigned) - LOKI_PRINTF_STATE_FORWARD(long) + #define LOKI_PRINTF_STATE_FORWARD(type) \ + PrintfState& operator()(type par) {\ + return (*this)(static_cast< unsigned long >(par)); \ + } - // Print (or gobble in case of the "*" specifier) an int - PrintfState& operator()(unsigned long i) { - if (result_ == -1) return *this; // don't even bother - // % [flags] [width] [.prec] [modifier] type_char - // Fetch the flags - ReadFlags(); - if (*format_ == '*') { - // read the width and get out - SetWidth(static_cast(i)); - ++format_; - return *this; - } - ReadWidth(); - // precision - if (*format_ == '.') { - // deal with precision - if (format_[1] == '*') { - // read the precision and get out - SetPrec(static_cast(i)); - format_ += 2; - return *this; - } - ReadPrecision(); - } - ReadModifiers(); - // input size modifier - if (ForceShort()) { - // short int - const Char c = *format_; - if (c == 'x' || c == 'X' || c == 'u' || c == 'o') { - i = static_cast(static_cast(i)); - } - } - FormatWithCurrentFlags(i); - return *this; - } - - PrintfState& operator()(double n) { - if (result_ == -1) return *this; // don't even bother - PrintFloatingPoint(n); - return *this; - } + LOKI_PRINTF_STATE_FORWARD(bool) + LOKI_PRINTF_STATE_FORWARD(char) + LOKI_PRINTF_STATE_FORWARD(signed char) + LOKI_PRINTF_STATE_FORWARD(unsigned char) + LOKI_PRINTF_STATE_FORWARD(short) + LOKI_PRINTF_STATE_FORWARD(unsigned short) + LOKI_PRINTF_STATE_FORWARD(int) + LOKI_PRINTF_STATE_FORWARD(unsigned) + LOKI_PRINTF_STATE_FORWARD(long) - PrintfState& operator()(long double n) { - if (result_ == -1) return *this; // don't even bother - PrintFloatingPoint(n); - return *this; - } + // Print (or gobble in case of the "*" specifier) an int + PrintfState& operator()(unsigned long i) { + if (result_ == -1) return *this; // don't even bother + // % [flags] [width] [.prec] [modifier] type_char + // Fetch the flags + ReadFlags(); + if (*format_ == '*') { + // read the width and get out + SetWidth(static_cast(i)); + ++format_; + return *this; + } + ReadWidth(); + // precision + if (*format_ == '.') { + // deal with precision + if (format_[1] == '*') { + // read the precision and get out + SetPrec(static_cast(i)); + format_ += 2; + return *this; + } + ReadPrecision(); + } + ReadModifiers(); + // input size modifier + if (ForceShort()) { + // short int + const Char c = *format_; + if (c == 'x' || c == 'X' || c == 'u' || c == 'o') { + i = static_cast(static_cast(i)); + } + } + FormatWithCurrentFlags(i); + return *this; + } + + PrintfState& operator()(double n) { + if (result_ == -1) return *this; // don't even bother + PrintFloatingPoint(n); + return *this; + } - // Store the number of characters printed so far - PrintfState& operator()(int * pi) { - return StoreCountHelper(pi); - } - - // Store the number of characters printed so far - PrintfState& operator()(short * pi) { - return StoreCountHelper(pi); - } - - // Store the number of characters printed so far - PrintfState& operator()(long * pi) { - return StoreCountHelper(pi); - } - - PrintfState& operator()(const char *const s) { - if (result_ == -1) return *this; - ReadLeaders(); - const char fmt = *format_; - if (fmt == 'p') { - FormatWithCurrentFlags(reinterpret_cast(s)); - return *this; - } - if (fmt != 's') { - result_ = -1; - return *this; - } - const size_t len = std::min(strlen(s), prec_); - if (width_ > len) { - if (LeftJustify()) { - Write(s, s + len); - Fill(' ', width_ - len); - } else { - Fill(' ', width_ - len); - Write(s, s + len); - } - } else { - Write(s, s + len); - } - Next(); - return *this; - } - - PrintfState& operator()(const void *const p) { - return (*this)(reinterpret_cast(p)); - } - - // read the result - operator int() const { - return result_; - } - -private: - PrintfState& operator=(const PrintfState&); - template - PrintfState& StoreCountHelper(T *const pi) { - if (result_ == -1) return *this; // don't even bother - ReadLeaders(); - const char fmt = *format_; - if (fmt == 'p') { // pointer - FormatWithCurrentFlags(reinterpret_cast(pi)); - return *this; - } - if (fmt != 'n') { - result_ = -1; - return *this; - } - assert(pi != 0); - *pi = result_; - Next(); - return *this; - } + PrintfState& operator()(long double n) { + if (result_ == -1) return *this; // don't even bother + PrintFloatingPoint(n); + return *this; + } - void FormatWithCurrentFlags(const unsigned long i) { - // look at the format character - Char formatChar = *format_; - bool isSigned = formatChar == 'd' || formatChar == 'i'; - if (formatChar == 'p') { - formatChar = 'x'; // pointers go to hex - SetAlternateForm(); // printed with '0x' in front - isSigned = true; // that's what gcc does - } - if (!strchr("cdiuoxX", formatChar)) { - result_ = -1; - return; - } - Char buf[ - sizeof(unsigned long) * 3 // digits - + 1 // sign or ' ' - + 2 // 0x or 0X - + 1]; // terminating zero - const Char *const bufEnd = buf + (sizeof(buf) / sizeof(Char)); - Char * bufLast = buf + (sizeof(buf) / sizeof(Char) - 1); - Char signChar = 0; - unsigned int base = 10; - - if (formatChar == 'c') { - // Format only one character - // The 'fill with zeros' flag is ignored - ResetFillZeros(); - *bufLast = static_cast(i); - } else { - // TODO: inefficient code, refactor - const bool negative = isSigned && static_cast(i) < 0; - if (formatChar == 'o') base = 8; - else if (formatChar == 'x' || formatChar == 'X') base = 16; - bufLast = isSigned - ? RenderWithoutSign(static_cast(i), bufLast, base, - formatChar == 'X') - : RenderWithoutSign(i, bufLast, base, - formatChar == 'X'); - // Add the sign - if (isSigned) { - negative ? signChar = '-' - : ShowSignAlways() ? signChar = '+' - : Blank() ? signChar = ' ' - : 0; - } - } - // precision - size_t - countDigits = bufEnd - bufLast, - countZeros = prec_ != size_t(-1) && countDigits < prec_ && - formatChar != 'c' - ? prec_ - countDigits - : 0, - countBase = base != 10 && AlternateForm() && i != 0 - ? (base == 16 ? 2 : countZeros > 0 ? 0 : 1) - : 0, - countSign = (signChar != 0), - totalPrintable = countDigits + countZeros + countBase + countSign; - size_t countPadLeft = 0, countPadRight = 0; - if (width_ > totalPrintable) { - if (LeftJustify()) { - countPadRight = width_ - totalPrintable; - countPadLeft = 0; - } else { - countPadLeft = width_ - totalPrintable; - countPadRight = 0; - } - } - if (FillZeros() && prec_ == size_t(-1)) { - // pad with zeros and no precision - transfer padding to precision - countZeros = countPadLeft; - countPadLeft = 0; - } - // ok, all computed, ready to print to device - Fill(' ', countPadLeft); - if (signChar != 0) Write(&signChar, &signChar + 1); - if (countBase > 0) Fill('0', 1); - if (countBase == 2) Fill(formatChar, 1); - Fill('0', countZeros); - Write(bufLast, bufEnd); - Fill(' ', countPadRight); - // done, advance - Next(); - } - - void Write(const Char* b, const Char* e) { - if (result_ < 0) return; - const ptrdiff_t x = e - b; - write(device_, b, e); - result_ += x; - } + // Store the number of characters printed so far + PrintfState& operator()(int * pi) { + return StoreCountHelper(pi); + } + + // Store the number of characters printed so far + PrintfState& operator()(short * pi) { + return StoreCountHelper(pi); + } + + // Store the number of characters printed so far + PrintfState& operator()(long * pi) { + return StoreCountHelper(pi); + } + + PrintfState& operator()(const char *const s) { + if (result_ == -1) return *this; + ReadLeaders(); + const char fmt = *format_; + if (fmt == 'p') { + FormatWithCurrentFlags(reinterpret_cast(s)); + return *this; + } + if (fmt != 's') { + result_ = -1; + return *this; + } + const size_t len = std::min(strlen(s), prec_); + if (width_ > len) { + if (LeftJustify()) { + Write(s, s + len); + Fill(' ', width_ - len); + } else { + Fill(' ', width_ - len); + Write(s, s + len); + } + } else { + Write(s, s + len); + } + Next(); + return *this; + } + + PrintfState& operator()(const void *const p) { + return (*this)(reinterpret_cast(p)); + } + + // read the result + operator int() const { + return result_; + } + + private: + PrintfState& operator=(const PrintfState&); + template + PrintfState& StoreCountHelper(T *const pi) { + if (result_ == -1) return *this; // don't even bother + ReadLeaders(); + const char fmt = *format_; + if (fmt == 'p') { // pointer + FormatWithCurrentFlags(reinterpret_cast(pi)); + return *this; + } + if (fmt != 'n') { + result_ = -1; + return *this; + } + assert(pi != 0); + *pi = result_; + Next(); + return *this; + } - template - void PrintFloatingPoint(Double n) { - const Char *const fmt = format_ - 1; - assert(*fmt == '%'); - // enforce format string validity - ReadLeaders(); - // enforce format spec - if (!strchr("eEfgG", *format_)) { - result_ = -1; - return; - } - // format char validated, copy it to a temp and use legacy sprintf - ++format_; - Char fmtBuf[128], resultBuf[1024]; - if (format_ >= fmt + sizeof(fmtBuf) / sizeof(Char)) { - result_ = -1; - return; - } - memcpy(fmtBuf, fmt, (format_ - fmt) * sizeof(Char)); - fmtBuf[format_ - fmt] = 0; -#ifdef _MSC_VER - const int stored = _snprintf(resultBuf, -#else - const int stored = snprintf(resultBuf, -#endif - sizeof(resultBuf) / sizeof(Char), fmtBuf, n); - if (stored < 0) { - result_ = -1; - return; - } - Write(resultBuf, resultBuf + strlen(resultBuf)); - Advance(); // output stuff to the next format directive - } + void FormatWithCurrentFlags(const unsigned long i) { + // look at the format character + Char formatChar = *format_; + bool isSigned = formatChar == 'd' || formatChar == 'i'; + if (formatChar == 'p') { + formatChar = 'x'; // pointers go to hex + SetAlternateForm(); // printed with '0x' in front + isSigned = true; // that's what gcc does + } + if (!strchr("cdiuoxX", formatChar)) { + result_ = -1; + return; + } + Char buf[ + sizeof(unsigned long) * 3 // digits + + 1 // sign or ' ' + + 2 // 0x or 0X + + 1]; // terminating zero + const Char *const bufEnd = buf + (sizeof(buf) / sizeof(Char)); + Char * bufLast = buf + (sizeof(buf) / sizeof(Char) - 1); + Char signChar = 0; + unsigned int base = 10; + + if (formatChar == 'c') { + // Format only one character + // The 'fill with zeros' flag is ignored + ResetFillZeros(); + *bufLast = static_cast(i); + } else { + // TODO: inefficient code, refactor + const bool negative = isSigned && static_cast(i) < 0; + if (formatChar == 'o') base = 8; + else if (formatChar == 'x' || formatChar == 'X') base = 16; + bufLast = isSigned + ? RenderWithoutSign(static_cast(i), bufLast, base, + formatChar == 'X') + : RenderWithoutSign(i, bufLast, base, + formatChar == 'X'); + // Add the sign + if (isSigned) { + negative ? signChar = '-' + : ShowSignAlways() ? signChar = '+' + : Blank() ? signChar = ' ' + : 0; + } + } + // precision + size_t + countDigits = bufEnd - bufLast, + countZeros = prec_ != size_t(-1) && countDigits < prec_ && + formatChar != 'c' + ? prec_ - countDigits + : 0, + countBase = base != 10 && AlternateForm() && i != 0 + ? (base == 16 ? 2 : countZeros > 0 ? 0 : 1) + : 0, + countSign = (signChar != 0), + totalPrintable = countDigits + countZeros + countBase + countSign; + size_t countPadLeft = 0, countPadRight = 0; + if (width_ > totalPrintable) { + if (LeftJustify()) { + countPadRight = width_ - totalPrintable; + countPadLeft = 0; + } else { + countPadLeft = width_ - totalPrintable; + countPadRight = 0; + } + } + if (FillZeros() && prec_ == size_t(-1)) { + // pad with zeros and no precision - transfer padding to precision + countZeros = countPadLeft; + countPadLeft = 0; + } + // ok, all computed, ready to print to device + Fill(' ', countPadLeft); + if (signChar != 0) Write(&signChar, &signChar + 1); + if (countBase > 0) Fill('0', 1); + if (countBase == 2) Fill(formatChar, 1); + Fill('0', countZeros); + Write(bufLast, bufEnd); + Fill(' ', countPadRight); + // done, advance + Next(); + } + + void Write(const Char* b, const Char* e) { + if (result_ < 0) return; + const ptrdiff_t x = e - b; + write(device_, b, e); + result_ += x; + } - void Fill(const Char c, size_t n) { - for (; n > 0; --n) { - Write(&c, &c + 1); - } - } - - Char* RenderWithoutSign(unsigned long n, char* bufLast, - unsigned int base, bool uppercase) { - const Char hex1st = uppercase ? 'A' : 'a'; - for (;;) { - const unsigned long next = n / base; - Char c = n - next * base; - c += (c <= 9) ? '0' : hex1st - 10; - *bufLast = c; - n = next; - if (n == 0) break; - --bufLast; - } - return bufLast; - } - - char* RenderWithoutSign(long n, char* bufLast, unsigned int base, - bool uppercase) { - if (n != LONG_MIN) { - return RenderWithoutSign(static_cast(n < 0 ? -n : n), - bufLast, base, uppercase); - } - // annoying corner case - char* save = bufLast; - ++n; - bufLast = RenderWithoutSign(static_cast(n), - bufLast, base, uppercase); - --(*save); - return bufLast; - } - - void Next() { - ++format_; - Advance(); - } - - void Advance() { - ResetAll(); - const Char* begin = format_; - for (;;) { - if (*format_ == '%') { - if (format_[1] != '%') { // It's a format specifier - Write(begin, format_); - ++format_; - break; - } - // It's a "%%" - Write(begin, ++format_); - begin = ++format_; - continue; - } - if (*format_ == 0) { - Write(begin, format_); - break; - } - ++format_; - } - } - - void ReadFlags() { - for (;; ++format_) { - switch (*format_) { - case '-': SetLeftJustify(); break; - case '+': SetShowSignAlways(); break; - case ' ': SetBlank(); break; - case '#': SetAlternateForm(); break; - case '0': SetFillZeros(); break; - default: return; - } - } - } - - void ParseDecimalSizeT(size_t& dest) { - if (!std::isdigit(*format_, std::locale())) return; - size_t r = 0; - do { - // TODO: inefficient - rewrite - r *= 10; - r += *format_ - '0'; - ++format_; - } while (std::isdigit(*format_, std::locale())); - dest = r; - } - - void ReadWidth() { - ParseDecimalSizeT(width_); - } - - void ReadPrecision() { - assert(*format_ == '.'); - ++format_; - ParseDecimalSizeT(prec_); - } - - void ReadModifiers() { - switch (*format_) { - case 'h': SetForceShort(); ++format_; break; - case 'l': ++format_; break; - // more (C99 and platform-specific modifiers) to come - } - } - - void ReadLeaders() { - ReadFlags(); - ReadWidth(); - if (*format_ == '.') ReadPrecision(); - ReadModifiers(); - } - - enum { - leftJustify = 1, - showSignAlways = 2, - blank = 4, - alternateForm = 8, - fillZeros = 16, - forceShort = 32 - }; - - bool LeftJustify() const { return (flags_ & leftJustify) != 0; } - bool ShowSignAlways() const { return (flags_ & showSignAlways) != 0; } - void SetWidth(size_t w) { width_ = w; } - void SetLeftJustify() { flags_ |= leftJustify; } - void SetShowSignAlways() { flags_ |= showSignAlways; } - bool Blank() const { return (flags_ & blank) != 0; } - bool AlternateForm() const { return (flags_ & alternateForm) != 0; } - bool FillZeros() const { return (flags_ & fillZeros) != 0; } - bool ForceShort() const { return (flags_ & forceShort) != 0; } + template + void PrintFloatingPoint(Double n) { + const Char *const fmt = format_ - 1; + assert(*fmt == '%'); + // enforce format string validity + ReadLeaders(); + // enforce format spec + if (!strchr("eEfgG", *format_)) { + result_ = -1; + return; + } + // format char validated, copy it to a temp and use legacy sprintf + ++format_; + Char fmtBuf[128], resultBuf[1024]; + if (format_ >= fmt + sizeof(fmtBuf) / sizeof(Char)) { + result_ = -1; + return; + } + memcpy(fmtBuf, fmt, (format_ - fmt) * sizeof(Char)); + fmtBuf[format_ - fmt] = 0; + #ifdef _MSC_VER + const int stored = _snprintf(resultBuf, + #else + const int stored = snprintf(resultBuf, + #endif + sizeof(resultBuf) / sizeof(Char), fmtBuf, n); + if (stored < 0) { + result_ = -1; + return; + } + Write(resultBuf, resultBuf + strlen(resultBuf)); + Advance(); // output stuff to the next format directive + } - void SetPrec(size_t p) { prec_ = p; } - void SetBlank() { flags_ |= blank; } - void SetAlternateForm() { flags_ |= alternateForm; } - void SetFillZeros() { flags_ |= fillZeros; } - void ResetFillZeros() { flags_ &= ~fillZeros; } - void SetForceShort() { flags_ |= forceShort; } - - void ResetAll() { - assert(result_ != EOF); - width_ = 0; - prec_ = size_t(-1); - flags_ = 0; - } + void Fill(const Char c, size_t n) { + for (; n > 0; --n) { + Write(&c, &c + 1); + } + } + + Char* RenderWithoutSign(unsigned long n, char* bufLast, + unsigned int base, bool uppercase) { + const Char hex1st = uppercase ? 'A' : 'a'; + for (;;) { + const unsigned long next = n / base; + Char c = n - next * base; + c += (c <= 9) ? '0' : hex1st - 10; + *bufLast = c; + n = next; + if (n == 0) break; + --bufLast; + } + return bufLast; + } + + char* RenderWithoutSign(long n, char* bufLast, unsigned int base, + bool uppercase) { + if (n != LONG_MIN) { + return RenderWithoutSign(static_cast(n < 0 ? -n : n), + bufLast, base, uppercase); + } + // annoying corner case + char* save = bufLast; + ++n; + bufLast = RenderWithoutSign(static_cast(n), + bufLast, base, uppercase); + --(*save); + return bufLast; + } + + void Next() { + ++format_; + Advance(); + } + + void Advance() { + ResetAll(); + const Char* begin = format_; + for (;;) { + if (*format_ == '%') { + if (format_[1] != '%') { // It's a format specifier + Write(begin, format_); + ++format_; + break; + } + // It's a "%%" + Write(begin, ++format_); + begin = ++format_; + continue; + } + if (*format_ == 0) { + Write(begin, format_); + break; + } + ++format_; + } + } + + void ReadFlags() { + for (;; ++format_) { + switch (*format_) { + case '-': SetLeftJustify(); break; + case '+': SetShowSignAlways(); break; + case ' ': SetBlank(); break; + case '#': SetAlternateForm(); break; + case '0': SetFillZeros(); break; + default: return; + } + } + } + + void ParseDecimalSizeT(size_t& dest) { + if (!std::isdigit(*format_, std::locale())) return; + size_t r = 0; + do { + // TODO: inefficient - rewrite + r *= 10; + r += *format_ - '0'; + ++format_; + } while (std::isdigit(*format_, std::locale())); + dest = r; + } + + void ReadWidth() { + ParseDecimalSizeT(width_); + } + + void ReadPrecision() { + assert(*format_ == '.'); + ++format_; + ParseDecimalSizeT(prec_); + } + + void ReadModifiers() { + switch (*format_) { + case 'h': SetForceShort(); ++format_; break; + case 'l': ++format_; break; + // more (C99 and platform-specific modifiers) to come + } + } + + void ReadLeaders() { + ReadFlags(); + ReadWidth(); + if (*format_ == '.') ReadPrecision(); + ReadModifiers(); + } + + enum { + leftJustify = 1, + showSignAlways = 2, + blank = 4, + alternateForm = 8, + fillZeros = 16, + forceShort = 32 + }; + + bool LeftJustify() const { return (flags_ & leftJustify) != 0; } + bool ShowSignAlways() const { return (flags_ & showSignAlways) != 0; } + void SetWidth(size_t w) { width_ = w; } + void SetLeftJustify() { flags_ |= leftJustify; } + void SetShowSignAlways() { flags_ |= showSignAlways; } + bool Blank() const { return (flags_ & blank) != 0; } + bool AlternateForm() const { return (flags_ & alternateForm) != 0; } + bool FillZeros() const { return (flags_ & fillZeros) != 0; } + bool ForceShort() const { return (flags_ & forceShort) != 0; } - // state - Device device_; - const Char* format_; - size_t width_; - size_t prec_; - unsigned int flags_; - int result_; -}; + void SetPrec(size_t p) { prec_ = p; } + void SetBlank() { flags_ |= blank; } + void SetAlternateForm() { flags_ |= alternateForm; } + void SetFillZeros() { flags_ |= fillZeros; } + void ResetFillZeros() { flags_ &= ~fillZeros; } + void SetForceShort() { flags_ |= forceShort; } + + void ResetAll() { + assert(result_ != EOF); + width_ = 0; + prec_ = size_t(-1); + flags_ = 0; + } -PrintfState Printf(const char* format) { - return PrintfState(stdout, format); -} + // state + Device device_; + const Char* format_; + size_t width_; + size_t prec_; + unsigned int flags_; + int result_; + }; -PrintfState FPrintf(FILE* f, const char* format) { - return PrintfState(f, format); -} + PrintfState Printf(const char* format) { + return PrintfState(stdout, format); + } -PrintfState SPrintf(std::string& s, const char* format) { - return PrintfState(s, format); -} + PrintfState FPrintf(FILE* f, const char* format) { + return PrintfState(f, format); + } -template -PrintfState XPrintf(T& device, const Char* format) { - return PrintfState(device, format); -} + PrintfState SPrintf(std::string& s, const char* format) { + return PrintfState(s, format); + } -template -PrintfState, Char> -BufPrintf(Char (&buf)[N], const Char* format) { - std::pair temp(buf, N); - return PrintfState, Char>(temp, format); -} + template + PrintfState XPrintf(T& device, const Char* format) { + return PrintfState(device, format); + } + + template + PrintfState, Char> + BufPrintf(Char (&buf)[N], const Char* format) { + std::pair temp(buf, N); + return PrintfState, Char>(temp, format); + } + +}// namespace Loki #endif //SAFEFORMAT_H_