-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathformatspecifier.hpp
More file actions
209 lines (181 loc) · 5.29 KB
/
formatspecifier.hpp
File metadata and controls
209 lines (181 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#ifndef _FORMATSPECIFIER_HPP_
#define _FORMATSPECIFIER_HPP_
#ifdef __STDC_HOSTED__
#include <stdint.h>
#include <stddef.h>
#include <utility>
#endif
#include <iostream>
#include "utfstringview.hpp"
#include "constants.hpp"
#include "result.hpp"
namespace hls
{
class FormatSpecifier
{
public:
enum FormatType : uint8_t
{
LITERAL, // For when what we get is a literal character instead of a format specifier
SPECIFIER // For when we get a format specifier
};
private:
FormatType m_format;
bool m_has_argid = false;
size_t m_argid;
bool m_has_align = false;
char32_t m_align = '<';
bool m_has_fill = false;
char32_t m_fill;
bool m_has_sign = true;
char32_t m_sign = NEG_SIGN;
char32_t m_integer_type;
public:
static constexpr size_t INVALID_ARGID = size_t(0) - 1;
// A format specifier is considered a literal until set otherwise
FormatSpecifier() : m_format(FormatType::LITERAL), m_argid(INVALID_ARGID) {};
void set_format_type(FormatType type)
{
m_format = type;
}
FormatType get_format_type() const
{
return m_format;
}
void set_argid(size_t id)
{
m_argid = id;
m_has_argid = true;
m_format = FormatType::SPECIFIER;
}
bool has_argid() const
{
return m_has_argid;
}
size_t get_argid() const
{
return m_argid;
}
void set_align(char align)
{
if (align == '<' || align == '>' || align == '^')
{
m_has_align = true;
m_align = align;
}
}
char32_t get_align() const
{
return m_align;
}
void set_fill(char32_t codepoint)
{
if (codepoint != OP_FORMAT_CH || codepoint != CL_FORMAT_CH)
{
m_fill = codepoint;
m_has_fill = true;
}
}
bool has_fill() const
{
return m_has_fill;
}
char32_t get_fill() const
{
return m_fill;
}
void set_sign(char32_t codepoint)
{
if (codepoint == '+' || codepoint == '-' || codepoint == ' ')
{
m_has_sign = true;
m_sign = codepoint;
}
}
bool has_sign() const
{
return m_has_sign;
}
char32_t get_sign() const
{
return m_sign;
}
void set_integer_display_type(char32_t codepoint)
{
m_integer_type = codepoint;
switch (codepoint)
{
case OCT_FORMAT:
set_sign(' ');
break;
case DEC_FORMAT:
set_sign('-');
break;
case HEX_FORMAT:
set_sign(' ');
break;
}
}
char32_t get_integer_display_type() const
{
return m_integer_type;
}
};
template <typename CharType>
Result<size_t> parse_specifier(const UTFStringView<CharType> &str, FormatSpecifier &fs)
{
for (auto it = str.begin(); it != str.end(); ++it)
{
auto codepoint = *it;
switch (codepoint)
{
case OCT_FORMAT:
case DEC_FORMAT:
case HEX_FORMAT:
fs.set_integer_display_type(codepoint);
break;
default:
return error<size_t>(Error::INVALID_ARGUMENT);
}
break;
}
return value(size_t(1));
}
template <typename CharType>
Result<size_t> parse_fs(const UTFStringView<CharType> &str, FormatSpecifier &fs)
{
if (*str.begin() == OP_FORMAT_CH || *str.begin() == CL_FORMAT_CH)
{
for (auto it = str.begin() + 1; it != str.end(); ++it)
{
auto codepoint = *it;
if (isdigit(*it))
{
auto argid_result = parse_argid(it.from_it(), fs);
it += argid_result.get_value();
}
else if (codepoint == ':')
{
// We want to parse from the next character, not from : itself
auto fsparse_result = parse_specifier((it + 1).from_it(), fs);
if (fsparse_result.is_error())
return fsparse_result;
it += fsparse_result.get_value();
}
else if (codepoint == *str.begin() || codepoint == CL_FORMAT_CH)
{
if (*str.begin() == OP_FORMAT_CH && codepoint == CL_FORMAT_CH)
fs.set_format_type(FormatSpecifier::FormatType::SPECIFIER);
// We have a literal character
return value(it - str.begin());
}
else
{
break;
}
}
}
return error<size_t>(Error::INVALID_ARGUMENT);
}
} // namespace hls
#endif