Shamelessly copied fmtlib code for decimal formatting; Added comment with idea about error handling
This commit is contained in:
parent
afa7831e93
commit
c0d0bb5bad
@ -17,7 +17,7 @@ add_executable(logger src/main.cpp)
|
|||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_compile_options(logger PRIVATE /W4 /WX)
|
target_compile_options(logger PRIVATE /W4 /WX)
|
||||||
else()
|
else()
|
||||||
target_compile_options(logger PRIVATE -Wall -Wextra -pedantic)
|
target_compile_options(logger PRIVATE -O3 -Wall -Wextra -pedantic -fno-exceptions)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
29
inc/format.h
29
inc/format.h
@ -2,9 +2,11 @@
|
|||||||
#define LOGGER_FORMAT_H
|
#define LOGGER_FORMAT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include <cstring>
|
#include "format_impl.h"
|
||||||
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -32,16 +34,6 @@ constexpr void check_fmt_params() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Type-specific formatting functions
|
|
||||||
* (Most of this code is shamelessly stolen from fmtlib)
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Formatting wrapper functions
|
* Formatting wrapper functions
|
||||||
@ -50,14 +42,12 @@ constexpr void check_fmt_params() {
|
|||||||
|
|
||||||
|
|
||||||
template <std::integral arg_t>
|
template <std::integral arg_t>
|
||||||
constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t) {
|
constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t arg) {
|
||||||
*(dest + fmt_data.position) = 'i';
|
detail::format_integral(dest, arg, fmt_data);
|
||||||
// dest = dest + fmt_data.position;
|
|
||||||
// format_int(dest, fmt_data.length, arg);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::floating_point arg_t>
|
template <std::floating_point arg_t>
|
||||||
constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t) {
|
constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t) {
|
||||||
dest = dest + fmt_data.position;
|
|
||||||
*(dest) = 'f';
|
*(dest) = 'f';
|
||||||
*(dest + fmt_data.length - fmt_data.precision - 1) = '.';
|
*(dest + fmt_data.length - fmt_data.precision - 1) = '.';
|
||||||
};
|
};
|
||||||
@ -66,7 +56,7 @@ constexpr void format_arg(char* dest, fmt_data_t fmt_data, const char* arg) {
|
|||||||
const std::size_t len = const_strlen(arg);
|
const std::size_t len = const_strlen(arg);
|
||||||
if (len > fmt_data.length) return;
|
if (len > fmt_data.length) return;
|
||||||
|
|
||||||
dest = dest + fmt_data.position + fmt_data.length - len;
|
dest = dest + fmt_data.length - len;
|
||||||
|
|
||||||
if (!std::is_constant_evaluated()) {
|
if (!std::is_constant_evaluated()) {
|
||||||
std::memcpy(dest, arg, len);
|
std::memcpy(dest, arg, len);
|
||||||
@ -84,7 +74,7 @@ constexpr void format_args(char*) {
|
|||||||
|
|
||||||
template <auto fmt_data_array, typename first_arg_t, typename... args_t>
|
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) {
|
constexpr void format_args(char* dest, first_arg_t first_arg, args_t... args) {
|
||||||
format_arg(dest, fmt_data_array[0], first_arg);
|
format_arg(dest + fmt_data_array[0].position, fmt_data_array[0], first_arg);
|
||||||
format_args<drop_first(fmt_data_array)>(dest, args...);
|
format_args<drop_first(fmt_data_array)>(dest, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +107,7 @@ consteval std::array<char, get_ast_output_len<ast>()> get_preproc_string() {
|
|||||||
|
|
||||||
|
|
||||||
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 auto format(args_t... args) {
|
||||||
constexpr auto ast = detail::parse_string<s>().value;
|
constexpr auto ast = detail::parse_string<s>().value;
|
||||||
constexpr auto fmt_data = detail::get_fmt_data<ast>();
|
constexpr auto fmt_data = detail::get_fmt_data<ast>();
|
||||||
|
|
||||||
@ -128,6 +118,7 @@ constexpr std::array<char, detail::get_output_len<s>()> format(args_t... args) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<detail::ConstString t_s>
|
template<detail::ConstString t_s>
|
||||||
class fmt_literal_obj_t {
|
class fmt_literal_obj_t {
|
||||||
public:
|
public:
|
||||||
|
|||||||
105
inc/format_impl.h
Normal file
105
inc/format_impl.h
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#ifndef LOGGER_FORMAT_IMPL_H
|
||||||
|
#define LOGGER_FORMAT_IMPL_H
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ****************************************************************
|
||||||
|
* Disclaimer: Most of this code is shamelessly stolen from fmtlib
|
||||||
|
* ****************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Utility functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Converts value in the range [0, 100) to a string.
|
||||||
|
constexpr inline const char* digits2(size_t value) {
|
||||||
|
// GCC generates slightly better code when value is pointer-size.
|
||||||
|
return &"0001020304050607080910111213141516171819"
|
||||||
|
"2021222324252627282930313233343536373839"
|
||||||
|
"4041424344454647484950515253545556575859"
|
||||||
|
"6061626364656667686970717273747576777879"
|
||||||
|
"8081828384858687888990919293949596979899"[value * 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constexpr inline void copy2(char* dst, const char* src) {
|
||||||
|
if (!std::is_constant_evaluated()) {
|
||||||
|
std::memcpy(dst, src, 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst++ = static_cast<char>(*src++);
|
||||||
|
*dst = static_cast<char>(*src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename UInt>
|
||||||
|
constexpr inline void format_decimal(char* out, UInt value, int size) {
|
||||||
|
// TODO: Error handling (Maybe calculate "ffff..." as a constant expression
|
||||||
|
// and then set the out pointer with a branchless statement)
|
||||||
|
|
||||||
|
out += size;
|
||||||
|
while (value >= 100) {
|
||||||
|
out -= 2;
|
||||||
|
copy2(out, digits2(static_cast<size_t>(value % 100)));
|
||||||
|
value /= 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 10) *--out = static_cast<char>('0' + value);
|
||||||
|
|
||||||
|
out -= 2;
|
||||||
|
copy2(out, digits2(static_cast<size_t>(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Integral types
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
template <std::unsigned_integral uint_t>
|
||||||
|
constexpr inline void format_integral(char* out, uint_t value,
|
||||||
|
fmt_data_t fmt_node) {
|
||||||
|
format_decimal(out, value, fmt_node.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::signed_integral uint_t>
|
||||||
|
constexpr inline void format_integral(char* out, uint_t value,
|
||||||
|
fmt_data_t fmt_node) {
|
||||||
|
if (value < 0) value = -value;
|
||||||
|
format_decimal(out, value, fmt_node.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Floating point types
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
template <std::floating_point float_t>
|
||||||
|
constexpr inline void format_integral(char* out, float_t value,
|
||||||
|
fmt_data_t fmt_node) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
|
#endif // LOGGER_FORMAT_IMPL_H
|
||||||
@ -1,14 +1,14 @@
|
|||||||
#include <iostream>
|
//#include <iostream>
|
||||||
|
|
||||||
#include <Logger.h>
|
#include <Logger.h>
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
int main(int argc, char* argv[]) {
|
||||||
constexpr auto formatted = "Test: {:012.5} {:6} {:8}"_fmt(142.4334, "abcdef", -1234);
|
auto formatted = "Test: {:12} {:012.5} {:8}"_fmt(argv[0], argc, -1234);
|
||||||
|
|
||||||
for (const auto& c : formatted)
|
for (const auto& c : formatted)
|
||||||
std::cout << c;
|
std::cout << c;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
return 0;
|
return formatted[6];
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user