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)
|
||||
target_compile_options(logger PRIVATE /W4 /WX)
|
||||
else()
|
||||
target_compile_options(logger PRIVATE -Wall -Wextra -pedantic)
|
||||
target_compile_options(logger PRIVATE -O3 -Wall -Wextra -pedantic -fno-exceptions)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
29
inc/format.h
29
inc/format.h
@ -2,9 +2,11 @@
|
||||
#define LOGGER_FORMAT_H
|
||||
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "parse.h"
|
||||
#include "utility.h"
|
||||
#include <cstring>
|
||||
#include "format_impl.h"
|
||||
|
||||
|
||||
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
|
||||
@ -50,14 +42,12 @@ constexpr void check_fmt_params() {
|
||||
|
||||
|
||||
template <std::integral arg_t>
|
||||
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);
|
||||
constexpr void format_arg(char* dest, fmt_data_t fmt_data, arg_t arg) {
|
||||
detail::format_integral(dest, arg, fmt_data);
|
||||
};
|
||||
|
||||
template <std::floating_point arg_t>
|
||||
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) = '.';
|
||||
};
|
||||
@ -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);
|
||||
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()) {
|
||||
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>
|
||||
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...);
|
||||
}
|
||||
|
||||
@ -117,7 +107,7 @@ consteval std::array<char, get_ast_output_len<ast>()> get_preproc_string() {
|
||||
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
|
||||
template<detail::ConstString t_s>
|
||||
class fmt_literal_obj_t {
|
||||
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>
|
||||
|
||||
|
||||
int main() {
|
||||
constexpr auto formatted = "Test: {:012.5} {:6} {:8}"_fmt(142.4334, "abcdef", -1234);
|
||||
int main(int argc, char* argv[]) {
|
||||
auto formatted = "Test: {:12} {:012.5} {:8}"_fmt(argv[0], argc, -1234);
|
||||
|
||||
for (const auto& c : formatted)
|
||||
std::cout << c;
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
return formatted[6];
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user