Commit message: Fix segfault on complex pointer formatting (#642)
CVE: CVE-2018-1000052
CWE: CWE-787
Vulnerability description: fmtlib version prior to version 4.1.0 (before commit 0555cea5fc0bf890afe0071a558e44625a34ba85) contains a Memory corruption (SIGSEGV), CWE-134 vulnerability in fmt::print() library function that can result in Denial of Service. This attack appear to be exploitable via Specifying an invalid format specifier in the fmt::print() function results in a SIGSEGV (memory corruption, invalid write). This vulnerability appears to have been fixed in after commit 8cf30aa2be256eba07bb1cefb998c52326e846e7.

Project: fmt
File: format.h

  const Char *c_str() const {
    std::size_t size = buffer_.size();
    buffer_.reserve(size + 1);
    buffer_[size] = '\0';
    return &buffer_[0];
  }

Project: fmt
File: format.h

  void write(const char *value) {
    Arg::StringValue<char> str = {value, value ? std::strlen(value) : 0};
    writer_.write_str(str, spec_);
  }

Project: fmt
File: format-test.cc

TEST(WriterTest, pad) {
  using fmt::hex;
  EXPECT_EQ("    cafe", (MemoryWriter() << pad(hex(0xcafe), 8)).str());
  EXPECT_EQ("    babe", (MemoryWriter() << pad(hex(0xbabeu), 8)).str());
  EXPECT_EQ("    dead", (MemoryWriter() << pad(hex(0xdeadl), 8)).str());
  EXPECT_EQ("    beef", (MemoryWriter() << pad(hex(0xbeeful), 8)).str());
  EXPECT_EQ("    dead", (MemoryWriter() << pad(hex(0xdeadll), 8)).str());
  EXPECT_EQ("    beef", (MemoryWriter() << pad(hex(0xbeefull), 8)).str());

  EXPECT_EQ("     11", (MemoryWriter() << pad(11, 7)).str());
  EXPECT_EQ("     22", (MemoryWriter() << pad(22u, 7)).str());
  EXPECT_EQ("     33", (MemoryWriter() << pad(33l, 7)).str());
  EXPECT_EQ("     44", (MemoryWriter() << pad(44ul, 7)).str());
  EXPECT_EQ("     33", (MemoryWriter() << pad(33ll, 7)).str());
  EXPECT_EQ("     44", (MemoryWriter() << pad(44ull, 7)).str());

  MemoryWriter w;
  w.clear();
  w << pad(42, 5, '0');
  EXPECT_EQ("00042", w.str());
  w.clear();
  w << Date(2012, 12, 9);
  EXPECT_EQ("2012-12-9", w.str());
  w.clear();
  w << iso8601(Date(2012, 1, 9));
  EXPECT_EQ("2012-01-09", w.str());
}

Project: fmt
File: format.h

  unsigned width() const { return 0; }

Project: fmt
File: format.h

  static bool is_negative(T) { return false; }

Project: fmt
File: format-test.cc

TEST(FormatTest, Variadic) {
  EXPECT_EQ("abc1", format("{}c{}", "ab", 1));
  EXPECT_EQ(L"abc1", format(L"{}c{}", L"ab", 1));
}

Project: fmt
File: format.h

  explicit FormatInt(unsigned value) : str_(format_decimal(value)) {}

Project: fmt
File: format.h

  void operator()(Char *) {}

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteWithoutArgs) {
  MemoryWriter w;
  w.write("test");
  EXPECT_EQ("test", std::string(w.data(), w.size()));
}

Project: fmt
File: format.h

inline T const_check(T value) { return value; }

Project: fmt
File: format-test.cc

TEST(FormatterTest, NumericAlign) {
  EXPECT_EQ("  42", format("{0:=4}", 42));
  EXPECT_EQ("+ 42", format("{0:=+4}", 42));
  EXPECT_EQ("  42", format("{0:=4o}", 042));
  EXPECT_EQ("+ 42", format("{0:=+4o}", 042));
  EXPECT_EQ("  42", format("{0:=4x}", 0x42));
  EXPECT_EQ("+ 42", format("{0:=+4x}", 0x42));
  EXPECT_EQ("-  42", format("{0:=5}", -42));
  EXPECT_EQ("   42", format("{0:=5}", 42u));
  EXPECT_EQ("-  42", format("{0:=5}", -42l));
  EXPECT_EQ("   42", format("{0:=5}", 42ul));
  EXPECT_EQ("-  42", format("{0:=5}", -42ll));
  EXPECT_EQ("   42", format("{0:=5}", 42ull));
  EXPECT_EQ("-  42", format("{0:=5}", -42.0));
  EXPECT_EQ("-  42", format("{0:=5}", -42.0l));
  EXPECT_THROW_MSG(format("{0:=5", 'c'),
      FormatError, "missing '}' in format string");
  EXPECT_THROW_MSG(format("{0:=5}", 'c'),
      FormatError, "invalid format specifier for char");
  EXPECT_THROW_MSG(format("{0:=5}", "abc"),
      FormatError, "format specifier '=' requires numeric argument");
  EXPECT_THROW_MSG(format("{0:=8}", reinterpret_cast<void*>(0xface)),
      FormatError, "format specifier '=' requires numeric argument");
}

Project: fmt
File: format.h

inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
  return t0.type | (t1.type << 4) | (t2.type << 8) | (t3.type << 12) |
      (t4.type << 16) | (t5.type << 20) | (t6.type << 24) | (t7.type << 28) |
      (t8.type << 32) | (t9.type << 36) | (t10.type << 40) | (t11.type << 44) |
      (t12.type << 48) | (t13.type << 52) | (t14.type << 56);
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, CenterAlign) {
  EXPECT_EQ(" 42  ", format("{0:^5}", 42));
  EXPECT_EQ(" 42  ", format("{0:^5o}", 042));
  EXPECT_EQ(" 42  ", format("{0:^5x}", 0x42));
  EXPECT_EQ(" -42 ", format("{0:^5}", -42));
  EXPECT_EQ(" 42  ", format("{0:^5}", 42u));
  EXPECT_EQ(" -42 ", format("{0:^5}", -42l));
  EXPECT_EQ(" 42  ", format("{0:^5}", 42ul));
  EXPECT_EQ(" -42 ", format("{0:^5}", -42ll));
  EXPECT_EQ(" 42  ", format("{0:^5}", 42ull));
  EXPECT_EQ(" -42  ", format("{0:^6}", -42.0));
  EXPECT_EQ(" -42 ", format("{0:^5}", -42.0l));
  EXPECT_EQ("  c  ", format("{0:^5}", 'c'));
  EXPECT_EQ(" abc  ", format("{0:^6}", "abc"));
  EXPECT_EQ(" 0xface ", format("{0:^8}", reinterpret_cast<void*>(0xface)));
}

Project: fmt
File: format-test.cc

TEST(FormatTest, CustomArgFormatter) {
  custom_format("{}", 42);
}

Project: fmt
File: format.h

operator"" _a(const char *s, std::size_t) { return {s}; }

Project: fmt
File: format.h

  BasicWriter &operator<<(double value) {
    write_double(value, FormatSpec());
    return *this;
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, Escape) {
  EXPECT_EQ("{", format("{{"));
  EXPECT_EQ("before {", format("before {{"));
  EXPECT_EQ("{ after", format("{{ after"));
  EXPECT_EQ("before { after", format("before {{ after"));

  EXPECT_EQ("}", format("}}"));
  EXPECT_EQ("before }", format("before }}"));
  EXPECT_EQ("} after", format("}} after"));
  EXPECT_EQ("before } after", format("before }} after"));

  EXPECT_EQ("{}", format("{{}}"));
  EXPECT_EQ("{42}", format("{{{0}}}", 42));
}

Project: fmt
File: format.h

  MakeValue(typename WCharHelper<wchar_t, Char>::Supported value) {
    int_value = value;
  }

Project: fmt
File: format-test.cc

  operator fmt::LongLong() const {
    return fmt::LongLong(1) << 32;
  }

Project: fmt
File: format.h

  void visit_pointer(const void *value) {
    if (spec_.type_ && spec_.type_ != 'p')
      report_unknown_type(spec_.type_, "pointer");
    write_pointer(value);
  }

Project: fmt
File: format.h

  char type() const { return TYPE; }

Project: fmt
File: format.h

  FormatSpec(
    unsigned width = 0, char type = 0, wchar_t fill = ' ')
  : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {}

Project: fmt
File: format-test.cc

TEST(FormatterTest, RuntimePrecision) {
  char format_str[BUFFER_SIZE];
  safe_sprintf(format_str, "{0:.{%u", UINT_MAX);
  increment(format_str + 5);
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
  std::size_t size = std::strlen(format_str);
  format_str[size] = '}';
  format_str[size + 1] = 0;
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
  format_str[size + 1] = '}';
  format_str[size + 2] = 0;
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");

  EXPECT_THROW_MSG(format("{0:.{", 0),
      FormatError, "invalid format string");
  EXPECT_THROW_MSG(format("{0:.{}", 0),
      FormatError, "cannot switch from manual to automatic argument indexing");
  EXPECT_THROW_MSG(format("{0:.{?}}", 0),
      FormatError, "invalid format string");
  EXPECT_THROW_MSG(format("{0:.{1}", 0, 0),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}}", 0),
      FormatError, "argument index out of range");

  EXPECT_THROW_MSG(format("{0:.{0:}}", 0),
      FormatError, "invalid format string");

  EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1),
      FormatError, "negative precision");
  EXPECT_THROW_MSG(format("{0:.{1}}", 0, (INT_MAX + 1u)),
      FormatError, "number is too big");
  EXPECT_THROW_MSG(format("{0:.{1}}", 0, -1l),
      FormatError, "negative precision");
  if (fmt::internal::const_check(sizeof(long) > sizeof(int))) {
    long value = INT_MAX;
    EXPECT_THROW_MSG(format("{0:.{1}}", 0, (value + 1)),
        FormatError, "number is too big");
  }
  EXPECT_THROW_MSG(format("{0:.{1}}", 0, (INT_MAX + 1ul)),
      FormatError, "number is too big");

  EXPECT_THROW_MSG(format("{0:.{1}}", 0, '0'),
      FormatError, "precision is not integer");
  EXPECT_THROW_MSG(format("{0:.{1}}", 0, 0.0),
      FormatError, "precision is not integer");

  EXPECT_THROW_MSG(format("{0:.{1}}", 42, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}f}", 42, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}}", 42u, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}f}", 42u, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}}", 42l, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}f}", 42l, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}}", 42ul, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}f}", 42ul, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}}", 42ll, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}f}", 42ll, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}}", 42ull, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}f}", 42ull, 2),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:3.{1}}", 'x', 0),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_EQ("1.2", format("{0:.{1}}", 1.2345, 2));
  EXPECT_EQ("1.2", format("{1:.{0}}", 2, 1.2345l));

  EXPECT_THROW_MSG(format("{0:.{1}}", reinterpret_cast<void*>(0xcafe), 2),
      FormatError, "precision not allowed in pointer format specifier");
  EXPECT_THROW_MSG(format("{0:.{1}f}", reinterpret_cast<void*>(0xcafe), 2),
      FormatError, "precision not allowed in pointer format specifier");

  EXPECT_EQ("st", format("{0:.{1}}", "str", 2));
}

Project: fmt
File: format.h

inline StrFormatSpec<Char> pad(
    const Char *str, unsigned width, Char fill = ' ') {
  return StrFormatSpec<Char>(str, width, fill);
}

Project: fmt
File: format.h

  virtual ~BasicWriter() {}

Project: fmt
File: format.h

  auto operator()(Args && ... args) const
                  -> decltype(format(str, std::forward<Args>(args)...)) {
    return format(str, std::forward<Args>(args)...);
  }

Project: fmt
File: format.h

  MakeValue(long value) {
    // To minimize the number of types we need to deal with, long is
    // translated either to int or to long long depending on its size.
    if (const_check(sizeof(long) == sizeof(int)))
      int_value = static_cast<int>(value);
    else
      long_long_value = value;
  }

Project: fmt
File: format.h

  const Char *data() const FMT_NOEXCEPT { return &buffer_[0]; }

Project: fmt
File: format.h

  std::string str() const { return std::string(&buffer_[0], size()); }

Project: fmt
File: format.h

void BasicWriter<Char>::write_int(T value, Spec spec) {
  unsigned prefix_size = 0;
  typedef typename internal::IntTraits<T>::MainType UnsignedType;
  UnsignedType abs_value = static_cast<UnsignedType>(value);
  char prefix[4] = "";
  if (internal::is_negative(value)) {
    prefix[0] = '-';
    ++prefix_size;
    abs_value = 0 - abs_value;
  } else if (spec.flag(SIGN_FLAG)) {
    prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' ';
    ++prefix_size;
  }
  switch (spec.type()) {
  case 0: case 'd': {
    unsigned num_digits = internal::count_digits(abs_value);
    CharPtr p = prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1;
    internal::format_decimal(get(p), abs_value, 0);
    break;
  }
  case 'x': case 'X': {
    UnsignedType n = abs_value;
    if (spec.flag(HASH_FLAG)) {
      prefix[prefix_size++] = '0';
      prefix[prefix_size++] = spec.type_prefix();
    }
    unsigned num_digits = 0;
    do {
      ++num_digits;
    } while ((n >>= 4) != 0);
    Char *p = get(prepare_int_buffer(
      num_digits, spec, prefix, prefix_size));
    n = abs_value;
    const char *digits = spec.type() == 'x' ?
        "0123456789abcdef" : "0123456789ABCDEF";
    do {
      *p-- = digits[n & 0xf];
    } while ((n >>= 4) != 0);
    break;
  }
  case 'b': case 'B': {
    UnsignedType n = abs_value;
    if (spec.flag(HASH_FLAG)) {
      prefix[prefix_size++] = '0';
      prefix[prefix_size++] = spec.type_prefix();
    }
    unsigned num_digits = 0;
    do {
      ++num_digits;
    } while ((n >>= 1) != 0);
    Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size));
    n = abs_value;
    do {
      *p-- = static_cast<Char>('0' + (n & 1));
    } while ((n >>= 1) != 0);
    break;
  }
  case 'o': {
    UnsignedType n = abs_value;
    if (spec.flag(HASH_FLAG))
      prefix[prefix_size++] = '0';
    unsigned num_digits = 0;
    do {
      ++num_digits;
    } while ((n >>= 3) != 0);
    Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size));
    n = abs_value;
    do {
      *p-- = static_cast<Char>('0' + (n & 7));
    } while ((n >>= 3) != 0);
    break;
  }
  case 'n': {
    unsigned num_digits = internal::count_digits(abs_value);
    fmt::StringRef sep = "";
#if !(defined(ANDROID) || defined(__ANDROID__))
    sep = internal::thousands_sep(std::localeconv());
#endif
    unsigned size = static_cast<unsigned>(
          num_digits + sep.size() * ((num_digits - 1) / 3));
    CharPtr p = prepare_int_buffer(size, spec, prefix, prefix_size) + 1;
    internal::format_decimal(get(p), abs_value, 0, internal::ThousandsSep(sep));
    break;
  }
  default:
    internal::report_unknown_type(
      spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer");
    break;
  }
}

Project: fmt
File: format.h

  T value() const { return value_; }

Project: fmt
File: format.h

  BasicCStringRef(const Char *s) : data_(s) {}

Project: fmt
File: format.h

  Result visit_unhandled_arg() {
    FMT_DISPATCH(report_unhandled_arg());
    return Result();
  }

Project: fmt
File: format.h

  virtual ~Buffer() {}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatFloat) {
  EXPECT_EQ("392.500000", format("{0:f}", 392.5f));
}

Project: fmt
File: format.h

inline DummyInt _isnan(...) { return DummyInt(); }

Project: fmt
File: format.h

  bool flag(unsigned) const { return false; }

Project: fmt
File: format.h

  friend bool operator>=(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) >= 0;
  }

Project: fmt
File: format.h

  Arg next_arg(const char *&error) {
    if (next_arg_index_ >= 0)
      return do_get_arg(internal::to_unsigned(next_arg_index_++), error);
    error = "cannot switch from manual to automatic argument indexing";
    return Arg();
  }

Project: fmt
File: format-test.cc

TEST(StrTest, Convert) {
  EXPECT_EQ("42", str(42));
  std::string s = str(Date(2012, 12, 9));
  EXPECT_EQ("2012-12-9", s);
}

Project: fmt
File: format.h

  MakeArg(const T &value)
  : Arg(MakeValue<Formatter>(value)) {
    type = static_cast<Arg::Type>(MakeValue<Formatter>::type(value));
  }

Project: fmt
File: format.h

void BasicWriter<Char>::write_str(
    const internal::Arg::StringValue<StrChar> &s, const Spec &spec) {
  // Check if StrChar is convertible to Char.
  internal::CharTraits<Char>::convert(StrChar());
  if (spec.type_ && spec.type_ != 's')
    internal::report_unknown_type(spec.type_, "string");
  const StrChar *str_value = s.value;
  std::size_t str_size = s.size;
  if (str_size == 0) {
    if (!str_value) {
      FMT_THROW(FormatError("string pointer is null"));
    }
  }
  std::size_t precision = static_cast<std::size_t>(spec.precision_);
  if (spec.precision_ >= 0 && precision < str_size)
    str_size = precision;
  write_str(str_value, str_size, spec);
}

Project: fmt
File: format.h

  Buffer(T *ptr = FMT_NULL, std::size_t capacity = 0)
    : ptr_(ptr), size_(0), capacity_(capacity) {}

Project: fmt
File: format.h

  explicit FormatInt(long value) { FormatSigned(value); }

Project: fmt
File: format.h

  std::size_t size() const { return buffer_.size(); }

Project: fmt
File: format.h

  explicit BasicMemoryWriter(const Allocator& alloc = Allocator())
    : BasicWriter<Char>(buffer_), buffer_(alloc) {}

