diff --git a/include/spdlog/common.h b/include/spdlog/common.h index c1e06f86..48ff80e6 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -2,7 +2,6 @@ // Distributed under the MIT License (http://opensource.org/licenses/MIT) #pragma once - #include #include diff --git a/include/spdlog/details/file_helper-inl.h b/include/spdlog/details/file_helper-inl.h deleted file mode 100644 index 51bc46bd..00000000 --- a/include/spdlog/details/file_helper-inl.h +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace spdlog { -namespace details { - - file_helper::file_helper(const file_event_handlers &event_handlers) - : event_handlers_(event_handlers) -{} - - file_helper::~file_helper() -{ - close(); -} - - void file_helper::open(const filename_t &fname, bool truncate) -{ - close(); - filename_ = fname; - - auto *mode = SPDLOG_FILENAME_T("ab"); - auto *trunc_mode = SPDLOG_FILENAME_T("wb"); - - if (event_handlers_.before_open) - { - event_handlers_.before_open(filename_); - } - for (int tries = 0; tries < open_tries_; ++tries) - { - // create containing folder if not exists already. - os::create_dir(os::dir_name(fname)); - if (truncate) - { - // Truncate by opening-and-closing a tmp file in "wb" mode, always - // opening the actual log-we-write-to in "ab" mode, since that - // interacts more politely with eternal processes that might - // rotate/truncate the file underneath us. - std::FILE *tmp; - if (os::fopen_s(&tmp, fname, trunc_mode)) - { - continue; - } - std::fclose(tmp); - } - if (!os::fopen_s(&fd_, fname, mode)) - { - if (event_handlers_.after_open) - { - event_handlers_.after_open(filename_, fd_); - } - return; - } - - details::os::sleep_for_millis(open_interval_); - } - - throw_spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing", errno); -} - - void file_helper::reopen(bool truncate) -{ - if (filename_.empty()) - { - throw_spdlog_ex("Failed re opening file - was not opened before"); - } - this->open(filename_, truncate); -} - - void file_helper::flush() -{ - if (std::fflush(fd_) != 0) - { - throw_spdlog_ex("Failed flush to file " + os::filename_to_str(filename_), errno); - } -} - - void file_helper::sync() -{ - if (!os::fsync(fd_)) - { - throw_spdlog_ex("Failed to fsync file " + os::filename_to_str(filename_), errno); - } -} - - void file_helper::close() -{ - if (fd_ != nullptr) - { - if (event_handlers_.before_close) - { - event_handlers_.before_close(filename_, fd_); - } - - std::fclose(fd_); - fd_ = nullptr; - - if (event_handlers_.after_close) - { - event_handlers_.after_close(filename_); - } - } -} - - void file_helper::write(const memory_buf_t &buf) -{ - size_t msg_size = buf.size(); - auto data = buf.data(); - if (std::fwrite(data, 1, msg_size, fd_) != msg_size) - { - throw_spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno); - } -} - - size_t file_helper::size() const -{ - if (fd_ == nullptr) - { - throw_spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_)); - } - return os::filesize(fd_); -} - - const filename_t &file_helper::filename() const -{ - return filename_; -} - -// -// return file path and its extension: -// -// "mylog.txt" => ("mylog", ".txt") -// "mylog" => ("mylog", "") -// "mylog." => ("mylog.", "") -// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") -// -// the starting dot in filenames is ignored (hidden files): -// -// ".mylog" => (".mylog". "") -// "my_folder/.mylog" => ("my_folder/.mylog", "") -// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") - std::tuple file_helper::split_by_extension(const filename_t &fname) -{ - auto ext_index = fname.rfind('.'); - - // no valid extension found - return whole path and empty string as - // extension - if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1) - { - return std::make_tuple(fname, filename_t()); - } - - // treat cases like "/etc/rc.d/somelogfile or "/abc/.hiddenfile" - auto folder_index = fname.find_last_of(details::os::folder_seps_filename); - if (folder_index != filename_t::npos && folder_index >= ext_index - 1) - { - return std::make_tuple(fname, filename_t()); - } - - // finally - return a valid base and extension tuple - return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); -} - -} // namespace details -} // namespace spdlog diff --git a/include/spdlog/details/log_msg-inl.h b/include/spdlog/details/log_msg-inl.h deleted file mode 100644 index 738c6324..00000000 --- a/include/spdlog/details/log_msg-inl.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -# include - -#include - -namespace spdlog { -namespace details { - - log_msg::log_msg(spdlog::log_clock::time_point log_time, spdlog::source_loc loc, string_view_t a_logger_name, - spdlog::level lvl, spdlog::string_view_t msg) - : logger_name(a_logger_name) - , log_level(lvl) - , time(log_time) -#ifndef SPDLOG_NO_THREAD_ID - , thread_id(os::thread_id()) -#endif - , source(loc) - , payload(msg) -{} - - log_msg::log_msg( - spdlog::source_loc loc, string_view_t a_logger_name, spdlog::level lvl, spdlog::string_view_t msg) - : log_msg(os::now(), loc, a_logger_name, lvl, msg) -{} - - log_msg::log_msg(string_view_t a_logger_name, spdlog::level lvl, spdlog::string_view_t msg) - : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg) -{} - -} // namespace details -} // namespace spdlog diff --git a/include/spdlog/details/log_msg_buffer-inl.h b/include/spdlog/details/log_msg_buffer-inl.h deleted file mode 100644 index a8b5b8ca..00000000 --- a/include/spdlog/details/log_msg_buffer-inl.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -# include - -namespace spdlog { -namespace details { - - log_msg_buffer::log_msg_buffer(const log_msg &orig_msg) - : log_msg{orig_msg} -{ - buffer.append(logger_name.begin(), logger_name.end()); - buffer.append(payload.begin(), payload.end()); - update_string_views(); -} - - log_msg_buffer::log_msg_buffer(const log_msg_buffer &other) - : log_msg{other} -{ - buffer.append(logger_name.begin(), logger_name.end()); - buffer.append(payload.begin(), payload.end()); - update_string_views(); -} - - log_msg_buffer::log_msg_buffer(log_msg_buffer &&other) noexcept - : log_msg{other} - , buffer{std::move(other.buffer)} -{ - update_string_views(); -} - - log_msg_buffer &log_msg_buffer::operator=(const log_msg_buffer &other) -{ - log_msg::operator=(other); - buffer.clear(); - buffer.append(other.buffer.data(), other.buffer.data() + other.buffer.size()); - update_string_views(); - return *this; -} - - log_msg_buffer &log_msg_buffer::operator=(log_msg_buffer &&other) noexcept -{ - log_msg::operator=(other); - buffer = std::move(other.buffer); - update_string_views(); - return *this; -} - - void log_msg_buffer::update_string_views() -{ - logger_name = string_view_t{buffer.data(), logger_name.size()}; - payload = string_view_t{buffer.data() + logger_name.size(), payload.size()}; -} - -} // namespace details -} // namespace spdlog diff --git a/include/spdlog/details/os-inl.h b/include/spdlog/details/os-inl.h deleted file mode 100644 index e991f9cf..00000000 --- a/include/spdlog/details/os-inl.h +++ /dev/null @@ -1,630 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -# include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 - -# include // for _get_osfhandle, _isatty, _fileno -# include // for _get_pid -# include -# include // for FlushFileBuffers - -# ifdef __MINGW32__ -# include -# endif - -# if defined(SPDLOG_WCHAR_FILENAMES) -# include -# include -# endif - -# include // for _mkdir/_wmkdir - -#else // unix - -# include -# include - -# ifdef __linux__ -# include //Use gettid() syscall under linux to get thread id - -# elif defined(_AIX) -# include // for pthread_getthrds_np - -# elif defined(__DragonFly__) || defined(__FreeBSD__) -# include // for pthread_getthreadid_np - -# elif defined(__NetBSD__) -# include // for _lwp_self - -# elif defined(__sun) -# include // for thr_self -# endif - -#endif // unix - -#if defined __APPLE__ -# include -#endif - -#ifndef __has_feature // Clang - feature checking macros. -# define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif - -namespace spdlog { -namespace details { -namespace os { - - spdlog::log_clock::time_point now() noexcept -{ - -#if defined __linux__ && defined SPDLOG_CLOCK_COARSE - timespec ts; - ::clock_gettime(CLOCK_REALTIME_COARSE, &ts); - return std::chrono::time_point( - std::chrono::duration_cast(std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); - -#else - return log_clock::now(); -#endif -} - std::tm localtime(const std::time_t &time_tt) noexcept -{ - -#ifdef _WIN32 - std::tm tm; - ::localtime_s(&tm, &time_tt); -#else - std::tm tm; - ::localtime_r(&time_tt, &tm); -#endif - return tm; -} - - std::tm localtime() noexcept -{ - std::time_t now_t = ::time(nullptr); - return localtime(now_t); -} - - std::tm gmtime(const std::time_t &time_tt) noexcept -{ - -#ifdef _WIN32 - std::tm tm; - ::gmtime_s(&tm, &time_tt); -#else - std::tm tm; - ::gmtime_r(&time_tt, &tm); -#endif - return tm; -} - - std::tm gmtime() noexcept -{ - std::time_t now_t = ::time(nullptr); - return gmtime(now_t); -} - -// fopen_s on non windows for writing - bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) -{ -#ifdef _WIN32 -# ifdef SPDLOG_WCHAR_FILENAMES - *fp = ::_wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); -# else - *fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO); -# endif -# if defined(SPDLOG_PREVENT_CHILD_FD) - if (*fp != nullptr) - { - auto file_handle = reinterpret_cast(_get_osfhandle(::_fileno(*fp))); - if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) - { - ::fclose(*fp); - *fp = nullptr; - } - } -# endif -#else // unix -# if defined(SPDLOG_PREVENT_CHILD_FD) - const int mode_flag = mode == SPDLOG_FILENAME_T("ab") ? O_APPEND : O_TRUNC; - const int fd = ::open((filename.c_str()), O_CREAT | O_WRONLY | O_CLOEXEC | mode_flag, mode_t(0644)); - if (fd == -1) - { - return true; - } - *fp = ::fdopen(fd, mode.c_str()); - if (*fp == nullptr) - { - ::close(fd); - } -# else - *fp = ::fopen((filename.c_str()), mode.c_str()); -# endif -#endif - - return *fp == nullptr; -} - - int remove(const filename_t &filename) noexcept -{ -#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) - return ::_wremove(filename.c_str()); -#else - return std::remove(filename.c_str()); -#endif -} - - int remove_if_exists(const filename_t &filename) noexcept -{ - return path_exists(filename) ? remove(filename) : 0; -} - - int rename(const filename_t &filename1, const filename_t &filename2) noexcept -{ -#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) - return ::_wrename(filename1.c_str(), filename2.c_str()); -#else - return std::rename(filename1.c_str(), filename2.c_str()); -#endif -} - -// Return true if path exists (file or directory) - bool path_exists(const filename_t &filename) noexcept -{ -#ifdef _WIN32 -# ifdef SPDLOG_WCHAR_FILENAMES - auto attribs = ::GetFileAttributesW(filename.c_str()); -# else - auto attribs = ::GetFileAttributesA(filename.c_str()); -# endif - return attribs != INVALID_FILE_ATTRIBUTES; -#else // common linux/unix all have the stat system call - struct stat buffer; - return (::stat(filename.c_str(), &buffer) == 0); -#endif -} - -#ifdef _MSC_VER -// avoid warning about unreachable statement at the end of filesize() -# pragma warning(push) -# pragma warning(disable : 4702) -#endif - -// Return file size according to open FILE* object - size_t filesize(FILE *f) -{ - if (f == nullptr) - { - throw_spdlog_ex("Failed getting file size. fd is null"); - } -#if defined(_WIN32) && !defined(__CYGWIN__) - int fd = ::_fileno(f); -# if defined(_WIN64) // 64 bits - __int64 ret = ::_filelengthi64(fd); - if (ret >= 0) - { - return static_cast(ret); - } - -# else // windows 32 bits - long ret = ::_filelength(fd); - if (ret >= 0) - { - return static_cast(ret); - } -# endif - -#else // unix -// OpenBSD and AIX doesn't compile with :: before the fileno(..) -# if defined(__OpenBSD__) || defined(_AIX) - int fd = fileno(f); -# else - int fd = ::fileno(f); -# endif -// 64 bits(but not in osx, linux/musl or cygwin, where fstat64 is deprecated) -# if ((defined(__linux__) && defined(__GLIBC__)) || defined(__sun) || defined(_AIX)) && (defined(__LP64__) || defined(_LP64)) - struct stat64 st; - if (::fstat64(fd, &st) == 0) - { - return static_cast(st.st_size); - } -# else // other unix or linux 32 bits or cygwin - struct stat st; - if (::fstat(fd, &st) == 0) - { - return static_cast(st.st_size); - } -# endif -#endif - throw_spdlog_ex("Failed getting file size from fd", errno); - return 0; // will not be reached. -} - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -// Return utc offset in minutes or throw spdlog_ex on failure - int utc_minutes_offset(const std::tm &tm) -{ - -#ifdef _WIN32 -# if _WIN32_WINNT < _WIN32_WINNT_WS08 - TIME_ZONE_INFORMATION tzinfo; - auto rv = ::GetTimeZoneInformation(&tzinfo); -# else - DYNAMIC_TIME_ZONE_INFORMATION tzinfo; - auto rv = ::GetDynamicTimeZoneInformation(&tzinfo); -# endif - if (rv == TIME_ZONE_ID_INVALID) - throw_spdlog_ex("Failed getting timezone info. ", errno); - - int offset = -tzinfo.Bias; - if (tm.tm_isdst) - { - offset -= tzinfo.DaylightBias; - } - else - { - offset -= tzinfo.StandardBias; - } - return offset; -#else - -# if defined(sun) || defined(__sun) || defined(_AIX) || (defined(__NEWLIB__) && !defined(__TM_GMTOFF)) || \ - (!defined(_BSD_SOURCE) && !defined(_GNU_SOURCE)) - // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris - struct helper - { - static long int calculate_gmt_offset(const std::tm &localtm = details::os::localtime(), const std::tm &gmtm = details::os::gmtime()) - { - int local_year = localtm.tm_year + (1900 - 1); - int gmt_year = gmtm.tm_year + (1900 - 1); - - long int days = ( - // difference in day of year - localtm.tm_yday - - gmtm.tm_yday - - // + intervening leap days - + ((local_year >> 2) - (gmt_year >> 2)) - (local_year / 100 - gmt_year / 100) + - ((local_year / 100 >> 2) - (gmt_year / 100 >> 2)) - - // + difference in years * 365 */ - + static_cast(local_year - gmt_year) * 365); - - long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour); - long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min); - long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec); - - return secs; - } - }; - - auto offset_seconds = helper::calculate_gmt_offset(tm); -# else - auto offset_seconds = tm.tm_gmtoff; -# endif - - return static_cast(offset_seconds / 60); -#endif -} - -// Return current thread id as size_t -// It exists because the std::this_thread::get_id() is much slower(especially -// under VS 2013) - size_t _thread_id() noexcept -{ -#ifdef _WIN32 - return static_cast(::GetCurrentThreadId()); -#elif defined(__linux__) -# if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) -# define SYS_gettid __NR_gettid -# endif - return static_cast(::syscall(SYS_gettid)); -#elif defined(_AIX) - struct __pthrdsinfo buf; - int reg_size = 0; - pthread_t pt = pthread_self(); - int retval = pthread_getthrds_np(&pt, PTHRDSINFO_QUERY_TID, &buf, sizeof(buf), NULL, ®_size); - int tid = (!retval) ? buf.__pi_tid : 0; - return static_cast(tid); -#elif defined(__DragonFly__) || defined(__FreeBSD__) - return static_cast(::pthread_getthreadid_np()); -#elif defined(__NetBSD__) - return static_cast(::_lwp_self()); -#elif defined(__OpenBSD__) - return static_cast(::getthrid()); -#elif defined(__sun) - return static_cast(::thr_self()); -#elif __APPLE__ - uint64_t tid; - // There is no pthread_threadid_np prior to 10.6, and it is not supported on any PPC, - // including 10.6.8 Rosetta. __POWERPC__ is Apple-specific define encompassing ppc and ppc64. -# if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060) || defined(__POWERPC__) - tid = pthread_mach_thread_np(pthread_self()); -# elif MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - if (&pthread_threadid_np) - { - pthread_threadid_np(nullptr, &tid); - } - else - { - tid = pthread_mach_thread_np(pthread_self()); - } -# else - pthread_threadid_np(nullptr, &tid); -# endif - return static_cast(tid); -#else // Default to standard C++11 (other Unix) - return static_cast(std::hash()(std::this_thread::get_id())); -#endif -} - -// Return current thread id as size_t (from thread local storage) - size_t thread_id() noexcept -{ - // cache thread id in tls - static thread_local const size_t tid = _thread_id(); - return tid; -} - -// This is avoid msvc issue in sleep_for that happens if the clock changes. -// See https://github.com/gabime/spdlog/issues/609 - void sleep_for_millis(unsigned int milliseconds) noexcept -{ -#if defined(_WIN32) - ::Sleep(milliseconds); -#else - std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); -#endif -} - -// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined) -#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) - std::string filename_to_str(const filename_t &filename) -{ - memory_buf_t buf; - wstr_to_utf8buf(filename, buf); - return SPDLOG_BUF_TO_STRING(buf); -} -#else - std::string filename_to_str(const filename_t &filename) -{ - return filename; -} -#endif - - int pid() noexcept -{ - -#ifdef _WIN32 - return static_cast(::GetCurrentProcessId()); -#else - return static_cast(::getpid()); -#endif -} - -// Determine if the terminal supports colors -// Based on: https://github.com/agauniyal/rang/ - bool is_color_terminal() noexcept -{ -#ifdef _WIN32 - return true; -#else - - static const bool result = []() { - const char *env_colorterm_p = std::getenv("COLORTERM"); - if (env_colorterm_p != nullptr) - { - return true; - } - - static constexpr std::array terms = {{"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux", - "msys", "putty", "rxvt", "screen", "vt100", "xterm", "alacritty", "vt102"}}; - - const char *env_term_p = std::getenv("TERM"); - if (env_term_p == nullptr) - { - return false; - } - - return std::any_of(terms.begin(), terms.end(), [&](const char *term) { return std::strstr(env_term_p, term) != nullptr; }); - }(); - - return result; -#endif -} - -// Determine if the terminal attached -// Source: https://github.com/agauniyal/rang/ - bool in_terminal(FILE *file) noexcept -{ - -#ifdef _WIN32 - return ::_isatty(_fileno(file)) != 0; -#else - return ::isatty(fileno(file)) != 0; -#endif -} - -#if defined(SPDLOG_WCHAR_FILENAMES) && defined(_WIN32) - void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target) -{ - if (wstr.size() > static_cast((std::numeric_limits::max)()) / 2 - 1) - { - throw_spdlog_ex("UTF-16 string is too big to be converted to UTF-8"); - } - - int wstr_size = static_cast(wstr.size()); - if (wstr_size == 0) - { - target.resize(0); - return; - } - - int result_size = static_cast(target.capacity()); - if ((wstr_size + 1) * 2 > result_size) - { - result_size = ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr_size, NULL, 0, NULL, NULL); - } - - if (result_size > 0) - { - target.resize(result_size); - result_size = ::WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr_size, target.data(), result_size, NULL, NULL); - - if (result_size > 0) - { - target.resize(result_size); - return; - } - } - - throw_spdlog_ex(fmt_lib::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())); -} - - void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target) -{ - if (str.size() > static_cast((std::numeric_limits::max)()) - 1) - { - throw_spdlog_ex("UTF-8 string is too big to be converted to UTF-16"); - } - - int str_size = static_cast(str.size()); - if (str_size == 0) - { - target.resize(0); - return; - } - - // find the size to allocate for the result buffer - int result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, NULL, 0); - - if (result_size > 0) - { - target.resize(result_size); - result_size = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.data(), str_size, target.data(), result_size); - if (result_size > 0) - { - assert(result_size == target.size()); - return; - } - } - - throw_spdlog_ex(fmt_lib::format("MultiByteToWideChar failed. Last error: {}", ::GetLastError())); -} -#endif // defined(SPDLOG_WCHAR_FILENAMES) && defined(_WIN32) - -// return true on success -static bool mkdir_(const filename_t &path) -{ -#ifdef _WIN32 -# ifdef SPDLOG_WCHAR_FILENAMES - return ::_wmkdir(path.c_str()) == 0; -# else - return ::_mkdir(path.c_str()) == 0; -# endif -#else - return ::mkdir(path.c_str(), mode_t(0755)) == 0; -#endif -} - -// create the given directory - and all directories leading to it -// return true on success or if the directory already exists - bool create_dir(const filename_t &path) -{ - if (path_exists(path)) - { - return true; - } - - if (path.empty()) - { - return false; - } - - size_t search_offset = 0; - do - { - auto token_pos = path.find_first_of(folder_seps_filename, search_offset); - // treat the entire path as a folder if no folder separator not found - if (token_pos == filename_t::npos) - { - token_pos = path.size(); - } - - auto subdir = path.substr(0, token_pos); - - if (!subdir.empty() && !path_exists(subdir) && !mkdir_(subdir)) - { - return false; // return error if failed creating dir - } - search_offset = token_pos + 1; - } while (search_offset < path.size()); - - return true; -} - -// Return directory name from given path or empty string -// "abc/file" => "abc" -// "abc/" => "abc" -// "abc" => "" -// "abc///" => "abc//" - filename_t dir_name(const filename_t &path) -{ - auto pos = path.find_last_of(folder_seps_filename); - return pos != filename_t::npos ? path.substr(0, pos) : filename_t{}; -} - -std::string getenv(const char *field) -{ - -#if defined(_MSC_VER) -# if defined(__cplusplus_winrt) - return std::string{}; // not supported under uwp -# else - size_t len = 0; - char buf[128]; - bool ok = ::getenv_s(&len, buf, sizeof(buf), field) == 0; - return ok ? buf : std::string{}; -# endif -#else // revert to getenv - char *buf = ::getenv(field); - return buf ? buf : std::string{}; -#endif -} - -// Do fsync by FILE handlerpointer -// Return true on success - bool fsync(FILE *fp) -{ -#ifdef _WIN32 - return FlushFileBuffers(reinterpret_cast(_get_osfhandle(_fileno(fp)))) != 0; -#else - return ::fsync(fileno(fp)) == 0; -#endif -} - -} // namespace os -} // namespace details -} // namespace spdlog diff --git a/include/spdlog/details/periodic_worker-inl.h b/include/spdlog/details/periodic_worker-inl.h deleted file mode 100644 index 82098c70..00000000 --- a/include/spdlog/details/periodic_worker-inl.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -# include - -namespace spdlog { -namespace details { - -// stop the worker thread and join it - periodic_worker::~periodic_worker() -{ - if (worker_thread_.joinable()) - { - { - std::lock_guard lock(mutex_); - active_ = false; - } - cv_.notify_one(); - worker_thread_.join(); - } -} - -} // namespace details -} // namespace spdlog diff --git a/include/spdlog/details/periodic_worker.h b/include/spdlog/details/periodic_worker.h index 68d1d102..451f3192 100644 --- a/include/spdlog/details/periodic_worker.h +++ b/include/spdlog/details/periodic_worker.h @@ -14,6 +14,9 @@ #include #include #include + +#include + namespace spdlog { namespace details { @@ -52,5 +55,6 @@ private: std::mutex mutex_; std::condition_variable cv_; }; + } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/registry-inl.h b/include/spdlog/details/registry-inl.h deleted file mode 100644 index babc31d7..00000000 --- a/include/spdlog/details/registry-inl.h +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -# include - -#include -#include -#include -#include - -#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER -// support for the default stdout color logger -# ifdef _WIN32 -# include -# else -# include -# endif -#endif // SPDLOG_DISABLE_DEFAULT_LOGGER - -#include -#include -#include -#include -#include - -namespace spdlog { -namespace details { - - registry::registry() - : formatter_(new pattern_formatter()) -{ - -#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER - // create default logger (ansicolor_stdout_sink_mt or wincolor_stdout_sink_mt in windows). -# ifdef _WIN32 - auto color_sink = std::make_shared(); -# else - auto color_sink = std::make_shared(); -# endif - - const char *default_logger_name = ""; - default_logger_ = std::make_shared(default_logger_name, std::move(color_sink)); - loggers_[default_logger_name] = default_logger_; - -#endif // SPDLOG_DISABLE_DEFAULT_LOGGER -} - - registry::~registry() = default; - - void registry::register_logger(std::shared_ptr new_logger) -{ - std::lock_guard lock(logger_map_mutex_); - register_logger_(std::move(new_logger)); -} - - void registry::initialize_logger(std::shared_ptr new_logger) -{ - std::lock_guard lock(logger_map_mutex_); - new_logger->set_formatter(formatter_->clone()); - - if (err_handler_) - { - new_logger->set_error_handler(err_handler_); - } - - // set new level according to previously configured level or default level - auto it = log_levels_.find(new_logger->name()); - auto new_level = it != log_levels_.end() ? it->second : global_log_level_; - new_logger->set_level(new_level); - - new_logger->flush_on(flush_level_); - - if (automatic_registration_) - { - register_logger_(std::move(new_logger)); - } -} - - std::shared_ptr registry::get(const std::string &logger_name) -{ - std::lock_guard lock(logger_map_mutex_); - auto found = loggers_.find(logger_name); - return found == loggers_.end() ? nullptr : found->second; -} - - std::shared_ptr registry::default_logger() -{ - std::lock_guard lock(logger_map_mutex_); - return default_logger_; -} - -// Return raw ptr to the default logger. -// To be used directly by the spdlog default api (e.g. spdlog::info) -// This make the default API faster, but cannot be used concurrently with set_default_logger(). -// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another. - logger *registry::get_default_raw() -{ - return default_logger_.get(); -} - -// set default logger. -// default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. - void registry::set_default_logger(std::shared_ptr new_default_logger) -{ - std::lock_guard lock(logger_map_mutex_); - // remove previous default logger from the map - if (default_logger_ != nullptr) - { - loggers_.erase(default_logger_->name()); - } - if (new_default_logger != nullptr) - { - loggers_[new_default_logger->name()] = new_default_logger; - } - default_logger_ = std::move(new_default_logger); -} - - void registry::set_tp(std::shared_ptr tp) -{ - std::lock_guard lock(tp_mutex_); - tp_ = std::move(tp); -} - - std::shared_ptr registry::get_tp() -{ - std::lock_guard lock(tp_mutex_); - return tp_; -} - -// Set global formatter. Each sink in each logger will get a clone of this object - void registry::set_formatter(std::unique_ptr formatter) -{ - std::lock_guard lock(logger_map_mutex_); - formatter_ = std::move(formatter); - for (auto &l : loggers_) - { - l.second->set_formatter(formatter_->clone()); - } -} - - void registry::set_level(level level) -{ - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - l.second->set_level(level); - } - global_log_level_ = level; -} - - void registry::flush_on(level level) -{ - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - l.second->flush_on(level); - } - flush_level_ = level; -} - - void registry::set_error_handler(err_handler handler) -{ - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - l.second->set_error_handler(handler); - } - err_handler_ = std::move(handler); -} - - void registry::apply_all(const std::function)> &fun) -{ - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - fun(l.second); - } -} - - void registry::flush_all() -{ - std::lock_guard lock(logger_map_mutex_); - for (auto &l : loggers_) - { - l.second->flush(); - } -} - - void registry::drop(const std::string &logger_name) -{ - std::lock_guard lock(logger_map_mutex_); - auto is_default_logger = default_logger_ && default_logger_->name() == logger_name; - loggers_.erase(logger_name); - if (is_default_logger) - { - default_logger_.reset(); - } -} - - void registry::drop_all() -{ - std::lock_guard lock(logger_map_mutex_); - loggers_.clear(); - default_logger_.reset(); -} - -// clean all resources and threads started by the registry - void registry::shutdown() -{ - { - std::lock_guard lock(flusher_mutex_); - periodic_flusher_.reset(); - } - - drop_all(); - - { - std::lock_guard lock(tp_mutex_); - tp_.reset(); - } -} - - std::recursive_mutex ®istry::tp_mutex() -{ - return tp_mutex_; -} - - void registry::set_automatic_registration(bool automatic_registration) -{ - std::lock_guard lock(logger_map_mutex_); - automatic_registration_ = automatic_registration; -} - - void registry::set_levels(log_levels levels, level *global_level) -{ - std::lock_guard lock(logger_map_mutex_); - log_levels_ = std::move(levels); - auto global_level_requested = global_level != nullptr; - global_log_level_ = global_level_requested ? *global_level : global_log_level_; - - for (auto &logger : loggers_) - { - auto logger_entry = log_levels_.find(logger.first); - if (logger_entry != log_levels_.end()) - { - logger.second->set_level(logger_entry->second); - } - else if (global_level_requested) - { - logger.second->set_level(*global_level); - } - } -} - - registry ®istry::instance() -{ - static registry s_instance; - return s_instance; -} - - void registry::apply_logger_env_levels(std::shared_ptr new_logger) -{ - std::lock_guard lock(logger_map_mutex_); - auto it = log_levels_.find(new_logger->name()); - auto new_level = it != log_levels_.end() ? it->second : global_log_level_; - new_logger->set_level(new_level); -} - - void registry::throw_if_exists_(const std::string &logger_name) -{ - if (loggers_.find(logger_name) != loggers_.end()) - { - throw_spdlog_ex("logger with name '" + logger_name + "' already exists"); - } -} - - void registry::register_logger_(std::shared_ptr new_logger) -{ - auto logger_name = new_logger->name(); - throw_if_exists_(logger_name); - loggers_[logger_name] = std::move(new_logger); -} - -} // namespace details -} // namespace spdlog diff --git a/include/spdlog/details/thread_pool-inl.h b/include/spdlog/details/thread_pool-inl.h deleted file mode 100644 index ac335a72..00000000 --- a/include/spdlog/details/thread_pool-inl.h +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -#include - -#include -#include - -namespace spdlog { -namespace details { - - thread_pool::thread_pool( - size_t q_max_items, size_t threads_n, std::function on_thread_start, std::function on_thread_stop) - : q_(q_max_items) -{ - if (threads_n == 0 || threads_n > 1000) - { - throw_spdlog_ex("spdlog::thread_pool(): invalid threads_n param (valid " - "range is 1-1000)"); - } - for (size_t i = 0; i < threads_n; i++) - { - threads_.emplace_back([this, on_thread_start, on_thread_stop] { - on_thread_start(); - this->thread_pool::worker_loop_(); - on_thread_stop(); - }); - } -} - - thread_pool::thread_pool(size_t q_max_items, size_t threads_n, std::function on_thread_start) - : thread_pool(q_max_items, threads_n, on_thread_start, [] {}) -{} - - thread_pool::thread_pool(size_t q_max_items, size_t threads_n) - : thread_pool( - q_max_items, threads_n, [] {}, [] {}) -{} - -// message all threads to terminate gracefully join them - thread_pool::~thread_pool() -{ - SPDLOG_TRY - { - for (size_t i = 0; i < threads_.size(); i++) - { - post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block); - } - - for (auto &t : threads_) - { - t.join(); - } - } - SPDLOG_CATCH_STD -} - -void thread_pool::post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy) -{ - async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg); - post_async_msg_(std::move(async_m), overflow_policy); -} - -void thread_pool::post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy) -{ - post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy); -} - -size_t thread_pool::overrun_counter() -{ - return q_.overrun_counter(); -} - -void thread_pool::reset_overrun_counter() -{ - q_.reset_overrun_counter(); -} - -size_t thread_pool::discard_counter() -{ - return q_.discard_counter(); -} - -void thread_pool::reset_discard_counter() -{ - q_.reset_discard_counter(); -} - -size_t thread_pool::queue_size() -{ - return q_.size(); -} - -void thread_pool::post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy) -{ - if (overflow_policy == async_overflow_policy::block) - { - q_.enqueue(std::move(new_msg)); - } - else if (overflow_policy == async_overflow_policy::overrun_oldest) - { - q_.enqueue_nowait(std::move(new_msg)); - } - else - { - assert(overflow_policy == async_overflow_policy::discard_new); - q_.enqueue_if_have_room(std::move(new_msg)); - } -} - -void thread_pool::worker_loop_() -{ - while (process_next_msg_()) {} -} - -// process next message in the queue -// return true if this thread should still be active (while no terminate msg -// was received) -bool thread_pool::process_next_msg_() -{ - async_msg incoming_async_msg; - q_.dequeue(incoming_async_msg); - - switch (incoming_async_msg.msg_type) - { - case async_msg_type::log: { - incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg); - return true; - } - case async_msg_type::flush: { - incoming_async_msg.worker_ptr->backend_flush_(); - return true; - } - - case async_msg_type::terminate: { - return false; - } - - default: { - assert(false); - } - } - - return true; -} - -} // namespace details -} // namespace spdlog diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index edb9bf91..f1a4a0b3 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/include/spdlog/sinks/stdout_color_sinks-inl.h b/include/spdlog/sinks/stdout_color_sinks-inl.h deleted file mode 100644 index adc6e4c6..00000000 --- a/include/spdlog/sinks/stdout_color_sinks-inl.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -# include - -#include -#include - -namespace spdlog { - -template - std::shared_ptr stdout_color_mt(const std::string &logger_name, color_mode mode) -{ - return Factory::template create(logger_name, mode); -} - -template - std::shared_ptr stdout_color_st(const std::string &logger_name, color_mode mode) -{ - return Factory::template create(logger_name, mode); -} - -template - std::shared_ptr stderr_color_mt(const std::string &logger_name, color_mode mode) -{ - return Factory::template create(logger_name, mode); -} - -template - std::shared_ptr stderr_color_st(const std::string &logger_name, color_mode mode) -{ - return Factory::template create(logger_name, mode); -} -} // namespace spdlog diff --git a/include/spdlog/sinks/stdout_color_sinks.h b/include/spdlog/sinks/stdout_color_sinks.h index a3630727..27cd0571 100644 --- a/include/spdlog/sinks/stdout_color_sinks.h +++ b/include/spdlog/sinks/stdout_color_sinks.h @@ -10,6 +10,7 @@ #endif #include +#include namespace spdlog { namespace sinks { @@ -26,6 +27,8 @@ using stderr_color_sink_st = ansicolor_stderr_sink_st; #endif } // namespace sinks +// template instantations + template std::shared_ptr stdout_color_mt(const std::string &logger_name, color_mode mode = color_mode::automatic); diff --git a/include/spdlog/sinks/stdout_sinks-inl.h b/include/spdlog/sinks/stdout_sinks-inl.h deleted file mode 100644 index 43fe3741..00000000 --- a/include/spdlog/sinks/stdout_sinks-inl.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -#include - -#include -#include -#include - -#ifdef _WIN32 -// under windows using fwrite to non-binary stream results in \r\r\n (see issue #1675) -// so instead we use ::FileWrite -# include - -# ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp -# include // WriteFile (..) -# endif - -# include // _get_osfhandle(..) -# include // _fileno(..) -#endif // WIN32 - -namespace spdlog { - -namespace sinks { - -template - stdout_sink_base::stdout_sink_base(FILE *file) - : mutex_(ConsoleMutex::mutex()) - , file_(file) - , formatter_(std::make_unique()) -{ -#ifdef _WIN32 - // get windows handle from the FILE* object - - handle_ = reinterpret_cast(::_get_osfhandle(::_fileno(file_))); - - // don't throw to support cases where no console is attached, - // and let the log method to do nothing if (handle_ == INVALID_HANDLE_VALUE). - // throw only if non stdout/stderr target is requested (probably regular file and not console). - if (handle_ == INVALID_HANDLE_VALUE && file != stdout && file != stderr) - { - throw_spdlog_ex("spdlog::stdout_sink_base: _get_osfhandle() failed", errno); - } -#endif // WIN32 -} - -template - void stdout_sink_base::log(const details::log_msg &msg) -{ -#ifdef _WIN32 - if (handle_ == INVALID_HANDLE_VALUE) - { - return; - } - std::lock_guard lock(mutex_); - memory_buf_t formatted; - formatter_->format(msg, formatted); - auto size = static_cast(formatted.size()); - DWORD bytes_written = 0; - bool ok = ::WriteFile(handle_, formatted.data(), size, &bytes_written, nullptr) != 0; - if (!ok) - { - throw_spdlog_ex("stdout_sink_base: WriteFile() failed. GetLastError(): " + std::to_string(::GetLastError())); - } -#else - std::lock_guard lock(mutex_); - memory_buf_t formatted; - formatter_->format(msg, formatted); - ::fwrite(formatted.data(), sizeof(char), formatted.size(), file_); -#endif // WIN32 - ::fflush(file_); // flush every line to terminal -} - -template - void stdout_sink_base::flush() -{ - std::lock_guard lock(mutex_); - fflush(file_); -} - -template - void stdout_sink_base::set_pattern(const std::string &pattern) -{ - std::lock_guard lock(mutex_); - formatter_ = std::unique_ptr(new pattern_formatter(pattern)); -} - -template - void stdout_sink_base::set_formatter(std::unique_ptr sink_formatter) -{ - std::lock_guard lock(mutex_); - formatter_ = std::move(sink_formatter); -} - -// stdout sink -template - stdout_sink::stdout_sink() - : stdout_sink_base(stdout) -{} - -// stderr sink -template - stderr_sink::stderr_sink() - : stdout_sink_base(stderr) -{} - -} // namespace sinks - -// factory methods -template - std::shared_ptr stdout_logger_mt(const std::string &logger_name) -{ - return Factory::template create(logger_name); -} - -template - std::shared_ptr stdout_logger_st(const std::string &logger_name) -{ - return Factory::template create(logger_name); -} - -template - std::shared_ptr stderr_logger_mt(const std::string &logger_name) -{ - return Factory::template create(logger_name); -} - -template - std::shared_ptr stderr_logger_st(const std::string &logger_name) -{ - return Factory::template create(logger_name); -} -} // namespace spdlog diff --git a/include/spdlog/spdlog-inl.h b/include/spdlog/spdlog-inl.h deleted file mode 100644 index 78ce44ef..00000000 --- a/include/spdlog/spdlog-inl.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#pragma once - -# include - -#include -#include - -namespace spdlog { - - void initialize_logger(std::shared_ptr logger) -{ - details::registry::instance().initialize_logger(std::move(logger)); -} - - std::shared_ptr get(const std::string &name) -{ - return details::registry::instance().get(name); -} - - void set_formatter(std::unique_ptr formatter) -{ - details::registry::instance().set_formatter(std::move(formatter)); -} - - void set_pattern(std::string pattern, pattern_time_type time_type) -{ - set_formatter(std::unique_ptr(new pattern_formatter(std::move(pattern), time_type))); -} - - level get_level() -{ - return default_logger_raw()->log_level(); -} - - bool should_log(level level) -{ - return default_logger_raw()->should_log(level); -} - - void set_level(level level) -{ - details::registry::instance().set_level(level); -} - - void flush_on(level level) -{ - details::registry::instance().flush_on(level); -} - - void set_error_handler(void (*handler)(const std::string &msg)) -{ - details::registry::instance().set_error_handler(handler); -} - - void register_logger(std::shared_ptr logger) -{ - details::registry::instance().register_logger(std::move(logger)); -} - - void apply_all(const std::function)> &fun) -{ - details::registry::instance().apply_all(fun); -} - - void drop(const std::string &name) -{ - details::registry::instance().drop(name); -} - - void drop_all() -{ - details::registry::instance().drop_all(); -} - - void shutdown() -{ - details::registry::instance().shutdown(); -} - - void set_automatic_registration(bool automatic_registration) -{ - details::registry::instance().set_automatic_registration(automatic_registration); -} - - std::shared_ptr default_logger() -{ - return details::registry::instance().default_logger(); -} - - spdlog::logger *default_logger_raw() -{ - return details::registry::instance().get_default_raw(); -} - - void set_default_logger(std::shared_ptr default_logger) -{ - details::registry::instance().set_default_logger(std::move(default_logger)); -} - - void apply_logger_env_levels(std::shared_ptr logger) -{ - details::registry::instance().apply_logger_env_levels(std::move(logger)); -} - -} // namespace spdlog diff --git a/src/async.cpp b/src/async.cpp deleted file mode 100644 index bf4b078c..00000000 --- a/src/async.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#include -#include -#include -#include diff --git a/include/spdlog/async_logger-inl.h b/src/async_logger.cpp similarity index 99% rename from include/spdlog/async_logger-inl.h rename to src/async_logger.cpp index 7c606509..1ead1e1e 100644 --- a/include/spdlog/async_logger-inl.h +++ b/src/async_logger.cpp @@ -1,10 +1,7 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - #include - #include #include diff --git a/src/cfg.cpp b/src/cfg.cpp deleted file mode 100644 index 0c3535f3..00000000 --- a/src/cfg.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#include diff --git a/include/spdlog/cfg/helpers-inl.h b/src/cfg/.helpers.cpp similarity index 97% rename from include/spdlog/cfg/helpers-inl.h rename to src/cfg/.helpers.cpp index a8099137..b0f0a8d4 100644 --- a/include/spdlog/cfg/helpers-inl.h +++ b/src/cfg/.helpers.cpp @@ -1,12 +1,9 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - -# include +#include #include -#include #include #include diff --git a/include/spdlog/common-inl.h b/src/common.cpp similarity index 96% rename from include/spdlog/common-inl.h rename to src/common.cpp index e708dfff..9b19c2c3 100644 --- a/include/spdlog/common-inl.h +++ b/src/common.cpp @@ -1,9 +1,7 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - -# include +#include #include #include diff --git a/src/details/file_helper.cpp b/src/details/file_helper.cpp index 51bc46bd..3901e7af 100644 --- a/src/details/file_helper.cpp +++ b/src/details/file_helper.cpp @@ -1,19 +1,13 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - - #include - #include #include #include -#include #include #include -#include #include namespace spdlog { diff --git a/src/details/log_msg.cpp b/src/details/log_msg.cpp index 738c6324..58818edc 100644 --- a/src/details/log_msg.cpp +++ b/src/details/log_msg.cpp @@ -1,10 +1,7 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - -# include - +#include #include namespace spdlog { diff --git a/src/details/log_msg_buffer.cpp b/src/details/log_msg_buffer.cpp index a8b5b8ca..956689b3 100644 --- a/src/details/log_msg_buffer.cpp +++ b/src/details/log_msg_buffer.cpp @@ -1,9 +1,7 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - -# include +#include namespace spdlog { namespace details { diff --git a/src/details/os.cpp b/src/details/os.cpp index e991f9cf..7165469f 100644 --- a/src/details/os.cpp +++ b/src/details/os.cpp @@ -1,10 +1,7 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - -# include - +#include #include #include @@ -17,7 +14,6 @@ #include #include #include -#include #ifdef _WIN32 diff --git a/src/details/periodic_worker.cpp b/src/details/periodic_worker.cpp index 82098c70..c7f3d126 100644 --- a/src/details/periodic_worker.cpp +++ b/src/details/periodic_worker.cpp @@ -1,9 +1,7 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - -# include +#include namespace spdlog { namespace details { diff --git a/src/details/registry.cpp b/src/details/registry.cpp index babc31d7..1e627f1b 100644 --- a/src/details/registry.cpp +++ b/src/details/registry.cpp @@ -1,9 +1,7 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - -# include +#include #include #include diff --git a/src/details/thread_pool.cpp b/src/details/thread_pool.cpp index ac335a72..c4e8e2ac 100644 --- a/src/details/thread_pool.cpp +++ b/src/details/thread_pool.cpp @@ -1,10 +1,7 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - #include - #include #include diff --git a/include/spdlog/logger-inl.h b/src/logger.cpp similarity index 99% rename from include/spdlog/logger-inl.h rename to src/logger.cpp index 42072b4f..596cd66b 100644 --- a/include/spdlog/logger-inl.h +++ b/src/logger.cpp @@ -1,14 +1,12 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - #include - #include #include #include +#include namespace spdlog { diff --git a/include/spdlog/pattern_formatter-inl.h b/src/pattern_formatter.cpp similarity index 99% rename from include/spdlog/pattern_formatter-inl.h rename to src/pattern_formatter.cpp index 8a99f6ee..848e9441 100644 --- a/include/spdlog/pattern_formatter-inl.h +++ b/src/pattern_formatter.cpp @@ -1,10 +1,7 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - #include - #include #include #include @@ -17,13 +14,9 @@ #include #include #include -#include -#include -#include #include #include #include -#include namespace spdlog { namespace details { @@ -31,7 +24,6 @@ namespace details { /////////////////////////////////////////////////////////////////////// // name & level pattern appender /////////////////////////////////////////////////////////////////////// - class scoped_padder { public: diff --git a/include/spdlog/sinks/ansicolor_sink-inl.h b/src/sinks/ansicolor_sink.cpp similarity index 90% rename from include/spdlog/sinks/ansicolor_sink-inl.h rename to src/sinks/ansicolor_sink.cpp index 4fc03214..080c6674 100644 --- a/include/spdlog/sinks/ansicolor_sink-inl.h +++ b/src/sinks/ansicolor_sink.cpp @@ -1,13 +1,13 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once -# include +#include #include #include + namespace spdlog { namespace sinks { @@ -141,3 +141,10 @@ template } // namespace sinks } // namespace spdlog + +// template instantiations +template SPDLOG_API class spdlog::sinks::ansicolor_stdout_sink; +template SPDLOG_API class spdlog::sinks::ansicolor_stdout_sink; + +template SPDLOG_API class spdlog::sinks::ansicolor_stderr_sink; +template SPDLOG_API class spdlog::sinks::ansicolor_stderr_sink; diff --git a/include/spdlog/sinks/base_sink-inl.h b/src/sinks/base_sink.cpp similarity index 87% rename from include/spdlog/sinks/base_sink-inl.h rename to src/sinks/base_sink.cpp index faa03133..188ab0ee 100644 --- a/include/spdlog/sinks/base_sink-inl.h +++ b/src/sinks/base_sink.cpp @@ -1,14 +1,14 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once -# include +#include #include #include #include +#include template spdlog::sinks::base_sink::base_sink() @@ -59,3 +59,8 @@ void spdlog::sinks::base_sink::set_formatter_(std::unique_ptr; +template class SPDLOG_API spdlog::sinks::base_sink; \ No newline at end of file diff --git a/include/spdlog/sinks/basic_file_sink-inl.h b/src/sinks/basic_file_sink.cpp similarity index 84% rename from include/spdlog/sinks/basic_file_sink-inl.h rename to src/sinks/basic_file_sink.cpp index f933b95f..36d58ee3 100644 --- a/include/spdlog/sinks/basic_file_sink-inl.h +++ b/src/sinks/basic_file_sink.cpp @@ -1,9 +1,6 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - - #include #include @@ -41,3 +38,7 @@ template } // namespace sinks } // namespace spdlog + +// template instantiations +template class SPDLOG_API spdlog::sinks::basic_file_sink; +template class SPDLOG_API spdlog::sinks::basic_file_sink; \ No newline at end of file diff --git a/src/sinks/color_sinks.cpp b/src/sinks/color_sinks.cpp index 277ba720..a82934a6 100644 --- a/src/sinks/color_sinks.cpp +++ b/src/sinks/color_sinks.cpp @@ -9,7 +9,7 @@ // color sinks // #ifdef _WIN32 -# include +# include template class SPDLOG_API spdlog::sinks::wincolor_sink; template class SPDLOG_API spdlog::sinks::wincolor_sink; template class SPDLOG_API spdlog::sinks::wincolor_stdout_sink; @@ -17,7 +17,7 @@ template class SPDLOG_API spdlog::sinks::wincolor_stdout_sink; template class SPDLOG_API spdlog::sinks::wincolor_stderr_sink; #else -# include "spdlog/sinks/ansicolor_sink-inl.h" +# include template class SPDLOG_API spdlog::sinks::ansicolor_sink; template class SPDLOG_API spdlog::sinks::ansicolor_sink; template class SPDLOG_API spdlog::sinks::ansicolor_stdout_sink; @@ -27,21 +27,21 @@ template class SPDLOG_API spdlog::sinks::ansicolor_stderr_sink spdlog::stdout_color_mt( - const std::string &logger_name, color_mode mode); -template SPDLOG_API std::shared_ptr spdlog::stdout_color_st( - const std::string &logger_name, color_mode mode); -template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt( - const std::string &logger_name, color_mode mode); -template SPDLOG_API std::shared_ptr spdlog::stderr_color_st( - const std::string &logger_name, color_mode mode); - -template SPDLOG_API std::shared_ptr spdlog::stdout_color_mt( - const std::string &logger_name, color_mode mode); -template SPDLOG_API std::shared_ptr spdlog::stdout_color_st( - const std::string &logger_name, color_mode mode); -template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt( - const std::string &logger_name, color_mode mode); -template SPDLOG_API std::shared_ptr spdlog::stderr_color_st( - const std::string &logger_name, color_mode mode); +//#include +//template SPDLOG_API std::shared_ptr spdlog::stdout_color_mt( +// const std::string &logger_name, color_mode mode); +//template SPDLOG_API std::shared_ptr spdlog::stdout_color_st( +// const std::string &logger_name, color_mode mode); +//template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt( +// const std::string &logger_name, color_mode mode); +//template SPDLOG_API std::shared_ptr spdlog::stderr_color_st( +// const std::string &logger_name, color_mode mode); +// +//template SPDLOG_API std::shared_ptr spdlog::stdout_color_mt( +// const std::string &logger_name, color_mode mode); +//template SPDLOG_API std::shared_ptr spdlog::stdout_color_st( +// const std::string &logger_name, color_mode mode); +//template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt( +// const std::string &logger_name, color_mode mode); +//template SPDLOG_API std::shared_ptr spdlog::stderr_color_st( +// const std::string &logger_name, color_mode mode); diff --git a/src/sinks/file_sinks.cpp b/src/sinks/file_sinks.cpp index f85ed38c..e69de29b 100644 --- a/src/sinks/file_sinks.cpp +++ b/src/sinks/file_sinks.cpp @@ -1,16 +0,0 @@ -// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) - -#include -#include -#include -#include - -#include - -template class SPDLOG_API spdlog::sinks::basic_file_sink; -template class SPDLOG_API spdlog::sinks::basic_file_sink; - -#include -template class SPDLOG_API spdlog::sinks::rotating_file_sink; -template class SPDLOG_API spdlog::sinks::rotating_file_sink; diff --git a/include/spdlog/sinks/rotating_file_sink-inl.h b/src/sinks/rotating_file_sink.cpp similarity index 94% rename from include/spdlog/sinks/rotating_file_sink-inl.h rename to src/sinks/rotating_file_sink.cpp index 581e02dd..077fd5a2 100644 --- a/include/spdlog/sinks/rotating_file_sink-inl.h +++ b/src/sinks/rotating_file_sink.cpp @@ -1,19 +1,14 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once - -# include +#include #include - #include -#include +#include #include #include -#include -#include #include #include #include @@ -148,3 +143,7 @@ template } // namespace sinks } // namespace spdlog + +// template instantiations +template class SPDLOG_API spdlog::sinks::rotating_file_sink; +template class SPDLOG_API spdlog::sinks::rotating_file_sink; \ No newline at end of file diff --git a/include/spdlog/sinks/sink-inl.h b/src/sinks/sink.cpp similarity index 92% rename from include/spdlog/sinks/sink-inl.h rename to src/sinks/sink.cpp index 37306a78..19144bda 100644 --- a/include/spdlog/sinks/sink-inl.h +++ b/src/sinks/sink.cpp @@ -1,9 +1,8 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#pragma once -# include +#include #include diff --git a/src/sinks/stdout_color_sinks.cpp b/src/sinks/stdout_color_sinks.cpp new file mode 100644 index 00000000..296a2a39 --- /dev/null +++ b/src/sinks/stdout_color_sinks.cpp @@ -0,0 +1,58 @@ +// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) + +#include +#include +#include +#include +#include + +namespace spdlog { + + template + std::shared_ptr stdout_color_mt(const std::string &logger_name, color_mode mode) { + return Factory::template create(logger_name, mode); + } + + template + std::shared_ptr stdout_color_st(const std::string &logger_name, color_mode mode) { + return Factory::template create(logger_name, mode); + } + + template + std::shared_ptr stderr_color_mt(const std::string &logger_name, color_mode mode) { + return Factory::template create(logger_name, mode); + } + + template + std::shared_ptr stderr_color_st(const std::string &logger_name, color_mode mode) { + return Factory::template create(logger_name, mode); + } +} // namespace spdlog + +// template instantiations +template SPDLOG_API std::shared_ptr spdlog::stdout_color_mt( + const std::string &logger_name, color_mode mode); + +template SPDLOG_API std::shared_ptr spdlog::stdout_color_st( + const std::string &logger_name, color_mode mode); + +template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt( + const std::string &logger_name, color_mode mode); + +template SPDLOG_API std::shared_ptr spdlog::stderr_color_st( + const std::string &logger_name, color_mode mode); + +template SPDLOG_API std::shared_ptr spdlog::stdout_color_mt( + const std::string &logger_name, color_mode mode); + +template SPDLOG_API std::shared_ptr spdlog::stdout_color_st( + const std::string &logger_name, color_mode mode); + +template SPDLOG_API std::shared_ptr spdlog::stderr_color_mt( + const std::string &logger_name, color_mode mode); + +template SPDLOG_API std::shared_ptr spdlog::stderr_color_st( + const std::string &logger_name, color_mode mode); + + diff --git a/src/sinks/stdout_sinks.cpp b/src/sinks/stdout_sinks.cpp index 61264a4c..31084538 100644 --- a/src/sinks/stdout_sinks.cpp +++ b/src/sinks/stdout_sinks.cpp @@ -1,12 +1,138 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#include +#include +#include +#include -#include -#include -#include +#ifdef _WIN32 +// under windows using fwrite to non-binary stream results in \r\r\n (see issue #1675) +// so instead we use ::FileWrite +# include +# ifndef _USING_V110_SDK71_ // fileapi.h doesn't exist in winxp +# include // WriteFile (..) +# endif + +# include // _get_osfhandle(..) +# include // _fileno(..) +#endif // WIN32 + +namespace spdlog { + + namespace sinks { + + template + stdout_sink_base::stdout_sink_base(FILE *file) + : mutex_(ConsoleMutex::mutex()) + , file_(file) + , formatter_(std::make_unique()) + { +#ifdef _WIN32 + // get windows handle from the FILE* object + + handle_ = reinterpret_cast(::_get_osfhandle(::_fileno(file_))); + + // don't throw to support cases where no console is attached, + // and let the log method to do nothing if (handle_ == INVALID_HANDLE_VALUE). + // throw only if non stdout/stderr target is requested (probably regular file and not console). + if (handle_ == INVALID_HANDLE_VALUE && file != stdout && file != stderr) + { + throw_spdlog_ex("spdlog::stdout_sink_base: _get_osfhandle() failed", errno); + } +#endif // WIN32 + } + + template + void stdout_sink_base::log(const details::log_msg &msg) + { +#ifdef _WIN32 + if (handle_ == INVALID_HANDLE_VALUE) + { + return; + } + std::lock_guard lock(mutex_); + memory_buf_t formatted; + formatter_->format(msg, formatted); + auto size = static_cast(formatted.size()); + DWORD bytes_written = 0; + bool ok = ::WriteFile(handle_, formatted.data(), size, &bytes_written, nullptr) != 0; + if (!ok) + { + throw_spdlog_ex("stdout_sink_base: WriteFile() failed. GetLastError(): " + std::to_string(::GetLastError())); + } +#else + std::lock_guard lock(mutex_); + memory_buf_t formatted; + formatter_->format(msg, formatted); + ::fwrite(formatted.data(), sizeof(char), formatted.size(), file_); +#endif // WIN32 + ::fflush(file_); // flush every line to terminal + } + + template + void stdout_sink_base::flush() + { + std::lock_guard lock(mutex_); + fflush(file_); + } + + template + void stdout_sink_base::set_pattern(const std::string &pattern) + { + std::lock_guard lock(mutex_); + formatter_ = std::unique_ptr(new pattern_formatter(pattern)); + } + + template + void stdout_sink_base::set_formatter(std::unique_ptr sink_formatter) + { + std::lock_guard lock(mutex_); + formatter_ = std::move(sink_formatter); + } + +// stdout sink + template + stdout_sink::stdout_sink() + : stdout_sink_base(stdout) + {} + +// stderr sink + template + stderr_sink::stderr_sink() + : stdout_sink_base(stderr) + {} + + } // namespace sinks + +// factory methods + template + std::shared_ptr stdout_logger_mt(const std::string &logger_name) + { + return Factory::template create(logger_name); + } + + template + std::shared_ptr stdout_logger_st(const std::string &logger_name) + { + return Factory::template create(logger_name); + } + + template + std::shared_ptr stderr_logger_mt(const std::string &logger_name) + { + return Factory::template create(logger_name); + } + + template + std::shared_ptr stderr_logger_st(const std::string &logger_name) + { + return Factory::template create(logger_name); + } +} // namespace spdlog + +// template instantiations for stdout/stderr loggers +#include template class SPDLOG_API spdlog::sinks::stdout_sink_base; template class SPDLOG_API spdlog::sinks::stdout_sink_base; template class SPDLOG_API spdlog::sinks::stdout_sink; @@ -14,6 +140,10 @@ template class SPDLOG_API spdlog::sinks::stdout_sink; template class SPDLOG_API spdlog::sinks::stderr_sink; +// template instantiations for stdout/stderr factory functions +#include +#include + template SPDLOG_API std::shared_ptr spdlog::stdout_logger_mt(const std::string &logger_name); template SPDLOG_API std::shared_ptr spdlog::stdout_logger_st(const std::string &logger_name); template SPDLOG_API std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name); @@ -23,3 +153,5 @@ template SPDLOG_API std::shared_ptr spdlog::stdout_logger_mt spdlog::stdout_logger_st(const std::string &logger_name); template SPDLOG_API std::shared_ptr spdlog::stderr_logger_mt(const std::string &logger_name); template SPDLOG_API std::shared_ptr spdlog::stderr_logger_st(const std::string &logger_name); + + diff --git a/include/spdlog/sinks/wincolor_sink-inl.h b/src/sinks/wincolor_sink.cpp similarity index 99% rename from include/spdlog/sinks/wincolor_sink-inl.h rename to src/sinks/wincolor_sink.cpp index 0efcc9f5..d56cbd88 100644 --- a/include/spdlog/sinks/wincolor_sink-inl.h +++ b/src/sinks/wincolor_sink.cpp @@ -1,5 +1,6 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) +#ifdef _WIN32 #pragma once @@ -171,3 +172,5 @@ template {} } // namespace sinks } // namespace spdlog + +#endif // _WIN32 \ No newline at end of file diff --git a/src/spdlog.cpp b/src/spdlog.cpp index 1f003c9d..b30e389e 100644 --- a/src/spdlog.cpp +++ b/src/spdlog.cpp @@ -1,21 +1,105 @@ // Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include -#include +namespace spdlog { -// template instantiate logger constructor with sinks init list -template SPDLOG_API spdlog::logger::logger(std::string name, sinks_init_list::iterator begin, sinks_init_list::iterator end); -template class SPDLOG_API spdlog::sinks::base_sink; -template class SPDLOG_API spdlog::sinks::base_sink; +void initialize_logger(std::shared_ptr logger) +{ + details::registry::instance().initialize_logger(std::move(logger)); +} + + std::shared_ptr get(const std::string &name) +{ + return details::registry::instance().get(name); +} + + void set_formatter(std::unique_ptr formatter) +{ + details::registry::instance().set_formatter(std::move(formatter)); +} + + void set_pattern(std::string pattern, pattern_time_type time_type) +{ + set_formatter(std::unique_ptr(new pattern_formatter(std::move(pattern), time_type))); +} + + level get_level() +{ + return default_logger_raw()->log_level(); +} + + bool should_log(level level) +{ + return default_logger_raw()->should_log(level); +} + + void set_level(level level) +{ + details::registry::instance().set_level(level); +} + + void flush_on(level level) +{ + details::registry::instance().flush_on(level); +} + + void set_error_handler(void (*handler)(const std::string &msg)) +{ + details::registry::instance().set_error_handler(handler); +} + + void register_logger(std::shared_ptr logger) +{ + details::registry::instance().register_logger(std::move(logger)); +} + + void apply_all(const std::function)> &fun) +{ + details::registry::instance().apply_all(fun); +} + + void drop(const std::string &name) +{ + details::registry::instance().drop(name); +} + + void drop_all() +{ + details::registry::instance().drop_all(); +} + + void shutdown() +{ + details::registry::instance().shutdown(); +} + + void set_automatic_registration(bool automatic_registration) +{ + details::registry::instance().set_automatic_registration(automatic_registration); +} + + std::shared_ptr default_logger() +{ + return details::registry::instance().default_logger(); +} + + spdlog::logger *default_logger_raw() +{ + return details::registry::instance().get_default_raw(); +} + + void set_default_logger(std::shared_ptr default_logger) +{ + details::registry::instance().set_default_logger(std::move(default_logger)); +} + + void apply_logger_env_levels(std::shared_ptr logger) +{ + details::registry::instance().apply_logger_env_levels(std::move(logger)); +} + +} // namespace spdlog