changa  3.5
 All Classes Files Functions Variables Typedefs Enumerations Friends Macros Groups Pages
formatted_string.h
1 #pragma once
2 
3 #include <algorithm>
4 #include <array>
5 #include <cstdio>
6 #include <string>
7 #include <vector>
8 
36 template <typename... Args> class formatted_string {
37 public:
39  static constexpr auto max_len = 32;
40 
41 private:
42  /*
43  * The storage for the formatted string
44  * A union is used to save space.
45  */
46  union arena {
47  std::array<char, max_len> array;
48  std::vector<char> vector;
49  arena() {}
50  ~arena() {}
51  };
52  arena storage;
53 
55  int len = 0;
56 
57  bool is_short() const noexcept { return len < max_len; }
58 
59 public:
69  explicit formatted_string(char const *format, Args... args) {
70  static_assert(sizeof...(args) > 0, "Must specify at least one argument");
71 
72  len = std::snprintf(nullptr, 0, format, args...);
73  char *const buffer = [&]() {
74  if (is_short()) {
75  new (&storage.array) decltype(storage.array)();
76  return storage.array.data();
77  } else {
78  new (&storage.vector) decltype(storage.vector)(
79  static_cast<size_t>(len) + 1);
80  return storage.vector.data();
81  }
82  }();
83  std::snprintf(buffer, static_cast<size_t>(len + 1), format, args...);
84  }
85 
87  template <typename... Ts>
89  this->len = rhs.len;
90  if (is_short()) {
91  new (&this->storage.array) decltype(this->storage.array)();
92  std::copy(rhs.storage.array.begin(), rhs.storage.array.end(),
93  this->storage.array.begin());
94  } else {
95  new (&this->storage.vector) decltype(storage.vector)(
96  std::move(rhs.storage.vector));
97  }
98  }
99 
101  template <typename... Ts>
103  new (this) formatted_string<Ts...>(std::move(rhs));
104  return *this;
105  }
106 
110  formatted_string(formatted_string const &) = delete;
111  formatted_string &operator=(formatted_string const &) = delete;
112 
117  char const *c_str() const noexcept {
118  return (is_short()) ? storage.array.data() : storage.vector.data();
119  }
120 
125  std::string to_string() const { return c_str(); }
126 
132  if (!is_short()) {
133  storage.vector.~vector();
134  }
135  }
136 };
137 
153 template <typename... Args>
154 formatted_string<Args...> make_formatted_string(char const *format,
155  Args... args) {
156  return formatted_string<Args...>(format, args...);
157 }
158 
168 inline formatted_string<uint64_t, uint64_t> make_formatted_string(CmiUInt16 ui) {
169  const auto lq = static_cast<uint64_t>(ui); // lower quad word
170  const auto uq = static_cast<uint64_t>(ui>>64UL); // upper quad word
171  return formatted_string<uint64_t, uint64_t>{"%016lx%016lx", uq, lq};
172 }
173 
182 inline formatted_string<uint64_t> make_formatted_string(CmiUInt8 ui) {
183  return formatted_string<uint64_t>{"%016lx", static_cast<uint64_t>(ui)};
184 }
~formatted_string()
Definition: formatted_string.h:131
formatted_string & operator=(formatted_string< Ts...> &&rhs) noexcept
Move assignment operator.
Definition: formatted_string.h:102
formatted_string(formatted_string< Ts...> &&rhs) noexcept
Move constructor.
Definition: formatted_string.h:88
static constexpr auto max_len
Maximum length of the formatted string before heap allocation is used.
Definition: formatted_string.h:39
formatted_string(char const *format, Args...args)
Definition: formatted_string.h:69
std::string to_string() const
Definition: formatted_string.h:125
A simple formatted string to replace s[n]printf usage.
Definition: formatted_string.h:36
char const * c_str() const noexcept
Definition: formatted_string.h:117