Project: fmt
File: format.h

  static char convert(char value) { return value; }

Project: fmt
File: format-test.cc

TEST(FormatterTest, UnmatchedBraces) {
  EXPECT_THROW_MSG(format("{"), FormatError, "invalid format string");
  EXPECT_THROW_MSG(format("}"), FormatError, "unmatched '}' in format string");
  EXPECT_THROW_MSG(format("{0{}"), FormatError, "invalid format string");
}

Project: fmt
File: format-test.cc

TEST(WriterTest, PadWString) {
  EXPECT_EQ(L"test    ", (WMemoryWriter() << pad(L"test", 8)).str());
  EXPECT_EQ(L"test******", (WMemoryWriter() << pad(L"test", 10, '*')).str());
  EXPECT_EQ(L"test******", (WMemoryWriter() << pad(L"test", 10, L'*')).str());
}

Project: fmt
File: format.h

  Allocator get_allocator() const { return *this; }

Project: fmt
File: format.h

inline StringRef thousands_sep(
    LConv *lc, LConvCheck<char *LConv::*, &LConv::thousands_sep> = 0) {
  return lc->thousands_sep;
}

Project: fmt
File: format-test.cc

TEST(WriterTest, Ctor) {
  MemoryWriter w;
  EXPECT_EQ(0u, w.size());
  EXPECT_STREQ("", w.c_str());
  EXPECT_EQ("", w.str());
}

Project: fmt
File: format.h

  void write_decimal(Int value) {
    typedef typename internal::IntTraits<Int>::MainType MainType;
    MainType abs_value = static_cast<MainType>(value);
    if (internal::is_negative(value)) {
      abs_value = 0 - abs_value;
      *write_unsigned_decimal(abs_value, 1) = '-';
    } else {
      write_unsigned_decimal(abs_value, 0);
    }
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatConvertibleToLongLong) {
  EXPECT_EQ("100000000", format("{:x}", ConvertibleToLongLong()));
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatChar) {
  const char types[] = "cbBdoxXn";
  check_unknown_types('a', types, "char");
  EXPECT_EQ("a", format("{0}", 'a'));
  EXPECT_EQ("z", format("{0:c}", 'z'));
  EXPECT_EQ(L"a", format(L"{0}", 'a'));
  int n = 'x';
  for (const char *type = types + 1; *type; ++type) {
    std::string format_str = fmt::format("{{:{}}}", *type);
    EXPECT_EQ(fmt::format(format_str, n), fmt::format(format_str, 'x'));
  }
  EXPECT_EQ(fmt::format("{:02X}", n), fmt::format("{:02X}", 'x'));
}

Project: fmt
File: format-test.cc

void std_format(long double value, std::wstring &result) {
  wchar_t buffer[100];
  swprintf(buffer, L"%Lg", value);
  result = buffer;
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, ArgsInDifferentPositions) {
  EXPECT_EQ("42", format("{0}", 42));
  EXPECT_EQ("before 42", format("before {0}", 42));
  EXPECT_EQ("42 after", format("{0} after", 42));
  EXPECT_EQ("before 42 after", format("before {0} after", 42));
  EXPECT_EQ("answer = 42", format("{0} = {1}", "answer", 42));
  EXPECT_EQ("42 is the answer", format("{1} is the {0}", "answer", 42));
  EXPECT_EQ("abracadabra", format("{0}{1}{0}", "abra", "cad"));
}

Project: fmt
File: format.h

inline uint64_t make_type(const T &arg) {
  return MakeValue< BasicFormatter<char> >::type(arg);
}

Project: fmt
File: format-test.cc

TEST(FormatTest, ConvertCollision) {
  fmt::format("{}", 42);
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, MinusSign) {
  EXPECT_EQ("42", format("{0:-}", 42));
  EXPECT_EQ("-42", format("{0:-}", -42));
  EXPECT_EQ("42", format("{0:-}", 42));
  EXPECT_THROW_MSG(format("{0:-}", 42u),
      FormatError, "format specifier '-' requires signed argument");
  EXPECT_EQ("42", format("{0:-}", 42l));
  EXPECT_THROW_MSG(format("{0:-}", 42ul),
      FormatError, "format specifier '-' requires signed argument");
  EXPECT_EQ("42", format("{0:-}", 42ll));
  EXPECT_THROW_MSG(format("{0:-}", 42ull),
      FormatError, "format specifier '-' requires signed argument");
  EXPECT_EQ("42", format("{0:-}", 42.0));
  EXPECT_EQ("42", format("{0:-}", 42.0l));
  EXPECT_THROW_MSG(format("{0:-", 'c'),
      FormatError, "missing '}' in format string");
  EXPECT_THROW_MSG(format("{0:-}", 'c'),
      FormatError, "invalid format specifier for char");
  EXPECT_THROW_MSG(format("{0:-}", "abc"),
      FormatError, "format specifier '-' requires numeric argument");
  EXPECT_THROW_MSG(format("{0:-}", reinterpret_cast<void*>(0x42)),
      FormatError, "format specifier '-' requires numeric argument");
}

Project: fmt
File: format.h

  static uint64_t type(const NamedArgWithType<Char_, T> &) { return Arg::NAMED_ARG; }

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteDoubleAtBufferBoundary) {
  MemoryWriter writer;
  for (int i = 0; i < 100; ++i)
    writer << 1.23456789;
}

Project: fmt
File: format.h

  const Char *c_str() const { return data_; }

Project: fmt
File: format.h

ArgJoin<char, It> join(It first, It last, const BasicCStringRef<char>& sep) {
  return ArgJoin<char, It>(first, last, sep);
}

Project: fmt
File: format-test.cc

  static std::string format(fmt::CStringRef format_str, const Args & ... args) {
    return fmt::format(format_str, args...);
  }

Project: fmt
File: format.h

operator"" _a(const wchar_t *s, std::size_t) { return {s}; }

Project: fmt
File: format.h

  void set_string(StringRef str) {
    string.value = str.data();
    string.size = str.size();
  }

Project: fmt
File: format.h

  BasicWriter &operator<<(LongLong value) {
    write_decimal(value);
    return *this;
  }

Project: fmt
File: format.h

  const Char *data() const { return data_; }

Project: fmt
File: format.h

  ArgFormatter(BasicFormatter<Char> &formatter,
               FormatSpec &spec, const Char *fmt)
  : BasicArgFormatter<ArgFormatter<Char>,
                      Char, FormatSpec>(formatter, spec, fmt) {}

Project: fmt
File: format.h

  static uint64_t type(unsigned long) {
    return sizeof(unsigned long) == sizeof(unsigned) ?
          Arg::UINT : Arg::ULONG_LONG;
  }

Project: fmt
File: format.h

typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
      const StrChar *s, std::size_t size, const AlignSpec &spec) {
  CharPtr out = CharPtr();
  if (spec.width() > size) {
    out = grow_buffer(spec.width());
    Char fill = internal::CharTraits<Char>::cast(spec.fill());
    if (spec.align() == ALIGN_RIGHT) {
      std::uninitialized_fill_n(out, spec.width() - size, fill);
      out += spec.width() - size;
    } else if (spec.align() == ALIGN_CENTER) {
      out = fill_padding(out, spec.width(), size, fill);
    } else {
      std::uninitialized_fill_n(out + size, spec.width() - size, fill);
    }
  } else {
    out = grow_buffer(size);
  }
  std::uninitialized_copy(s, s + size, out);
  return out;
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, Examples) {
  EXPECT_EQ("First, thou shalt count to three",
      format("First, thou shalt count to {0}", "three"));
  EXPECT_EQ("Bring me a shrubbery",
      format("Bring me a {}", "shrubbery"));
  EXPECT_EQ("From 1 to 3", format("From {} to {}", 1, 3));

  char buffer[BUFFER_SIZE];
  safe_sprintf(buffer, "%03.2f", -1.2);
  EXPECT_EQ(buffer, format("{:03.2f}", -1.2));

  EXPECT_EQ("a, b, c", format("{0}, {1}, {2}", 'a', 'b', 'c'));
  EXPECT_EQ("a, b, c", format("{}, {}, {}", 'a', 'b', 'c'));
  EXPECT_EQ("c, b, a", format("{2}, {1}, {0}", 'a', 'b', 'c'));
  EXPECT_EQ("abracadabra", format("{0}{1}{0}", "abra", "cad"));

  EXPECT_EQ("left aligned                  ",
      format("{:<30}", "left aligned"));
  EXPECT_EQ("                 right aligned",
      format("{:>30}", "right aligned"));
  EXPECT_EQ("           centered           ",
      format("{:^30}", "centered"));
  EXPECT_EQ("***********centered***********",
      format("{:*^30}", "centered"));

  EXPECT_EQ("+3.140000; -3.140000",
      format("{:+f}; {:+f}", 3.14, -3.14));
  EXPECT_EQ(" 3.140000; -3.140000",
      format("{: f}; {: f}", 3.14, -3.14));
  EXPECT_EQ("3.140000; -3.140000",
      format("{:-f}; {:-f}", 3.14, -3.14));

  EXPECT_EQ("int: 42;  hex: 2a;  oct: 52",
      format("int: {0:d};  hex: {0:x};  oct: {0:o}", 42));
  EXPECT_EQ("int: 42;  hex: 0x2a;  oct: 052",
      format("int: {0:d};  hex: {0:#x};  oct: {0:#o}", 42));

  EXPECT_EQ("The answer is 42", format("The answer is {}", 42));
  EXPECT_THROW_MSG(
    format("The answer is {:d}", "forty-two"), FormatError,
    "unknown format code 'd' for string");

  EXPECT_EQ(L"Cyrillic letter \x42e",
    format(L"Cyrillic letter {}", L'\x42e'));

  EXPECT_WRITE(stdout,
      fmt::print("{}", std::numeric_limits<double>::infinity()), "inf");
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatDouble) {
  check_unknown_types(1.2, "eEfFgGaA", "double");
  EXPECT_EQ("0", format("{0:}", 0.0));
  EXPECT_EQ("0.000000", format("{0:f}", 0.0));
  EXPECT_EQ("392.65", format("{0:}", 392.65));
  EXPECT_EQ("392.65", format("{0:g}", 392.65));
  EXPECT_EQ("392.65", format("{0:G}", 392.65));
  EXPECT_EQ("392.650000", format("{0:f}", 392.65));
  EXPECT_EQ("392.650000", format("{0:F}", 392.65));
  char buffer[BUFFER_SIZE];
  safe_sprintf(buffer, "%e", 392.65);
  EXPECT_EQ(buffer, format("{0:e}", 392.65));
  safe_sprintf(buffer, "%E", 392.65);
  EXPECT_EQ(buffer, format("{0:E}", 392.65));
  EXPECT_EQ("+0000392.6", format("{0:+010.4g}", 392.65));
  safe_sprintf(buffer, "%a", -42.0);
  EXPECT_EQ(buffer, format("{:a}", -42.0));
  safe_sprintf(buffer, "%A", -42.0);
  EXPECT_EQ(buffer, format("{:A}", -42.0));
}

Project: fmt
File: format.h

  MakeValue(const T &value,
            typename EnableIf<Not<
              ConvertToInt<T>::value>::value, int>::type = 0) {
    custom.value = &value;
    custom.format = &format_custom_arg<T>;
  }

Project: fmt
File: format.h

  std::size_t size() const {
    return internal::to_unsigned(buffer_ - str_ + BUFFER_SIZE - 1);
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatInt) {
  EXPECT_THROW_MSG(format("{0:v", 42),
      FormatError, "missing '}' in format string");
  check_unknown_types(42, "bBdoxXn", "integer");
}

Project: fmt
File: format.h

  void reserve(std::size_t capacity) {
    if (capacity > capacity_)
      grow(capacity);
  }

Project: fmt
File: format-test.cc

TEST(BoolTest, FormatBool) {
  EXPECT_EQ("true", format("{}", true));
  EXPECT_EQ("false", format("{}", false));
  EXPECT_EQ("1", format("{:d}", true));
  EXPECT_EQ("true ", format("{:5}", true));
  EXPECT_EQ(L"true", format(L"{}", true));
}

Project: fmt
File: format.h

  Result visit_ulong_long(ULongLong value) {
    return FMT_DISPATCH(visit_any_int(value));
  }

Project: fmt
File: format-test.cc

void check_unknown_types(
    const T &value, const char *types, const char *type_name) {
  char format_str[BUFFER_SIZE], message[BUFFER_SIZE];
  const char *special = ".0123456789}";
  for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) {
    char c = static_cast<char>(i);
    if (std::strchr(types, c) || std::strchr(special, c) || !c) continue;
    safe_sprintf(format_str, "{0:10%c}", c);
    if (std::isprint(static_cast<unsigned char>(c))) {
      safe_sprintf(message, "unknown format code '%c' for %s", c, type_name);
    } else {
      safe_sprintf(message, "unknown format code '\\x%02x' for %s", c,
                   type_name);
    }
    EXPECT_THROW_MSG(format(format_str, value), FormatError, message)
      << format_str << " " << message;
  }
}

Project: fmt
File: format.h

  ArgList() : types_(0) {}

Project: fmt
File: format-test.cc

TEST(FormatterTest, LeftAlign) {
  EXPECT_EQ("42  ", format("{0:<4}", 42));
  EXPECT_EQ("42  ", format("{0:<4o}", 042));
  EXPECT_EQ("42  ", format("{0:<4x}", 0x42));
  EXPECT_EQ("-42  ", format("{0:<5}", -42));
  EXPECT_EQ("42   ", format("{0:<5}", 42u));
  EXPECT_EQ("-42  ", format("{0:<5}", -42l));
  EXPECT_EQ("42   ", format("{0:<5}", 42ul));
  EXPECT_EQ("-42  ", format("{0:<5}", -42ll));
  EXPECT_EQ("42   ", format("{0:<5}", 42ull));
  EXPECT_EQ("-42  ", format("{0:<5}", -42.0));
  EXPECT_EQ("-42  ", format("{0:<5}", -42.0l));
  EXPECT_EQ("c    ", format("{0:<5}", 'c'));
  EXPECT_EQ("abc  ", format("{0:<5}", "abc"));
  EXPECT_EQ("0xface  ", format("{0:<8}", reinterpret_cast<void*>(0xface)));
}

Project: fmt
File: format-test.cc

  ::testing::AssertionResult operator()(const char *, const T &value) const {
    return check_write<Char>(value, "char");
  }

Project: fmt
File: format.h

  const char *c_str() const { return &buffer_[0]; }

Project: fmt
File: format.h

  RuntimeError() : std::runtime_error("") {}

Project: fmt
File: format.h

  char type_prefix() const { return TYPE; }

Project: fmt
File: format-test.cc

  std::string format_message(int id, const char *format,const fmt::ArgList &args) const {
    MemoryWriter w;
    w.write("[{}] ", id);
    w.write(format, args);
    return w.str();
  }

Project: fmt
File: format.h

  void write_pointer(const void *p) {
    spec_.flags_ = HASH_FLAG;
    spec_.type_ = 'x';
    writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
  }

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteWideString) {
  CHECK_WRITE_WCHAR(L"abc");
  // The following line shouldn't compile:
  //fmt::WMemoryWriter() << "abc";
}

Project: fmt
File: format.h

  Result visit_bool(bool value) {
    return FMT_DISPATCH(visit_any_int(value));
  }

Project: fmt
File: format.h

  void append_float_length(Char *&format_ptr, long double) {
    *format_ptr++ = 'L';
  }

Project: fmt
File: format-test.cc

void check_move_writer(const std::string &str, MemoryWriter &w) {
  MemoryWriter w2(std::move(w));
  // Move shouldn't destroy the inline content of the first writer.
  EXPECT_EQ(str, w.str());
  EXPECT_EQ(str, w2.str());
}

Project: fmt
File: format.h

  explicit FormatInt(ULongLong value) : str_(format_decimal(value)) {}

Project: fmt
File: format-test.cc

TEST(FormatterTest, PlusSign) {
  EXPECT_EQ("+42", format("{0:+}", 42));
  EXPECT_EQ("-42", format("{0:+}", -42));
  EXPECT_EQ("+42", format("{0:+}", 42));
  EXPECT_THROW_MSG(format("{0:+}", 42u),
      FormatError, "format specifier '+' requires signed argument");
  EXPECT_EQ("+42", format("{0:+}", 42l));
  EXPECT_THROW_MSG(format("{0:+}", 42ul),
      FormatError, "format specifier '+' requires signed argument");
  EXPECT_EQ("+42", format("{0:+}", 42ll));
  EXPECT_THROW_MSG(format("{0:+}", 42ull),
      FormatError, "format specifier '+' requires signed argument");
  EXPECT_EQ("+42", format("{0:+}", 42.0));
  EXPECT_EQ("+42", format("{0:+}", 42.0l));
  EXPECT_THROW_MSG(format("{0:+", 'c'),
      FormatError, "missing '}' in format string");
  EXPECT_THROW_MSG(format("{0:+}", 'c'),
      FormatError, "invalid format specifier for char");
  EXPECT_THROW_MSG(format("{0:+}", "abc"),
      FormatError, "format specifier '+' requires numeric argument");
  EXPECT_THROW_MSG(format("{0:+}", reinterpret_cast<void*>(0x42)),
      FormatError, "format specifier '+' requires numeric argument");
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatExperimentalStringView) {
	EXPECT_EQ("test", format("{0}", std::experimental::string_view("test")));
}

Project: fmt
File: format-test.cc

void format_arg(fmt::BasicFormatter<char> &f, const char *, const Date &d) {
  f.writer() << d.year() << '-' << d.month() << '-' << d.day();
}

Project: fmt
File: format.h

inline unsigned count_digits(uint32_t n) {
  int t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12;
  return to_unsigned(t) - (n < Data::POWERS_OF_10_32[t]) + 1;
}

