musique/lib/link/include/ableton/util/Log.hpp
2023-01-14 22:52:45 +01:00

177 lines
3.5 KiB
C++

// Copyright: 2014, Ableton AG, Berlin, all rights reserved
#pragma once
#include <ableton/util/Injected.hpp>
#include <iostream>
#include <string>
namespace ableton
{
namespace util
{
// Null object for the Log concept
struct NullLog
{
template <typename T>
friend const NullLog& operator<<(const NullLog& log, const T&)
{
return log;
}
friend const NullLog& debug(const NullLog& log)
{
return log;
}
friend const NullLog& info(const NullLog& log)
{
return log;
}
friend const NullLog& warning(const NullLog& log)
{
return log;
}
friend const NullLog& error(const NullLog& log)
{
return log;
}
friend NullLog channel(const NullLog&, std::string)
{
return {};
}
};
// std streams-based log
struct StdLog
{
StdLog(std::string channelName = "")
: mChannelName(std::move(channelName))
{
}
// Stream type used by std log to prepend the channel name to log messages
struct StdLogStream
{
StdLogStream(std::ostream& ioStream, const std::string& channelName)
: mpIoStream(&ioStream)
, mChannelName(channelName)
{
ioStream << "[" << mChannelName << "] ";
}
StdLogStream(StdLogStream&& rhs)
: mpIoStream(rhs.mpIoStream)
, mChannelName(rhs.mChannelName)
{
rhs.mpIoStream = nullptr;
}
~StdLogStream()
{
if (mpIoStream)
{
(*mpIoStream) << "\n";
}
}
template <typename T>
std::ostream& operator<<(const T& rhs)
{
(*mpIoStream) << rhs;
return *mpIoStream;
}
std::ostream* mpIoStream;
const std::string& mChannelName;
};
friend StdLogStream debug(const StdLog& log)
{
return {std::clog, log.mChannelName};
}
friend StdLogStream info(const StdLog& log)
{
return {std::clog, log.mChannelName};
}
friend StdLogStream warning(const StdLog& log)
{
return {std::clog, log.mChannelName};
}
friend StdLogStream error(const StdLog& log)
{
return {std::cerr, log.mChannelName};
}
friend StdLog channel(const StdLog& log, const std::string& channelName)
{
auto compositeName =
log.mChannelName.empty() ? channelName : log.mChannelName + "::" + channelName;
return {std::move(compositeName)};
}
std::string mChannelName;
};
// Log adapter that adds timestamps
template <typename Log>
struct Timestamped
{
using InnerLog = typename util::Injected<Log>::type;
Timestamped() = default;
Timestamped(util::Injected<Log> log)
: mLog(std::move(log))
{
}
util::Injected<Log> mLog;
friend decltype(debug(std::declval<InnerLog>())) debug(const Timestamped& log)
{
return log.logTimestamp(debug(*log.mLog));
}
friend decltype(info(std::declval<InnerLog>())) info(const Timestamped& log)
{
return log.logTimestamp(info(*log.mLog));
}
friend decltype(warning(std::declval<InnerLog>())) warning(const Timestamped& log)
{
return log.logTimestamp(warning(*log.mLog));
}
friend decltype(error(std::declval<InnerLog>())) error(const Timestamped& log)
{
return log.logTimestamp(error(*log.mLog));
}
friend Timestamped channel(const Timestamped& log, const std::string& channelName)
{
return {channel(*log.mLog, channelName)};
}
template <typename Stream>
Stream logTimestamp(Stream&& streamRef) const
{
using namespace std::chrono;
Stream stream = std::forward<Stream>(streamRef);
stream << "|"
<< duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count()
<< "ms| ";
return stream;
}
};
} // namespace util
} // namespace ableton