#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 consteval int get_ast_output_len() { unsigned result = 0; for (const auto& ast_node : t_ast) { if (ast_node.is_char()) ++result; else result += ast_node.get_node().length; } return result; } template constexpr int get_output_len() { constexpr auto parse_result = parse_string(); static_assert(parse_result.is_valid, "Syntax error in format string"); return get_ast_output_len(); } //// 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 consteval std::array()> get_preproc_string() { auto result = get_zero_array()>(); int i = 0; for (const auto& ast_node : ast) { if (ast_node.is_char()) result[i++] = ast_node.get_char(); else i += ast_node.get_node().length; } return result; } template constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t arg) { *(dest + fmt_data.position) = 'i'; // dest = dest + fmt_data.position; // format_int(dest, fmt_data.length, arg); }; template constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t) { *(dest + fmt_data.position) = 'f'; }; constexpr void format_arg(char* dest, fmt_data_t fmt_data, const char*) { *(dest + fmt_data.position) = 'c'; }; template constexpr void format_args(char*) { } template constexpr void format_args(char* dest, first_arg_t first_arg, args_t... args) { format_arg(dest, fmt_data_array[0], first_arg); format_args(dest, args...); } } // namespace detail template constexpr std::array()> format(args_t... args) { constexpr auto ast = detail::parse_string().value; constexpr auto fmt_data = detail::get_fmt_data(); auto result = detail::get_preproc_string(); detail::format_args(result.begin(), args...); return result; } #endif // LOGGER_FORMAT_H