12 #define FMT_CONST(FMT) \
13 static constexpr auto fmt = FMT; \
14 static constexpr auto fmt_full = "%" FMT;
16 template <
class T,
class U =
void>
20 struct FmtStr<int8_t> {
FMT_CONST(
"c"); };
23 struct FmtStr<int16_t> {
FMT_CONST(PRId16); };
26 struct FmtStr<int32_t> {
FMT_CONST(PRId32); };
29 struct FmtStr<int64_t> {
FMT_CONST(PRId64); };
32 struct FmtStr<uint8_t> {
FMT_CONST(
"c"); };
35 struct FmtStr<uint16_t> {
FMT_CONST(PRIu16); };
38 struct FmtStr<uint32_t> {
FMT_CONST(PRIu32); };
41 struct FmtStr<uint64_t> {
FMT_CONST(PRIu64); };
47 struct FmtStr<double> {
FMT_CONST(
"f"); };
50 struct FmtStr<long double> {
FMT_CONST(
"Lf"); };
53 struct FmtStr<T, typename std::enable_if<std::is_pointer<T>::value>::type> {
58 class DefaultSprintfFormatter :
public Formatable {
62 DefaultSprintfFormatter(T val)
67 constexpr
const int SIZE = 64;
69 snprintf(buffer, SIZE, FmtStr<T>::fmt_full, _val);
70 for (
char* c = buffer; *c !=
'\0'; c++)
76 struct SprintfFormatter :
public Formatable {
77 SprintfFormatter(T val)
80 , _reserveSpaceForSign(false)
82 , _leadingZeroes(false)
90 void format(It it)
const {
98 if (_reserveSpaceForSign)
105 pos += sprintf(pos,
"%d", _width);
107 pos += sprintf(pos,
".%d", _precision);
108 strcpy(pos, FmtStr<T>::fmt);
109 pos += strlen(FmtStr<T>::fmt);
110 if (_replacement !=
'\0')
111 *(pos - 1) = _replacement;
113 *(pos - 1) = toupper(*(pos - 1));
116 constexpr
const int SIZE = 64;
118 snprintf(buffer, SIZE, fmt, _val);
119 for (
char* c = buffer; *c !=
'\0'; c++)
126 bool _reserveSpaceForSign;
138 template <
typename T,
typename Enable =
void>
139 struct NumberSprintfFormatter;
141 template <
typename T>
142 struct NumberSprintfFormatter<T,
143 typename std::enable_if<std::is_integral<T>::value>::type>
144 :
public SprintfFormatter<T> {
145 NumberSprintfFormatter(T t)
146 : SprintfFormatter<T>(t) {}
148 NumberSprintfFormatter& alignLeft() {
149 SprintfFormatter<T>::_alignLeft =
true;
153 NumberSprintfFormatter& alignRight() {
154 SprintfFormatter<T>::_alignLeft =
false;
158 NumberSprintfFormatter& forceSign() {
159 SprintfFormatter<T>::_forceSign =
true;
163 NumberSprintfFormatter& spaceForSign() {
164 SprintfFormatter<T>::_reserveSpaceForSign =
true;
168 NumberSprintfFormatter& basePrefix() {
169 SprintfFormatter<T>::_showPrefix =
true;
173 NumberSprintfFormatter& leadingZeroes() {
174 SprintfFormatter<T>::_leadingZeroes =
true;
178 NumberSprintfFormatter& upperCase() {
179 SprintfFormatter<T>::_upperCase =
true;
183 NumberSprintfFormatter& precision(
unsigned prec) {
184 SprintfFormatter<T>::_precision =
static_cast<int>(prec);
188 NumberSprintfFormatter& width(
unsigned width) {
189 SprintfFormatter<T>::_width =
static_cast<int>(width);
193 NumberSprintfFormatter& hex() {
194 SprintfFormatter<T>::_replacement =
'x';
198 NumberSprintfFormatter& octal() {
199 SprintfFormatter<T>::_replacement =
'o';
204 template <
typename T>
205 struct NumberSprintfFormatter<T,
206 typename std::enable_if<std::is_floating_point<T>::value>::type>
207 :
public SprintfFormatter<T> {
208 NumberSprintfFormatter(T t)
209 : SprintfFormatter<T>(t) {}
211 NumberSprintfFormatter& alignLeft() {
212 SprintfFormatter<T>::_alignLeft =
true;
216 NumberSprintfFormatter& alignRight() {
217 SprintfFormatter<T>::_alignLeft =
false;
221 NumberSprintfFormatter& forceSign() {
222 SprintfFormatter<T>::_forceSign =
true;
226 NumberSprintfFormatter& spaceForSign() {
227 SprintfFormatter<T>::_reserveSpaceForSign =
true;
231 NumberSprintfFormatter& basePrefix() {
232 SprintfFormatter<T>::_showPrefix =
true;
236 NumberSprintfFormatter& leadingZeroes() {
237 SprintfFormatter<T>::_leadingZeroes =
true;
241 NumberSprintfFormatter& upperCase() {
242 SprintfFormatter<T>::_upperCase =
true;
246 NumberSprintfFormatter& precision(
unsigned prec) {
247 SprintfFormatter<T>::_precision =
static_cast<int>(prec);
251 NumberSprintfFormatter& width(
unsigned width) {
252 SprintfFormatter<T>::_width =
static_cast<int>(width);
256 NumberSprintfFormatter& hex() {
257 SprintfFormatter<T>::_replacement =
'a';
261 NumberSprintfFormatter& decimal() {
262 SprintfFormatter<T>::_replacement =
'f';
266 NumberSprintfFormatter& scientific() {
267 SprintfFormatter<T>::_replacement =
'e';
271 NumberSprintfFormatter& shortest() {
272 SprintfFormatter<T>::_replacement =
'g';
277 template <
typename String>
278 struct StringFormatter :
public Formatable {
279 StringFormatter(
const char* msg)
285 StringFormatter(
const String& s)
293 template <
typename It>
294 void format(It it)
const {
296 format(_msg, strlen(_msg), it);
298 format(_str.begin(), _str.size(), it);
301 StringFormatter& width(
unsigned width) {
302 _width =
static_cast<int>(width);
306 StringFormatter& alignLeft() {
311 StringFormatter& alignRight() {
316 StringFormatter& center() {
321 StringFormatter& clip() {
327 template <
typename Elem,
typename It>
328 void format(Elem msg,
int len, It it)
const {
330 std::copy_n(msg, len, it);
332 int spaces = _width - len;
334 std::copy_n(msg, _clip ? _width : len, it);
335 }
else if (_center) {
336 int oddity = spaces % 2;
337 std::fill_n(it, spaces / 2 + (_alignLeft ? 0 : oddity),
' ');
338 std::copy_n(msg, len, it);
339 std::fill_n(it, spaces / 2 + (_alignLeft ? oddity : 0),
' ');
340 }
else if (_alignLeft) {
341 std::copy_n(msg, len, it);
342 std::fill_n(it, spaces,
' ');
344 std::fill_n(it, spaces,
' ');
345 std::copy_n(msg, len, it);