8 Commits

5 changed files with 139 additions and 7 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
build build
cmake-build-debug cmake-build-debug
cmake-build-release cmake-build-release
cmake-build-relwithdebinfo
.idea .idea

View File

@@ -11,8 +11,7 @@ During compile-time, the string to be formatted is preprocessed to the point onl
have to be written (If they are not available at compile time). have to be written (If they are not available at compile time).
For example `One number: {:03}; And another one: {:05.3}` is preprocessed into `One number: 000; And another one: 00.000`. For example `One number: {:03}; And another one: {:05.3}` is preprocessed into `One number: 000; And another one: 00.000`.
This is returned as a `std::array<char, N>`, where `N` is automatically evaluated. The only code executed at compile This is returned as a `std::array<char, N>`, where `N` is automatically evaluated. The only code executed at runtime then formats the numbers and writes them into their places in the array.
time then formats the numbers and writes them into their place in the array.
Disclaimer: The actual formatting code is largely shamelessly stolen from `fmtlib`. Disclaimer: The actual formatting code is largely shamelessly stolen from `fmtlib`.
@@ -48,8 +47,11 @@ $ ctest --test-dir build/
## Limitations ## Limitations
For the compile time preprocessing of format strings non non-type template parameters are heavily relied upon,
which means C++20 is required.
Only a relatively limited subset of the `fmtlib` syntax is recognized (for now anyway). In particular, Only a relatively limited subset of the `fmtlib` syntax is recognized (for now anyway). In particular,
there is no support for positional arguments, alignment, chrono format specs and custom const_format specifications. float formatting in decimal and integer formatting in decimal, binary and hexadecimal are supported.
By nature of the library design, which forces compile-time preprocessing of the const_format string, no dynamic width or By nature of the library design, which forces compile-time preprocessing of the const_format string, no dynamic width or
dynamic precision can be implemented. dynamic precision can be implemented.

127
const_fmt/std_lib.h Normal file
View File

@@ -0,0 +1,127 @@
#ifndef CONST_FMT_STD_LIB_H
#define CONST_FMT_STD_LIB_H
#ifndef CONST_FMT_NO_CPP_STD_LIB
#include <array>
#else
#include <stdint.h>
#include <string.h>
namespace std {
using size_t = uint16_t;
/*
*
* type_traits
*
*/
// clang-format off
template<typename T> struct remove_reference { using type = T; };
template<typename T> struct remove_reference<T&> { using type = T; };
template<typename T> struct remove_reference<T&&> { using type = T; };
template<typename T>
using remove_reference_t = typename std::remove_reference<T>::type;
// clang-format on
/*
*
* utility
*
*/
template <typename T>
std::remove_reference_t<T>&& move(T&& arg) noexcept {
return reinterpret_cast<std::remove_reference_t<T>&&>(arg);
}
template <typename T>
void swap(T& t1, T& t2) {
T temp = std::move(t1);
t1 = std::move(t2);
t2 = std::move(temp);
}
/*
*
* std::array
*
*/
// TODO: Is std::size_t really the best bet here?
template <typename data_t, std::size_t t_size>
class array {
public:
template<typename... args_t>
constexpr array(args_t... args) noexcept : m_data{args...} {
static_assert(sizeof...(args) == t_size, "Invalid number of arguments");
}
constexpr array() noexcept = default;
constexpr array(array&) = default;
constexpr array(array&&) = default;
constexpr array& operator=(array& other) = default;
constexpr array& operator=(array&& other) = default;
constexpr void swap(array<data_t, t_size>& other) noexcept {
for (int i = 0; i < t_size; ++i) {
using std::swap;
swap(m_data[i], other.m_data[i]);
}
}
constexpr data_t& operator[](std::size_t index) noexcept {
return m_data[index];
}
constexpr const data_t& operator[](std::size_t index) const noexcept {
return m_data[index];
}
using iterator = data_t*;
using const_iterator = const data_t*;
constexpr iterator begin() noexcept {
return &(m_data[0]);
}
constexpr iterator end() noexcept {
return (&(m_data[t_size - 1]) + 1);
}
constexpr const_iterator cbegin() const noexcept {
return &(m_data[0]);
}
constexpr const_iterator cend() const noexcept {
return (&(m_data[t_size - 1]) + 1);
}
private:
data_t m_data[t_size];
};
} // namespace std
#endif
#endif // CONST_FMT_STD_LIB_H

View File

@@ -2,7 +2,8 @@
#define LOGGER_TYPES_H #define LOGGER_TYPES_H
#include <array>
#include "std_lib.h"
namespace const_fmt { namespace const_fmt_detail { namespace const_fmt { namespace const_fmt_detail {
@@ -19,8 +20,8 @@ template <std::size_t N>
class ConstString { class ConstString {
public: public:
constexpr ConstString(const char (&content)[N]) noexcept { constexpr ConstString(const char (&content)[N]) noexcept {
std::copy(std::begin(content), std::end(content), std::copy(&content[0], (&content[N-1] + 1),
std::begin(m_content)); m_content.begin());
} }
constexpr char operator[](std::size_t index) const noexcept { constexpr char operator[](std::size_t index) const noexcept {

View File

@@ -2,8 +2,9 @@
#define LOGGER_UTILITY_H #define LOGGER_UTILITY_H
#include <cstring> #include <string.h>
#include "std_lib.h"
#include "types.h" #include "types.h"