Added FixedArrayOutputIterator and use it for logging without heap allocations.

This commit is contained in:
2025-07-12 16:57:20 +02:00
parent 1208f1f59f
commit f7daa58b38
2 changed files with 82 additions and 9 deletions

View File

@@ -11,6 +11,7 @@
#include <vector>
#include "../internal/common.hpp"
#include "../util/annot.hpp"
#include "../util/iterators.hpp"
namespace mijin
{
@@ -126,11 +127,8 @@ public:
{}
BaseLogger(const BaseLogger&) = default;
BaseLogger(BaseLogger&&) = default;
BaseLogger& operator=(const BaseLogger&) = default;
BaseLogger& operator=(BaseLogger&&) = default;
void addSink(sink_t& sink)
@@ -158,12 +156,28 @@ public:
template<typename... TArgs>
void log(const level_t& level, const channel_t& channel, std::source_location sourceLocation,
std::basic_format_string<char_t, std::type_identity_t<TArgs>...> fmt, TArgs&& ... args) const
MIJIN_NOEXCEPT_IF(noexcept(std::declval<allocator_t>().allocate(1)))
std::basic_format_string<char_t, std::type_identity_t<TArgs>...> fmt, TArgs&& ... args) const MIJIN_NOEXCEPT
{
string_t buffer(allocator_t(mSinks.get_allocator()));
std::format_to(std::back_inserter(buffer), fmt, std::forward<TArgs>(args)...);
log(level, channel, std::move(sourceLocation), buffer.c_str());
// TODO: make the logger use a traits struct to make this adjustable
static constexpr std::size_t BUFFER_SIZE = 256;
std::array<char_t, BUFFER_SIZE> buffer;
// first try to write into a buffer on the stack
FixedArrayOutputIterator itAfter = std::format_to(FixedArrayOutputIterator(buffer), fmt, std::forward<TArgs>(args)...);
*itAfter = '\0';
++itAfter;
if (!itAfter.didOverflow())
{
log(level, channel, std::move(sourceLocation), buffer.data());
return;
}
// if that didn't work, allocate more space
const std::size_t newBufferSize = itAfter.getCounter();
char_t* newBuffer = static_cast<char_t*>(alloca(newBufferSize * sizeof(char_t)));
const std::format_to_n_result result = std::format_to_n(newBuffer, newBufferSize - 1, fmt, std::forward<TArgs>(args)...);
*result.out = '\0';
log(level, channel, std::move(sourceLocation), newBuffer);
}
};