format_arg(float) now works with the desired precision

This commit is contained in:
Andreas Tsouchlos 2021-11-21 19:42:56 +01:00
parent ce2006694e
commit f2de0773ed
3 changed files with 63 additions and 9 deletions

View File

@ -3,10 +3,16 @@
#include "parse.h"
#include "utility.h"
namespace detail {
template<fmt_node_t fmt_node, typename T>
constexpr void check_fmt_params() {
static_assert(fmt_node.length > fmt_node.precision + 1, "Insufficient length for desired precision");
}
template <ConstString s>
constexpr int get_output_len() {
@ -28,50 +34,78 @@ constexpr int get_output_len() {
template <fmt_node_t fmt_node, std::integral arg_t>
constexpr std::array<char, fmt_node.length> format_arg(arg_t arg) {
check_fmt_params<fmt_node, arg_t>();
std::array<char, fmt_node.length> result;
// TODO: See if this is possible with charconv
for (unsigned i = 1; i <= result.size(); ++i) {
result[result.size() - i] = arg % 10 + 48;
arg = arg / 10;
arg = arg / 10;
}
return result;
}
template <fmt_node_t fmt_node, std::floating_point arg_t>
constexpr std::array<char, fmt_node.length> format_arg(arg_t) {
constexpr std::array<char, fmt_node.length> format_arg(arg_t arg) {
check_fmt_params<fmt_node, arg_t>();
std::array<char, fmt_node.length> result;
constexpr unsigned len_before_point =
fmt_node.length - fmt_node.precision - 1;
result[result.size() - fmt_node.precision - 1] = '.';
// TODO: See if this is possible with charconv
for (auto& c : result)
c = 'f';
constexpr unsigned multiplier = const_pow(10, fmt_node.precision);
arg = arg * multiplier;
for (unsigned i = result.size()-1; i >= result.size() - fmt_node.precision; --i) {
result[i] = static_cast<int>(arg) % 10 + 48;
arg = arg / 10;
}
for (unsigned i = fmt_node.precision + 2; i <= result.size(); ++i) {
result[result.size() - i] = static_cast<int>(arg) % 10 + 48;
arg = arg / 10;
}
/*
for (unsigned i = fmt_node.precision + 1; i <= result.size(); ++i) {
result[result.size() - i] = static_cast<int>(arg) % 10 + 48;
arg = arg / 10;
}
*/
return result;
}
template <fmt_node_t fmt_node>
constexpr std::array<char, fmt_node.length> format_arg(const char* arg) {
check_fmt_params<fmt_node, const char*>();
std::array<char, fmt_node.length> result;
for (auto& c : result) {
if (*arg != '\0')
c = *(arg++);
else
c = '-';
c = '_';
}
return result;
}
template <auto t_ast, unsigned t_ast_i = 0, unsigned t_result_i = 0,
typename char_array_t>
typename char_array_t>
constexpr char_array_t format_args(char_array_t result) {
return result;
}
template <auto t_ast, unsigned t_ast_i = 0, unsigned t_result_i = 0,
typename char_array_t, typename first_arg_t, typename... other_args_t>
constexpr char_array_t format_args(char_array_t result, first_arg_t first_arg,
@ -93,7 +127,8 @@ constexpr char_array_t format_args(char_array_t result, first_arg_t first_arg,
result.begin() + t_result_i);
return format_args<t_ast, t_ast_i + 1,
t_result_i + fmt_node.length>(result, other_args...);
t_result_i + fmt_node.length>(result,
other_args...);
}
}
}

19
inc/utility.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef LOGGER_UTILITY_H
#define LOGGER_UTILITY_H
namespace detail {
constexpr std::size_t const_pow(std::size_t base, std::size_t pow) {
if (pow == 0)
return 1;
else
return base * const_pow(base, pow - 1);
}
} // namespace detail
#endif // LOGGER_UTILITY_H

View File

@ -12,7 +12,7 @@ public:
int main() {
constexpr auto formatted = format<"Test: {:3.8f} {:5.5} {:05.2}">(3.4, "abc", 1234);
const auto formatted = format<"Test: {:8.3} {:6.3} {:05.2}">(1432.4334, "abc", 1234);
for (const auto& c : formatted)
std::cout << c;