LogLevel log_level = LogLevel::WARN;
bool log_to_console = true; // whether we should output log messages to console
+bool log_current_line;
// Log a message
void log(LogLevel lvl, const char *msg) noexcept
}
}
+// Log a multi-part message beginning
+void logMsgBegin(LogLevel lvl, const char *msg) noexcept
+{
+ log_current_line = lvl >= log_level;
+ if (log_current_line) {
+ if (log_to_console) {
+ std::cout << "dinit: " << msg;
+ }
+ }
+}
+
+// Continue a multi-part log message
+void logMsgPart(const char *msg) noexcept
+{
+ if (log_current_line) {
+ if (log_to_console) {
+ std::cout << msg;
+ }
+ }
+}
+
+// Complete a multi-part log message
+void logMsgEnd(const char *msg) noexcept
+{
+ if (log_current_line) {
+ if (log_to_console) {
+ std::cout << msg << std::endl;
+ }
+ }
+}
+
void logServiceStarted(const char *service_name) noexcept
{
if (log_to_console) {
// Logging for Dinit
#include <string>
+#include <cstdio>
+#include <climits>
enum class LogLevel {
DEBUG,
extern bool log_to_console;
void log(LogLevel lvl, const char *msg) noexcept;
+void logMsgBegin(LogLevel lvl, const char *msg) noexcept;
+void logMsgPart(const char *msg) noexcept;
+void logMsgEnd(const char *msg) noexcept;
void logServiceStarted(const char *service_name) noexcept;
void logServiceFailed(const char *service_name) noexcept;
void logServiceStopped(const char *service_name) noexcept;
-static inline void log(LogLevel lvl, const std::string &str)
+// Convenience methods which perform type conversion of the argument.
+// There is some duplication here that could possibly be avoided, but
+// it doesn't seem like a big deal.
+static inline void log(LogLevel lvl, const std::string &str) noexcept
{
log(lvl, str.c_str());
}
-static inline void logServiceStarted(const std::string &str)
+static inline void logMsgBegin(LogLevel lvl, const std::string &str) noexcept
+{
+ logMsgBegin(lvl, str.c_str());
+}
+
+static inline void logMsgBegin(LogLevel lvl, int a) noexcept
+{
+ constexpr int bufsz = (CHAR_BIT * sizeof(int) - 1) / 3 + 2;
+ char nbuf[bufsz];
+ snprintf(nbuf, bufsz, "%d", a);
+ logMsgBegin(lvl, nbuf);
+}
+
+static inline void logMsgPart(const std::string &str) noexcept
+{
+ logMsgPart(str.c_str());
+}
+
+static inline void logMsgPart(int a) noexcept
+{
+ constexpr int bufsz = (CHAR_BIT * sizeof(int) - 1) / 3 + 2;
+ char nbuf[bufsz];
+ snprintf(nbuf, bufsz, "%d", a);
+ logMsgPart(nbuf);
+}
+
+static inline void logMsgEnd(const std::string &str) noexcept
+{
+ logMsgEnd(str.c_str());
+}
+
+static inline void logMsgEnd(int a) noexcept
+{
+ constexpr int bufsz = (CHAR_BIT * sizeof(int) - 1) / 3 + 2;
+ char nbuf[bufsz];
+ snprintf(nbuf, bufsz, "%d", a);
+ logMsgEnd(nbuf);
+}
+
+static inline void logServiceStarted(const std::string &str) noexcept
{
logServiceStarted(str.c_str());
}
-static inline void logServiceFailed(const std::string &str)
+static inline void logServiceFailed(const std::string &str) noexcept
{
logServiceFailed(str.c_str());
}
-static inline void logServiceStopped(const std::string &str)
+static inline void logServiceStopped(const std::string &str) noexcept
{
logServiceStopped(str.c_str());
}
+// It's not intended that methods in this namespace be called directly:
+namespace dinit_log {
+ template <typename A> static inline void logParts(A a) noexcept
+ {
+ logMsgEnd(a);
+ }
+
+ template <typename A, typename ...B> static inline void logParts(A a, B... b) noexcept
+ {
+ logMsgPart(a);
+ logParts(b...);
+ }
+}
+
+// Variadic 'log' method.
+template <typename A, typename ...B> static inline void log(LogLevel lvl, A a, B ...b) noexcept
+{
+ logMsgBegin(lvl, a);
+ dinit_log::logParts(b...);
+}
+
#endif