184 lines
6.1 KiB
C++
184 lines
6.1 KiB
C++
#ifndef FSFW_EXAMPLE_HOSTED_TESTFMT_H
|
|
#define FSFW_EXAMPLE_HOSTED_TESTFMT_H
|
|
|
|
#include <fmt/chrono.h>
|
|
#include <fmt/color.h>
|
|
#include <fmt/compile.h>
|
|
#include <fmt/core.h>
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
|
|
#include "fsfw/ipc/MutexFactory.h"
|
|
#include "fsfw/ipc/MutexGuard.h"
|
|
#include "fsfw/ipc/MutexIF.h"
|
|
#include "fsfw/timemanager/Clock.h"
|
|
|
|
#define __FILENAME_REL__ (((const char *)__FILE__ + SOURCE_PATH_SIZE))
|
|
#define __FILENAME__ \
|
|
(strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
|
|
|
void fmtTests();
|
|
|
|
namespace sif {
|
|
|
|
static std::array<char, 524> PRINT_BUF = {};
|
|
|
|
static const char INFO_PREFIX[] = "INFO";
|
|
static const char DEBUG_PREFIX[] = "DEBUG";
|
|
static const char WARNING_PREFIX[] = "WARNING";
|
|
static const char ERROR_PREFIX[] = "ERROR";
|
|
|
|
enum class LogLevel : unsigned int {
|
|
DEBUG = 0,
|
|
INFO = 1,
|
|
WARNING = 2,
|
|
ERROR = 3
|
|
};
|
|
|
|
static const char *PREFIX_ARR[4] = {DEBUG_PREFIX, INFO_PREFIX, WARNING_PREFIX,
|
|
ERROR_PREFIX};
|
|
|
|
static const std::array<fmt::color, 4> LOG_COLOR_ARR = {
|
|
fmt::color::deep_sky_blue, fmt::color::forest_green, fmt::color::orange_red,
|
|
fmt::color::red};
|
|
|
|
static MutexIF *PRINT_MUTEX = MutexFactory::instance()->createMutex();
|
|
|
|
static size_t writeTypePrefix(LogLevel level) {
|
|
auto idx = static_cast<unsigned int>(level);
|
|
const auto result = fmt::format_to_n(
|
|
PRINT_BUF.begin(), PRINT_BUF.size() - 1,
|
|
fmt::runtime(fmt::format(fg(LOG_COLOR_ARR[idx]), PREFIX_ARR[idx])));
|
|
return result.size;
|
|
}
|
|
|
|
template <typename... T>
|
|
size_t logTraced(LogLevel level, const char *file, unsigned int line,
|
|
bool timed, fmt::format_string<T...> fmt,
|
|
T &&...args) noexcept {
|
|
try {
|
|
MutexGuard mg(PRINT_MUTEX);
|
|
size_t bufPos = writeTypePrefix(level);
|
|
auto currentIter = PRINT_BUF.begin() + bufPos;
|
|
if (timed) {
|
|
Clock::TimeOfDay_t logTime;
|
|
Clock::getDateAndTime(&logTime);
|
|
const auto result =
|
|
fmt::format_to_n(currentIter, PRINT_BUF.size() - 1 - bufPos,
|
|
" | {}[l.{}] | {:02}:{:02}:{:02}.{:03} | {}", file,
|
|
line, logTime.hour, logTime.minute, logTime.second,
|
|
logTime.usecond / 1000, fmt::format(fmt, args...));
|
|
*result.out = '\0';
|
|
bufPos += result.size;
|
|
} else {
|
|
const auto result = fmt::format_to_n(
|
|
currentIter, PRINT_BUF.size() - 1 - bufPos, " | {}[l.{}] | {}", file,
|
|
line, fmt::format(fmt, args...));
|
|
*result.out = '\0';
|
|
bufPos += result.size;
|
|
}
|
|
|
|
fmt::print(fmt::runtime(PRINT_BUF.data()));
|
|
return bufPos;
|
|
} catch (const fmt::v8::format_error &e) {
|
|
fmt::print("Printing failed with error: {}\n", e.what());
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
template <typename... T>
|
|
size_t log(LogLevel level, bool timed, fmt::format_string<T...> fmt,
|
|
T &&...args) noexcept {
|
|
try {
|
|
MutexGuard mg(PRINT_MUTEX);
|
|
size_t bufPos = writeTypePrefix(level);
|
|
auto currentIter = PRINT_BUF.begin() + bufPos;
|
|
if (timed) {
|
|
Clock::TimeOfDay_t logTime;
|
|
Clock::getDateAndTime(&logTime);
|
|
const auto result = fmt::format_to_n(
|
|
currentIter, PRINT_BUF.size() - bufPos,
|
|
" | {:02}:{:02}:{:02}.{:03} | {}", logTime.hour, logTime.minute,
|
|
logTime.second, logTime.usecond / 1000, fmt::format(fmt, args...));
|
|
bufPos += result.size;
|
|
}
|
|
fmt::print(fmt::runtime(PRINT_BUF.data()));
|
|
return bufPos;
|
|
} catch (const fmt::v8::format_error &e) {
|
|
fmt::print("Printing failed with error: {}\n", e.what());
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
template <typename... T>
|
|
void fdebug(const char *file, unsigned int line, fmt::format_string<T...> fmt,
|
|
T &&...args) noexcept {
|
|
logTraced(LogLevel::DEBUG, file, line, false, fmt, args...);
|
|
}
|
|
|
|
template <typename... T>
|
|
void fdebug_t(const char *file, unsigned int line, fmt::format_string<T...> fmt,
|
|
T &&...args) noexcept {
|
|
logTraced(LogLevel::DEBUG, file, line, true, fmt, args...);
|
|
}
|
|
|
|
template <typename... T>
|
|
void finfo_t(fmt::format_string<T...> fmt, T &&...args) {
|
|
log(LogLevel::INFO, true, fmt, args...);
|
|
}
|
|
|
|
template <typename... T> void finfo(fmt::format_string<T...> fmt, T &&...args) {
|
|
log(LogLevel::INFO, false, fmt, args...);
|
|
}
|
|
|
|
template <typename... T>
|
|
void fwarning(const char *file, unsigned int line, fmt::format_string<T...> fmt,
|
|
T &&...args) {
|
|
logTraced(LogLevel::WARNING, file, line, false, fmt, args...);
|
|
}
|
|
|
|
template <typename... T>
|
|
void fwarning_t(const char *file, unsigned int line,
|
|
fmt::format_string<T...> fmt, T &&...args) {
|
|
logTraced(LogLevel::WARNING, file, line, true, fmt, args...);
|
|
}
|
|
|
|
template <typename... T>
|
|
void ferror(const char *file, unsigned int line, fmt::format_string<T...> fmt,
|
|
T &&...args) {
|
|
logTraced(LogLevel::ERROR, file, line, false, fmt, args...);
|
|
}
|
|
|
|
template <typename... T>
|
|
void ferror_t(const char *file, unsigned int line, fmt::format_string<T...> fmt,
|
|
T &&...args) {
|
|
logTraced(LogLevel::ERROR, file, line, true, fmt, args...);
|
|
}
|
|
|
|
} // namespace sif
|
|
|
|
#define FSFW_LOGI(format, ...) finfo(FMT_STRING(format), __VA_ARGS__)
|
|
|
|
#define FSFW_LOGIT(format, ...) finfo_t(FMT_STRING(format), __VA_ARGS__)
|
|
|
|
#define FSFW_LOGD(format, ...) \
|
|
sif::fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
|
|
|
#define FSFW_LOGDT(format, ...) \
|
|
fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
|
|
|
#define FSFW_LOGW(format, ...) \
|
|
fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
|
|
|
#define FSFW_LOGWT(format, ...) \
|
|
fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
|
|
|
#define FSFW_LOGE(format, ...) \
|
|
fdebug(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
|
|
|
#define FSFW_LOGET(format, ...) \
|
|
fdebug_t(__FILENAME__, __LINE__, FMT_STRING(format), __VA_ARGS__)
|
|
|
|
#endif // FSFW_EXAMPLE_HOSTED_TESTFMT_H
|