changa 3.5
Loading...
Searching...
No Matches
formatted_string.h
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <cstdio>
6#include <string>
7#include <vector>
8
36template <typename... Args> class formatted_string {
37public:
39 static constexpr auto max_len = 32;
40
41private:
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
59public:
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
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
153template <typename... Args>
154formatted_string<Args...> make_formatted_string(char const *format,
155 Args... args) {
156 return formatted_string<Args...>(format, args...);
157}
158
168inline 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
182inline formatted_string<uint64_t> make_formatted_string(CmiUInt8 ui) {
183 return formatted_string<uint64_t>{"%016lx", static_cast<uint64_t>(ui)};
184}
A simple formatted string to replace s[n]printf usage.
Definition formatted_string.h:36
std::string to_string() const
Definition formatted_string.h:125
formatted_string(formatted_string const &)=delete
formatted_string(formatted_string< Ts... > &&rhs) noexcept
Move constructor.
Definition formatted_string.h:88
formatted_string & operator=(formatted_string< Ts... > &&rhs) noexcept
Move assignment operator.
Definition formatted_string.h:102
char const * c_str() const noexcept
Definition formatted_string.h:117
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
~formatted_string()
Definition formatted_string.h:131
STL class.