From 3f46775b35bd21bec449f075822ade4f12d876b5 Mon Sep 17 00:00:00 2001 From: Andreas Tsouchlos Date: Thu, 25 Nov 2021 11:04:24 +0100 Subject: [PATCH] Moved functions to appropriate header files; Implemented const char* formatting --- inc/ConstString.h | 38 --------- inc/Logger.h | 1 - inc/format.h | 201 ++++++++++++++++++---------------------------- inc/parse.h | 1 - inc/types.h | 31 +++++++ inc/utility.h | 25 ++++++ src/main.cpp | 2 +- 7 files changed, 133 insertions(+), 166 deletions(-) delete mode 100644 inc/ConstString.h diff --git a/inc/ConstString.h b/inc/ConstString.h deleted file mode 100644 index c531dcd..0000000 --- a/inc/ConstString.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef LOGGER_CONSTSTRING_H -#define LOGGER_CONSTSTRING_H - - -#include - - -namespace detail { - - -template -class ConstString { -public: - constexpr ConstString(const char (&content)[N]) noexcept { - std::copy(std::begin(content), std::end(content), - std::begin(m_content)); - } - - constexpr char operator[](std::size_t index) const noexcept { - return m_content[index]; - } - - constexpr std::size_t size() const noexcept { - return N - 1; - } - - std::array m_content; -}; - - -template -ConstString(const char (&)[N]) -> ConstString; - - -} // namespace detail - - -#endif // LOGGER_CONSTSTRING_H diff --git a/inc/Logger.h b/inc/Logger.h index bbe952e..bd06c88 100644 --- a/inc/Logger.h +++ b/inc/Logger.h @@ -7,7 +7,6 @@ #include #include -#include /* diff --git a/inc/format.h b/inc/format.h index 513aa89..a012e4b 100644 --- a/inc/format.h +++ b/inc/format.h @@ -4,30 +4,18 @@ #include "parse.h" #include "utility.h" +#include namespace detail { -template -constexpr void check_fmt_params() { - static_assert(fmt_node.length > fmt_node.precision + 1, - "Insufficient length for desired precision"); -} +/* + * + * Utility functions + * + */ -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() { @@ -37,87 +25,69 @@ constexpr int get_output_len() { 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 +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() { @@ -136,35 +106,16 @@ consteval std::array()> get_preproc_string() { } -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 +/* + * + * Public API + * + */ + + template constexpr std::array()> format(args_t... args) { constexpr auto ast = detail::parse_string().value; diff --git a/inc/parse.h b/inc/parse.h index a9a1260..ab1a161 100644 --- a/inc/parse.h +++ b/inc/parse.h @@ -2,7 +2,6 @@ #define LOGGER_PARSE_H -#include "ConstString.h" #include "types.h" diff --git a/inc/types.h b/inc/types.h index d0fcd81..1bd9049 100644 --- a/inc/types.h +++ b/inc/types.h @@ -8,6 +8,37 @@ namespace detail { +/* + * + * Types used everywhere + * + */ + + +template +class ConstString { +public: + constexpr ConstString(const char (&content)[N]) noexcept { + std::copy(std::begin(content), std::end(content), + std::begin(m_content)); + } + + constexpr char operator[](std::size_t index) const noexcept { + return m_content[index]; + } + + constexpr std::size_t size() const noexcept { + return N - 1; + } + + std::array m_content; +}; + + +template +ConstString(const char (&)[N]) -> ConstString; + + /* * * Types used mainly in parsing diff --git a/inc/utility.h b/inc/utility.h index 284a3e4..42a2697 100644 --- a/inc/utility.h +++ b/inc/utility.h @@ -2,6 +2,8 @@ #define LOGGER_UTILITY_H +#include + #include "types.h" @@ -95,6 +97,29 @@ drop_first(std::array array) { } +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; +} + +constexpr std::size_t const_strlen(const char* arg) { + if (std::is_constant_evaluated()) { + return *arg ? 1 + const_strlen(arg + 1) : 0; + } else { + return strlen(arg); + } +} + + } // namespace detail diff --git a/src/main.cpp b/src/main.cpp index 65559b6..aa2f8fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ int main() { - constexpr auto formatted = format<"Test: {:012.5} {} {:8}">(142.4334, "abc", -1234); + constexpr auto formatted = format<"Test: {:012.5} {} {:8}">(142.4334, "abcdef", -1234); for (const auto& c : formatted) std::cout << c;