Moved functions to appropriate header files; Implemented const char* formatting
This commit is contained in:
parent
8ccceeef0d
commit
3f46775b35
@ -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
|
|
||||||
@ -7,7 +7,6 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <ConstString.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
201
inc/format.h
201
inc/format.h
@ -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;
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
#define LOGGER_PARSE_H
|
#define LOGGER_PARSE_H
|
||||||
|
|
||||||
|
|
||||||
#include "ConstString.h"
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
31
inc/types.h
31
inc/types.h
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user