Moved functions to appropriate header files; Implemented const char* formatting

This commit is contained in:
Andreas Tsouchlos 2021-11-25 11:04:24 +01:00
parent 8ccceeef0d
commit 3f46775b35
7 changed files with 133 additions and 166 deletions

View File

@ -1,38 +0,0 @@
#ifndef LOGGER_CONSTSTRING_H
#define LOGGER_CONSTSTRING_H
#include <array>
namespace detail {
template <std::size_t N>
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<char, N> m_content;
};
template <std::size_t N>
ConstString(const char (&)[N]) -> ConstString<N>;
} // namespace detail
#endif // LOGGER_CONSTSTRING_H

View File

@ -7,7 +7,6 @@
#include <tuple> #include <tuple>
#include <format.h> #include <format.h>
#include <ConstString.h>
/* /*

View File

@ -4,30 +4,18 @@
#include "parse.h" #include "parse.h"
#include "utility.h" #include "utility.h"
#include <cstring>
namespace detail { namespace detail {
template <fmt_node_t fmt_node, typename T>
constexpr void check_fmt_params() {
static_assert(fmt_node.length > fmt_node.precision + 1,
"Insufficient length for desired precision");
}
/*
*
* Utility functions
*
*/
template <auto t_ast>
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 <ConstString s> template <ConstString s>
constexpr int get_output_len() { constexpr int get_output_len() {
@ -37,87 +25,69 @@ constexpr int get_output_len() {
return get_ast_output_len<parse_result.value>(); return get_ast_output_len<parse_result.value>();
} }
//// TODO: See if this is possible with <charconv> template <fmt_node_t fmt_node, typename T>
//// TODO: Steal some code from fmtlib constexpr void check_fmt_params() {
//// TODO: In case of error, set chars to all 'f's static_assert(fmt_node.length > fmt_node.precision + 1,
// template <fmt_node_t fmt_node, std::integral arg_t> "Insufficient length for desired precision");
// constexpr std::array<char, fmt_node.length> format_arg(arg_t arg) { }
// check_fmt_params<fmt_node, arg_t>();
//
// auto result = get_init_array<fmt_node>(); /*
// *
// unsigned offset = 0; * Type-specific formatting functions
// * (Most of this code is shamelessly stolen from fmtlib)
// if (arg < 0) { */
// result[0] = '-';
// arg = -arg;
// ++offset; // TODO
// }
//
// for (int i = result.size() - 1; /*
// (i >= static_cast<int>(offset)) && (arg > 0); --i) { *
// result[i] = arg % 10 + 48; * Formatting wrapper functions
// arg = arg / 10; *
// } */
//
// return result;
// } template <std::integral arg_t>
// constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t) {
//// TODO: See if this is possible with <charconv> *(dest + fmt_data.position) = 'i';
//// TODO: Steal some code from fmtlib // dest = dest + fmt_data.position;
//// TODO: In case of error, set chars to all 'f's // format_int(dest, fmt_data.length, arg);
// template <fmt_node_t fmt_node, std::floating_point arg_t> };
// constexpr std::array<char, fmt_node.length> format_arg(arg_t arg) { template <std::floating_point arg_t>
// check_fmt_params<fmt_node, arg_t>(); constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t) {
// dest = dest + fmt_data.position;
// constexpr unsigned point_index = fmt_node.length - fmt_node.precision - *(dest) = 'f';
// 1; constexpr unsigned multiplier = const_pow(10, fmt_node.precision); *(dest + fmt_data.length - fmt_data.precision - 1) = '.';
// };
// auto result = get_init_array<fmt_node>(); // TODO: Error handling
// result[point_index] = '.'; 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;
// arg = arg * multiplier;
// dest = dest + fmt_data.position + fmt_data.length - len;
// for (int i = result.size() - 1;
// (i > static_cast<int>(point_index)) && (arg >= 1); --i) { if (!std::is_constant_evaluated()) {
// std::memcpy(dest, arg, len);
// result[i] = static_cast<int>(arg) % 10 + 48; return;
// arg = arg / 10; }
// } for (std::size_t i = 0; i < len; ++i) {
// *(dest++) = *(arg++);
// for (int i = point_index - 1; (i >= 0) && (arg >= 1); --i) { }
// result[i] = static_cast<int>(arg) % 10 + 48; };
// arg = arg / 10;
// }
// template <auto ast>
// return result; constexpr void format_args(char*) {
// } }
//
//// TODO: Steal some code from fmtlib template <auto fmt_data_array, typename first_arg_t, typename... args_t>
//// TODO: In case of error, set chars to all 'f's constexpr void format_args(char* dest, first_arg_t first_arg, args_t... args) {
// template <fmt_node_t fmt_node> format_arg(dest, fmt_data_array[0], first_arg);
// constexpr std::array<char, fmt_node.length> format_arg(const char* arg) { format_args<drop_first(fmt_data_array)>(dest, args...);
// check_fmt_params<fmt_node, const char*>(); }
//
// std::array<char, fmt_node.length> result;
//
// for (auto& c : result) {
// if (*arg != '\0')
// c = *(arg++);
// else
// c = ' ';
// }
//
// return result;
// }
//
//
// template <auto t_ast, unsigned t_ast_i = 0, unsigned t_result_i = 0,
// typename char_array_t>
// constexpr char_array_t format_args(char_array_t result) {
// return result;
// }
template <auto ast> template <auto ast>
consteval std::array<char, get_ast_output_len<ast>()> get_preproc_string() { consteval std::array<char, get_ast_output_len<ast>()> get_preproc_string() {
@ -136,35 +106,16 @@ consteval std::array<char, get_ast_output_len<ast>()> get_preproc_string() {
} }
template <std::integral arg_t>
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 <std::floating_point arg_t>
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 <auto ast>
constexpr void format_args(char*) {
}
template <auto fmt_data_array, typename first_arg_t, typename... args_t>
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<drop_first(fmt_data_array)>(dest, args...);
}
} // namespace detail } // namespace detail
/*
*
* Public API
*
*/
template <detail::ConstString s, typename... args_t> template <detail::ConstString s, typename... args_t>
constexpr std::array<char, detail::get_output_len<s>()> format(args_t... args) { constexpr std::array<char, detail::get_output_len<s>()> format(args_t... args) {
constexpr auto ast = detail::parse_string<s>().value; constexpr auto ast = detail::parse_string<s>().value;

View File

@ -2,7 +2,6 @@
#define LOGGER_PARSE_H #define LOGGER_PARSE_H
#include "ConstString.h"
#include "types.h" #include "types.h"

View File

@ -8,6 +8,37 @@
namespace detail { namespace detail {
/*
*
* Types used everywhere
*
*/
template <std::size_t N>
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<char, N> m_content;
};
template <std::size_t N>
ConstString(const char (&)[N]) -> ConstString<N>;
/* /*
* *
* Types used mainly in parsing * Types used mainly in parsing

View File

@ -2,6 +2,8 @@
#define LOGGER_UTILITY_H #define LOGGER_UTILITY_H
#include <cstring>
#include "types.h" #include "types.h"
@ -95,6 +97,29 @@ drop_first(std::array<elem_t, t_n> array) {
} }
template <auto t_ast>
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 } // namespace detail

View File

@ -4,7 +4,7 @@
int main() { 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) for (const auto& c : formatted)
std::cout << c; std::cout << c;