Project: fmt
File: format.h

  bool flag(unsigned f) const { return (flags_ & f) != 0; }

Project: fmt
File: format.h

  const ArgList &args() const { return args_; }

Project: fmt
File: format.h

  WidthSpec(unsigned width, wchar_t fill) : width_(width), fill_(fill) {}

Project: fmt
File: format.h

void BasicFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) {
  const Char *s = format_str.c_str();
  const Char *start = s;
  while (*s) {
    Char c = *s++;
    if (c != '{' && c != '}') continue;
    if (*s == c) {
      write(writer_, start, s);
      start = ++s;
      continue;
    }
    if (c == '}')
      FMT_THROW(FormatError("unmatched '}' in format string"));
    write(writer_, start, s - 1);
    internal::Arg arg = internal::is_name_start(*s) ?
          parse_arg_name(s) : parse_arg_index(s);
    start = s = format(s, arg);
  }
  write(writer_, start, s);
}

Project: fmt
File: format.h

  explicit FormatError(CStringRef message)
  : std::runtime_error(message.c_str()) {}

Project: fmt
File: format.h

  AlignSpec(unsigned width, wchar_t fill, Alignment align = ALIGN_DEFAULT)
  : WidthSpec(width, fill), align_(align) {}

Project: fmt
File: format.h

inline void format_decimal(char *&buffer, T value) {
  typedef typename internal::IntTraits<T>::MainType MainType;
  MainType abs_value = static_cast<MainType>(value);
  if (internal::is_negative(value)) {
    *buffer++ = '-';
    abs_value = 0 - abs_value;
  }
  if (abs_value < 100) {
    if (abs_value < 10) {
      *buffer++ = static_cast<char>('0' + abs_value);
      return;
    }
    unsigned index = static_cast<unsigned>(abs_value * 2);
    *buffer++ = internal::Data::DIGITS[index];
    *buffer++ = internal::Data::DIGITS[index + 1];
    return;
  }
  unsigned num_digits = internal::count_digits(abs_value);
  internal::format_decimal(buffer, abs_value, num_digits);
  buffer += num_digits;
}

Project: fmt
File: format-test.cc

std::string str(const T &value) {
  return fmt::format("{}", value);
}

Project: fmt
File: format.h

  static bool isnotanumber(T x) {
    using namespace fmt::internal;
    if (const_check(sizeof(isnan(x)) != sizeof(fmt::internal::DummyInt))) {
      return isnan(x) != 0;
    }
    return _isnan(static_cast<double>(x)) != 0;
  }

Project: fmt
File: format-test.cc

  MockArgFormatter(fmt::BasicFormatter<char, MockArgFormatter> &f,
                   fmt::FormatSpec &s, const char *)
    : fmt::internal::ArgFormatterBase<MockArgFormatter, char>(f.writer(), s) {
    EXPECT_CALL(*this, visit_int(42));
  }

Project: fmt
File: format-test.cc

TEST(FormatTest, JoinArg) {
  using fmt::join;
  int v1[3] = { 1, 2, 3 };
  std::vector<float> v2;
  v2.push_back(1.2f);
  v2.push_back(3.4f);

  EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, v1 + 3, ", ")));
  EXPECT_EQ("(1)", format("({})", join(v1, v1 + 1, ", ")));
  EXPECT_EQ("()", format("({})", join(v1, v1, ", ")));
  EXPECT_EQ("(001, 002, 003)", format("({:03})", join(v1, v1 + 3, ", ")));
  EXPECT_EQ("(+01.20, +03.40)",
            format("({:+06.2f})", join(v2.begin(), v2.end(), ", ")));

  EXPECT_EQ(L"(1, 2, 3)", format(L"({})", join(v1, v1 + 3, L", ")));
  EXPECT_EQ("1, 2, 3", format("{0:{1}}", join(v1, v1 + 3, ", "), 1)); 

#if FMT_HAS_GXX_CXX11
  EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, ", ")));
  EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", join(v2, ", ")));
#endif
}

Project: fmt
File: format.h

  void visit_bool(bool value) {
    if (spec_.type_) {
      visit_any_int(value);
      return;
    }
    write(value);
  }

Project: fmt
File: format.h

  BasicMemoryWriter &operator=(BasicMemoryWriter &&other) {
    buffer_ = std::move(other.buffer_);
    return *this;
  }

Project: fmt
File: format.h

  friend bool operator!=(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) != 0;
  }

Project: fmt
File: format.h

inline uint32_t clzll(uint64_t x) {
  unsigned long r = 0;
# ifdef _WIN64
  _BitScanReverse64(&r, x);
# else
  // Scan the high 32 bits.
  if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
    return 63 - (r + 32);

  // Scan the low 32 bits.
  _BitScanReverse(&r, static_cast<uint32_t>(x));
# endif

  assert(x != 0);
  // Static analysis complains about using uninitialized data
  // "r", but the only way that can happen is if "x" is 0,
  // which the callers guarantee to not happen.
# pragma warning(suppress: 6102)
  return 63 - r;
}

Project: fmt
File: format.h

  BasicWriter &operator<<(unsigned long value) {
    return *this << IntFormatSpec<unsigned long>(value);
  }

Project: fmt
File: format.h

  char type_prefix() const { return type_; }

Project: fmt
File: format-test.cc

TEST(ArrayWriterTest, Ctor) {
  char array[10] = "garbage";
  fmt::ArrayWriter w(array, sizeof(array));
  EXPECT_EQ(0u, w.size());
  EXPECT_STREQ("", w.c_str());
}

Project: fmt
File: format.h

  internal::Arg operator[](unsigned index) const {
    using internal::Arg;
    Arg arg;
    bool use_values = type(MAX_PACKED_ARGS - 1) == Arg::NONE;
    if (index < MAX_PACKED_ARGS) {
      Arg::Type arg_type = type(index);
      internal::Value &val = arg;
      if (arg_type != Arg::NONE)
        val = use_values ? values_[index] : args_[index];
      arg.type = arg_type;
      return arg;
    }
    if (use_values) {
      // The index is greater than the number of arguments that can be stored
      // in values, so return a "none" argument.
      arg.type = Arg::NONE;
      return arg;
    }
    for (unsigned i = MAX_PACKED_ARGS; i <= index; ++i) {
      if (args_[i].type == Arg::NONE)
        return args_[i];
    }
    return args_[index];
  }

Project: fmt
File: format.h

  BasicFormatter(const ArgList &args, BasicWriter<Char> &w)
    : internal::FormatterBase(args), writer_(w) {}

Project: fmt
File: format.h

inline DummyInt isinf(...) { return DummyInt(); }

Project: fmt
File: format.h

inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
  return stdext::checked_array_iterator<T*>(ptr, size);
}

Project: fmt
File: format.h

inline DummyInt isnan(...) { return DummyInt(); }

Project: fmt
File: format.h

  static uint64_t type(long) {
    return sizeof(long) == sizeof(int) ? Arg::INT : Arg::LONG_LONG;
  }

Project: fmt
File: format.h

  RuntimeError(const RuntimeError &rerr) : std::runtime_error(rerr) {}

Project: fmt
File: format-test.cc

ISO8601DateFormatter iso8601(const Date &d) { return ISO8601DateFormatter(d); }

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteChar) {
  CHECK_WRITE('a');
}

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteString) {
  CHECK_WRITE_CHAR("abc");
  CHECK_WRITE_WCHAR("abc");
  // The following line shouldn't compile:
  //MemoryWriter() << L"abc";
}

Project: fmt
File: format.h

  operator int() const { return 0; }

Project: fmt
File: format.h

  BasicWriter &operator<<(unsigned value) {
    return *this << IntFormatSpec<unsigned>(value);
  }

Project: fmt
File: format-test.cc

void custom_format(const char *format_str, fmt::ArgList args) {
  fmt::MemoryWriter writer;
  fmt::BasicFormatter<char, MockArgFormatter> formatter(args, writer);
  formatter.format(format_str);
}

Project: fmt
File: format.h

  static uint64_t type(T) { return Arg::INT; }

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteDouble) {
  CHECK_WRITE(4.2);
  CHECK_WRITE(-4.2);
  CHECK_WRITE(std::numeric_limits<double>::min());
  CHECK_WRITE(std::numeric_limits<double>::max());
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatCStringRef) {
  EXPECT_EQ("test", format("{0}", CStringRef("test")));
}

Project: fmt
File: format.h

  IntFormatSpec(T val, const SpecT &spec = SpecT())
  : SpecT(spec), value_(val) {}

Project: fmt
File: format.h

  BasicWriter &operator<<(
      typename internal::WCharHelper<wchar_t, Char>::Supported value) {
    buffer_.push_back(value);
    return *this;
  }

Project: fmt
File: format.h

  void clear() FMT_NOEXCEPT { buffer_.clear(); }

Project: fmt
File: format.h

  BasicWriter &operator<<(long double value) {
    write_double(value, FormatSpec());
    return *this;
  }

Project: fmt
File: format.h

  Result visit_int(int value) {
    return FMT_DISPATCH(visit_any_int(value));
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, Precision) {
  char format_str[BUFFER_SIZE];
  safe_sprintf(format_str, "{0:.%u", UINT_MAX);
  increment(format_str + 4);
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
  std::size_t size = std::strlen(format_str);
  format_str[size] = '}';
  format_str[size + 1] = 0;
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");

  safe_sprintf(format_str, "{0:.%u", INT_MAX + 1u);
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
  safe_sprintf(format_str, "{0:.%u}", INT_MAX + 1u);
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");

  EXPECT_THROW_MSG(format("{0:.", 0),
      FormatError, "missing precision specifier");
  EXPECT_THROW_MSG(format("{0:.}", 0),
      FormatError, "missing precision specifier");

  EXPECT_THROW_MSG(format("{0:.2", 0),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2}", 42),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2f}", 42),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2}", 42u),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2f}", 42u),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2}", 42l),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2f}", 42l),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2}", 42ul),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2f}", 42ul),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2}", 42ll),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2f}", 42ll),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2}", 42ull),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:.2f}", 42ull),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_THROW_MSG(format("{0:3.0}", 'x'),
      FormatError, "precision not allowed in integer format specifier");
  EXPECT_EQ("1.2", format("{0:.2}", 1.2345));
  EXPECT_EQ("1.2", format("{0:.2}", 1.2345l));

  EXPECT_THROW_MSG(format("{0:.2}", reinterpret_cast<void*>(0xcafe)),
      FormatError, "precision not allowed in pointer format specifier");
  EXPECT_THROW_MSG(format("{0:.2f}", reinterpret_cast<void*>(0xcafe)),
      FormatError, "precision not allowed in pointer format specifier");

  EXPECT_EQ("st", format("{0:.2}", "str"));
}

Project: fmt
File: format.h

  int compare(BasicStringRef other) const {
    std::size_t size = size_ < other.size_ ? size_ : other.size_;
    int result = std::char_traits<Char>::compare(data_, other.data_, size);
    if (result == 0)
      result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
    return result;
  }

Project: fmt
File: format.h

  void visit_any_double(T value) { writer_.write_double(value, spec_); }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatStringFromSpeedTest) {
  EXPECT_EQ("1.2340000000:0042:+3.13:str:0x3e8:X:%",
      format("{0:0.10f}:{1:04}:{2:+g}:{3}:{4}:{5}:%",
          1.234, 42, 3.13, "str", reinterpret_cast<void*>(1000), 'X'));
}

Project: fmt
File: format-test.cc

TEST(FormatTest, ConstFormatMessage) {
  test_class c;
  EXPECT_EQ("[42] something happened",
    c.format_message(42, "{} happened", "something"));
}

Project: fmt
File: format.h

  std::string str() const { return std::string(str_, size()); }

Project: fmt
File: format-test.cc

TEST(WriterTest, oct) {
  using fmt::oct;
  EXPECT_EQ("12", (MemoryWriter() << oct(static_cast<short>(012))).str());
  EXPECT_EQ("12", (MemoryWriter() << oct(012)).str());
  EXPECT_EQ("34", (MemoryWriter() << oct(034u)).str());
  EXPECT_EQ("56", (MemoryWriter() << oct(056l)).str());
  EXPECT_EQ("70", (MemoryWriter() << oct(070ul)).str());
  EXPECT_EQ("1234", (MemoryWriter() << oct(01234ll)).str());
  EXPECT_EQ("5670", (MemoryWriter() << oct(05670ull)).str());
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatStringRef) {
  EXPECT_EQ("test", format("{0}", StringRef("test")));
}

Project: fmt
File: format.h

  BasicStringRef(const Char *s)
    : data_(s), size_(std::char_traits<Char>::length(s)) {}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatDec) {
  EXPECT_EQ("0", format("{0}", 0));
  EXPECT_EQ("42", format("{0}", 42));
  EXPECT_EQ("42", format("{0:d}", 42));
  EXPECT_EQ("42", format("{0}", 42u));
  EXPECT_EQ("-42", format("{0}", -42));
  EXPECT_EQ("12345", format("{0}", 12345));
  EXPECT_EQ("67890", format("{0}", 67890));
  char buffer[BUFFER_SIZE];
  safe_sprintf(buffer, "%d", INT_MIN);
  EXPECT_EQ(buffer, format("{0}", INT_MIN));
  safe_sprintf(buffer, "%d", INT_MAX);
  EXPECT_EQ(buffer, format("{0}", INT_MAX));
  safe_sprintf(buffer, "%u", UINT_MAX);
  EXPECT_EQ(buffer, format("{0}", UINT_MAX));
  safe_sprintf(buffer, "%ld", 0 - static_cast<unsigned long>(LONG_MIN));
  EXPECT_EQ(buffer, format("{0}", LONG_MIN));
  safe_sprintf(buffer, "%ld", LONG_MAX);
  EXPECT_EQ(buffer, format("{0}", LONG_MAX));
  safe_sprintf(buffer, "%lu", ULONG_MAX);
  EXPECT_EQ(buffer, format("{0}", ULONG_MAX));
}

Project: fmt
File: format.h

  MakeValue(unsigned long value) {
    if (const_check(sizeof(unsigned long) == sizeof(unsigned)))
      uint_value = static_cast<unsigned>(value);
    else
      ulong_long_value = value;
  }

Project: fmt
File: format.h

  wchar_t fill() const { return fill_; }

Project: fmt
File: format-test.cc

std::string format_decimal(T value) {
  char buffer[10];
  char *ptr = buffer;
  fmt::format_decimal(ptr, value);
  return std::string(buffer, ptr);
}

Project: fmt
File: format.h

  static bool is_negative(T value) { return value < 0; }

Project: fmt
File: format.h

  Result visit_custom(Arg::CustomValue) {
    return FMT_DISPATCH(visit_unhandled_arg());
  }

Project: fmt
File: format.h

inline DummyInt _ecvt_s(...) { return DummyInt(); }

Project: fmt
File: format.h

  Result visit_long_double(long double value) {
    return FMT_DISPATCH(visit_any_double(value));
  }

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteInt) {
  CHECK_WRITE(42);
  CHECK_WRITE(-42);
  CHECK_WRITE(static_cast<short>(12));
  CHECK_WRITE(34u);
  CHECK_WRITE(std::numeric_limits<int>::min());
  CHECK_WRITE(std::numeric_limits<int>::max());
  CHECK_WRITE(std::numeric_limits<unsigned>::max());
}

Project: fmt
File: format.h

  explicit FormatInt(int value) { FormatSigned(value); }

Project: fmt
File: format.h

  AlignTypeSpec(unsigned width, wchar_t fill) : AlignSpec(width, fill) {}

Project: fmt
File: format.h

  const Char *str() const { return str_; }

Project: fmt
File: format.h

  SystemError(int error_code, CStringRef message) {
    init(error_code, message, ArgList());
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatCustom) {
  Date date(2012, 12, 9);
  EXPECT_THROW_MSG(fmt::format("{:s}", date), FormatError,
                   "unmatched '}' in format string");
}

Project: fmt
File: format.h

  int precision() const { return precision_; }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatCString) {
  check_unknown_types("test", "sp", "string");
  EXPECT_EQ("test", format("{0}", "test"));
  EXPECT_EQ("test", format("{0:s}", "test"));
  char nonconst[] = "nonconst";
  EXPECT_EQ("nonconst", format("{0}", nonconst));
  EXPECT_THROW_MSG(format("{0}", reinterpret_cast<const char*>(0)),
      FormatError, "string pointer is null");
}

Project: fmt
File: format.h

  explicit BasicArrayWriter(Char (&array)[SIZE])
    : BasicWriter<Char>(buffer_), buffer_(array, SIZE) {}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatPointer) {
  check_unknown_types(reinterpret_cast<void*>(0x1234), "p", "pointer");
  EXPECT_EQ("0x0", format("{0}", reinterpret_cast<void*>(0)));
  EXPECT_EQ("0x1234", format("{0}", reinterpret_cast<void*>(0x1234)));
  EXPECT_EQ("0x1234", format("{0:p}", reinterpret_cast<void*>(0x1234)));
  EXPECT_EQ("0x" + std::string(sizeof(void*) * CHAR_BIT / 4, 'f'),
      format("{0}", reinterpret_cast<void*>(~uintptr_t())));
}

Project: fmt
File: format.h

  Result visit_wstring(Arg::StringValue<wchar_t>) {
    return FMT_DISPATCH(visit_unhandled_arg());
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, ArgErrors) {
  EXPECT_THROW_MSG(format("{"), FormatError, "invalid format string");
  EXPECT_THROW_MSG(format("{?}"), FormatError, "invalid format string");
  EXPECT_THROW_MSG(format("{0"), FormatError, "invalid format string");
  EXPECT_THROW_MSG(format("{0}"), FormatError, "argument index out of range");

  char format_str[BUFFER_SIZE];
  safe_sprintf(format_str, "{%u", INT_MAX);
  EXPECT_THROW_MSG(format(format_str), FormatError, "invalid format string");
  safe_sprintf(format_str, "{%u}", INT_MAX);
  EXPECT_THROW_MSG(format(format_str), FormatError,
      "argument index out of range");

  safe_sprintf(format_str, "{%u", INT_MAX + 1u);
  EXPECT_THROW_MSG(format(format_str), FormatError, "number is too big");
  safe_sprintf(format_str, "{%u}", INT_MAX + 1u);
  EXPECT_THROW_MSG(format(format_str), FormatError, "number is too big");
}

