Shamelessly copied fmtlib code for decimal formatting; Added comment with idea about error handling

This commit is contained in:
Andreas Tsouchlos 2021-11-26 01:02:10 +01:00
parent afa7831e93
commit c0d0bb5bad
4 changed files with 120 additions and 24 deletions

View File

@ -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()

View File

@ -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
View 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

View File

@ -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];
}