parse_fmt_string now returning struct containing actual format parameters

This commit is contained in:
Andreas Tsouchlos 2021-11-19 00:17:28 +01:00
parent f1952186e0
commit 7226241097
2 changed files with 59 additions and 30 deletions

View File

@ -15,15 +15,22 @@ namespace detail {
*/ */
enum class FormatType { s, c, b, B, d, o, x, X, a, A, e, E, f, F, g, G, p };
template <typename result_t> template <typename result_t>
struct parse_result { struct parse_result_t {
bool valid = false; bool is_valid = false;
unsigned new_index = 0; unsigned new_index = 0;
unsigned length = 0; unsigned length = 0;
result_t result; result_t result;
}; };
enum class FormatType { s, c, b, B, d, o, x, X, a, A, e, E, f, F, g, G, p }; struct fmt_string_result_t {
bool has_zero_padding = false;
int length = 6;
int precision = 2;
FormatType type = FormatType::s;
};
// clang-format off // clang-format off
@ -73,7 +80,7 @@ constexpr bool is_digit(ConstString<N> s, unsigned i) {
template <std::size_t N> template <std::size_t N>
constexpr parse_result<int> parse_number(ConstString<N> s, unsigned i) { constexpr parse_result_t<int> parse_number(ConstString<N> s, unsigned i) {
int number = 0; int number = 0;
while ((i < s.size()) && is_digit(s, i)) { while ((i < s.size()) && is_digit(s, i)) {
@ -86,7 +93,7 @@ constexpr parse_result<int> parse_number(ConstString<N> s, unsigned i) {
} }
template <std::size_t N> template <std::size_t N>
constexpr parse_result<FormatType> parse_type(ConstString<N> s, unsigned i) { constexpr parse_result_t<FormatType> parse_type(ConstString<N> s, unsigned i) {
if (s[i] == 's') { // string if (s[i] == 's') { // string
++i; ++i;
return {true, i, 1, FormatType::s}; return {true, i, 1, FormatType::s};
@ -99,9 +106,9 @@ constexpr parse_result<FormatType> parse_type(ConstString<N> s, unsigned i) {
} else if (s[i] == 'B') { } else if (s[i] == 'B') {
++i; ++i;
return {true, i, 1, FormatType::B}; return {true, i, 1, FormatType::B};
// } else if (s[i] == 'c') { // } else if (s[i] == 'c') {
// ++i; // ++i;
// return {true, i, 1, FormatType::c}; // return {true, i, 1, FormatType::c};
} else if (s[i] == 'd') { } else if (s[i] == 'd') {
++i; ++i;
return {true, i, 1, FormatType::d}; return {true, i, 1, FormatType::d};
@ -143,40 +150,48 @@ constexpr parse_result<FormatType> parse_type(ConstString<N> s, unsigned i) {
return {true, i, 1, FormatType::p}; return {true, i, 1, FormatType::p};
} }
return {false, i, 0, FormatType::a}; return {false, i, 0, FormatType::s};
} }
template <std::size_t N> template <std::size_t N>
constexpr std::pair<unsigned, int> parse_fmt_string(ConstString<N> s, constexpr parse_result_t<fmt_string_result_t> parse_fmt_string(ConstString<N> s,
unsigned i) { unsigned i) {
int result_extra_len = 0;
if (s[i] == '0') fmt_string_result_t result;
unsigned result_extra_len = 0;
if (s[i] == '0') {
++i; ++i;
result.has_zero_padding = true;
}
if (is_digit(s, i)) { if (is_digit(s, i)) {
auto [is_valid, new_i, len, number] = parse_number(s, i); auto [is_valid, new_i, len, number] = parse_number(s, i);
if (!is_valid) return {i, -1}; if (!is_valid)
return {false, i, 0, result};
i = new_i; i = new_i;
result_extra_len += number; result.length = number;
} }
if (s[i] == '.') { if (s[i] == '.') {
++i; ++i;
auto [is_valid, new_i, len, number] = parse_number(s, i); auto [is_valid, new_i, len, number] = parse_number(s, i);
if (!is_valid) return {i, -1}; if (!is_valid)
return {false, i, 0, result};
i = new_i; i = new_i;
result_extra_len += len; result.precision = number;
} }
if (s[i] != '}') { if (s[i] != '}') {
auto [is_valid, new_i, len, type] = parse_type(s, i); auto [is_valid, new_i, len, type] = parse_type(s, i);
if (is_valid) return {i, -1}; if (!is_valid)
return {false, i, 0, result};
i = new_i; i = new_i;
// result_extra_len += len; result.type = type;
} }
return {i, result_extra_len}; return {true, i, result_extra_len, result};
} }
template <std::size_t N> template <std::size_t N>
@ -189,10 +204,11 @@ constexpr std::pair<unsigned, int> parse_braces(ConstString<N> s, unsigned i) {
} else if (s[i] == ':') { } else if (s[i] == ':') {
++i; ++i;
auto [new_i, extra_len] = parse_fmt_string(s, i); auto [is_valid, new_i, len, format_node] = parse_fmt_string(s, i);
if (extra_len < 0) return {i, -1}; if (!is_valid)
return {i, -1};
i = new_i; i = new_i;
result_extra_len += extra_len; result_extra_len += len;
if (s[i] == '}') { if (s[i] == '}') {
++i; ++i;
@ -212,7 +228,8 @@ constexpr int get_output_len(ConstString<N> s) {
++i; ++i;
auto [new_i, extra_len] = parse_braces(s, i); auto [new_i, extra_len] = parse_braces(s, i);
if (extra_len < 0) return -1; if (extra_len < 0)
return -1;
i = new_i; i = new_i;
result_extra_len += extra_len; result_extra_len += extra_len;

View File

@ -13,10 +13,22 @@ private:
int main() { int main() {
Uart uart; //Uart uart;
// Logger logger(uart);
// logger.log<"Test:{:8.2}">(1, 2, 3);
constexpr detail::ConstString s = "{:8.14c}";
constexpr auto result = detail::parse_fmt_string(s, 2);
std::cout << "Is valid: " << result.is_valid << std::endl << std::endl;
std::cout << "\tresult.has_zero_padding: " << result.result.has_zero_padding << std::endl;
std::cout << "\tresult.length: " << result.result.length << std::endl;
std::cout << "\tresult.precision: " << result.result.precision << std::endl;
std::cout << "\tresult.type: " << static_cast<int>(result.result.type) << std::endl;
Logger logger(uart);
logger.log<"Test:{:88}">(1, 2, 3);
return 0; return 0;
} }