Project: fmt
File: format.h

  ArgType() : type(0) {}

Project: fmt
File: format.h

  CharPtr prepare_int_buffer(unsigned num_digits,
      const EmptySpec &, const char *prefix, unsigned prefix_size) {
    unsigned size = prefix_size + num_digits;
    CharPtr p = grow_buffer(size);
    std::uninitialized_copy(prefix, prefix + prefix_size, p);
    return p + size - 1;
  }

Project: fmt
File: format-test.cc

TEST(WriterTest, MoveAssignment) {
  MemoryWriter w;
  w << "test";
  CheckMoveAssignWriter("test", w);
  // This fills the inline buffer, but doesn't cause dynamic allocation.
  std::string s;
  for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE; ++i)
    s += '*';
  w.clear();
  w << s;
  CheckMoveAssignWriter(s, w);
  const char *inline_buffer_ptr = w.data();
  // Adding one more character causes the content to move from the inline to
  // a dynamically allocated buffer.
  w << '*';
  MemoryWriter w2;
  w2 = std::move(w);
  // Move should rip the guts of the first writer.
  EXPECT_EQ(inline_buffer_ptr, w.data());
  EXPECT_EQ(s + '*', w2.str());
}

Project: fmt
File: format.h

  BasicWriter<Char>::fill_padding(
    CharPtr buffer, unsigned total_size,
    std::size_t content_size, wchar_t fill) {
  std::size_t padding = total_size - content_size;
  std::size_t left_padding = padding / 2;
  Char fill_char = internal::CharTraits<Char>::cast(fill);
  std::uninitialized_fill_n(buffer, left_padding, fill_char);
  buffer += left_padding;
  CharPtr content = buffer;
  std::uninitialized_fill_n(buffer + content_size,
                            padding - left_padding, fill_char);
  return content;
}

Project: fmt
File: format.h

  Result visit_double(double value) {
    return FMT_DISPATCH(visit_any_double(value));
  }

Project: fmt
File: format.h

  BasicStringRef(
      const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
  : data_(s.c_str()), size_(s.size()) {}

Project: fmt
File: format.h

  MakeArg() {
    type = Arg::NONE;
  }

Project: fmt
File: format.h

  ArgList(ULongLong types, const internal::Arg *args)
  : types_(types), args_(args) {}

Project: fmt
File: format.h

  explicit FormatInt(LongLong value) { FormatSigned(value); }

Project: fmt
File: format-test.cc

TEST(FormatIntTest, Data) {
  fmt::FormatInt format_int(42);
  EXPECT_EQ("42", std::string(format_int.data(), format_int.size()));
}

Project: fmt
File: format.h

  static void format_custom_arg(
      void *formatter, const void *arg, void *format_str_ptr) {
    format_arg(*static_cast<Formatter*>(formatter),
               *static_cast<const Char**>(format_str_ptr),
               *static_cast<const T*>(arg));
  }

Project: fmt
File: format.h

  static Value make(const T &value) {
#ifdef __clang__
    Value result = MakeValue<Formatter>(value);
    // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang:
    // https://github.com/fmtlib/fmt/issues/276
    (void)result.custom.format;
    return result;
#else
    return MakeValue<Formatter>(value);
#endif
  }

Project: fmt
File: format.h

  ArgType(const T &arg) : type(make_type(arg)) {}

Project: fmt
File: format.h

  std::basic_string<Char> to_string() const {
    return std::basic_string<Char>(data_, size_);
  }

Project: fmt
File: format.h

inline void format_decimal(Char *buffer, UInt value, unsigned num_digits,
                           ThousandsSep thousands_sep) {
  buffer += num_digits;
  while (value >= 100) {
    // Integer division is slow so do it for a group of two digits instead
    // of for every digit. The idea comes from the talk by Alexandrescu
    // "Three Optimization Tips for C++". See speed-test for a comparison.
    unsigned index = static_cast<unsigned>((value % 100) * 2);
    value /= 100;
    *--buffer = Data::DIGITS[index + 1];
    thousands_sep(buffer);
    *--buffer = Data::DIGITS[index];
    thousands_sep(buffer);
  }
  if (value < 10) {
    *--buffer = static_cast<char>('0' + value);
    return;
  }
  unsigned index = static_cast<unsigned>(value * 2);
  *--buffer = Data::DIGITS[index + 1];
  thousands_sep(buffer);
  *--buffer = Data::DIGITS[index];
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, WideFormatString) {
  EXPECT_EQ(L"42", format(L"{}", 42));
  EXPECT_EQ(L"4.2", format(L"{}", 4.2));
  EXPECT_EQ(L"abc", format(L"{}", L"abc"));
  EXPECT_EQ(L"z", format(L"{}", L'z'));
}

Project: fmt
File: format.h

  Result visit_any_double(T) {
    return FMT_DISPATCH(visit_unhandled_arg());
  }

Project: fmt
File: format.h

  Buffer<Char> &buffer() FMT_NOEXCEPT { return buffer_; }

Project: fmt
File: format.h

inline uint64_t make_type() { return 0; }

Project: fmt
File: format.h

inline bool is_name_start(Char c) {
  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
}

Project: fmt
File: format.h

  char *format_decimal(ULongLong value) {
    char *buffer_end = buffer_ + BUFFER_SIZE - 1;
    while (value >= 100) {
      // Integer division is slow so do it for a group of two digits instead
      // of for every digit. The idea comes from the talk by Alexandrescu
      // "Three Optimization Tips for C++". See speed-test for a comparison.
      unsigned index = static_cast<unsigned>((value % 100) * 2);
      value /= 100;
      *--buffer_end = internal::Data::DIGITS[index + 1];
      *--buffer_end = internal::Data::DIGITS[index];
    }
    if (value < 10) {
      *--buffer_end = static_cast<char>('0' + value);
      return buffer_end;
    }
    unsigned index = static_cast<unsigned>(value * 2);
    *--buffer_end = internal::Data::DIGITS[index + 1];
    *--buffer_end = internal::Data::DIGITS[index];
    return buffer_end;
  }

Project: fmt
File: format-test.cc

void std_format(const T &value, std::basic_string<Char> &result) {
  std::basic_ostringstream<Char> os;
  os << value;
  result = os.str();
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatStringView) {
  EXPECT_EQ("test", format("{0}", std::string_view("test")));
}

Project: fmt
File: format.h

  Result visit_string(Arg::StringValue<char>) {
    return FMT_DISPATCH(visit_unhandled_arg());
  }

Project: fmt
File: format.h

  const char *c_str() const {
    buffer_[BUFFER_SIZE - 1] = '\0';
    return str_;
  }

Project: fmt
File: format.h

void Buffer<T>::append(const U *begin, const U *end) {
  FMT_ASSERT(end >= begin, "negative value");
  std::size_t new_size = size_ + static_cast<std::size_t>(end - begin);
  if (new_size > capacity_)
    grow(new_size);
  std::uninitialized_copy(begin, end,
                          internal::make_ptr(ptr_, capacity_) + size_);
  size_ = new_size;
}

Project: fmt
File: format.h

  Alignment align() const { return ALIGN_DEFAULT; }

Project: fmt
File: format.h

  static uint64_t type(wchar_t) { return Arg::CHAR; }

Project: fmt
File: format-test.cc

TEST(FormatterTest, Fill) {
  EXPECT_THROW_MSG(format("{0:{<5}", 'c'),
      FormatError, "invalid fill character '{'");
  EXPECT_THROW_MSG(format("{0:{<5}}", 'c'),
      FormatError, "invalid fill character '{'");
  EXPECT_EQ("**42", format("{0:*>4}", 42));
  EXPECT_EQ("**-42", format("{0:*>5}", -42));
  EXPECT_EQ("***42", format("{0:*>5}", 42u));
  EXPECT_EQ("**-42", format("{0:*>5}", -42l));
  EXPECT_EQ("***42", format("{0:*>5}", 42ul));
  EXPECT_EQ("**-42", format("{0:*>5}", -42ll));
  EXPECT_EQ("***42", format("{0:*>5}", 42ull));
  EXPECT_EQ("**-42", format("{0:*>5}", -42.0));
  EXPECT_EQ("**-42", format("{0:*>5}", -42.0l));
  EXPECT_EQ("c****", format("{0:*<5}", 'c'));
  EXPECT_EQ("abc**", format("{0:*<5}", "abc"));
  EXPECT_EQ("**0xface", format("{0:*>8}", reinterpret_cast<void*>(0xface)));
}

Project: fmt
File: format-test.cc

void format_arg(fmt::BasicFormatter<Char> &f, const Char *, Answer) {
  f.writer() << "42";
}

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteLongLong) {
  CHECK_WRITE(56ll);
  CHECK_WRITE(78ull);
  CHECK_WRITE(std::numeric_limits<long long>::min());
  CHECK_WRITE(std::numeric_limits<long long>::max());
  CHECK_WRITE(std::numeric_limits<unsigned long long>::max());
}

Project: fmt
File: format.h

  explicit operator std::experimental::basic_string_view<Char>() const FMT_NOEXCEPT {
	  return std::experimental::basic_string_view<Char>(data_, size_);
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatLongDouble) {
  EXPECT_EQ("0", format("{0:}", 0.0l));
  EXPECT_EQ("0.000000", format("{0:f}", 0.0l));
  EXPECT_EQ("392.65", format("{0:}", 392.65l));
  EXPECT_EQ("392.65", format("{0:g}", 392.65l));
  EXPECT_EQ("392.65", format("{0:G}", 392.65l));
  EXPECT_EQ("392.650000", format("{0:f}", 392.65l));
  EXPECT_EQ("392.650000", format("{0:F}", 392.65l));
  char buffer[BUFFER_SIZE];
  safe_sprintf(buffer, "%Le", 392.65l);
  EXPECT_EQ(buffer, format("{0:e}", 392.65l));
  EXPECT_EQ("+0000392.6", format("{0:+010.4g}", 392.64l));
}

Project: fmt
File: format.h

inline internal::Arg BasicFormatter<Char, AF>::get_arg(
    BasicStringRef<Char> arg_name, const char *&error) {
  if (check_no_auto_index(error)) {
    map_.init(args());
    const internal::Arg *arg = map_.find(arg_name);
    if (arg)
      return *arg;
    error = "argument not found";
  }
  return internal::Arg();
}

Project: fmt
File: format.h

inline internal::Arg BasicFormatter<Char, AF>::parse_arg_index(const Char *&s) {
  const char *error = FMT_NULL;
  internal::Arg arg = *s < '0' || *s > '9' ?
        next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error);
  if (error) {
    FMT_THROW(FormatError(
                *s != '}' && *s != ':' ? "invalid format string" : error));
  }
  return arg;
}

Project: fmt
File: format.h

  BasicWriter &operator<<(fmt::BasicStringRef<Char> value) {
    const Char *str = value.data();
    buffer_.append(str, str + value.size());
    return *this;
  }

Project: fmt
File: format.h

  BasicWriter &operator<<(int value) {
    write_decimal(value);
    return *this;
  }

Project: fmt
File: format.h

  Result visit_uint(unsigned value) {
    return FMT_DISPATCH(visit_any_int(value));
  }

Project: fmt
File: format.h

  static Char cast(int value) { return static_cast<Char>(value); }

Project: fmt
File: format-test.cc

TEST(ArrayWriterTest, WChar) {
  wchar_t array[10];
  fmt::WArrayWriter w(array);
  w.write(L"{}", 42);
  EXPECT_EQ(L"42", w.str());
}

Project: fmt
File: format.h

  operator StringRef() const { return StringRef(&buffer_[0], size()); }

Project: fmt
File: format.h

  std::basic_string<Char> str() const {
    return std::basic_string<Char>(&buffer_[0], buffer_.size());
  }

Project: fmt
File: format.h

  size_t size() const { return buffer_.size() - 1; }

Project: fmt
File: format.h

  char type() const { return type_; }

Project: fmt
File: format.h

  std::size_t capacity() const { return capacity_; }

Project: fmt
File: format-test.cc

TEST(FormatTest, FixedEnum) {
  EXPECT_EQ("0", fmt::format("{}", B));
}

Project: fmt
File: format-test.cc

TEST(CStringRefTest, Ctor) {
  EXPECT_STREQ("abc", CStringRef("abc").c_str());
  EXPECT_STREQ("defg", CStringRef(std::string("defg")).c_str());

#if FMT_HAS_STRING_VIEW
  EXPECT_STREQ("hijk", CStringRef(std::string_view("hijk")).c_str());
#endif

#if FMT_HAS_EXPERIMENTAL_STRING_VIEW
  EXPECT_STREQ("hijk", CStringRef(std::experimental::string_view("hijk")).c_str());
#endif
}

Project: fmt
File: format.h

  friend bool operator<(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) < 0;
  }

Project: fmt
File: format.h

  NamedArg(BasicStringRef<Char> argname, const T &value)
  : Arg(MakeArg< BasicFormatter<Char> >(value)), name(argname) {}

Project: fmt
File: format.h

  explicit FormatterBase(const ArgList &args) {
    args_ = args;
    next_arg_index_ = 0;
  }

Project: fmt
File: format.h

  void clear() FMT_NOEXCEPT { size_ = 0; }

Project: fmt
File: format.h

  static wchar_t convert(wchar_t value) { return value; }

Project: fmt
File: format.h

  void visit_wstring(internal::Arg::StringValue<Char> value) {
    writer_.write_str(value, spec_);
  }

Project: fmt
File: format.h

  BasicWriter &operator<<(const StrFormatSpec<StrChar> &spec) {
    const StrChar *s = spec.str();
    write_str(s, std::char_traits<Char>::length(s), spec);
    return *this;
  }

Project: fmt
File: format.h

  static wchar_t convert(char value) { return value; }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatOct) {
  EXPECT_EQ("0", format("{0:o}", 0));
  EXPECT_EQ("42", format("{0:o}", 042));
  EXPECT_EQ("42", format("{0:o}", 042u));
  EXPECT_EQ("-42", format("{0:o}", -042));
  EXPECT_EQ("12345670", format("{0:o}", 012345670));
  char buffer[BUFFER_SIZE];
  safe_sprintf(buffer, "-%o", 0 - static_cast<unsigned>(INT_MIN));
  EXPECT_EQ(buffer, format("{0:o}", INT_MIN));
  safe_sprintf(buffer, "%o", INT_MAX);
  EXPECT_EQ(buffer, format("{0:o}", INT_MAX));
  safe_sprintf(buffer, "%o", UINT_MAX);
  EXPECT_EQ(buffer, format("{0:o}", UINT_MAX));
  safe_sprintf(buffer, "-%lo", 0 - static_cast<unsigned long>(LONG_MIN));
  EXPECT_EQ(buffer, format("{0:o}", LONG_MIN));
  safe_sprintf(buffer, "%lo", LONG_MAX);
  EXPECT_EQ(buffer, format("{0:o}", LONG_MAX));
  safe_sprintf(buffer, "%lo", ULONG_MAX);
  EXPECT_EQ(buffer, format("{0:o}", ULONG_MAX));
}

Project: fmt
File: format.h

  WindowsError(int error_code, CStringRef message) {
    init(error_code, message, ArgList());
  }

Project: fmt
File: format.h

  BasicWriter &operator<<(char value) {
    buffer_.push_back(value);
    return *this;
  }

Project: fmt
File: format.h

inline bool is_negative(T value) {
  return SignChecker<std::numeric_limits<T>::is_signed>::is_negative(value);
}

Project: fmt
File: format-test.cc

  ::testing::AssertionResult operator()(const char *, const T &value) const {
    ::testing::AssertionResult result = check_write<char>(value, "char");
    return result ? check_write<wchar_t>(value, "wchar_t") : result;
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatInfinity) {
  double inf = std::numeric_limits<double>::infinity();
  EXPECT_EQ("inf", format("{}", inf));
  EXPECT_EQ("+inf", format("{:+}", inf));
  EXPECT_EQ("-inf", format("{}", -inf));
  EXPECT_EQ(" inf", format("{: }", inf));
  EXPECT_EQ("INF", format("{:F}", inf));
  EXPECT_EQ("inf    ", format("{:<7}", inf));
  EXPECT_EQ("  inf  ", format("{:^7}", inf));
  EXPECT_EQ("    inf", format("{:>7}", inf));
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, CustomFormat) {
  EXPECT_EQ("42", format("{0}", Answer()));
}

Project: fmt
File: format.h

  void move(MemoryBuffer &other) {
    Allocator &this_alloc = *this, &other_alloc = other;
    this_alloc = std::move(other_alloc);
    this->size_ = other.size_;
    this->capacity_ = other.capacity_;
    if (other.ptr_ == other.data_) {
      this->ptr_ = data_;
      std::uninitialized_copy(other.data_, other.data_ + this->size_,
                              make_ptr(data_, this->capacity_));
    } else {
      this->ptr_ = other.ptr_;
      // Set pointer to the inline array so that delete is not called
      // when deallocating.
      other.ptr_ = other.data_;
    }
  }

Project: fmt
File: format.h

  Char *write_unsigned_decimal(UInt value, unsigned prefix_size = 0) {
    unsigned num_digits = internal::count_digits(value);
    Char *ptr = get(grow_buffer(prefix_size + num_digits));
    internal::format_decimal(ptr + prefix_size, value, num_digits);
    return ptr;
  }

Project: fmt
File: format.h

  static internal::Arg::Type type(uint64_t types, unsigned index) {
    unsigned shift = index * 4;
    uint64_t mask = 0xf;
    return static_cast<internal::Arg::Type>(
          (types & (mask << shift)) >> shift);
  }

