#ifndef LOGGER_FORMAT_H #define LOGGER_FORMAT_H #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() { constexpr auto parse_result = parse_string(); static_assert(parse_result.is_valid, "Syntax error in format string"); unsigned result = 0; for (const auto& ast_node : parse_result.value) { if (ast_node.is_char()) ++result; else result += ast_node.get_node().length; } return result; } // TODO: See if this is possible with // TODO: Steal some code from fmtlib // TODO: In case of error, set chars to all 'f's template constexpr std::array format_arg(arg_t arg) { check_fmt_params(); auto result = get_init_array(); unsigned offset = 0; if (arg < 0) { result[0] = '-'; arg = -arg; ++offset; } for (int i = result.size() - 1; (i >= static_cast(offset)) && (arg > 0); --i) { result[i] = arg % 10 + 48; arg = arg / 10; } return result; } // TODO: See if this is possible with // TODO: Steal some code from fmtlib // TODO: In case of error, set chars to all 'f's template constexpr std::array format_arg(arg_t arg) { check_fmt_params(); constexpr unsigned point_index = fmt_node.length - fmt_node.precision - 1; constexpr unsigned multiplier = const_pow(10, fmt_node.precision); auto result = get_init_array(); result[point_index] = '.'; arg = arg * multiplier; for (int i = result.size() - 1; (i > static_cast(point_index)) && (arg >= 1); --i) { result[i] = static_cast(arg) % 10 + 48; arg = arg / 10; } for (int i = point_index - 1; (i >= 0) && (arg >= 1); --i) { result[i] = static_cast(arg) % 10 + 48; arg = arg / 10; } return result; } // TODO: Steal some code from fmtlib // TODO: In case of error, set chars to all 'f's 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 = ' '; } return result; } template 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, other_args_t... other_args) { if constexpr (t_ast_i >= t_ast.size()) { return result; } else { constexpr auto ast_node = t_ast[t_ast_i]; if (ast_node.is_char()) { result[t_result_i] = ast_node.get_char(); return format_args( result, first_arg, other_args...); } else { constexpr auto fmt_node = ast_node.get_node(); const auto formatted_arg = format_arg(first_arg); std::copy(formatted_arg.begin(), formatted_arg.end(), result.begin() + t_result_i); return format_args(result, other_args...); } } } } // namespace detail template constexpr std::array()> format(args_t... args) { constexpr auto parse_result = detail::parse_string(); static_assert(parse_result.is_valid, "Syntax error in format string"); std::array()> result = {}; return detail::format_args(result, args...); } #endif // LOGGER_FORMAT_H