summaryrefslogtreecommitdiff
path: root/shared/loki/SafeFormat.h
diff options
context:
space:
mode:
Diffstat (limited to 'shared/loki/SafeFormat.h')
-rw-r--r--shared/loki/SafeFormat.h682
1 files changed, 0 insertions, 682 deletions
diff --git a/shared/loki/SafeFormat.h b/shared/loki/SafeFormat.h
deleted file mode 100644
index bd2837f9..00000000
--- a/shared/loki/SafeFormat.h
+++ /dev/null
@@ -1,682 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2005 by Andrei Alexandrescu
-// Copyright (c) 2006 Peter Kümmel
-// Permission to use, copy, modify, distribute, and sell this software for any
-// purpose is hereby granted without fee, provided that the above copyright
-// notice appear in all copies and that both that copyright notice and this
-// permission notice appear in supporting documentation.
-// The author makes no representations about the suitability of this software
-// for any purpose. It is provided "as is" without express or implied
-// warranty.
-////////////////////////////////////////////////////////////////////////////////
-#ifndef LOKI_SAFEFORMAT_INC_
-#define LOKI_SAFEFORMAT_INC_
-
-// $Id: SafeFormat.h 911 2008-12-15 20:55:24Z syntheticpp $
-
-
-////////////////////////////////////////////////////////////////////////////////
-// This file contains definitions for SafePrintf. SafeScanf coming soon (the
-// design is similar).
-// See Alexandrescu, Andrei: Type-safe Formatting, C/C++ Users Journal, Aug 2005
-////////////////////////////////////////////////////////////////////////////////
-
-#include <cstdio>
-#include <climits>
-#include <string>
-#include <cstring>
-#include <stdexcept>
-#include <utility>
-#include <cassert>
-#include <locale>
-#include <iostream>
-
-#include <loki/LokiExport.h>
-
-
-// long is 32 bit on 64-bit Windows!
-// intptr_t used to get 64 bit on Win64
-#if defined(_WIN32) || defined(_WIN64)
-# define LOKI_SAFEFORMAT_SIGNED_LONG intptr_t
-# define LOKI_SAFEFORMAT_UNSIGNED_LONG uintptr_t
-#else
-# define LOKI_SAFEFORMAT_SIGNED_LONG signed long
-# define LOKI_SAFEFORMAT_UNSIGNED_LONG unsigned long
-#endif
-
-// Windows headers could have min/max defined
-#ifdef max
-# undef max
-#endif
-#ifdef min
-# undef min
-#endif
-
-namespace Loki
-{
-
-// Crude writing method: writes straight to the file, unbuffered
-// Must be combined with a buffer to work properly (and efficiently)
-LOKI_EXPORT
-void write(std::FILE* f, const char* from, const char* to);
-
-// Write to an ostream
-LOKI_EXPORT
-void write(std::ostream& f, const char* from, const char* to);
-
-// Write to a string
-LOKI_EXPORT
-void write(std::string& s, const char* from, const char* to);
-
-// Write to a fixed-size buffer
-template <class Char>
-void write(std::pair<Char*, std::size_t>& s, const Char* from, const Char* to)
-{
- assert(from <= to);
- if (from + s.second < to)
- throw std::overflow_error("");
- // s.first: position one past the final copied element
- s.first = std::copy(from, to, s.first);
- // remaining buffer size
- s.second -= to - from;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// PrintfState class template
-// Holds the formatting state, and implements operator() to format stuff
-// Todo: make sure errors are handled properly
-////////////////////////////////////////////////////////////////////////////////
-
-template <class Device, class Char>
-struct PrintfState
-{
- PrintfState(Device dev, const Char* format)
- : device_(dev)
- , format_(format)
- , width_(0)
- , prec_(0)
- , flags_(0)
- , result_(0)
- {
- Advance();
- }
-
- ~PrintfState()
- {
- }
-
-#define LOKI_PRINTF_STATE_FORWARD(type) \
- PrintfState& operator()(type par) {\
- return (*this)(static_cast< LOKI_SAFEFORMAT_UNSIGNED_LONG >(par)); \
- }
-
- 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(signed short)
- LOKI_PRINTF_STATE_FORWARD(unsigned short)
- LOKI_PRINTF_STATE_FORWARD(signed int)
- LOKI_PRINTF_STATE_FORWARD(signed long)
-#if (defined(_WIN32) || defined(_WIN64))
- LOKI_PRINTF_STATE_FORWARD(unsigned long)
-#else
- // on Windows already defined by uintptr_t
- LOKI_PRINTF_STATE_FORWARD(unsigned int)
-#endif
-
- // Print (or gobble in case of the "*" specifier) an int
- PrintfState& operator()(LOKI_SAFEFORMAT_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<size_t>(i));
- ++format_;
- return *this;
- }
- ReadWidth();
- // precision
- if (*format_ == '.')
- {
- // deal with precision
- if (format_[1] == '*')
- {
- // read the precision and get out
- SetPrec(static_cast<size_t>(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<LOKI_SAFEFORMAT_UNSIGNED_LONG>(static_cast<unsigned short>(i));
- }
- }
- FormatWithCurrentFlags(i);
- return *this;
- }
-
- PrintfState& operator()(void* n)
- {
- if (result_ == -1) return *this; // don't even bother
- PrintUsing_snprintf(n, "p");
- return *this;
- }
-
- PrintfState& operator()(double n)
- {
- if (result_ == -1) return *this; // don't even bother
- PrintUsing_snprintf(n, "eEfgG");
- return *this;
- }
-
- PrintfState& operator()(long double n)
- {
- if (result_ == -1) return *this; // don't even bother
- PrintUsing_snprintf(n, "eEfgG");
- 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 std::string& stdstr)
- {
- return operator()(stdstr.c_str());
- }
-
- PrintfState& operator()(const char* const s)
- {
- if (result_ == -1) return *this;
- ReadLeaders();
- const char fmt = *format_;
- if (fmt == 'p')
- {
- FormatWithCurrentFlags(reinterpret_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(s));
- return *this;
- }
- if (fmt != 's')
- {
- result_ = -1;
- return *this;
- }
- const size_t len = std::min(std::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<LOKI_SAFEFORMAT_UNSIGNED_LONG>(p));
- }
-
- // read the result
- operator int() const
- {
- return static_cast<int>(result_);
- }
-
-private:
- PrintfState& operator=(const PrintfState&);
- template <typename T>
- 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<LOKI_SAFEFORMAT_UNSIGNED_LONG>(pi));
- return *this;
- }
- if (fmt != 'n')
- {
- result_ = -1;
- return *this;
- }
- assert(pi != 0);
- *pi = result_;
- Next();
- return *this;
- }
-
- void FormatWithCurrentFlags(const LOKI_SAFEFORMAT_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(LOKI_SAFEFORMAT_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<char>(i);
- }
- else
- {
- // TODO: inefficient code, refactor
- const bool negative = isSigned && static_cast<LOKI_SAFEFORMAT_SIGNED_LONG>(i) < 0;
- if (formatChar == 'o') base = 8;
- else if (formatChar == 'x' || formatChar == 'X') base = 16;
- bufLast = isSigned
- ? RenderWithoutSign(static_cast<LOKI_SAFEFORMAT_SIGNED_LONG>(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 LOKI_SAFEFORMAT_SIGNED_LONG x = e - b;
- write(device_, b, e);
- result_ += x;
- }
-
- template <class Value>
- void PrintUsing_snprintf(Value n, const char* check_fmt_char)
- {
- const Char* const fmt = format_ - 1;
- assert(*fmt == '%');
- // enforce format string validity
- ReadLeaders();
- // enforce format spec
- if (!strchr(check_fmt_char, *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;
-
- const int stored =
-#ifdef _MSC_VER
-#if _MSC_VER < 1400
- _snprintf
-#else
- _snprintf_s
-#endif
-#else
- snprintf
-#endif
- (resultBuf, 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 Fill(const Char c, size_t n)
- {
- for (; n > 0; --n)
- {
- Write(&c, &c + 1);
- }
- }
-
- Char* RenderWithoutSign(LOKI_SAFEFORMAT_UNSIGNED_LONG n, char* bufLast,
- unsigned int base, bool uppercase)
- {
- const Char hex1st = uppercase ? 'A' : 'a';
- for (;;)
- {
- const LOKI_SAFEFORMAT_UNSIGNED_LONG next = n / base;
- Char c = static_cast<Char>(n - next * base);
- c = static_cast<Char>(c + (c <= 9 ? '0' : static_cast<Char>(hex1st - 10)));
- *bufLast = c;
- n = next;
- if (n == 0) break;
- --bufLast;
- }
- return bufLast;
- }
-
- char* RenderWithoutSign(LOKI_SAFEFORMAT_SIGNED_LONG n, char* bufLast, unsigned int base,
- bool uppercase)
- {
- if (n != LONG_MIN)
- {
- return RenderWithoutSign(static_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(n < 0 ? -n : n),
- bufLast, base, uppercase);
- }
- // annoying corner case
- char* save = bufLast;
- ++n;
- bufLast = RenderWithoutSign(static_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(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; }
-
- 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;
- }
-
- // state
- Device device_;
- const Char* format_;
- size_t width_;
- size_t prec_;
- unsigned int flags_;
- LOKI_SAFEFORMAT_SIGNED_LONG result_;
-};
-
-LOKI_EXPORT
-PrintfState<std::FILE*, char> Printf(const char* format);
-
-LOKI_EXPORT
-PrintfState<std::FILE*, char> Printf(const std::string& format);
-
-LOKI_EXPORT
-PrintfState<std::FILE*, char> FPrintf(std::FILE* f, const char* format);
-
-LOKI_EXPORT
-PrintfState<std::FILE*, char> FPrintf(std::FILE* f, const std::string& format);
-
-LOKI_EXPORT
-PrintfState<std::ostream&, char> FPrintf(std::ostream& f, const char* format);
-
-LOKI_EXPORT
-PrintfState<std::ostream&, char> FPrintf(std::ostream& f, const std::string& format);
-
-LOKI_EXPORT
-PrintfState<std::string&, char> SPrintf(std::string& s, const char* format);
-
-LOKI_EXPORT
-PrintfState<std::string&, char> SPrintf(std::string& s, const std::string& format);
-
-template <class T, class Char>
-PrintfState<T&, Char> XPrintf(T& device, const Char* format)
-{
- return PrintfState<T&, Char>(device, format);
-}
-
-template <class T>
-PrintfState<T&, char> XPrintf(T& device, const std::string& format)
-{
- return PrintfState<T&, char>(device, format.c_str());
-}
-
-template <class Char, std::size_t N>
-PrintfState<std::pair<Char*, std::size_t>, Char>
-BufPrintf(Char (&buf)[N], const Char* format)
-{
- std::pair<Char*, std::size_t> temp(buf, N);
- return PrintfState<std::pair<Char*, std::size_t>, Char>(temp, format);
-}
-
-}// namespace Loki
-
-
-#endif // end file guardian
-
bgstack15