7 #ifndef INCLUDE_SCINE_UTILS_LOG_H
8 #define INCLUDE_SCINE_UTILS_LOG_H
15 #include <unordered_map>
28 static auto testIsStreamWriter(
long) -> std::false_type;
57 struct CORE_EXPORT
Log {
64 using SinkPtr = std::shared_ptr<std::ostream>;
91 sinks_.emplace(std::move(n), std::move(s));
96 sinks_.emplace(std::move(n), std::move(s));
108 inline void remove(
const std::string& name) {
109 sinks_.erase(expectantFind(name));
119 auto findIter = expectantFind(name);
120 auto ptr = std::move(findIter->second);
121 sinks_.erase(findIter);
126 inline explicit operator bool()
const {
127 return !sinks_.empty();
138 template<
typename... Args>
140 const int sz = snprintf(NULL, 0, std::forward<Args>(args)...);
141 char* buf =
new char[sz + 1];
142 snprintf(buf, sz + 1, std::forward<Args>(args)...);
143 (*this) << std::string(buf);
153 std::enable_if_t<Traits::isStreamWriter<T>::value,
Domain&> operator<<(T&& f) {
154 for (
auto& nameSinkPair : sinks_) {
155 f(*nameSinkPair.second);
167 std::enable_if_t<!Traits::isStreamWriter<T>::value,
Domain&> operator<<(T&& t) {
168 for (
auto& nameSinkPair : sinks_) {
169 *nameSinkPair.second << t;
195 template<
typename... Args>
196 inline void lazy(Args&&... args) {
198 sink(std::forward<Args>(args)...);
203 inline void line(
const std::string& s) {
213 template<
typename F,
typename... Args>
214 inline void sink(F&& f, Args&&... args) {
216 return sink(args...);
219 using MapType = std::unordered_map<std::string, SinkPtr>;
220 using iterator =
typename MapType::iterator;
222 inline iterator expectantFind(
const std::string& sinkName) {
223 const auto findIter = sinks_.find(sinkName);
224 if (findIter == std::end(sinks_)) {
225 throw std::out_of_range(
"Sink name not found");
230 std::unordered_map<std::string, SinkPtr> sinks_;
244 return std::make_shared<std::ofstream>(filename, std::ios_base::out | std::ios_base::app);
249 return std::make_shared<std::ostream>(std::cout.rdbuf());
254 return std::make_shared<std::ostream>(std::cerr.rdbuf());
263 static inline std::ostream&
nl(std::ostream& os) {
269 static inline std::ostream&
flush(std::ostream& os) {
275 static inline std::ostream&
endl(std::ostream& os) {
285 for (
Domain& domain : *
this) {
295 inline void sinkAllToFile(
const std::string& file, std::string sinkName =
"") {
296 if (sinkName.empty()) {
297 sinkName = std::to_string(std::hash<std::string>{}(file));
300 auto sink = fileSink(file);
301 for (
Domain& domain : *
this) {
302 domain.
add(sinkName, sink);
310 inline iterator begin() {
311 return std::addressof(debug);
313 inline iterator end() {
314 return std::addressof(output) + 1;
316 inline const_iterator begin()
const {
317 return std::addressof(debug);
319 inline const_iterator end()
const {
320 return std::addressof(output) + 1;
std::shared_ptr< std::ostream > SinkPtr
Type used to represent stream sinks for logging domains.
Definition: Log.h:64
void sinkAllToFile(const std::string &file, std::string sinkName="")
Add a sink to file for all domains.
Definition: Log.h:295
void printf(Args &&...args)
Formatted logging analog to pfrintf.
Definition: Log.h:139
void clear()
Add a sink to file for all domains.
Definition: Log.h:284
static SinkPtr coutSink()
Sink referring to std::cout.
Definition: Log.h:248
static SinkPtr fileSink(const std::string &filename)
Sink referring to std::cout.
Definition: Log.h:243
Multi-sink object representing a single logging domain.
Definition: Log.h:85
static std::ostream & endl(std::ostream &os)
Inserts a newline character and flushes the stream.
Definition: Log.h:275
void line(const std::string &s)
Prints a single string with a newline character.
Definition: Log.h:203
Multi-domain multi-sink logger.
Definition: Log.h:57
static SinkPtr cerrSink()
Sink referring to std::cerr.
Definition: Log.h:253
SinkPtr extract(const std::string &name)
Extracts a sink by name.
Definition: Log.h:118
static std::ostream & nl(std::ostream &os)
Inserts a newline character into the stream.
Definition: Log.h:263
void add(std::string n, SinkPtr s)
Add a sink.
Definition: Log.h:95
void clear()
Remove all sinks.
Definition: Log.h:100
Domain(std::string n, SinkPtr s)
Single-sink constructor.
Definition: Log.h:90
static Log silent()
Creates a silent Log instance (i.e. all levels are cleared)
Definition: Log.h:258
Domain debug
Non-transient debug statements.
Definition: Log.h:333
static std::ostream & flush(std::ostream &os)
Forces flush of stream.
Definition: Log.h:269
void lazy(Args &&...args)
Conditional logging with nullary callables.
Definition: Log.h:196