mirror of
				https://github.com/fmtlib/fmt.git
				synced 2025-11-03 23:51:41 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			248 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 Small, safe and fast printf-like formatting library for C++
 | 
						|
 Author: Victor Zverovich
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef FORMAT_H_
 | 
						|
#define FORMAT_H_
 | 
						|
 | 
						|
#include <cstddef>
 | 
						|
#include <cstdio>
 | 
						|
#include <stdexcept>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
namespace format {
 | 
						|
 | 
						|
class FormatError : public std::runtime_error {
 | 
						|
 public:
 | 
						|
  FormatError(const std::string &message) : std::runtime_error(message) {}
 | 
						|
};
 | 
						|
 | 
						|
class ArgFormatter;
 | 
						|
 | 
						|
template <typename Callback>
 | 
						|
class ArgFormatterWithCallback;
 | 
						|
 | 
						|
// A sprintf-like formatter that automatically allocates enough storage to
 | 
						|
// fit all the output.
 | 
						|
class Formatter {
 | 
						|
 private:
 | 
						|
  std::vector<char> buffer_;
 | 
						|
 | 
						|
  enum Type {
 | 
						|
    CHAR, INT, UINT, LONG, ULONG, DOUBLE, LONG_DOUBLE, STRING, WSTRING, POINTER
 | 
						|
  };
 | 
						|
 | 
						|
  struct Arg {
 | 
						|
    Type type;
 | 
						|
    union {
 | 
						|
      int int_value;
 | 
						|
      unsigned uint_value;
 | 
						|
      double double_value;
 | 
						|
      long long_value;
 | 
						|
      unsigned long ulong_value;
 | 
						|
      long double long_double_value;
 | 
						|
      const char *string_value;
 | 
						|
      const wchar_t *wstring_value;
 | 
						|
      const void *pointer_value;
 | 
						|
    };
 | 
						|
 | 
						|
    explicit Arg(char value) : type(CHAR), int_value(value) {}
 | 
						|
    explicit Arg(int value) : type(INT), int_value(value) {}
 | 
						|
    explicit Arg(unsigned value) : type(UINT), uint_value(value) {}
 | 
						|
    explicit Arg(long value) : type(LONG), long_value(value) {}
 | 
						|
    explicit Arg(unsigned long value) : type(ULONG), ulong_value(value) {}
 | 
						|
    explicit Arg(double value) : type(DOUBLE), double_value(value) {}
 | 
						|
    explicit Arg(long double value)
 | 
						|
    : type(LONG_DOUBLE), long_double_value(value) {}
 | 
						|
    explicit Arg(const char *value) : type(STRING), string_value(value) {}
 | 
						|
    explicit Arg(const wchar_t *value) : type(WSTRING), wstring_value(value) {}
 | 
						|
    explicit Arg(const void *value) : type(POINTER), pointer_value(value) {}
 | 
						|
  };
 | 
						|
 | 
						|
  std::vector<Arg> args_;
 | 
						|
 | 
						|
  // Pointer to the part of the format string that hasn't been written yet.
 | 
						|
  const char *format_;
 | 
						|
 | 
						|
  friend class ArgFormatter;
 | 
						|
 | 
						|
  void Add(const Arg &arg) {
 | 
						|
    if (args_.empty())
 | 
						|
      args_.reserve(10);
 | 
						|
    args_.push_back(arg);
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename T>
 | 
						|
  void FormatArg(const char *format, const T &arg, int width, int precision);
 | 
						|
 | 
						|
  void Format();
 | 
						|
 | 
						|
 public:
 | 
						|
  Formatter() : format_(0) {}
 | 
						|
 | 
						|
  ArgFormatter operator()(const char *format);
 | 
						|
 | 
						|
  template <typename Callback>
 | 
						|
  ArgFormatterWithCallback<Callback> FormatWithCallback(const char *format);
 | 
						|
 | 
						|
  const char *c_str() const { return &buffer_[0]; }
 | 
						|
  std::size_t size() const { return buffer_.size() - 1; }
 | 
						|
};
 | 
						|
 | 
						|
class ArgFormatter {
 | 
						|
 private:
 | 
						|
  friend class Formatter;
 | 
						|
 | 
						|
 protected:
 | 
						|
  mutable Formatter *formatter_;
 | 
						|
 | 
						|
  ArgFormatter(const ArgFormatter& other) : formatter_(other.formatter_) {
 | 
						|
    other.formatter_ = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter& operator=(const ArgFormatter& other) {
 | 
						|
    formatter_ = other.formatter_;
 | 
						|
    other.formatter_ = 0;
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  Formatter *FinishFormatting() const {
 | 
						|
    Formatter *f = formatter_;
 | 
						|
    if (f) {
 | 
						|
      formatter_ = 0;
 | 
						|
      f->Format();
 | 
						|
    }
 | 
						|
    return f;
 | 
						|
  }
 | 
						|
 | 
						|
 public:
 | 
						|
  explicit ArgFormatter(Formatter &f) : formatter_(&f) {}
 | 
						|
  ~ArgFormatter();
 | 
						|
 | 
						|
  friend const char *c_str(const ArgFormatter &af) {
 | 
						|
    return af.FinishFormatting()->c_str();
 | 
						|
  }
 | 
						|
 | 
						|
  friend std::string str(const ArgFormatter &af) {
 | 
						|
    return af.FinishFormatting()->c_str();
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter &operator<<(char value) {
 | 
						|
    formatter_->Add(Formatter::Arg(value));
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter &operator<<(int value) {
 | 
						|
    formatter_->Add(Formatter::Arg(value));
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter &operator<<(unsigned value) {
 | 
						|
    formatter_->Add(Formatter::Arg(value));
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter &operator<<(long value) {
 | 
						|
    formatter_->Add(Formatter::Arg(value));
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter &operator<<(unsigned long value) {
 | 
						|
    formatter_->Add(Formatter::Arg(value));
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter &operator<<(double value) {
 | 
						|
    formatter_->Add(Formatter::Arg(value));
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter &operator<<(long double value) {
 | 
						|
    formatter_->Add(Formatter::Arg(value));
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter &operator<<(const char *value) {
 | 
						|
    formatter_->Add(Formatter::Arg(value));
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgFormatter &operator<<(const void *value) {
 | 
						|
    formatter_->Add(Formatter::Arg(value));
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  // This method is not implemented intentionally to disallow output of
 | 
						|
  // arbitrary pointers. If you want to output a pointer cast it to void*.
 | 
						|
  template <typename T>
 | 
						|
  ArgFormatter &operator<<(const T *value);
 | 
						|
};
 | 
						|
 | 
						|
template <typename Callback>
 | 
						|
class ArgFormatterWithCallback : public ArgFormatter {
 | 
						|
 public:
 | 
						|
  explicit ArgFormatterWithCallback(Formatter &f) : ArgFormatter(f) {}
 | 
						|
 | 
						|
  ~ArgFormatterWithCallback() {
 | 
						|
    if (!formatter_) return;
 | 
						|
    Callback callback;
 | 
						|
    callback(*formatter_);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
inline ArgFormatter Formatter::operator()(const char *format) {
 | 
						|
  format_ = format;
 | 
						|
  return ArgFormatter(*this);
 | 
						|
}
 | 
						|
 | 
						|
template <typename Callback>
 | 
						|
ArgFormatterWithCallback<Callback>
 | 
						|
Formatter::FormatWithCallback(const char *format) {
 | 
						|
  format_ = format;
 | 
						|
  return ArgFormatterWithCallback<Callback>(*this);
 | 
						|
}
 | 
						|
 | 
						|
class Format : public ArgFormatter {
 | 
						|
 private:
 | 
						|
  Formatter formatter_;
 | 
						|
 | 
						|
  // Do not implement.
 | 
						|
  Format(const Format&);
 | 
						|
  Format& operator=(const Format&);
 | 
						|
 | 
						|
 public:
 | 
						|
  explicit Format(const char *format) : ArgFormatter(formatter_) {
 | 
						|
    ArgFormatter::operator=(formatter_(format));
 | 
						|
  }
 | 
						|
 | 
						|
  ~Format() {
 | 
						|
    FinishFormatting();
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class Print : public ArgFormatter {
 | 
						|
 private:
 | 
						|
  Formatter formatter_;
 | 
						|
 | 
						|
  // Do not implement.
 | 
						|
  Print(const Print&);
 | 
						|
  Print& operator=(const Print&);
 | 
						|
 | 
						|
 public:
 | 
						|
  explicit Print(const char *format) : ArgFormatter(formatter_) {
 | 
						|
    ArgFormatter::operator=(formatter_(format));
 | 
						|
  }
 | 
						|
 | 
						|
  ~Print() {
 | 
						|
    FinishFormatting();
 | 
						|
    std::fwrite(formatter_.c_str(), 1, formatter_.size(), stdout);
 | 
						|
  }
 | 
						|
};
 | 
						|
}
 | 
						|
 | 
						|
namespace fmt = format;
 | 
						|
 | 
						|
#endif  // FORMAT_H_
 |