#ifndef LOGGER_FORMAT_H #define LOGGER_FORMAT_H #include "parse.h" #include "utility.h" #include namespace detail { /* * * Utility functions * */ 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(); } template constexpr void check_fmt_params() { static_assert(fmt_node.length > fmt_node.precision + 1, "Insufficient length for desired precision"); } /* * * Type-specific formatting functions * (Most of this code is shamelessly stolen from fmtlib) */ // TODO /* * * Formatting wrapper functions * */ template constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t) { *(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 = dest + fmt_data.position; *(dest) = 'f'; *(dest + fmt_data.length - fmt_data.precision - 1) = '.'; }; // TODO: Error handling constexpr void format_arg(char* dest, fmt_data_t fmt_data, const char* arg) { const std::size_t len = const_strlen(arg); if (len > fmt_data.length) return; dest = dest + fmt_data.position + fmt_data.length - len; if (!std::is_constant_evaluated()) { std::memcpy(dest, arg, len); return; } for (std::size_t i = 0; i < len; ++i) { *(dest++) = *(arg++); } }; 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...); } 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; } } // namespace detail /* * * Public API * */ 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