12 Commits

Author SHA1 Message Date
ea722ec5bf Changed includes; Implemented std::pair and std::make_unsigned; changed usage of std::memcpy to memcpy 2022-02-23 19:45:17 +01:00
5ba1723295 Made array a structural type 2022-02-20 14:29:58 +01:00
8e51facd10 fixed wrong clang-format comments 2022-02-20 00:27:45 +01:00
9bd1104e5f Code compiles and passes tests without NO_STDLIB define 2022-02-20 00:26:48 +01:00
6ba83fd582 Minor changes to make sure some stuff works with no stl headers 2022-02-20 00:15:31 +01:00
8f7b1cd4e3 Implemented std::array and a bunch of other stuff 2022-02-20 00:14:33 +01:00
ec70a5bba1 Merge branch 'master' into feature/no_std_lib 2022-02-19 19:21:34 +01:00
1263dfee98 Merge pull request 'Added cmake-build-relwithdebinfo to gitignore' (#8) from fix/gitignore_builddir into master
Reviewed-on: http://git.mercurial-manifold.eu/an.tsouchlos/const_fmt/pulls/8
2022-02-19 18:18:51 +00:00
52992e255e Added cmake-build-relwithdebinfo to gitignore 2022-02-19 19:13:54 +01:00
8526ae1d91 First version of std::array 2022-02-18 23:31:15 +01:00
b8f59710d3 Merge pull request 'Updated README.md' (#7) from fix/README_wording into master
Reviewed-on: http://git.mercurial-manifold.eu/an.tsouchlos/const_fmt/pulls/7
2022-02-15 13:54:04 +00:00
184815c75b Updated README.md 2022-02-15 13:53:47 +00:00
9 changed files with 232 additions and 16 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.

View File

@@ -57,7 +57,7 @@ constexpr inline void format_arg(char* dest, const char* arg) {
dest = dest + 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); memcpy(dest, arg, len);
return; return;
} }
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {

View File

@@ -12,6 +12,7 @@
#include <stdint.h> #include <stdint.h>
#include "stdlib.h"
#include "utility.h" #include "utility.h"
@@ -119,7 +120,7 @@ constexpr inline const char* digits2_base(size_t value) {
constexpr inline void copy2(char* dst, const char* src) { constexpr inline void copy2(char* dst, const char* src) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
std::memcpy(dst, src, 2); memcpy(dst, src, 2);
return; return;
} }
*dst++ = static_cast<char>(*src++); *dst++ = static_cast<char>(*src++);

View File

@@ -5,7 +5,7 @@
#include "types.h" #include "types.h"
// clang-const_format off // clang-format off
/* /*
* *
@@ -34,7 +34,7 @@
* *
*/ */
// clang-const_format on // clang-format on
namespace const_fmt { namespace const_fmt_detail { namespace const_fmt { namespace const_fmt_detail {

209
const_fmt/stdlib.h Normal file
View File

@@ -0,0 +1,209 @@
#ifndef CONST_FMT_STDLIB_H
#define CONST_FMT_STDLIB_H
/*
*
* Disclaimer: Probably very bad implementation of some features of the C++
* Standard Library. Not meant as a full-on stdlib implementation, only for
* usage in this project (Underlined by the fact, that in this case the
* namespace std is actually const_fmt::std)
*
*/
#ifndef CONST_FMT_NO_CPP_STDLIB
#include <array>
#include <cstring>
#else
#include <stdint.h>
#include <string.h>
namespace const_fmt { 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
constexpr inline bool is_constant_evaluated() noexcept {
return __builtin_is_constant_evaluated();
}
// clang-format off
template <typename type_t> struct make_unsigned { using type = type_t; };
template <> struct make_unsigned<signed char> { using type = char; };
template <> struct make_unsigned<unsigned short> { using type = unsigned short; };
template <> struct make_unsigned<signed int> { using type = unsigned int; };
template <> struct make_unsigned<signed long> { using type = unsigned long; };
template <> struct make_unsigned<signed long long> { using type = unsigned long long; };
// clang-format on
/*
*
* concepts
*
*/
//template <typename _Tp>
//concept integral = is_integral_v<_Tp>;
//
//template <typename _Tp>
//concept signed_integral = integral<_Tp> && is_signed_v<_Tp>;
//
//template <typename _Tp>
//concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>;
//
//template <typename _Tp>
//concept floating_point = is_floating_point_v<_Tp>;
/*
*
* algorithm
*
*/
template <typename input_t, typename output_t>
void copy(input_t* start, input_t* end, output_t* dest_start) {
memcpy(start, dest_start, end - start);
}
/*
*
* 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);
}
template <typename first_t, typename second_t>
struct pair {
first_t first;
second_t second;
};
/*
*
* 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);
}
data_t m_data[t_size];
};
}} // namespace const_fmt::std
#endif
#endif // CONST_FMT_STDLIB_H

View File

@@ -2,7 +2,8 @@
#define LOGGER_TYPES_H #define LOGGER_TYPES_H
#include <array>
#include "stdlib.h"
namespace const_fmt { namespace const_fmt_detail { namespace const_fmt { namespace const_fmt_detail {
@@ -19,8 +20,7 @@ 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), m_content.begin());
std::begin(m_content));
} }
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 "stdlib.h"
#include "types.h" #include "types.h"

View File

@@ -1,6 +1,8 @@
#define CONST_FMT_NO_CPP_STDLIB
#include <const_fmt/format.h> #include <const_fmt/format.h>
#include <iostream> //#include <iostream>
#include <string_view> //#include <string_view>
using namespace const_fmt; using namespace const_fmt;
@@ -9,9 +11,9 @@ int main() {
// Convert s (with a type of 'std::array<char, N>') into something // Convert s (with a type of 'std::array<char, N>') into something
// writable to std::cout // writable to std::cout
std::string_view sv{&s[0], s.size()}; // std::string_view sv{&s[0], s.size()};
//
std::cout << sv << std::endl; // std::cout << sv << std::endl;
return 0; return 0;
} }