Project: fmt
File: format-test.cc

TEST(ArrayWriterTest, CompileTimeSizeCtor) {
  char array[10] = "garbage";
  fmt::ArrayWriter w(array);
  EXPECT_EQ(0u, w.size());
  EXPECT_STREQ("", w.c_str());
  w.write("{:10}", 1);
}

Project: fmt
File: format.h

  BasicStringRef(
	  const std::experimental::basic_string_view<Char, std::char_traits<Char>> &s)
	  : data_(s.data()), size_(s.size()) {}

Project: fmt
File: format.h

  MemoryBuffer(MemoryBuffer &&other) {
    move(other);
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, Width) {
  char format_str[BUFFER_SIZE];
  safe_sprintf(format_str, "{0:%u", UINT_MAX);
  increment(format_str + 3);
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
  std::size_t size = std::strlen(format_str);
  format_str[size] = '}';
  format_str[size + 1] = 0;
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");

  safe_sprintf(format_str, "{0:%u", INT_MAX + 1u);
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
  safe_sprintf(format_str, "{0:%u}", INT_MAX + 1u);
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
  EXPECT_EQ(" -42", format("{0:4}", -42));
  EXPECT_EQ("   42", format("{0:5}", 42u));
  EXPECT_EQ("   -42", format("{0:6}", -42l));
  EXPECT_EQ("     42", format("{0:7}", 42ul));
  EXPECT_EQ("   -42", format("{0:6}", -42ll));
  EXPECT_EQ("     42", format("{0:7}", 42ull));
  EXPECT_EQ("   -1.23", format("{0:8}", -1.23));
  EXPECT_EQ("    -1.23", format("{0:9}", -1.23l));
  EXPECT_EQ("    0xcafe", format("{0:10}", reinterpret_cast<void*>(0xcafe)));
  EXPECT_EQ("x          ", format("{0:11}", 'x'));
  EXPECT_EQ("str         ", format("{0:12}", "str"));
}

Project: fmt
File: format.h

  BasicWriter &operator<<(IntFormatSpec<T, Spec, FillChar> spec) {
    internal::CharTraits<Char>::convert(FillChar());
    write_int(spec.value(), spec);
    return *this;
  }

Project: fmt
File: format.h

  BasicWriter &operator<<(
      typename internal::WCharHelper<StringRef, Char>::Supported value) {
    const char *str = value.data();
    buffer_.append(str, str + value.size());
    return *this;
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatSCharString) {
  signed char str[] = "test";
  EXPECT_EQ("test", format("{0:s}", str));
  const signed char *const_str = str;
  EXPECT_EQ("test", format("{0:s}", const_str));
}

Project: fmt
File: format-test.cc

TEST(WriterTest, WWriter) {
  EXPECT_EQ(L"cafe", (fmt::WMemoryWriter() << fmt::hex(0xcafe)).str());
}

Project: fmt
File: format.h

  void write(bool value) {
    const char *str_value = value ? "true" : "false";
    Arg::StringValue<char> str = { str_value, std::strlen(str_value) };
    writer_.write_str(str, spec_);
  }

Project: fmt
File: format.h

void format_arg(Formatter&, ...) {
  FMT_STATIC_ASSERT(FalseType<Formatter>::value,
                    "Cannot format argument. To enable the use of ostream "
                    "operator<< include fmt/ostream.h. Otherwise provide "
                    "an overload of format_arg.");
}

Project: fmt
File: format-test.cc

TEST(WriterTest, MoveCtor) {
  MemoryWriter w;
  w << "test";
  check_move_writer("test", w);
  // This fills the inline buffer, but doesn't cause dynamic allocation.
  std::string s;
  for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE; ++i)
    s += '*';
  w.clear();
  w << s;
  check_move_writer(s, w);
  const char *inline_buffer_ptr = w.data();
  // Adding one more character causes the content to move from the inline to
  // a dynamically allocated buffer.
  w << '*';
  MemoryWriter w2(std::move(w));
  // Move should rip the guts of the first writer.
  EXPECT_EQ(inline_buffer_ptr, w.data());
  EXPECT_EQ(s + '*', w2.str());
}

Project: fmt
File: format-test.cc

TEST(ArrayWriterTest, Write) {
  char array[10];
  fmt::ArrayWriter w(array, sizeof(array));
  w.write("{}", 42);
  EXPECT_EQ("42", w.str());
}

Project: fmt
File: format.h

operator"" _format(const wchar_t *s, std::size_t) { return {s}; }

Project: fmt
File: format.h

  ArgList(ULongLong types, const internal::Value *values)
  : types_(types), values_(values) {}

Project: fmt
File: format.h

ArgJoin<wchar_t, It> join(It first, It last, const BasicCStringRef<wchar_t>& sep) {
  return ArgJoin<wchar_t, It>(first, last, sep);
}

Project: fmt
File: format.h

  T &operator[](std::size_t index) { return ptr_[index]; }

Project: fmt
File: format.h

  uint64_t types() const { return types_; }

Project: fmt
File: format.h

  static uint64_t type(const NamedArg<Char_> &) { return Arg::NAMED_ARG; }

Project: fmt
File: format-test.cc

TEST(WriterTest, hex) {
  using fmt::hex;
  fmt::IntFormatSpec<int, fmt::TypeSpec<'x'> > (*phex)(int value) = hex;
  phex(42);
  // This shouldn't compile:
  //fmt::IntFormatSpec<short, fmt::TypeSpec<'x'> > (*phex2)(short value) = hex;

  EXPECT_EQ("cafe", (MemoryWriter() << hex(0xcafe)).str());
  EXPECT_EQ("babe", (MemoryWriter() << hex(0xbabeu)).str());
  EXPECT_EQ("dead", (MemoryWriter() << hex(0xdeadl)).str());
  EXPECT_EQ("beef", (MemoryWriter() << hex(0xbeeful)).str());
  EXPECT_EQ("cafebabe", (MemoryWriter() << hex(0xcafebabell)).str());
  EXPECT_EQ("deadbeef", (MemoryWriter() << hex(0xdeadbeefull)).str());
}

Project: fmt
File: format.h

  bool check_no_auto_index(const char *&error) {
    if (next_arg_index_ > 0) {
      error = "cannot switch from automatic to manual argument indexing";
      return false;
    }
    next_arg_index_ = -1;
    return true;
  }

Project: fmt
File: format.h

void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
  std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
  if (size > new_capacity)
      new_capacity = size;
#if FMT_USE_ALLOCATOR_TRAITS
  T *new_ptr =
      std::allocator_traits<Allocator>::allocate(*this, new_capacity, FMT_NULL);
#else
  T *new_ptr = this->allocate(new_capacity, FMT_NULL);
#endif
  // The following code doesn't throw, so the raw pointer above doesn't leak.
  std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
                          make_ptr(new_ptr, new_capacity));
  std::size_t old_capacity = this->capacity_;
  T *old_ptr = this->ptr_;
  this->capacity_ = new_capacity;
  this->ptr_ = new_ptr;
  // deallocate may throw (at least in principle), but it doesn't matter since
  // the buffer already uses the new storage and will deallocate it in case
  // of exception.
  if (old_ptr != data_)
    Allocator::deallocate(old_ptr, old_capacity);
}

Project: fmt
File: format.h

  SystemError() {}

Project: fmt
File: format-test.cc

::testing::AssertionResult check_write(const T &value, const char *type) {
  std::basic_string<Char> actual =
      (fmt::BasicMemoryWriter<Char>() << value).str();
  std::basic_string<Char> expected;
  std_format(value, expected);
  if (expected == actual)
    return ::testing::AssertionSuccess();
  return ::testing::AssertionFailure()
      << "Value of: (Writer<" << type << ">() << value).str()\n"
      << "  Actual: " << actual << "\n"
      << "Expected: " << expected << "\n";
}

Project: fmt
File: format.h

  BasicMemoryWriter(BasicMemoryWriter &&other)
    : BasicWriter<Char>(buffer_), buffer_(std::move(other.buffer_)) {
  }

Project: fmt
File: format.h

  NamedArgWithType<Char, T> operator=(T &&value) const {
    return {str, std::forward<T>(value)};
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, ZeroFlag) {
  EXPECT_EQ("42", format("{0:0}", 42));
  EXPECT_EQ("-0042", format("{0:05}", -42));
  EXPECT_EQ("00042", format("{0:05}", 42u));
  EXPECT_EQ("-0042", format("{0:05}", -42l));
  EXPECT_EQ("00042", format("{0:05}", 42ul));
  EXPECT_EQ("-0042", format("{0:05}", -42ll));
  EXPECT_EQ("00042", format("{0:05}", 42ull));
  EXPECT_EQ("-0042", format("{0:05}", -42.0));
  EXPECT_EQ("-0042", format("{0:05}", -42.0l));
  EXPECT_THROW_MSG(format("{0:0", 'c'),
      FormatError, "missing '}' in format string");
  EXPECT_THROW_MSG(format("{0:05}", 'c'),
      FormatError, "invalid format specifier for char");
  EXPECT_THROW_MSG(format("{0:05}", "abc"),
      FormatError, "format specifier '0' requires numeric argument");
  EXPECT_THROW_MSG(format("{0:05}", reinterpret_cast<void*>(0x42)),
      FormatError, "format specifier '0' requires numeric argument");
}

Project: fmt
File: format.h

  static bool isnegative(double x) {
    using namespace fmt::internal;
    if (const_check(sizeof(signbit(x)) != sizeof(fmt::internal::DummyInt))) {
      return signbit(x) != 0;
    }
    if (x < 0) return true;
    if (!isnotanumber(x)) return false;
    int dec = 0, sign = 0;
    char buffer[2];  // The buffer size must be >= 2 or _ecvt_s will fail.
    _ecvt_s(buffer, sizeof(buffer), x, 0, &dec, &sign);
    return sign != 0;
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, RightAlign) {
  EXPECT_EQ("  42", format("{0:>4}", 42));
  EXPECT_EQ("  42", format("{0:>4o}", 042));
  EXPECT_EQ("  42", format("{0:>4x}", 0x42));
  EXPECT_EQ("  -42", format("{0:>5}", -42));
  EXPECT_EQ("   42", format("{0:>5}", 42u));
  EXPECT_EQ("  -42", format("{0:>5}", -42l));
  EXPECT_EQ("   42", format("{0:>5}", 42ul));
  EXPECT_EQ("  -42", format("{0:>5}", -42ll));
  EXPECT_EQ("   42", format("{0:>5}", 42ull));
  EXPECT_EQ("  -42", format("{0:>5}", -42.0));
  EXPECT_EQ("  -42", format("{0:>5}", -42.0l));
  EXPECT_EQ("    c", format("{0:>5}", 'c'));
  EXPECT_EQ("  abc", format("{0:>5}", "abc"));
  EXPECT_EQ("  0xface", format("{0:>8}", reinterpret_cast<void*>(0xface)));
}

Project: fmt
File: format-test.cc

TEST(FormatTest, Print) {
#if FMT_USE_FILE_DESCRIPTORS
  EXPECT_WRITE(stdout, fmt::print("Don't {}!", "panic"), "Don't panic!");
  EXPECT_WRITE(stderr,
      fmt::print(stderr, "Don't {}!", "panic"), "Don't panic!");
#endif
}

Project: fmt
File: format.h

  internal::Arg::Type type(unsigned index) const {
    return type(types_, index);
  }

Project: fmt
File: format.h

inline DummyInt signbit(...) { return DummyInt(); }

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteLong) {
  CHECK_WRITE(56l);
  CHECK_WRITE(78ul);
  CHECK_WRITE(std::numeric_limits<long>::min());
  CHECK_WRITE(std::numeric_limits<long>::max());
  CHECK_WRITE(std::numeric_limits<unsigned long>::max());
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatExamples) {
  using fmt::hex;
  EXPECT_EQ("0000cafe", (MemoryWriter() << pad(hex(0xcafe), 8, '0')).str());

  std::string message = format("The answer is {}", 42);
  EXPECT_EQ("The answer is 42", message);

  EXPECT_EQ("42", format("{}", 42));
  EXPECT_EQ("42", format(std::string("{}"), 42));

  MemoryWriter out;
  out << "The answer is " << 42 << "\n";
  out.write("({:+f}, {:+f})", -3.14, 3.14);
  EXPECT_EQ("The answer is 42\n(-3.140000, +3.140000)", out.str());

  {
    MemoryWriter writer;
    for (int i = 0; i < 10; i++)
      writer.write("{}", i);
    std::string s = writer.str(); // s == 0123456789
    EXPECT_EQ("0123456789", s);
  }

  const char *filename = "nonexistent";
  FILE *ftest = safe_fopen(filename, "r");
  if (ftest) fclose(ftest);
  int error_code = errno;
  EXPECT_TRUE(ftest == 0);
  EXPECT_SYSTEM_ERROR({
    FILE *f = safe_fopen(filename, "r");
    if (!f)
      throw fmt::SystemError(errno, "Cannot open file '{}'", filename);
    fclose(f);
  }, error_code, "Cannot open file 'nonexistent'");
}

Project: fmt
File: format-test.cc

TEST(FormatTest, FormatMessageExample) {
  EXPECT_EQ("[42] something happened",
      format_message(42, "{} happened", "something"));
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatWChar) {
  EXPECT_EQ(L"a", format(L"{0}", L'a'));
  // This shouldn't compile:
  //format("{}", L'a');
}

Project: fmt
File: format.h

  Alignment align() const { return align_; }

Project: fmt
File: format.h

inline T *make_ptr(T *ptr, std::size_t) { return ptr; }

Project: fmt
File: format.h

  void visit_char(int value) {
    if (spec_.type_ && spec_.type_ != 'c') {
      spec_.flags_ |= CHAR_FLAG;
      writer_.write_int(value, spec_);
      return;
    }
    if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
      FMT_THROW(FormatError("invalid format specifier for char"));
    typedef typename BasicWriter<Char>::CharPtr CharPtr;
    Char fill = internal::CharTraits<Char>::cast(spec_.fill());
    CharPtr out = CharPtr();
    const unsigned CHAR_SIZE = 1;
    if (spec_.width_ > CHAR_SIZE) {
      out = writer_.grow_buffer(spec_.width_);
      if (spec_.align_ == ALIGN_RIGHT) {
        std::uninitialized_fill_n(out, spec_.width_ - CHAR_SIZE, fill);
        out += spec_.width_ - CHAR_SIZE;
      } else if (spec_.align_ == ALIGN_CENTER) {
        out = writer_.fill_padding(out, spec_.width_,
                                   internal::const_check(CHAR_SIZE), fill);
      } else {
        std::uninitialized_fill_n(out + CHAR_SIZE,
                                  spec_.width_ - CHAR_SIZE, fill);
      }
    } else {
      out = writer_.grow_buffer(CHAR_SIZE);
    }
    *out = internal::CharTraits<Char>::cast(value);
  }

Project: fmt
File: format.h

  BasicWriter<Char> &writer() { return writer_; }

Project: fmt
File: format.h

   MakeValue(T value) { int_value = value; }

Project: fmt
File: format.h

unsigned parse_nonnegative_int(const Char *&s) {
  assert('0' <= *s && *s <= '9');
  unsigned value = 0;
  // Convert to unsigned to prevent a warning.
  unsigned max_int = (std::numeric_limits<int>::max)();
  unsigned big = max_int / 10;
  do {
    // Check for overflow.
    if (value > big) {
      value = max_int + 1;
      break;
    }
    value = value * 10 + (*s - '0');
    ++s;
  } while ('0' <= *s && *s <= '9');
  // Convert to unsigned to prevent a warning.
  if (value > max_int)
    FMT_THROW(FormatError("number is too big"));
  return value;
}

Project: fmt
File: format.h

  BasicStringRef(
      const std::basic_string_view<Char, std::char_traits<Char>> &s)
  : data_(s.data()), size_(s.size()) {}

Project: fmt
File: format.h

  MakeValue() {}

Project: fmt
File: format.h

  BasicArrayWriter(Char *array, std::size_t size)
    : BasicWriter<Char>(buffer_), buffer_(array, size) {}

Project: fmt
File: format.h

inline DummyInt _finite(...) { return DummyInt(); }

Project: fmt
File: format.h

inline typename MakeUnsigned<Int>::Type to_unsigned(Int value) {
  FMT_ASSERT(value >= 0, "negative value");
  return static_cast<typename MakeUnsigned<Int>::Type>(value);
}

Project: fmt
File: format.h

  const wchar_t *c_str() const { return &buffer_[0]; }

Project: fmt
File: format-test.cc

TEST(WriterTest, NotCopyConstructible) {
  EXPECT_FALSE(std::is_copy_constructible<BasicWriter<char> >::value);
}

Project: fmt
File: format-test.cc

TEST(WriterTest, bin) {
  using fmt::bin;
  EXPECT_EQ("1100101011111110", (MemoryWriter() << bin(0xcafe)).str());
  EXPECT_EQ("1011101010111110", (MemoryWriter() << bin(0xbabeu)).str());
  EXPECT_EQ("1101111010101101", (MemoryWriter() << bin(0xdeadl)).str());
  EXPECT_EQ("1011111011101111", (MemoryWriter() << bin(0xbeeful)).str());
  EXPECT_EQ("11001010111111101011101010111110",
            (MemoryWriter() << bin(0xcafebabell)).str());
  EXPECT_EQ("11011110101011011011111011101111",
            (MemoryWriter() << bin(0xdeadbeefull)).str());
}

Project: fmt
File: format.h

  int precision() const { return -1; }

Project: fmt
File: format.h

  void push_back(const T &value) {
    if (size_ == capacity_)
      grow(size_ + 1);
    ptr_[size_++] = value;
  }

Project: fmt
File: format.h

inline std::string format(CStringRef format_str, ArgList args) {
  MemoryWriter w;
  w.write(format_str, args);
  return w.str();
}

