#ifndef LOGGER_FORMAT_H #define LOGGER_FORMAT_H #include #include "parse.h" #include "utility.h" #include "format_impl.h" namespace detail { /* * * Utility functions * */ template constexpr inline 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 inline void check_fmt_params() { static_assert(fmt_node.length > fmt_node.precision + 1, "Insufficient length for desired precision"); } /* * * Formatting wrapper functions * */ template constexpr inline void format_arg(char* dest, arg_t arg) { detail::format_int(dest, arg, fmt_data); }; template constexpr inline void format_arg(char* dest, arg_t arg) { //detail::format_float(dest, arg, fmt_data); }; // TODO: Error handling template constexpr inline void format_arg(char* dest, const char* arg) { const std::size_t len = const_strlen(arg); if (len > fmt_data.length) return; dest = dest + 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++); } }; // End of recursion template constexpr inline void format_args(char*) { } template constexpr inline void format_args(char* dest, first_arg_t first_arg, args_t... args) { format_arg(dest + fmt_data_array[0].position, first_arg); format_args(dest, args...); } template consteval inline std::array()> get_preproc_string() { auto result = get_init_array()>('f'); 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 Interface * */ template constexpr inline auto 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; } template class fmt_literal_obj_t { public: template constexpr auto operator()(args_t... args) { return format(args...); } }; template constexpr auto operator""_fmt() { return fmt_literal_obj_t{}; } #endif // LOGGER_FORMAT_H