Compare commits
6 Commits
2d5a7316f1
...
657b0d1ab1
Author | SHA1 | Date | |
---|---|---|---|
657b0d1ab1 | |||
![]() |
4bd6843ba5 | ||
![]() |
657d05341c | ||
![]() |
9cefc52568 | ||
![]() |
2d413764f0 | ||
![]() |
50532459ce |
@ -113,6 +113,42 @@ StreamError Stream::writeBinaryString(std::string_view str)
|
|||||||
return writeSpan(str.begin(), str.end());
|
return writeSpan(str.begin(), str.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StreamError Stream::readZString(std::string& outString)
|
||||||
|
{
|
||||||
|
char chr = '\0';
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (isAtEnd())
|
||||||
|
{
|
||||||
|
return StreamError::IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StreamError error = read(chr); error != StreamError::SUCCESS)
|
||||||
|
{
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (chr == '\0')
|
||||||
|
{
|
||||||
|
outString = std::move(result);
|
||||||
|
return StreamError::SUCCESS;
|
||||||
|
}
|
||||||
|
result.push_back(chr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamError Stream::writeZString(std::string_view str)
|
||||||
|
{
|
||||||
|
static const char ZERO = '\0';
|
||||||
|
|
||||||
|
if (StreamError error = writeRaw(str.data(), str.size() * sizeof(char)); error != StreamError::SUCCESS)
|
||||||
|
{
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
return write(ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
mijin::Task<StreamError> Stream::c_readBinaryString(std::string& outString)
|
mijin::Task<StreamError> Stream::c_readBinaryString(std::string& outString)
|
||||||
{
|
{
|
||||||
std::uint32_t length; // NOLINT(cppcoreguidelines-init-variables)
|
std::uint32_t length; // NOLINT(cppcoreguidelines-init-variables)
|
||||||
|
@ -221,7 +221,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
StreamError write(const T& value) requires(std::is_trivial_v<T>)
|
StreamError write(const T& value)
|
||||||
{
|
{
|
||||||
return writeRaw(&value, sizeof(T));
|
return writeRaw(&value, sizeof(T));
|
||||||
}
|
}
|
||||||
@ -261,6 +261,9 @@ public:
|
|||||||
StreamError readBinaryString(std::string& outString);
|
StreamError readBinaryString(std::string& outString);
|
||||||
StreamError writeBinaryString(std::string_view str);
|
StreamError writeBinaryString(std::string_view str);
|
||||||
|
|
||||||
|
StreamError readZString(std::string& outString);
|
||||||
|
StreamError writeZString(std::string_view str);
|
||||||
|
|
||||||
mijin::Task<StreamError> c_readBinaryString(std::string& outString);
|
mijin::Task<StreamError> c_readBinaryString(std::string& outString);
|
||||||
mijin::Task<StreamError> c_writeBinaryString(std::string_view str);
|
mijin::Task<StreamError> c_writeBinaryString(std::string_view str);
|
||||||
|
|
||||||
|
52
source/mijin/logging/filters.hpp
Normal file
52
source/mijin/logging/filters.hpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(MIJIN_LOGGING_FILTERS_HPP_INCLUDED)
|
||||||
|
#define MIJIN_LOGGING_FILTERS_HPP_INCLUDED 1
|
||||||
|
|
||||||
|
#include "./logger.hpp"
|
||||||
|
|
||||||
|
namespace mijin
|
||||||
|
{
|
||||||
|
template<typename TChar = MIJIN_DEFAULT_CHAR_TYPE>
|
||||||
|
class BaseLevelFilter : public BaseLogFilter<TChar>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using base_t = BaseLogFilter<TChar>;
|
||||||
|
using typename base_t::char_t;
|
||||||
|
using typename base_t::message_t;
|
||||||
|
private:
|
||||||
|
int mMinLevel = 0;
|
||||||
|
int mMaxLevel = 0;
|
||||||
|
public:
|
||||||
|
explicit BaseLevelFilter(int minLevel, int maxLevel = std::numeric_limits<int>::max()) MIJIN_NOEXCEPT
|
||||||
|
: mMinLevel(minLevel), mMaxLevel(maxLevel) {}
|
||||||
|
explicit BaseLevelFilter(const BaseLogLevel<char_t>& minLevel, const BaseLogLevel<char_t>& maxLevel = {nullptr, std::numeric_limits<int>::max()}) MIJIN_NOEXCEPT
|
||||||
|
: mMinLevel(minLevel.value), mMaxLevel(maxLevel.value) {}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
int getMinLevel() const MIJIN_NOEXCEPT { return mMinLevel; }
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
int getMaxLevel() const MIJIN_NOEXCEPT { return mMaxLevel; }
|
||||||
|
|
||||||
|
void setMinLevel(int level) MIJIN_NOEXCEPT { mMinLevel = level; }
|
||||||
|
|
||||||
|
void setMinLevel(const BaseLogLevel<char_t>& level) MIJIN_NOEXCEPT { mMinLevel = level.value; }
|
||||||
|
|
||||||
|
void setMaxLevel(int level) MIJIN_NOEXCEPT { mMaxLevel = level; }
|
||||||
|
|
||||||
|
void setMaxLevel(const BaseLogLevel<char_t>& level) MIJIN_NOEXCEPT { mMaxLevel = level.value; }
|
||||||
|
|
||||||
|
bool shouldShow(const message_t& message) MIJIN_NOEXCEPT override
|
||||||
|
{
|
||||||
|
return message.level->value >= mMinLevel && message.level->value <= mMaxLevel;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MIJIN_DEFINE_CHAR_VERSIONS(LevelFilter)
|
||||||
|
|
||||||
|
} // namespace mijin
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !defined(MIJIN_LOGGING_STDIO_SINK_HPP_INCLUDED)
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <format>
|
#include <format>
|
||||||
|
#include <mutex>
|
||||||
#include <source_location>
|
#include <source_location>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -105,6 +106,20 @@ public:
|
|||||||
|
|
||||||
MIJIN_DEFINE_CHAR_VERSIONS(LogSink)
|
MIJIN_DEFINE_CHAR_VERSIONS(LogSink)
|
||||||
|
|
||||||
|
template<typename TChar = MIJIN_DEFAULT_CHAR_TYPE>
|
||||||
|
class BaseLogFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using char_t = TChar;
|
||||||
|
using message_t = BaseLogMessage<char_t>;
|
||||||
|
|
||||||
|
virtual ~BaseLogFilter() noexcept = default;
|
||||||
|
|
||||||
|
virtual bool shouldShow(const message_t& message) MIJIN_NOEXCEPT = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
MIJIN_DEFINE_CHAR_VERSIONS(LogFilter)
|
||||||
|
|
||||||
#define LOGGER_COMMON_ARGS(chr_type) template<typename T> typename TAllocator = MIJIN_DEFAULT_ALLOCATOR
|
#define LOGGER_COMMON_ARGS(chr_type) template<typename T> typename TAllocator = MIJIN_DEFAULT_ALLOCATOR
|
||||||
template<typename TChar = MIJIN_DEFAULT_CHAR_TYPE, typename TTraits = std::char_traits<TChar>, LOGGER_COMMON_ARGS(TChar)>
|
template<typename TChar = MIJIN_DEFAULT_CHAR_TYPE, typename TTraits = std::char_traits<TChar>, LOGGER_COMMON_ARGS(TChar)>
|
||||||
class BaseLogger
|
class BaseLogger
|
||||||
@ -115,15 +130,22 @@ public:
|
|||||||
using allocator_t = TAllocator<char_t>;
|
using allocator_t = TAllocator<char_t>;
|
||||||
|
|
||||||
using sink_t = BaseLogSink<char_t>;
|
using sink_t = BaseLogSink<char_t>;
|
||||||
|
using filter_t = BaseLogFilter<char_t>;
|
||||||
using level_t = BaseLogLevel<char_t>;
|
using level_t = BaseLogLevel<char_t>;
|
||||||
using channel_t = BaseLogChannel<char_t>;
|
using channel_t = BaseLogChannel<char_t>;
|
||||||
using message_t = BaseLogMessage<char_t>;
|
using message_t = BaseLogMessage<char_t>;
|
||||||
using string_t = std::basic_string<char_t, traits_t, allocator_t>;
|
using string_t = std::basic_string<char_t, traits_t, allocator_t>;
|
||||||
private:
|
private:
|
||||||
std::vector<sink_t*, TAllocator<sink_t*>> mSinks;
|
struct SinkEntry
|
||||||
|
{
|
||||||
|
sink_t* sink;
|
||||||
|
filter_t* filter;
|
||||||
|
};
|
||||||
|
std::vector<SinkEntry, TAllocator<SinkEntry>> mSinks;
|
||||||
|
mutable std::mutex mMutex;
|
||||||
public:
|
public:
|
||||||
explicit BaseLogger(TAllocator<sink_t*> allocator = {}) MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v<TAllocator<sink_t*>>)
|
explicit BaseLogger(TAllocator<void> allocator = {}) MIJIN_NOEXCEPT_IF((std::is_nothrow_constructible_v<TAllocator<SinkEntry>, TAllocator<void>&&>))
|
||||||
: mSinks(std::move(allocator))
|
: mSinks(TAllocator<SinkEntry>(std::move(allocator)))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
BaseLogger(const BaseLogger&) = default;
|
BaseLogger(const BaseLogger&) = default;
|
||||||
@ -133,14 +155,25 @@ public:
|
|||||||
|
|
||||||
void addSink(sink_t& sink)
|
void addSink(sink_t& sink)
|
||||||
{
|
{
|
||||||
mSinks.push_back(&sink);
|
std::unique_lock _(mMutex);
|
||||||
|
mSinks.push_back({&sink, nullptr});
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSink(sink_t& sink, filter_t& filter)
|
||||||
|
{
|
||||||
|
std::unique_lock _(mMutex);
|
||||||
|
mSinks.push_back({&sink, &filter});
|
||||||
}
|
}
|
||||||
|
|
||||||
void postMessage(const message_t& message) const MIJIN_NOEXCEPT
|
void postMessage(const message_t& message) const MIJIN_NOEXCEPT
|
||||||
{
|
{
|
||||||
for (sink_t* sink: mSinks)
|
std::unique_lock _(mMutex);
|
||||||
|
for (const SinkEntry& entry : mSinks)
|
||||||
{
|
{
|
||||||
sink->handleMessage(message);
|
if (entry.filter != nullptr && !entry.filter->shouldShow(message)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entry.sink->handleMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
58
source/mijin/logging/stream_sink.hpp
Normal file
58
source/mijin/logging/stream_sink.hpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(MIJIN_LOGGING_STREAM_SINK_HPP_INCLUDED)
|
||||||
|
#define MIJIN_LOGGING_STREAM_SINK_HPP_INCLUDED 1
|
||||||
|
|
||||||
|
#include "./formatting.hpp"
|
||||||
|
#include "../io/stream.hpp"
|
||||||
|
#include "../util/traits.hpp"
|
||||||
|
|
||||||
|
namespace mijin
|
||||||
|
{
|
||||||
|
template<MIJIN_FORMATTING_SINK_TMPL_ARGS_INIT>
|
||||||
|
requires(allocator_type<TAllocator<TChar>>)
|
||||||
|
class BaseStreamSink : public BaseFormattingLogSink<MIJIN_FORMATTING_SINK_TMP_ARG_NAMES>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using base_t = BaseFormattingLogSink<MIJIN_FORMATTING_SINK_TMP_ARG_NAMES>;
|
||||||
|
using typename base_t::char_t;
|
||||||
|
using typename base_t::allocator_t;
|
||||||
|
using typename base_t::formatter_ptr_t;
|
||||||
|
using typename base_t::message_t;
|
||||||
|
using stream_ptr_t = DynamicPointer<Stream>;
|
||||||
|
private:
|
||||||
|
stream_ptr_t mStream;
|
||||||
|
int mMinStderrLevel = MIJIN_LOG_LEVEL_VALUE_WARNING;
|
||||||
|
public:
|
||||||
|
explicit BaseStreamSink(not_null_t<formatter_ptr_t> formatter, allocator_t allocator = {})
|
||||||
|
MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v<allocator_t>)
|
||||||
|
: base_t(std::move(formatter), std::move(allocator)) {}
|
||||||
|
explicit BaseStreamSink(not_null_t<stream_ptr_t> stream, not_null_t<formatter_ptr_t> formatter, allocator_t allocator = {})
|
||||||
|
MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v<allocator_t>)
|
||||||
|
: base_t(std::move(formatter), std::move(allocator)), mStream(std::move(stream)) {}
|
||||||
|
|
||||||
|
void setStream(not_null_t<stream_ptr_t> stream) {
|
||||||
|
mStream = std::move(stream).release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleMessageFormatted(const message_t& /* message */, const char_t* formatted) MIJIN_NOEXCEPT override
|
||||||
|
{
|
||||||
|
if (!mStream) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(void) mStream->writeSpan(std::basic_string_view(formatted));
|
||||||
|
(void) mStream->write('\n');
|
||||||
|
mStream->flush();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SINK_SET_ARGS(chr_type) chr_type, std::char_traits<chr_type>, TAllocator, TDeleter
|
||||||
|
|
||||||
|
MIJIN_DEFINE_CHAR_VERSIONS_TMPL(StreamSink, MIJIN_FORMATTING_SINK_COMMON_ARGS, SINK_SET_ARGS)
|
||||||
|
|
||||||
|
#undef SINK_SET_ARGS
|
||||||
|
} // namespace mijin
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !defined(MIJIN_LOGGING_STREAM_SINK_HPP_INCLUDED)
|
@ -17,7 +17,7 @@ namespace mijin
|
|||||||
{
|
{
|
||||||
MIJIN_DEFINE_FLAG(Owning);
|
MIJIN_DEFINE_FLAG(Owning);
|
||||||
|
|
||||||
template<typename T, deleter_type<T> TDeleter = std::default_delete<T>>
|
template<typename T, deleter_type<T> TDeleter = AllocatorDeleter<MIJIN_DEFAULT_ALLOCATOR<T>>>
|
||||||
class DynamicPointer
|
class DynamicPointer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -170,6 +170,9 @@ public:
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr const T& get() const MIJIN_NOEXCEPT { return base_; }
|
constexpr const T& get() const MIJIN_NOEXCEPT { return base_; }
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr T release() && MIJIN_NOEXCEPT { return std::exchange(base_, nullptr); }
|
||||||
|
|
||||||
template<nullable_type TOther>
|
template<nullable_type TOther>
|
||||||
friend class NotNullable;
|
friend class NotNullable;
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "../debug/assert.hpp"
|
||||||
|
|
||||||
namespace mijin
|
namespace mijin
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -253,6 +253,42 @@ struct optional_base<T, false>
|
|||||||
template<typename T, bool enable>
|
template<typename T, bool enable>
|
||||||
using optional_base_t = optional_base<T, enable>::type;
|
using optional_base_t = optional_base<T, enable>::type;
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
template<typename TFunc>
|
||||||
|
struct function_traits_base {};
|
||||||
|
|
||||||
|
template<typename TResult, typename... TParams>
|
||||||
|
struct function_traits_base<TResult (*)(TParams...)>
|
||||||
|
{
|
||||||
|
using result_t = TResult;
|
||||||
|
using params_t = std::tuple<TParams...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TResult, typename TType, typename... TParams>
|
||||||
|
struct function_traits_base<TResult (TType::*)(TParams...)>
|
||||||
|
{
|
||||||
|
using result_t = TResult;
|
||||||
|
using params_t = std::tuple<TType*, TParams...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TResult, typename TType, typename... TParams>
|
||||||
|
struct function_traits_base<TResult (TType::*)(TParams...) const>
|
||||||
|
{
|
||||||
|
using result_t = TResult;
|
||||||
|
using params_t = std::tuple<const TType*, TParams...>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename TFunc>
|
||||||
|
struct function_traits : impl::function_traits_base<TFunc>
|
||||||
|
{
|
||||||
|
static constexpr std::size_t NUM_PARAMS = std::tuple_size_v<typename impl::function_traits_base<TFunc>::params_t>;
|
||||||
|
|
||||||
|
template<std::size_t pos>
|
||||||
|
using param_t = std::tuple_element_t<pos, typename impl::function_traits_base<TFunc>::params_t>;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// public functions
|
// public functions
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user