Project: fmt
File: format-test.cc

void CheckMoveAssignWriter(const std::string &str, MemoryWriter &w) {
  MemoryWriter w2;
  w2 = std::move(w);
  // Move shouldn't destroy the inline content of the first writer.
  EXPECT_EQ(str, w.str());
  EXPECT_EQ(str, w2.str());
}

Project: fmt
File: format.h

inline unsigned count_digits(uint64_t n) {
  // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
  // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
  int t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12;
  return to_unsigned(t) - (n < Data::POWERS_OF_10_64[t]) + 1;
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, EmptySpecs) {
  EXPECT_EQ("42", format("{0:}", 42));
}

Project: fmt
File: format.h

  explicit ThousandsSep(fmt::StringRef sep) : sep_(sep), digit_index_(0) {}

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteWideChar) {
  CHECK_WRITE_WCHAR(L'a');
}

Project: fmt
File: format-test.cc

TEST(WriterTest, Format) {
  MemoryWriter w;
  w.write("part{0}", 1);
  EXPECT_EQ(strlen("part1"), w.size());
  EXPECT_STREQ("part1", w.c_str());
  EXPECT_STREQ("part1", w.data());
  EXPECT_EQ("part1", w.str());
  w.write("part{0}", 2);
  EXPECT_EQ(strlen("part1part2"), w.size());
  EXPECT_STREQ("part1part2", w.c_str());
  EXPECT_STREQ("part1part2", w.data());
  EXPECT_EQ("part1part2", w.str());
}

Project: fmt
File: format.h

  CharPtr grow_buffer(std::size_t n) {
    std::size_t size = buffer_.size();
    buffer_.resize(size + n);
    return internal::make_ptr(&buffer_[size], n);
  }

Project: fmt
File: format.h

  ~MemoryBuffer() FMT_OVERRIDE { deallocate(); }

Project: fmt
File: format-test.cc

TEST(StringRefTest, ConvertToString) {
  std::string s = StringRef("abc").to_string();
  EXPECT_EQ("abc", s);

#if FMT_HAS_STRING_VIEW
  StringRef str_ref("defg");
  std::string_view sv = static_cast<std::string_view>(str_ref);
  EXPECT_EQ("defg", sv);
#endif

#if FMT_HAS_EXPERIMENTAL_STRING_VIEW
  StringRef str_ref("defg");
  std::experimental::string_view sv = static_cast<std::experimental::string_view>(str_ref);
  EXPECT_EQ("defg", sv);
#endif
}

Project: fmt
File: format.h

inline uint64_t make_type(const Arg &first, const Args & ... tail) {
  return make_type(first) | (make_type(tail...) << 4);
}

Project: fmt
File: format.h

  explicit MemoryBuffer(const Allocator &alloc = Allocator())
      : Allocator(alloc), Buffer<T>(data_, SIZE) {}

Project: fmt
File: format-test.cc

  friend BasicWriter<Char> &operator<<(
      BasicWriter<Char> &w, const ISO8601DateFormatter &d) {
    return w << pad(d.date_->year(), 4, '0') << '-'
        << pad(d.date_->month(), 2, '0') << '-' << pad(d.date_->day(), 2, '0');
  }

Project: fmt
File: format.h

  friend bool operator<=(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) <= 0;
  }

Project: fmt
File: format.h

  void write(BasicCStringRef<Char> format, ArgList args) {
    BasicFormatter<Char>(args, *this).format(format);
  }

Project: fmt
File: format-test.cc

TEST(WriterTest, NoConflictWithIOManip) {
  using namespace std;
  using namespace fmt;
  EXPECT_EQ("cafe", (MemoryWriter() << hex(0xcafe)).str());
  EXPECT_EQ("12", (MemoryWriter() << oct(012)).str());
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, SpaceSign) {
  EXPECT_EQ(" 42", format("{0: }", 42));
  EXPECT_EQ("-42", format("{0: }", -42));
  EXPECT_EQ(" 42", format("{0: }", 42));
  EXPECT_THROW_MSG(format("{0: }", 42u),
      FormatError, "format specifier ' ' requires signed argument");
  EXPECT_EQ(" 42", format("{0: }", 42l));
  EXPECT_THROW_MSG(format("{0: }", 42ul),
      FormatError, "format specifier ' ' requires signed argument");
  EXPECT_EQ(" 42", format("{0: }", 42ll));
  EXPECT_THROW_MSG(format("{0: }", 42ull),
      FormatError, "format specifier ' ' requires signed argument");
  EXPECT_EQ(" 42", format("{0: }", 42.0));
  EXPECT_EQ(" 42", format("{0: }", 42.0l));
  EXPECT_THROW_MSG(format("{0: ", 'c'),
      FormatError, "missing '}' in format string");
  EXPECT_THROW_MSG(format("{0: }", 'c'),
      FormatError, "invalid format specifier for char");
  EXPECT_THROW_MSG(format("{0: }", "abc"),
      FormatError, "format specifier ' ' requires numeric argument");
  EXPECT_THROW_MSG(format("{0: }", reinterpret_cast<void*>(0x42)),
      FormatError, "format specifier ' ' requires numeric argument");
}

Project: fmt
File: format.h

  int error_code() const { return error_code_; }

Project: fmt
File: format-test.cc

TEST(FormatTest, Regression) {
  fmt::format("...........{:<77777.7p}", "foo");
}

Project: fmt
File: format.h

  BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {}

Project: fmt
File: format.h

  char fill() const { return ' '; }

Project: fmt
File: format.h

  std::size_t size() const { return size_; }

Project: fmt
File: format-test.cc

BasicWriter<Char> &operator<<(BasicWriter<Char> &f, const Date &d) {
  return f << d.year() << '-' << d.month() << '-' << d.day();
}

Project: fmt
File: format.h

  void resize(std::size_t new_size) {
    if (new_size > capacity_)
      grow(new_size);
    size_ = new_size;
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatHex) {
  EXPECT_EQ("0", format("{0:x}", 0));
  EXPECT_EQ("42", format("{0:x}", 0x42));
  EXPECT_EQ("42", format("{0:x}", 0x42u));
  EXPECT_EQ("-42", format("{0:x}", -0x42));
  EXPECT_EQ("12345678", format("{0:x}", 0x12345678));
  EXPECT_EQ("90abcdef", format("{0:x}", 0x90abcdef));
  EXPECT_EQ("12345678", format("{0:X}", 0x12345678));
  EXPECT_EQ("90ABCDEF", format("{0:X}", 0x90ABCDEF));

  char buffer[BUFFER_SIZE];
  safe_sprintf(buffer, "-%x", 0 - static_cast<unsigned>(INT_MIN));
  EXPECT_EQ(buffer, format("{0:x}", INT_MIN));
  safe_sprintf(buffer, "%x", INT_MAX);
  EXPECT_EQ(buffer, format("{0:x}", INT_MAX));
  safe_sprintf(buffer, "%x", UINT_MAX);
  EXPECT_EQ(buffer, format("{0:x}", UINT_MAX));
  safe_sprintf(buffer, "-%lx", 0 - static_cast<unsigned long>(LONG_MIN));
  EXPECT_EQ(buffer, format("{0:x}", LONG_MIN));
  safe_sprintf(buffer, "%lx", LONG_MAX);
  EXPECT_EQ(buffer, format("{0:x}", LONG_MAX));
  safe_sprintf(buffer, "%lx", ULONG_MAX);
  EXPECT_EQ(buffer, format("{0:x}", ULONG_MAX));
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatNaN) {
  double nan = std::numeric_limits<double>::quiet_NaN();
  EXPECT_EQ("nan", format("{}", nan));
  EXPECT_EQ("+nan", format("{:+}", nan));
  EXPECT_EQ(" nan", format("{: }", nan));
  EXPECT_EQ("NAN", format("{:F}", nan));
  EXPECT_EQ("nan    ", format("{:<7}", nan));
  EXPECT_EQ("  nan  ", format("{:^7}", nan));
  EXPECT_EQ("    nan", format("{:>7}", nan));
}

Project: fmt
File: format.h

  static Char *get(CharPtr p) { return p.base(); }

Project: fmt
File: format.h

  void visit_any_int(T value) { writer_.write_int(value, spec_); }

Project: fmt
File: format-test.cc

TEST(ArrayWriterTest, BufferOverflow) {
  char array[10];
  fmt::ArrayWriter w(array, sizeof(array));
  w.write("{:10}", 1);
  EXPECT_THROW_MSG(w.write("{}", 1), std::runtime_error, "buffer overflow");
}

Project: fmt
File: format.h

  std::wstring str() const { return std::wstring(&buffer_[0], size()); }

Project: fmt
File: format-test.cc

TEST(FormatIntTest, FormatDec) {
  EXPECT_EQ("-42", format_decimal(static_cast<signed char>(-42)));
  EXPECT_EQ("-42", format_decimal(static_cast<short>(-42)));
  std::ostringstream os;
  os << std::numeric_limits<unsigned short>::max();
  EXPECT_EQ(os.str(),
            format_decimal(std::numeric_limits<unsigned short>::max()));
  EXPECT_EQ("1", format_decimal(1));
  EXPECT_EQ("-1", format_decimal(-1));
  EXPECT_EQ("42", format_decimal(42));
  EXPECT_EQ("-42", format_decimal(-42));
  EXPECT_EQ("42", format_decimal(42l));
  EXPECT_EQ("42", format_decimal(42ul));
  EXPECT_EQ("42", format_decimal(42ll));
  EXPECT_EQ("42", format_decimal(42ull));
}

Project: fmt
File: format.h

inline internal::NamedArgWithType<wchar_t, T> arg(WStringRef name, const T &arg) {
  return internal::NamedArgWithType<wchar_t, T>(name, arg);
}

Project: fmt
File: format.h

  BasicCStringRef(
      const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
  : data_(s.c_str()) {}

Project: fmt
File: format.h

inline fmt::StringRef thousands_sep(...) { return ""; }

Project: fmt
File: format-test.cc

  static std::string format(fmt::CStringRef format_str, const Args & ... args) {
    return TestFormat<N - 1>::format(format_str, N - 1, args...);
  }

Project: fmt
File: format.h

  MemoryBuffer &operator=(MemoryBuffer &&other) {
    assert(this != &other);
    deallocate();
    move(other);
    return *this;
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatUCharString) {
  unsigned char str[] = "test";
  EXPECT_EQ("test", format("{0:s}", str));
  const unsigned char *const_str = str;
  EXPECT_EQ("test", format("{0:s}", const_str));
  unsigned char *ptr = str;
  EXPECT_EQ("test", format("{0:s}", ptr));
}

Project: fmt
File: format.h

  friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) == 0;
  }

Project: fmt
File: format-test.cc

TEST(WriterTest, hexu) {
  using fmt::hexu;
  EXPECT_EQ("CAFE", (MemoryWriter() << hexu(0xcafe)).str());
  EXPECT_EQ("BABE", (MemoryWriter() << hexu(0xbabeu)).str());
  EXPECT_EQ("DEAD", (MemoryWriter() << hexu(0xdeadl)).str());
  EXPECT_EQ("BEEF", (MemoryWriter() << hexu(0xbeeful)).str());
  EXPECT_EQ("CAFEBABE", (MemoryWriter() << hexu(0xcafebabell)).str());
  EXPECT_EQ("DEADBEEF", (MemoryWriter() << hexu(0xdeadbeefull)).str());
}

Project: fmt
File: format.h

void check_sign(const Char *&s, const Arg &arg) {
  char sign = static_cast<char>(*s);
  require_numeric_argument(arg, sign);
  if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
    FMT_THROW(FormatError(fmt::format(
      "format specifier '{}' requires signed argument", sign)));
  }
  ++s;
}

Project: fmt
File: format.h

  MakeValue(const NamedArg<Char_> &value) { pointer = &value; }

Project: fmt
File: format.h

  FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {}

Project: fmt
File: format.h

  void operator()(Char *&buffer) {
    if (++digit_index_ % 3 != 0)
      return;
    buffer -= sep_.size();
    std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(),
                            internal::make_ptr(buffer, sep_.size()));
  }

Project: fmt
File: format.h

  Result visit_any_int(T) {
    return FMT_DISPATCH(visit_unhandled_arg());
  }

Project: fmt
File: format.h

  void set_string(WStringRef str) {
    wstring.value = str.data();
    wstring.size = str.size();
  }

Project: fmt
File: format.h

inline std::wstring format(WCStringRef format_str, ArgList args) {
  WMemoryWriter w;
  w.write(format_str, args);
  return w.str();
}

Project: fmt
File: format.h

  void visit_custom(internal::Arg::CustomValue c) {
    c.format(&formatter_, c.value, &format_);
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatUnsignedChar) {
  EXPECT_EQ("42", format("{}", static_cast<unsigned char>(42)));
  EXPECT_EQ("42", format("{}", static_cast<uint8_t>(42)));
}

Project: fmt
File: format.h

  explicit BasicWriter(Buffer<Char> &b) : buffer_(b) {}

Project: fmt
File: format.h

  static bool isinfinity(T x) {
    using namespace fmt::internal;
    // The resolution "priority" is:
    // isinf macro > std::isinf > ::isinf > fmt::internal::isinf
    if (const_check(sizeof(isinf(x)) != sizeof(fmt::internal::DummyInt))) {
      return isinf(x) != 0;
    }
    return !_finite(static_cast<double>(x));
  }

Project: fmt
File: format.h

  Arg get_arg(unsigned arg_index, const char *&error) {
    return check_no_auto_index(error) ? do_get_arg(arg_index, error) : Arg();
  }

Project: fmt
File: format.h

  Result visit_pointer(const void *) {
    return FMT_DISPATCH(visit_unhandled_arg());
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatIntLocale) {
  ScopedMock<LocaleMock> mock;
  lconv lc = lconv();
  char sep[] = "--";
  lc.thousands_sep = sep;
  EXPECT_CALL(mock, localeconv()).Times(3).WillRepeatedly(testing::Return(&lc));
  EXPECT_EQ("123", format("{:n}", 123));
  EXPECT_EQ("1--234", format("{:n}", 1234));
  EXPECT_EQ("1--234--567", format("{:n}", 1234567));
}

Project: fmt
File: format.h

  const char *data() const { return str_; }

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteDoubleWithFilledBuffer) {
  MemoryWriter writer;
  // Fill the buffer.
  for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE; ++i)
    writer << ' ';
  writer << 1.2;
  EXPECT_STREQ("1.2", writer.c_str() + fmt::internal::INLINE_BUFFER_SIZE);
}

Project: fmt
File: format-test.cc

TEST(WriterTest, Allocator) {
  typedef testing::StrictMock< MockAllocator<char> > MockAllocator;
  typedef AllocatorRef<MockAllocator> TestAllocator;
  MockAllocator alloc;
  fmt::BasicMemoryWriter<char, TestAllocator> w((TestAllocator(&alloc)));
  std::size_t size =
      static_cast<std::size_t>(1.5 * fmt::internal::INLINE_BUFFER_SIZE);
  std::vector<char> mem(size);
  EXPECT_CALL(alloc, allocate(size, 0)).WillOnce(testing::Return(&mem[0]));
  for (int i = 0; i < fmt::internal::INLINE_BUFFER_SIZE + 1; ++i)
    w << '*';
  EXPECT_CALL(alloc, deallocate(&mem[0], size));
}

Project: fmt
File: format.h

