34#ifndef _SIR_HH_INCLUDED
35# define _SIR_HH_INCLUDED
38# include "sir/helpers.h"
39# include "sir/internal.h"
40# include <type_traits>
51# if HAS_INCLUDE(<format>) && !defined (SIR_NO_STD_FORMAT) && \
52 !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
54# define __SIR_HAVE_STD_FORMAT__
56# if HAS_INCLUDE(<boost/format.hpp>) && !defined(SIR_NO_BOOST_FORMAT)
57# include <boost/format.hpp>
58# define __SIR_HAVE_BOOST_FORMAT__
60# if HAS_INCLUDE(<fmt/format.h>) && !defined(SIR_NO_FMT_FORMAT)
61# define FMT_HEADER_ONLY
62# include <fmt/format.h>
63# define __SIR_HAVE_FMT_FORMAT__
65# if !defined(SIR_NO_STD_IOSTREAM)
95 constexpr bool is_os_error() const noexcept {
99 static error from_last_error() {
126 return { { errinfo.code, errinfo.msg }, errinfo.func, errinfo.file,
127 errinfo.line, errinfo.os_code, errinfo.os_msg };
146 using std::runtime_error::runtime_error;
250 static constexpr bool throw_on_error() noexcept {
288 template<DerivedFromPolicy TPolicy>
292 if constexpr(TPolicy::throw_on_error()) {
293 throw exception(error::from_last_error());
309 template<DerivedFromPolicy TPolicy>
316 PRINTF_FORMAT_ATTR(2, 3)
317 bool
debug(PRINTF_FORMAT const
char* format, ...)
const {
318 _SIR_L_START(format);
325 PRINTF_FORMAT_ATTR(2, 3)
326 bool
info(PRINTF_FORMAT const
char* format, ...)
const {
327 _SIR_L_START(format);
328 ret = _sir_logv(
SIRL_INFO, format, args);
334 PRINTF_FORMAT_ATTR(2, 3)
335 bool
notice(PRINTF_FORMAT const
char* format, ...)
const {
336 _SIR_L_START(format);
343 PRINTF_FORMAT_ATTR(2, 3)
344 bool
warn(PRINTF_FORMAT const
char* format, ...)
const {
345 _SIR_L_START(format);
346 ret = _sir_logv(
SIRL_WARN, format, args);
352 PRINTF_FORMAT_ATTR(2, 3)
353 bool
error(PRINTF_FORMAT const
char* format, ...)
const {
354 _SIR_L_START(format);
361 PRINTF_FORMAT_ATTR(2, 3)
362 bool
crit(PRINTF_FORMAT const
char* format, ...)
const {
363 _SIR_L_START(format);
364 ret = _sir_logv(
SIRL_CRIT, format, args);
370 PRINTF_FORMAT_ATTR(2, 3)
371 bool
alert(PRINTF_FORMAT const
char* format, ...)
const {
372 _SIR_L_START(format);
379 PRINTF_FORMAT_ATTR(2, 3)
380 bool
emerg(PRINTF_FORMAT const
char* format, ...)
const {
381 _SIR_L_START(format);
388# if defined(__SIR_HAVE_STD_FORMAT__)
412 template<DerivedFromPolicy TPolicy>
418 template<
typename... Args>
419 inline bool debug_std(std::format_string<Args...> fmt, Args&&... args)
const {
420 const auto str = std::vformat(fmt.get(), std::make_format_args(args...));
421 const bool ret =
sir_debug(
"%s", str.c_str());
425 template<
typename... Args>
426 inline bool info_std(std::format_string<Args...> fmt, Args&&... args)
const {
427 const auto str = std::vformat(fmt.get(), std::make_format_args(args...));
428 const bool ret =
sir_info(
"%s", str.c_str());
432 template<
typename... Args>
433 inline bool notice_std(std::format_string<Args...> fmt, Args&&... args)
const {
434 const auto str = std::vformat(fmt.get(), std::make_format_args(args...));
435 const bool ret =
sir_notice(
"%s", str.c_str());
439 template<
typename... Args>
440 inline bool warn_std(std::format_string<Args...> fmt, Args&&... args)
const {
441 const auto str = std::vformat(fmt.get(), std::make_format_args(args...));
442 const bool ret =
sir_warn(
"%s", str.c_str());
446 template<
typename... Args>
447 inline bool error_std(std::format_string<Args...> fmt, Args&&... args)
const {
448 const auto str = std::vformat(fmt.get(), std::make_format_args(args...));
449 const bool ret =
sir_error(
"%s", str.c_str());
453 template<
typename... Args>
454 inline bool crit_std(std::format_string<Args...> fmt, Args&&... args)
const {
455 const auto str = std::vformat(fmt.get(), std::make_format_args(args...));
456 const bool ret =
sir_crit(
"%s", str.c_str());
460 template<
typename... Args>
461 inline bool alert_std(std::format_string<Args...> fmt, Args&&... args)
const {
462 const auto str = std::vformat(fmt.get(), std::make_format_args(args...));
463 const bool ret =
sir_alert(
"%s", str.c_str());
467 template<
typename... Args>
468 inline bool emerg_std(std::format_string<Args...> fmt, Args&&... args)
const {
469 const auto str = std::vformat(fmt.get(), std::make_format_args(args...));
470 const bool ret =
sir_emerg(
"%s", str.c_str());
476# if defined(__SIR_HAVE_BOOST_FORMAT__)
500 template<DerivedFromPolicy TPolicy>
506 bool debug_bf(
const boost::format& fmt)
const {
507 const bool ret =
sir_debug(
"%s", fmt.str().c_str());
511 bool info_bf(
const boost::format& fmt)
const {
512 const bool ret =
sir_info(
"%s", fmt.str().c_str());
516 bool notice_bf(
const boost::format& fmt)
const {
517 const bool ret =
sir_notice(
"%s", fmt.str().c_str());
521 bool warn_bf(
const boost::format& fmt)
const {
522 const bool ret =
sir_warn(
"%s", fmt.str().c_str());
526 bool error_bf(
const boost::format& fmt)
const {
527 const bool ret =
sir_error(
"%s", fmt.str().c_str());
531 bool crit_bf(
const boost::format& fmt)
const {
532 const bool ret =
sir_crit(
"%s", fmt.str().c_str());
536 bool alert_bf(
const boost::format& fmt)
const {
537 const bool ret =
sir_alert(
"%s", fmt.str().c_str());
541 bool emerg_bf(
const boost::format& fmt)
const {
542 const bool ret =
sir_emerg(
"%s", fmt.str().c_str());
548# if defined(__SIR_HAVE_FMT_FORMAT__)
572 template<DerivedFromPolicy TPolicy>
578 template<
typename... Args>
579 inline bool debug_fmt(fmt::format_string<Args...> fmt, Args&&... args)
const {
580 const auto str = fmt::vformat(fmt, fmt::make_format_args(args...));
581 const auto ret =
sir_debug(
"%s", str.c_str());
585 template<
typename... Args>
586 inline bool info_fmt(fmt::format_string<Args...> fmt, Args&&... args)
const {
587 const auto str = fmt::vformat(fmt, fmt::make_format_args(args...));
588 const auto ret =
sir_info(
"%s", str.c_str());
592 template<
typename... Args>
593 inline bool notice_fmt(fmt::format_string<Args...> fmt, Args&&... args)
const {
594 const auto str = fmt::vformat(fmt, fmt::make_format_args(args...));
595 const auto ret =
sir_notice(
"%s", str.c_str());
599 template<
typename... Args>
600 inline bool warn_fmt(fmt::format_string<Args...> fmt, Args&&... args)
const {
601 const auto str = fmt::vformat(fmt, fmt::make_format_args(args...));
602 const auto ret =
sir_warn(
"%s", str.c_str());
606 template<
typename... Args>
607 inline bool error_fmt(fmt::format_string<Args...> fmt, Args&&... args)
const {
608 const auto str = fmt::vformat(fmt, fmt::make_format_args(args...));
609 const auto ret =
sir_error(
"%s", str.c_str());
613 template<
typename... Args>
614 inline bool crit_fmt(fmt::format_string<Args...> fmt, Args&&... args)
const {
615 const auto str = fmt::vformat(fmt, fmt::make_format_args(args...));
616 const auto ret =
sir_crit(
"%s", str.c_str());
620 template<
typename... Args>
621 inline bool alert_fmt(fmt::format_string<Args...> fmt, Args&&... args)
const {
622 const auto str = fmt::vformat(fmt, fmt::make_format_args(args...));
623 const auto ret =
sir_alert(
"%s", str.c_str());
627 template<
typename... Args>
628 inline bool emerg_fmt(fmt::format_string<Args...> fmt, Args&&... args)
const {
629 const auto str = fmt::vformat(fmt, fmt::make_format_args(args...));
630 const auto ret =
sir_emerg(
"%s", str.c_str());
636# if !defined(SIR_NO_STD_IOSTREAM)
666 template<DerivedFromPolicy TPolicy>
672 template<
typename TFunc>
673 class buffer :
public std::streambuf {
675 using array_type = std::array<char_type, SIR_MAXMESSAGE>;
679 explicit buffer(TFunc pfn) : _pfn(pfn) {
685 ~buffer()
override =
default;
691 setp(_arr->data(), _arr->data() + _arr->size() - 1);
696 for (
auto it = _arr->rbegin(); it != _arr->rend(); it++) {
697 if ((*it !=
'\0') && (*it ==
'\n')) {
703 const bool write = _pfn ? _pfn(_arr->data()) :
false;
708 int_type overflow(int_type ch)
override {
709 if (ch != traits_type::eof() && write_out()) {
712 return traits_type::eof();
715 int sync()
override {
716 return write_out() ? 0 : -1;
719 std::streamsize xsputn(
const char_type* s, std::streamsize count)
override {
720 std::streamsize written = 0;
722 ptrdiff_t left = epptr() - pptr();
724 int_type ch = overflow(traits_type::to_int_type(*(s + written)));
725 if (ch != traits_type::eof()) {
732 auto this_write = std::min(
static_cast<std::streamsize
>(left),
734 std::memcpy(pptr(), s + written,
static_cast<std::size_t
>(this_write));
735 pbump(
static_cast<int>(this_write));
736 written += this_write;
737 }
while (written < count);
743 std::shared_ptr<array_type> _arr = std::make_shared<array_type>();
744 TFunc _pfn =
nullptr;
747 template<DerivedFromStreamBuf TBuffer>
748 class stream :
public std::ostream {
750 explicit stream(
const TBuffer& buf) : std::ostream(&_buf), _buf(buf) {}
751 ~stream()
override =
default;
757 using log_func = bool(*)(
const char*, ...);
758 using buffer_type = buffer<log_func>;
759 using stream_type = stream<buffer_type>;
761 stream_type debug_stream {buffer_type {&
sir_debug}};
762 stream_type info_stream {buffer_type {&
sir_info}};
763 stream_type notice_stream {buffer_type {&
sir_notice}};
764 stream_type warn_stream {buffer_type {&
sir_warn}};
765 stream_type error_stream {buffer_type {&
sir_error}};
766 stream_type crit_stream {buffer_type {&
sir_crit}};
767 stream_type alert_stream {buffer_type {&
sir_alert}};
768 stream_type emerg_stream {buffer_type {&
sir_emerg}};
773 template<
size_t N,
typename ...Ts>
774 using NthTypeOf =
typename std::tuple_element<N, std::tuple<Ts...>>::type;
777 template<
size_t N,
typename TBase,
typename ...Ts>
779 if constexpr(!std::is_base_of_v<TBase,
NthTypeOf<N, Ts...>>)
780 return std::false_type::value;
782 return std::true_type::value;
788 template<
class TBase,
class ...Ts>
809 template<
bool RAII, DerivedFromPolicy TPolicy,
template<
class>
class ...TAdapters>
811 class logger :
public TAdapters<TPolicy>... {
813 logger() : TAdapters<TPolicy>()... {
834 bool init()
const noexcept {
835 return is_initialized() ?
false: _init();
838 bool cleanup()
const noexcept {
842 bool is_initialized()
const noexcept {
846 error get_error()
const {
847 return error::from_last_error();
851 return error_info::from_last_error();
856 const bool add =
sir_addfile(path.c_str(), levels, opts);
860 bool rem_file(
const sirfileid&
id)
const {
865 sirpluginid load_plugin(
const std::string& path)
const {
891 bool reset_text_styles()
const {
907 bool set_stdout_levels(
const sir_levels& levels)
const {
912 bool set_stdout_options(
const sir_options& opts)
const {
917 bool set_stderr_levels(
const sir_levels& levels)
const {
922 bool set_stderr_options(
const sir_options& opts)
const {
927 bool set_syslog_levels(
const sir_levels& levels)
const {
932 bool set_syslog_options(
const sir_options& opts)
const {
937 bool set_syslog_id(
const std::string&
id)
const {
942 bool set_syslog_category(
const std::string& category)
const {
947 std::string get_version_string()
const {
951 uint32_t get_version_hex()
const noexcept {
955 bool is_prerelease()
const noexcept {
960 bool _init()
const noexcept {
977# if defined(__SIR_HAVE_STD_FORMAT__)
992# if defined(__SIR_HAVE_BOOST_FORMAT__)
1007# if defined(__SIR_HAVE_FMT_FORMAT__)
1022# if !defined(SIR_NO_STD_IOSTREAM)
Defines the abstract interface for an adapter, which ultimately becomes a public base class of logger...
Definition sir.hh:267
The default adapter implementation.
Definition sir.hh:310
bool crit(PRINTF_FORMAT const char *format,...) const
Logs a critical message (see sir_crit).
Definition sir.hh:362
bool debug(PRINTF_FORMAT const char *format,...) const
Logs a debug message (see sir_debug).
Definition sir.hh:317
bool warn(PRINTF_FORMAT const char *format,...) const
Logs a warning message (see sir_warn).
Definition sir.hh:344
bool notice(PRINTF_FORMAT const char *format,...) const
Logs a notice message (see sir_notice).
Definition sir.hh:335
bool emerg(PRINTF_FORMAT const char *format,...) const
Logs an emergency message (see sir_emerg).
Definition sir.hh:380
bool info(PRINTF_FORMAT const char *format,...) const
Logs an informational message (see sir_info).
Definition sir.hh:326
bool alert(PRINTF_FORMAT const char *format,...) const
Logs an alert message (see sir_alert).
Definition sir.hh:371
In the event that no custom configuration or behavior is desired, provides defaults for everything.
Definition sir.hh:237
bool get_init_data(sirinit &data) const noexcept final
Called by logger before initializing libsir.
Definition sir.hh:242
constexpr bool on_init_complete() const noexcept final
Called by logger immediately after libsir has been initialized.
Definition sir.hh:246
The exception type thrown by libsir.
Definition sir.hh:144
The primary C++ interface to libsir.
Definition sir.hh:811
Defines the partially abstract interface for a policy which controls the behavior of logger at runtim...
Definition sir.hh:162
virtual bool on_init_complete() const noexcept=0
Called by logger immediately after libsir has been initialized.
static constexpr bool throw_on_error() noexcept
Determines whether or not exceptions are thrown in the event that an unercoverable error is encounter...
Definition sir.hh:219
virtual bool get_init_data(sirinit &data) const noexcept=0
Called by logger before initializing libsir.
Provides a std::iostream interface to libsir's logging functions.
Definition sir.hh:667
Ensures that T derives from policy.
Definition sir.hh:226
Ensures that T derives from std::streambuf.
Definition sir.hh:639
True if all Ts are derived classes of TBase, otherwise false.
Definition sir.hh:789
#define SIR_MAXERROR
The maximum size, in characters, of an error message.
Definition config.h:419
bool sir_stderropts(sir_options opts)
Set new formatting options for stderr.
Definition sir.c:211
bool sir_settextstyle(sir_level level, sir_textattr attr, sir_textcolor fg, sir_textcolor bg)
Set new text styling for stdio (stdout/stderr) destinations on a per-level basis.
Definition sir.c:170
sirpluginid sir_loadplugin(const char *path)
Loads a plugin module from disk.
Definition sir.c:140
bool sir_alert(PRINTF_FORMAT const char *format,...)
Dispatches a SIRL_ALERT level message.
Definition sir.c:117
bool sir_sysloglevels(sir_levels levels)
Set new level registrations for the system logger destination.
Definition sir.c:217
bool sir_setcolormode(sir_colormode mode)
Sets the ANSI color mode for stdio destinations.
Definition sir.c:189
bool sir_error(PRINTF_FORMAT const char *format,...)
Dispatches a SIRL_ERROR level message.
Definition sir.c:101
bool sir_notice(PRINTF_FORMAT const char *format,...)
Dispatches a SIRL_NOTICE level message.
Definition sir.c:85
bool sir_stderrlevels(sir_levels levels)
Set new level registrations for stderr.
Definition sir.c:205
sir_textcolor sir_makergb(sir_textcolor r, sir_textcolor g, sir_textcolor b)
Creates a sir_textcolor from red, green, and blue components.
Definition sir.c:185
bool sir_filelevels(sirfileid id, sir_levels levels)
Set new level registrations for a log file already managed by libsir.
Definition sir.c:158
bool sir_syslogopts(sir_options opts)
Set new formatting options for the system logger destination.
Definition sir.c:228
bool sir_unloadplugin(sirpluginid id)
Unloads a previously registered plugin module.
Definition sir.c:149
bool sir_stdoutlevels(sir_levels levels)
Set new level registrations for stdout.
Definition sir.c:193
uint32_t sir_getversionhex(void)
Returns the current libsir version as a number.
Definition sir.c:263
bool sir_debug(PRINTF_FORMAT const char *format,...)
Dispatches a SIRL_DEBUG level message.
Definition sir.c:69
bool sir_resettextstyles(void)
Reset text styling for stdio (stdout/stderr) destinations to their default values.
Definition sir.c:181
bool sir_info(PRINTF_FORMAT const char *format,...)
Dispatches a SIRL_INFO level message.
Definition sir.c:77
bool sir_cleanup(void)
Tears down and cleans up libsir after use.
Definition sir.c:52
sirfileid sir_addfile(const char *path, sir_levels levels, sir_options opts)
Adds a log file and registers it to receive log output.
Definition sir.c:132
bool sir_init(sirinit *si)
Initializes libsir for use.
Definition sir.c:48
bool sir_crit(PRINTF_FORMAT const char *format,...)
Dispatches a SIRL_CRIT level message.
Definition sir.c:109
bool sir_remfile(sirfileid id)
Removes a file previously added to libsir.
Definition sir.c:136
bool sir_syslogid(const char *identity)
Set new system logger identity.
Definition sir.c:239
bool sir_warn(PRINTF_FORMAT const char *format,...)
Dispatches a SIRL_WARN level message.
Definition sir.c:93
uint16_t sir_geterror(char message[SIR_MAXERROR])
Retrieves a formatted message for the last error that occurred on the calling thread and returns the ...
Definition sir.c:60
bool sir_stdoutopts(sir_options opts)
Set new formatting options for stdout.
Definition sir.c:199
bool sir_makeinit(sirinit *si)
Fills out a sirinit structure with default values.
Definition sir.c:44
bool sir_syslogcat(const char *category)
Set new system logger category.
Definition sir.c:249
bool sir_isinitialized(void)
Determines whether or not libsir is in the initialized state.
Definition sir.c:56
const char * sir_getversionstring(void)
Returns the current libsir version as a string.
Definition sir.c:259
void sir_geterrorinfo(sir_errorinfo *err)
Retrieves granular information about the last error that occurred on the calling thread.
Definition sir.c:64
bool sir_fileopts(sirfileid id, sir_options opts)
Set new formatting options for a log file already managed by libsir.
Definition sir.c:164
bool sir_isprerelease(void)
Whether or not this is a pre-release version of libsir.
Definition sir.c:267
bool sir_emerg(PRINTF_FORMAT const char *format,...)
Dispatches a SIRL_EMERG level message.
Definition sir.c:125
uint16_t sir_level
The sir_level type.
Definition types.h:71
uint32_t sirfileid
Log file identifier type.
Definition types.h:49
sir_textattr
Attributes for stdio output.
Definition types.h:107
#define SIRL_EMERG
Nuclear war, Armageddon, etc.
Definition types.h:59
sir_colormode
Color mode selection.
Definition types.h:99
#define SIRL_ERROR
Errors.
Definition types.h:62
uint16_t sir_levels
sir_level bitmask type.
Definition types.h:74
#define SIRL_ALERT
Action required ASAP.
Definition types.h:60
#define SIRL_WARN
Warnings that could likely be ignored.
Definition types.h:63
#define SIRL_INFO
Informational messages.
Definition types.h:65
#define SIRL_DEBUG
Debugging/diagnostic output.
Definition types.h:66
uint32_t sir_textcolor
stdio text color type.
Definition types.h:141
#define SIRL_CRIT
Critical errors.
Definition types.h:61
#define SIRL_NOTICE
Normal but significant.
Definition types.h:64
uint32_t sirpluginid
Plugin module identifier type.
Definition types.h:52
uint32_t sir_options
sir_option bitmask type.
Definition types.h:96
@ SIR_E_PLATFORM
Platform error code %d: %s.
Definition errors.h:67
Information about an error that occurred.
Definition types.h:150
libsir initialization and configuration data.
Definition types.h:244
libsir C++ wrapper implementation.
Definition sir.hh:79
consteval auto all_derived_from_t()
Ensures (at compile time) that all Ts are derived classes of TBase.
Definition sir.hh:778
static bool throw_on_policy(bool expr) noexcept(false)
Handles a potential error; if an error is present and the policy in place requires throwing an except...
Definition sir.hh:289
typename std::tuple_element< N, std::tuple< Ts... > >::type NthTypeOf
Utility template for obtaining the type of Nth item in a parameter pack.
Definition sir.hh:774
Public interface to libsir.
Contains all available information about an error.
Definition sir.hh:116
std::string os_message
If an OS/libc error, the associated message.
Definition sir.hh:121
std::string func
Name of the function in which the error occurred.
Definition sir.hh:117
int os_code
If an OS/libc error, the associated code.
Definition sir.hh:120
std::string file
Name of the file in which the error occurred.
Definition sir.hh:118
uint32_t line
Line number at which the error occurred.
Definition sir.hh:119
Contains basic information about an error.
Definition sir.hh:91
uint16_t code
Numeric error code (see sir_errorcode).
Definition sir.hh:92
std::string message
Formatted error message.
Definition sir.hh:93