diff --git a/inc/format.h b/inc/format.h index 814607d..f8a0d05 100644 --- a/inc/format.h +++ b/inc/format.h @@ -3,10 +3,16 @@ #include "parse.h" +#include "utility.h" namespace detail { +template +constexpr void check_fmt_params() { + static_assert(fmt_node.length > fmt_node.precision + 1, "Insufficient length for desired precision"); +} + template constexpr int get_output_len() { @@ -28,50 +34,78 @@ constexpr int get_output_len() { template constexpr std::array format_arg(arg_t arg) { + check_fmt_params(); + std::array 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 -constexpr std::array format_arg(arg_t) { +constexpr std::array format_arg(arg_t arg) { + check_fmt_params(); + std::array 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(arg) % 10 + 48; + arg = arg / 10; + } + + for (unsigned i = fmt_node.precision + 2; i <= result.size(); ++i) { + result[result.size() - i] = static_cast(arg) % 10 + 48; + arg = arg / 10; + } + + /* + for (unsigned i = fmt_node.precision + 1; i <= result.size(); ++i) { + result[result.size() - i] = static_cast(arg) % 10 + 48; + arg = arg / 10; + } + */ return result; } template constexpr std::array format_arg(const char* arg) { + check_fmt_params(); + std::array result; for (auto& c : result) { if (*arg != '\0') c = *(arg++); else - c = '-'; + c = '_'; } return result; } template + typename char_array_t> constexpr char_array_t format_args(char_array_t result) { return result; } - template 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(result, other_args...); + t_result_i + fmt_node.length>(result, + other_args...); } } } diff --git a/inc/utility.h b/inc/utility.h new file mode 100644 index 0000000..d11ecd8 --- /dev/null +++ b/inc/utility.h @@ -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 diff --git a/src/main.cpp b/src/main.cpp index a6c2d26..8df2b1c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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;