const Char *BasicFormatter<Char, ArgFormatter>::format(
    const Char *&format_str, const internal::Arg &arg) {
  using internal::Arg;
  const Char *s = format_str;
  typename ArgFormatter::SpecType spec;
  if (*s == ':') {
    if (arg.type == Arg::CUSTOM) {
      arg.custom.format(this, arg.custom.value, &s);
      return s;
    }
    ++s;
    // Parse fill and alignment.
    if (Char c = *s) {
      const Char *p = s + 1;
      spec.align_ = ALIGN_DEFAULT;
      do {
        switch (*p) {
          case '<':
            spec.align_ = ALIGN_LEFT;
            break;
          case '>':
            spec.align_ = ALIGN_RIGHT;
            break;
          case '=':
            spec.align_ = ALIGN_NUMERIC;
            break;
          case '^':
            spec.align_ = ALIGN_CENTER;
            break;
        }
        if (spec.align_ != ALIGN_DEFAULT) {
          if (p != s) {
            if (c == '}') break;
            if (c == '{')
              FMT_THROW(FormatError("invalid fill character '{'"));
            s += 2;
            spec.fill_ = c;
          } else ++s;
          if (spec.align_ == ALIGN_NUMERIC)
            require_numeric_argument(arg, '=');
          break;
        }
      } while (--p >= s);
    }

    // Parse sign.
    switch (*s) {
      case '+':
        check_sign(s, arg);
        spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
        break;
      case '-':
        check_sign(s, arg);
        spec.flags_ |= MINUS_FLAG;
        break;
      case ' ':
        check_sign(s, arg);
        spec.flags_ |= SIGN_FLAG;
        break;
    }

    if (*s == '#') {
      require_numeric_argument(arg, '#');
      spec.flags_ |= HASH_FLAG;
      ++s;
    }

    // Parse zero flag.
    if (*s == '0') {
      require_numeric_argument(arg, '0');
      spec.align_ = ALIGN_NUMERIC;
      spec.fill_ = '0';
      ++s;
    }

    // Parse width.
    if ('0' <= *s && *s <= '9') {
      spec.width_ = internal::parse_nonnegative_int(s);
    } else if (*s == '{') {
      ++s;
      Arg width_arg = internal::is_name_start(*s) ?
            parse_arg_name(s) : parse_arg_index(s);
      if (*s++ != '}')
        FMT_THROW(FormatError("invalid format string"));
      ULongLong value = 0;
      switch (width_arg.type) {
      case Arg::INT:
        if (width_arg.int_value < 0)
          FMT_THROW(FormatError("negative width"));
        value = width_arg.int_value;
        break;
      case Arg::UINT:
        value = width_arg.uint_value;
        break;
      case Arg::LONG_LONG:
        if (width_arg.long_long_value < 0)
          FMT_THROW(FormatError("negative width"));
        value = width_arg.long_long_value;
        break;
      case Arg::ULONG_LONG:
        value = width_arg.ulong_long_value;
        break;
      default:
        FMT_THROW(FormatError("width is not integer"));
      }
      unsigned max_int = (std::numeric_limits<int>::max)();
      if (value > max_int)
        FMT_THROW(FormatError("number is too big"));
      spec.width_ = static_cast<int>(value);
    }

    // Parse precision.
    if (*s == '.') {
      ++s;
      spec.precision_ = 0;
      if ('0' <= *s && *s <= '9') {
        spec.precision_ = internal::parse_nonnegative_int(s);
      } else if (*s == '{') {
        ++s;
        Arg precision_arg = internal::is_name_start(*s) ?
              parse_arg_name(s) : parse_arg_index(s);
        if (*s++ != '}')
          FMT_THROW(FormatError("invalid format string"));
        ULongLong value = 0;
        switch (precision_arg.type) {
          case Arg::INT:
            if (precision_arg.int_value < 0)
              FMT_THROW(FormatError("negative precision"));
            value = precision_arg.int_value;
            break;
          case Arg::UINT:
            value = precision_arg.uint_value;
            break;
          case Arg::LONG_LONG:
            if (precision_arg.long_long_value < 0)
              FMT_THROW(FormatError("negative precision"));
            value = precision_arg.long_long_value;
            break;
          case Arg::ULONG_LONG:
            value = precision_arg.ulong_long_value;
            break;
          default:
            FMT_THROW(FormatError("precision is not integer"));
        }
        unsigned max_int = (std::numeric_limits<int>::max)();
        if (value > max_int)
          FMT_THROW(FormatError("number is too big"));
        spec.precision_ = static_cast<int>(value);
      } else {
        FMT_THROW(FormatError("missing precision specifier"));
      }
      if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
        FMT_THROW(FormatError(
            fmt::format("precision not allowed in {} format specifier",
            arg.type == Arg::POINTER ? "pointer" : "integer")));
      }
    }

    // Parse type.
    if (*s != '}' && *s)
      spec.type_ = static_cast<char>(*s++);
  }

  if (*s++ != '}')
    FMT_THROW(FormatError("missing '}' in format string"));

  // Format argument.
  ArgFormatter(*this, spec, s - 1).visit(arg);
  return s;
}

Project: fmt
File: format.h

  explicit FormatInt(unsigned long value) : str_(format_decimal(value)) {}

Project: fmt
File: format.h

  void visit_cstring(const char *value) {
    if (spec_.type_ == 'p')
      return write_pointer(value);
    write(value);
  }

Project: fmt
File: format.h

  Result visit(const Arg &arg) {
    switch (arg.type) {
    case Arg::NONE:
    case Arg::NAMED_ARG:
      FMT_ASSERT(false, "invalid argument type");
      break;
    case Arg::INT:
      return FMT_DISPATCH(visit_int(arg.int_value));
    case Arg::UINT:
      return FMT_DISPATCH(visit_uint(arg.uint_value));
    case Arg::LONG_LONG:
      return FMT_DISPATCH(visit_long_long(arg.long_long_value));
    case Arg::ULONG_LONG:
      return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value));
    case Arg::BOOL:
      return FMT_DISPATCH(visit_bool(arg.int_value != 0));
    case Arg::CHAR:
      return FMT_DISPATCH(visit_char(arg.int_value));
    case Arg::DOUBLE:
      return FMT_DISPATCH(visit_double(arg.double_value));
    case Arg::LONG_DOUBLE:
      return FMT_DISPATCH(visit_long_double(arg.long_double_value));
    case Arg::CSTRING:
      return FMT_DISPATCH(visit_cstring(arg.string.value));
    case Arg::STRING:
      return FMT_DISPATCH(visit_string(arg.string));
    case Arg::WSTRING:
      return FMT_DISPATCH(visit_wstring(arg.wstring));
    case Arg::POINTER:
      return FMT_DISPATCH(visit_pointer(arg.pointer));
    case Arg::CUSTOM:
      return FMT_DISPATCH(visit_custom(arg.custom));
    }
    return Result();
  }

Project: fmt
File: format-test.cc

TEST(LiteralsTest, NamedArg) {
  auto udl_a = format("{first}{second}{first}{third}",
                      "first"_a="abra", "second"_a="cad", "third"_a=99);
  EXPECT_EQ(format("{first}{second}{first}{third}",
                   fmt::arg("first", "abra"), fmt::arg("second", "cad"),
                   fmt::arg("third", 99)),
            udl_a);
  auto udl_a_w = format(L"{first}{second}{first}{third}",
                        L"first"_a=L"abra", L"second"_a=L"cad", L"third"_a=99);
  EXPECT_EQ(format(L"{first}{second}{first}{third}",
                   fmt::arg(L"first", L"abra"), fmt::arg(L"second", L"cad"),
                   fmt::arg(L"third", 99)),
            udl_a_w);
}

Project: fmt
File: format.h

auto join(const Range& range, const BasicCStringRef<char>& sep)
    -> ArgJoin<char, decltype(std::begin(range))> {
  return join(std::begin(range), std::end(range), sep);
}

Project: fmt
File: format.h

  operator WStringRef() const { return WStringRef(&buffer_[0], size()); }

Project: fmt
File: format.h

  LConvCheck(int) {}

Project: fmt
File: format.h

inline unsigned count_digits(uint64_t n) {
  unsigned count = 1;
  for (;;) {
    // Integer division is slow so do it for a group of four digits instead
    // of for every digit. The idea comes from the talk by Alexandrescu
    // "Three Optimization Tips for C++". See speed-test for a comparison.
    if (n < 10) return count;
    if (n < 100) return count + 1;
    if (n < 1000) return count + 2;
    if (n < 10000) return count + 3;
    n /= 10000u;
    count += 4;
  }
}

Project: fmt
File: format.h

operator"" _format(const char *s, std::size_t) { return {s}; }

Project: fmt
File: format-test.cc

TEST(LiteralsTest, Format) {
  auto udl_format = "{}c{}"_format("ab", 1);
  EXPECT_EQ(format("{}c{}", "ab", 1), udl_format);
  auto udl_format_w = L"{}c{}"_format(L"ab", 1);
  EXPECT_EQ(format(L"{}c{}", L"ab", 1), udl_format_w);
}

Project: fmt
File: format-test.cc

TEST(FormatIntTest, FormatInt) {
  EXPECT_EQ("42", fmt::FormatInt(42).str());
  EXPECT_EQ(2u, fmt::FormatInt(42).size());
  EXPECT_EQ("-42", fmt::FormatInt(-42).str());
  EXPECT_EQ(3u, fmt::FormatInt(-42).size());
  EXPECT_EQ("42", fmt::FormatInt(42ul).str());
  EXPECT_EQ("-42", fmt::FormatInt(-42l).str());
  EXPECT_EQ("42", fmt::FormatInt(42ull).str());
  EXPECT_EQ("-42", fmt::FormatInt(-42ll).str());
  std::ostringstream os;
  os << std::numeric_limits<int64_t>::max();
  EXPECT_EQ(os.str(),
            fmt::FormatInt(std::numeric_limits<int64_t>::max()).str());
}

Project: fmt
File: format-test.cc

TEST(WriterTest, PadString) {
  EXPECT_EQ("test    ", (MemoryWriter() << pad("test", 8)).str());
  EXPECT_EQ("test******", (MemoryWriter() << pad("test", 10, '*')).str());
}

Project: fmt
File: format.h

inline StrFormatSpec<wchar_t> pad(
    const wchar_t *str, unsigned width, char fill = ' ') {
  return StrFormatSpec<wchar_t>(str, width, fill);
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, AutoArgIndex) {
  EXPECT_EQ("abc", format("{}{}{}", 'a', 'b', 'c'));
  EXPECT_THROW_MSG(format("{0}{}", 'a', 'b'),
      FormatError, "cannot switch from manual to automatic argument indexing");
  EXPECT_THROW_MSG(format("{}{0}", 'a', 'b'),
      FormatError, "cannot switch from automatic to manual argument indexing");
  EXPECT_EQ("1.2", format("{:.{}}", 1.2345, 2));
  EXPECT_THROW_MSG(format("{0}:.{}", 1.2345, 2),
      FormatError, "cannot switch from manual to automatic argument indexing");
  EXPECT_THROW_MSG(format("{:.{0}}", 1.2345, 2),
      FormatError, "cannot switch from automatic to manual argument indexing");
  EXPECT_THROW_MSG(format("{}"), FormatError, "argument index out of range");
}

Project: fmt
File: format-test.cc

TEST(FormatTest, Enum) {
  EXPECT_EQ("0", fmt::format("{}", A));
}

Project: fmt
File: format.h

  ArgJoin(It first, It last, const BasicCStringRef<Char>& sep) :
    first(first),
    last(last),
    sep(sep) {}

Project: fmt
File: format.h

      type(const T &) {
    return Arg::CUSTOM;
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, RuntimeWidth) {
  char format_str[BUFFER_SIZE];
  safe_sprintf(format_str, "{0:{%u", UINT_MAX);
  increment(format_str + 4);
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
  std::size_t size = std::strlen(format_str);
  format_str[size] = '}';
  format_str[size + 1] = 0;
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");
  format_str[size + 1] = '}';
  format_str[size + 2] = 0;
  EXPECT_THROW_MSG(format(format_str, 0), FormatError, "number is too big");

  EXPECT_THROW_MSG(format("{0:{", 0),
      FormatError, "invalid format string");
  EXPECT_THROW_MSG(format("{0:{}", 0),
      FormatError, "cannot switch from manual to automatic argument indexing");
  EXPECT_THROW_MSG(format("{0:{?}}", 0),
      FormatError, "invalid format string");
  EXPECT_THROW_MSG(format("{0:{1}}", 0),
      FormatError, "argument index out of range");

  EXPECT_THROW_MSG(format("{0:{0:}}", 0),
      FormatError, "invalid format string");

  EXPECT_THROW_MSG(format("{0:{1}}", 0, -1),
      FormatError, "negative width");
  EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1u)),
      FormatError, "number is too big");
  EXPECT_THROW_MSG(format("{0:{1}}", 0, -1l),
      FormatError, "negative width");
  if (fmt::internal::const_check(sizeof(long) > sizeof(int))) {
    long value = INT_MAX;
    EXPECT_THROW_MSG(format("{0:{1}}", 0, (value + 1)),
        FormatError, "number is too big");
  }
  EXPECT_THROW_MSG(format("{0:{1}}", 0, (INT_MAX + 1ul)),
      FormatError, "number is too big");

  EXPECT_THROW_MSG(format("{0:{1}}", 0, '0'),
      FormatError, "width is not integer");
  EXPECT_THROW_MSG(format("{0:{1}}", 0, 0.0),
      FormatError, "width is not integer");

  EXPECT_EQ(" -42", format("{0:{1}}", -42, 4));
  EXPECT_EQ("   42", format("{0:{1}}", 42u, 5));
  EXPECT_EQ("   -42", format("{0:{1}}", -42l, 6));
  EXPECT_EQ("     42", format("{0:{1}}", 42ul, 7));
  EXPECT_EQ("   -42", format("{0:{1}}", -42ll, 6));
  EXPECT_EQ("     42", format("{0:{1}}", 42ull, 7));
  EXPECT_EQ("   -1.23", format("{0:{1}}", -1.23, 8));
  EXPECT_EQ("    -1.23", format("{0:{1}}", -1.23l, 9));
  EXPECT_EQ("    0xcafe",
            format("{0:{1}}", reinterpret_cast<void*>(0xcafe), 10));
  EXPECT_EQ("x          ", format("{0:{1}}", 'x', 11));
  EXPECT_EQ("str         ", format("{0:{1}}", "str", 12));
}

Project: fmt
File: format-test.cc

void std_format(long double value, std::string &result) {
  char buffer[100];
  safe_sprintf(buffer, "%Lg", value);
  result = buffer;
}

Project: fmt
File: format.h

  MakeValue(const NamedArgWithType<Char_, T> &value) { pointer = &value; }

Project: fmt
File: format.h

  friend bool operator>(BasicStringRef lhs, BasicStringRef rhs) {
    return lhs.compare(rhs) > 0;
  }

Project: fmt
File: format.h

void BasicWriter<Char>::write_double(T value, const Spec &spec) {
  // Check type.
  char type = spec.type();
  bool upper = false;
  switch (type) {
  case 0:
    type = 'g';
    break;
  case 'e': case 'f': case 'g': case 'a':
    break;
  case 'F':
#if FMT_MSC_VER
    // MSVC's printf doesn't support 'F'.
    type = 'f';
#endif
    // Fall through.
  case 'E': case 'G': case 'A':
    upper = true;
    break;
  default:
    internal::report_unknown_type(type, "double");
    break;
  }

  char sign = 0;
  // Use isnegative instead of value < 0 because the latter is always
  // false for NaN.
  if (internal::FPUtil::isnegative(static_cast<double>(value))) {
    sign = '-';
    value = -value;
  } else if (spec.flag(SIGN_FLAG)) {
    sign = spec.flag(PLUS_FLAG) ? '+' : ' ';
  }

  if (internal::FPUtil::isnotanumber(value)) {
    // Format NaN ourselves because sprintf's output is not consistent
    // across platforms.
    std::size_t nan_size = 4;
    const char *nan = upper ? " NAN" : " nan";
    if (!sign) {
      --nan_size;
      ++nan;
    }
    CharPtr out = write_str(nan, nan_size, spec);
    if (sign)
      *out = sign;
    return;
  }

  if (internal::FPUtil::isinfinity(value)) {
    // Format infinity ourselves because sprintf's output is not consistent
    // across platforms.
    std::size_t inf_size = 4;
    const char *inf = upper ? " INF" : " inf";
    if (!sign) {
      --inf_size;
      ++inf;
    }
    CharPtr out = write_str(inf, inf_size, spec);
    if (sign)
      *out = sign;
    return;
  }

  std::size_t offset = buffer_.size();
  unsigned width = spec.width();
  if (sign) {
    buffer_.reserve(buffer_.size() + (width > 1u ? width : 1u));
    if (width > 0)
      --width;
    ++offset;
  }

  // Build format string.
  enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
  Char format[MAX_FORMAT_SIZE];
  Char *format_ptr = format;
  *format_ptr++ = '%';
  unsigned width_for_sprintf = width;
  if (spec.flag(HASH_FLAG))
    *format_ptr++ = '#';
  if (spec.align() == ALIGN_CENTER) {
    width_for_sprintf = 0;
  } else {
    if (spec.align() == ALIGN_LEFT)
      *format_ptr++ = '-';
    if (width != 0)
      *format_ptr++ = '*';
  }
  if (spec.precision() >= 0) {
    *format_ptr++ = '.';
    *format_ptr++ = '*';
  }

  append_float_length(format_ptr, value);
  *format_ptr++ = type;
  *format_ptr = '\0';

  // Format using snprintf.
  Char fill = internal::CharTraits<Char>::cast(spec.fill());
  unsigned n = 0;
  Char *start = FMT_NULL;
  for (;;) {
    std::size_t buffer_size = buffer_.capacity() - offset;
#if FMT_MSC_VER
    // MSVC's vsnprintf_s doesn't work with zero size, so reserve
    // space for at least one extra character to make the size non-zero.
    // Note that the buffer's capacity will increase by more than 1.
    if (buffer_size == 0) {
      buffer_.reserve(offset + 1);
      buffer_size = buffer_.capacity() - offset;
    }
#endif
    start = &buffer_[offset];
    int result = internal::CharTraits<Char>::format_float(
        start, buffer_size, format, width_for_sprintf, spec.precision(), value);
    if (result >= 0) {
      n = internal::to_unsigned(result);
      if (offset + n < buffer_.capacity())
        break;  // The buffer is large enough - continue with formatting.
      buffer_.reserve(offset + n + 1);
    } else {
      // If result is negative we ask to increase the capacity by at least 1,
      // but as std::vector, the buffer grows exponentially.
      buffer_.reserve(buffer_.capacity() + 1);
    }
  }
  if (sign) {
    if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
        *start != ' ') {
      *(start - 1) = sign;
      sign = 0;
    } else {
      *(start - 1) = fill;
    }
    ++n;
  }
  if (spec.align() == ALIGN_CENTER && spec.width() > n) {
    width = spec.width();
    CharPtr p = grow_buffer(width);
    std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(Char));
    fill_padding(p, spec.width(), n, fill);
    return;
  }
  if (spec.fill() != ' ' || sign) {
    while (*start == ' ')
      *start++ = fill;
    if (sign)
      *(start - 1) = sign;
  }
  grow_buffer(n);
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatShort) {
  short s = 42;
  EXPECT_EQ("42", format("{0:d}", s));
  unsigned short us = 42;
  EXPECT_EQ("42", format("{0:d}", us));
}

Project: fmt
File: format.h

  NamedArgWithType(BasicStringRef<Char> argname, const T &value)
  : NamedArg<Char>(argname, value) {}

Project: fmt
File: format.h

  ArgFormatterBase(BasicWriter<Char> &w, Spec &s)
  : writer_(w), spec_(s) {}

Project: fmt
File: format.h

  BasicArgFormatter(BasicFormatter<Char, Impl> &formatter,
                    Spec &spec, const Char *fmt)
  : internal::ArgFormatterBase<Impl, Char, Spec>(formatter.writer(), spec),
    formatter_(formatter), format_(fmt) {}

Project: fmt
File: format-test.cc

TEST(FormatTest, PrintColored) {
  EXPECT_WRITE(stdout, fmt::print_colored(fmt::RED, "Hello, {}!\n", "world"),
    "\x1b[31mHello, world!\n\x1b[0m");
}

