brintos

brintos / llvm-project-archived public Read only

0
0
Text · 1.9 KiB · 230f2e4 Raw
72 lines · c
1#ifndef TEST_SUPPORT_FORMAT_STRING_H2#define TEST_SUPPORT_FORMAT_STRING_H3 4#include <cstdio>5#include <string>6#include <memory>7#include <array>8#include <cstdarg>9 10namespace format_string_detail {11inline std::string format_string_imp(const char* msg, ...) {12  // we might need a second shot at this, so pre-emptively make a copy13  struct GuardVAList {14    va_list& xtarget;15    bool active;16    GuardVAList(va_list& val) : xtarget(val), active(true) {}17 18    void clear() {19      if (active)20        va_end(xtarget);21      active = false;22    }23    ~GuardVAList() {24      if (active)25        va_end(xtarget);26    }27  };28  va_list args;29  va_start(args, msg);30  GuardVAList args_guard(args);31 32  va_list args_cp;33  va_copy(args_cp, args);34  GuardVAList args_copy_guard(args_cp);35 36  std::array<char, 256> local_buff;37  std::size_t size = local_buff.size();38  auto ret = ::vsnprintf(local_buff.data(), size, msg, args_cp);39 40  args_copy_guard.clear();41 42  // handle empty expansion43  if (ret == 0)44    return std::string{};45  if (static_cast<std::size_t>(ret) < size)46    return std::string(local_buff.data());47 48  // we did not provide a long enough buffer on our first attempt.49  // add 1 to size to account for null-byte in size cast to prevent overflow50  size = static_cast<std::size_t>(ret) + 1;51  auto buff_ptr = std::unique_ptr<char[]>(new char[size]);52  ret = ::vsnprintf(buff_ptr.get(), size, msg, args);53  return std::string(buff_ptr.get());54}55 56const char* unwrap(std::string& s) { return s.c_str(); }57template <class Arg>58Arg const& unwrap(Arg& a) {59  static_assert(!std::is_class<Arg>::value, "cannot pass class here");60  return a;61}62 63} // namespace format_string_detail64 65template <class... Args>66std::string format_string(const char* fmt, Args const&... args) {67  return format_string_detail::format_string_imp(68      fmt, format_string_detail::unwrap(const_cast<Args&>(args))...);69}70 71#endif // TEST_SUPPORT_FORMAT_STRING_HPP72