Project: fmt
File: format.h

  unsigned width() const { return width_; }

Project: fmt
File: format-test.cc

TEST(WriterTest, Data) {
  MemoryWriter w;
  w << 42;
  EXPECT_EQ("42", std::string(w.data(), w.size()));
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, NamedArg) {
  EXPECT_EQ("1/a/A", format("{_1}/{a_}/{A_}", fmt::arg("a_", 'a'),
                            fmt::arg("A_", "A"), fmt::arg("_1", 1)));
  char a = 'A', b = 'B', c = 'C';
  EXPECT_EQ("BB/AA/CC", format("{1}{b}/{0}{a}/{2}{c}", FMT_CAPTURE(a, b, c)));
  EXPECT_EQ(" A", format("{a:>2}", FMT_CAPTURE(a)));
  EXPECT_THROW_MSG(format("{a+}", FMT_CAPTURE(a)), FormatError,
                   "missing '}' in format string");
  EXPECT_THROW_MSG(format("{a}"), FormatError, "argument not found");
  EXPECT_THROW_MSG(format("{d}", FMT_CAPTURE(a, b, c)), FormatError,
                   "argument not found");
  EXPECT_THROW_MSG(format("{a}{}", FMT_CAPTURE(a)),
    FormatError, "cannot switch from manual to automatic argument indexing");
  EXPECT_THROW_MSG(format("{}{a}", FMT_CAPTURE(a)),
    FormatError, "cannot switch from automatic to manual argument indexing");
  EXPECT_EQ(" -42", format("{0:{width}}", -42, fmt::arg("width", 4)));
  EXPECT_EQ("st", format("{0:.{precision}}", "str", fmt::arg("precision", 2)));
  int n = 100;
  EXPECT_EQ(L"n=100", format(L"n={n}", FMT_CAPTURE_W(n)));
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatBin) {
  EXPECT_EQ("0", format("{0:b}", 0));
  EXPECT_EQ("101010", format("{0:b}", 42));
  EXPECT_EQ("101010", format("{0:b}", 42u));
  EXPECT_EQ("-101010", format("{0:b}", -42));
  EXPECT_EQ("11000000111001", format("{0:b}", 12345));
  EXPECT_EQ("10010001101000101011001111000", format("{0:b}", 0x12345678));
  EXPECT_EQ("10010000101010111100110111101111", format("{0:b}", 0x90ABCDEF));
  EXPECT_EQ("11111111111111111111111111111111",
            format("{0:b}", std::numeric_limits<uint32_t>::max()));
}

Project: fmt
File: format.h

  static Char *get(Char *p) { return p; }

Project: fmt
File: format.h

inline uint32_t clz(uint32_t x) {
  unsigned long r = 0;
  _BitScanReverse(&r, x);

  assert(x != 0);
  // Static analysis complains about using uninitialized data
  // "r", but the only way that can happen is if "x" is 0,
  // which the callers guarantee to not happen.
# pragma warning(suppress: 6102)
  return 31 - r;
}

Project: fmt
File: format.h

  Result visit_long_long(LongLong value) {
    return FMT_DISPATCH(visit_any_int(value));
  }

Project: fmt
File: format.h

  void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
    if (start != end)
      w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
  }

Project: fmt
File: format.h

  StrFormatSpec(const Char *str, unsigned width, FillChar fill)
  : AlignSpec(width, fill), str_(str) {
    internal::CharTraits<Char>::convert(FillChar());
  }

Project: fmt
File: format.h

  void FormatSigned(LongLong value) {
    ULongLong abs_value = static_cast<ULongLong>(value);
    bool negative = value < 0;
    if (negative)
      abs_value = 0 - abs_value;
    str_ = format_decimal(abs_value);
    if (negative)
      *--str_ = '-';
  }

Project: fmt
File: format-test.cc

void print_error(const char *file, int line, const char *format,
                 const Args & ... args) {
  fmt::print("{}: {}: ", file, line);
  fmt::print(format, args...);
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, NoArgs) {
  EXPECT_EQ("test", format("test"));
}

Project: fmt
File: format.h

  static Arg make(const T &value) { return MakeArg<Formatter>(value); }

Project: fmt
File: format.h

  BasicWriter &operator<<(ULongLong value) {
    return *this << IntFormatSpec<ULongLong>(value);
  }

Project: fmt
File: format.h

  const internal::Arg *find(const fmt::BasicStringRef<Char> &name) const {
    // The list is unsorted, so just return the first matching name.
    for (typename MapType::const_iterator it = map_.begin(), end = map_.end();
         it != end; ++it) {
      if (it->first == name)
        return &it->second;
    }
    return FMT_NULL;
  }

Project: fmt
File: format.h

inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
  format_decimal(buffer, value, num_digits, NoThousandsSep());
  return;
}

Project: fmt
File: format-test.cc

TEST(WriterTest, WriteLongDouble) {
  CHECK_WRITE(4.2l);
  CHECK_WRITE_CHAR(-4.2l);
  std::wstring str;
  std_format(4.2l, str);
  if (str[0] != '-')
    CHECK_WRITE_WCHAR(-4.2l);
  else
    fmt::print("warning: long double formatting with std::swprintf is broken");
  CHECK_WRITE(std::numeric_limits<long double>::min());
  CHECK_WRITE(std::numeric_limits<long double>::max());
}

Project: fmt
File: format-test.cc

TEST(StringRefTest, Ctor) {
  EXPECT_STREQ("abc", StringRef("abc").data());
  EXPECT_EQ(3u, StringRef("abc").size());

  EXPECT_STREQ("defg", StringRef(std::string("defg")).data());
  EXPECT_EQ(4u, StringRef(std::string("defg")).size());

#if FMT_HAS_STRING_VIEW
  EXPECT_STREQ("hijk", StringRef(std::string_view("hijk")).data());
  EXPECT_EQ(4u, StringRef(std::string_view("hijk")).size());
#endif

#if FMT_HAS_EXPERIMENTAL_STRING_VIEW
  EXPECT_STREQ("hijk", StringRef(std::experimental::string_view("hijk")).data());
  EXPECT_EQ(4u, StringRef(std::experimental::string_view("hijk")).size());
#endif
}

Project: fmt
File: format.h

void ArgMap<Char>::init(const ArgList &args) {
  if (!map_.empty())
    return;
  typedef internal::NamedArg<Char> NamedArg;
  const NamedArg *named_arg = FMT_NULL;
  bool use_values =
      args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
  if (use_values) {
    for (unsigned i = 0;/*nothing*/; ++i) {
      internal::Arg::Type arg_type = args.type(i);
      switch (arg_type) {
      case internal::Arg::NONE:
        return;
      case internal::Arg::NAMED_ARG:
        named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
        map_.push_back(Pair(named_arg->name, *named_arg));
        break;
      default:
        /*nothing*/;
      }
    }
    return;
  }
  for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
    internal::Arg::Type arg_type = args.type(i);
    if (arg_type == internal::Arg::NAMED_ARG) {
      named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
      map_.push_back(Pair(named_arg->name, *named_arg));
    }
  }
  for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
    switch (args.args_[i].type) {
    case internal::Arg::NONE:
      return;
    case internal::Arg::NAMED_ARG:
      named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
      map_.push_back(Pair(named_arg->name, *named_arg));
      break;
    default:
      /*nothing*/;
    }
  }
}

Project: fmt
File: format-test.cc

std::string format_message(int id, const char *format,
    const fmt::ArgList &args) {
  MemoryWriter w;
  w.write("[{}] ", id);
  w.write(format, args);
  return w.str();
}

Project: fmt
File: format-test.cc

TEST(FormatTest, MaxArgs) {
  EXPECT_EQ("0123456789abcde",
            fmt::format("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
                        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e'));
}

Project: fmt
File: format.h

  void report_unhandled_arg() {}

Project: fmt
File: format.h

auto join(const Range& range, const BasicCStringRef<wchar_t>& sep)
    -> ArgJoin<wchar_t, decltype(std::begin(range))> {
  return join(std::begin(range), std::end(range), sep);
}

Project: fmt
File: format.h

  void visit_string(internal::Arg::StringValue<char> value) {
    writer_.write_str(value, spec_);
  }

Project: fmt
File: format-test.cc

TEST(FormatterTest, FormatString) {
  EXPECT_EQ("test", format("{0}", std::string("test")));
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, ManyArgs) {
  EXPECT_EQ("19", TestFormat<20>::format("{19}"));
  EXPECT_THROW_MSG(TestFormat<20>::format("{20}"),
                   FormatError, "argument index out of range");
  EXPECT_THROW_MSG(TestFormat<21>::format("{21}"),
                   FormatError, "argument index out of range");
  enum { MAX_PACKED_ARGS = fmt::ArgList::MAX_PACKED_ARGS };
  std::string format_str = fmt::format("{{{}}}", MAX_PACKED_ARGS + 1);
  EXPECT_THROW_MSG(TestFormat<MAX_PACKED_ARGS>::format(format_str),
                   FormatError, "argument index out of range");
}

Project: fmt
File: format.h

inline void require_numeric_argument(const Arg &arg, char spec) {
  if (arg.type > Arg::LAST_NUMERIC_TYPE) {
    std::string message =
        fmt::format("format specifier '{}' requires numeric argument", spec);
    FMT_THROW(fmt::FormatError(message));
  }
}

Project: fmt
File: format.h

  FormatError(const FormatError &ferr) : std::runtime_error(ferr) {}

Project: fmt
File: format.h

inline internal::NamedArgWithType<char, T> arg(StringRef name, const T &arg) {
  return internal::NamedArgWithType<char, T>(name, arg);
}

Project: fmt
File: format.h

  BasicWriter &operator<<(long value) {
    write_decimal(value);
    return *this;
  }

Project: fmt
File: format.h

  UTF16ToUTF8() {}

Project: fmt
File: format-test.cc

TEST(WriterTest, NotCopyAssignable) {
  EXPECT_FALSE(std::is_copy_assignable<BasicWriter<char> >::value);
}

Project: fmt
File: format.h

  const T &operator[](std::size_t index) const { return ptr_[index]; }

Project: fmt
File: format.h

  void deallocate() {
    if (this->ptr_ != data_) Allocator::deallocate(this->ptr_, this->capacity_);
  }

Project: fmt
File: format.h

inline internal::Arg BasicFormatter<Char, AF>::parse_arg_name(const Char *&s) {
  assert(internal::is_name_start(*s));
  const Char *start = s;
  Char c;
  do {
    c = *++s;
  } while (internal::is_name_start(c) || ('0' <= c && c <= '9'));
  const char *error = FMT_NULL;
  internal::Arg arg = get_arg(BasicStringRef<Char>(start, s - start), error);
  if (error)
    FMT_THROW(FormatError(error));
  return arg;
}

Project: fmt
File: format.h

void format_arg(fmt::BasicFormatter<Char, ArgFormatter> &f,
    const Char *&format_str, const ArgJoin<Char, It>& e) {
  const Char* end = format_str;
  int brace_level = 1;
  while (*end) {
    if (*end == '}' && --brace_level == 0)
      break;
    if (*end == '{')
      ++brace_level;
    ++end;
  }
  if (*end != '}')
    FMT_THROW(FormatError("missing '}' in format string"));

  It it = e.first;
  if (it != e.last) {
    const Char* save = format_str;
    f.format(format_str, internal::MakeArg<fmt::BasicFormatter<Char, ArgFormatter> >(*it++));
    while (it != e.last) {
      f.writer().write(e.sep);
      format_str = save;
      f.format(format_str, internal::MakeArg<fmt::BasicFormatter<Char, ArgFormatter> >(*it++));
    }
  }
  format_str = end + 1;
}

Project: fmt
File: format-test.cc

lconv *localeconv() {
  return LocaleMock::instance ?
        LocaleMock::instance->localeconv() : ::std::localeconv();
}

Project: fmt
File: format-test.cc

TEST(FormatterTest, HashFlag) {
  EXPECT_EQ("42", format("{0:#}", 42));
  EXPECT_EQ("-42", format("{0:#}", -42));
  EXPECT_EQ("0b101010", format("{0:#b}", 42));
  EXPECT_EQ("0B101010", format("{0:#B}", 42));
  EXPECT_EQ("-0b101010", format("{0:#b}", -42));
  EXPECT_EQ("0x42", format("{0:#x}", 0x42));
  EXPECT_EQ("0X42", format("{0:#X}", 0x42));
  EXPECT_EQ("-0x42", format("{0:#x}", -0x42));
  EXPECT_EQ("042", format("{0:#o}", 042));
  EXPECT_EQ("-042", format("{0:#o}", -042));
  EXPECT_EQ("42", format("{0:#}", 42u));
  EXPECT_EQ("0x42", format("{0:#x}", 0x42u));
  EXPECT_EQ("042", format("{0:#o}", 042u));

  EXPECT_EQ("-42", format("{0:#}", -42l));
  EXPECT_EQ("0x42", format("{0:#x}", 0x42l));
  EXPECT_EQ("-0x42", format("{0:#x}", -0x42l));
  EXPECT_EQ("042", format("{0:#o}", 042l));
  EXPECT_EQ("-042", format("{0:#o}", -042l));
  EXPECT_EQ("42", format("{0:#}", 42ul));
  EXPECT_EQ("0x42", format("{0:#x}", 0x42ul));
  EXPECT_EQ("042", format("{0:#o}", 042ul));

  EXPECT_EQ("-42", format("{0:#}", -42ll));
  EXPECT_EQ("0x42", format("{0:#x}", 0x42ll));
  EXPECT_EQ("-0x42", format("{0:#x}", -0x42ll));
  EXPECT_EQ("042", format("{0:#o}", 042ll));
  EXPECT_EQ("-042", format("{0:#o}", -042ll));
  EXPECT_EQ("42", format("{0:#}", 42ull));
  EXPECT_EQ("0x42", format("{0:#x}", 0x42ull));
  EXPECT_EQ("042", format("{0:#o}", 042ull));

  EXPECT_EQ("-42.0000", format("{0:#}", -42.0));
  EXPECT_EQ("-42.0000", format("{0:#}", -42.0l));
  EXPECT_THROW_MSG(format("{0:#", 'c'),
      FormatError, "missing '}' in format string");
  EXPECT_THROW_MSG(format("{0:#}", 'c'),
      FormatError, "invalid format specifier for char");
  EXPECT_THROW_MSG(format("{0:#}", "abc"),
      FormatError, "format specifier '#' requires numeric argument");
  EXPECT_THROW_MSG(format("{0:#}", reinterpret_cast<void*>(0x42)),
      FormatError, "format specifier '#' requires numeric argument");
}

Project: fmt
File: format.h

  BasicWriter<Char>::prepare_int_buffer(
    unsigned num_digits, const Spec &spec,
    const char *prefix, unsigned prefix_size) {
  unsigned width = spec.width();
  Alignment align = spec.align();
  Char fill = internal::CharTraits<Char>::cast(spec.fill());
  if (spec.precision() > static_cast<int>(num_digits)) {
    // Octal prefix '0' is counted as a digit, so ignore it if precision
    // is specified.
    if (prefix_size > 0 && prefix[prefix_size - 1] == '0')
      --prefix_size;
    unsigned number_size =
        prefix_size + internal::to_unsigned(spec.precision());
    AlignSpec subspec(number_size, '0', ALIGN_NUMERIC);
    if (number_size >= width)
      return prepare_int_buffer(num_digits, subspec, prefix, prefix_size);
    buffer_.reserve(width);
    unsigned fill_size = width - number_size;
    if (align != ALIGN_LEFT) {
      CharPtr p = grow_buffer(fill_size);
      std::uninitialized_fill(p, p + fill_size, fill);
    }
    std::ptrdiff_t offset = get(prepare_int_buffer(
        num_digits, subspec, prefix, prefix_size)) - &buffer_[0];
    if (align == ALIGN_LEFT) {
      CharPtr p = grow_buffer(fill_size);
      std::uninitialized_fill(p, p + fill_size, fill);
    }
    return internal::make_ptr(&buffer_[0], buffer_.size()) + offset;
  }
  unsigned size = prefix_size + num_digits;
  if (width <= size) {
    CharPtr p = grow_buffer(size);
    std::uninitialized_copy(prefix, prefix + prefix_size, p);
    return p + size - 1;
  }
  CharPtr p = grow_buffer(width);
  CharPtr end = p + width;
  if (align == ALIGN_LEFT) {
    std::uninitialized_copy(prefix, prefix + prefix_size, p);
    p += size;
    std::uninitialized_fill(p, end, fill);
  } else if (align == ALIGN_CENTER) {
    p = fill_padding(p, width, size, fill);
    std::uninitialized_copy(prefix, prefix + prefix_size, p);
    p += size;
  } else {
    if (align == ALIGN_NUMERIC) {
      if (prefix_size != 0) {
        p = std::uninitialized_copy(prefix, prefix + prefix_size, p);
        size -= prefix_size;
      }
    } else {
      std::uninitialized_copy(prefix, prefix + prefix_size, end - size);
    }
    std::uninitialized_fill(p, end - size, fill);
    p = end;
  }
  return p - 1;
}

Project: fmt
File: format.h

  Result visit_char(int value) {
    return FMT_DISPATCH(visit_any_int(value));
  }

Project: fmt
File: format.h

  void append_float_length(Char *&, T) {}

Project: fmt
File: format.h

  Result visit_cstring(const char *) {
    return FMT_DISPATCH(visit_unhandled_arg());
  }

Project: fmt
File: format.h

  Spec &spec() { return spec_; }

Project: fmt
File: format.h

  explicit operator std::basic_string_view<Char>() const FMT_NOEXCEPT {
    return std::basic_string_view<Char>(data_, size_);
  }

Project: fmt
File: format-test.cc

  ISO8601DateFormatter(const Date &d) : date_(&d) {}