127 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
		
		
			
		
	
	
			127 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
|  | // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
 | ||
|  | // Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | ||
|  | 
 | ||
|  | #pragma once
 | ||
|  | 
 | ||
|  | #ifndef SPDLOG_HEADER_ONLY
 | ||
|  |     #include <spdlog/sinks/stdout_sinks.h>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #include <memory>
 | ||
|  | #include <spdlog/details/console_globals.h>
 | ||
|  | #include <spdlog/pattern_formatter.h>
 | ||
|  | 
 | ||
|  | #ifdef _WIN32
 | ||
|  |     // under windows using fwrite to non-binary stream results in \r\r\n (see issue #1675)
 | ||
|  |     // so instead we use ::FileWrite
 | ||
|  |     #include <spdlog/details/windows_include.h>
 | ||
|  | 
 | ||
|  |     #ifndef _USING_V110_SDK71_  // fileapi.h doesn't exist in winxp
 | ||
|  |         #include <fileapi.h>    // WriteFile (..)
 | ||
|  |     #endif
 | ||
|  | 
 | ||
|  |     #include <io.h>     // _get_osfhandle(..)
 | ||
|  |     #include <stdio.h>  // _fileno(..)
 | ||
|  | #endif                  // WIN32
 | ||
|  | 
 | ||
|  | namespace spdlog { | ||
|  | 
 | ||
|  | namespace sinks { | ||
|  | 
 | ||
|  | template <typename ConsoleMutex> | ||
|  | SPDLOG_INLINE stdout_sink_base<ConsoleMutex>::stdout_sink_base(FILE *file) | ||
|  |     : mutex_(ConsoleMutex::mutex()), | ||
|  |       file_(file), | ||
|  |       formatter_(details::make_unique<spdlog::pattern_formatter>()) { | ||
|  | #ifdef _WIN32
 | ||
|  |     // get windows handle from the FILE* object
 | ||
|  | 
 | ||
|  |     handle_ = reinterpret_cast<HANDLE>(::_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 <typename ConsoleMutex> | ||
|  | SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::log(const details::log_msg &msg) { | ||
|  | #ifdef _WIN32
 | ||
|  |     if (handle_ == INVALID_HANDLE_VALUE) { | ||
|  |         return; | ||
|  |     } | ||
|  |     std::lock_guard<mutex_t> lock(mutex_); | ||
|  |     memory_buf_t formatted; | ||
|  |     formatter_->format(msg, formatted); | ||
|  |     auto size = static_cast<DWORD>(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<mutex_t> 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 <typename ConsoleMutex> | ||
|  | SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::flush() { | ||
|  |     std::lock_guard<mutex_t> lock(mutex_); | ||
|  |     fflush(file_); | ||
|  | } | ||
|  | 
 | ||
|  | template <typename ConsoleMutex> | ||
|  | SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_pattern(const std::string &pattern) { | ||
|  |     std::lock_guard<mutex_t> lock(mutex_); | ||
|  |     formatter_ = std::unique_ptr<spdlog::formatter>(new pattern_formatter(pattern)); | ||
|  | } | ||
|  | 
 | ||
|  | template <typename ConsoleMutex> | ||
|  | SPDLOG_INLINE void stdout_sink_base<ConsoleMutex>::set_formatter( | ||
|  |     std::unique_ptr<spdlog::formatter> sink_formatter) { | ||
|  |     std::lock_guard<mutex_t> lock(mutex_); | ||
|  |     formatter_ = std::move(sink_formatter); | ||
|  | } | ||
|  | 
 | ||
|  | // stdout sink
 | ||
|  | template <typename ConsoleMutex> | ||
|  | SPDLOG_INLINE stdout_sink<ConsoleMutex>::stdout_sink() | ||
|  |     : stdout_sink_base<ConsoleMutex>(stdout) {} | ||
|  | 
 | ||
|  | // stderr sink
 | ||
|  | template <typename ConsoleMutex> | ||
|  | SPDLOG_INLINE stderr_sink<ConsoleMutex>::stderr_sink() | ||
|  |     : stdout_sink_base<ConsoleMutex>(stderr) {} | ||
|  | 
 | ||
|  | }  // namespace sinks
 | ||
|  | 
 | ||
|  | // factory methods
 | ||
|  | template <typename Factory> | ||
|  | SPDLOG_INLINE std::shared_ptr<logger> stdout_logger_mt(const std::string &logger_name) { | ||
|  |     return Factory::template create<sinks::stdout_sink_mt>(logger_name); | ||
|  | } | ||
|  | 
 | ||
|  | template <typename Factory> | ||
|  | SPDLOG_INLINE std::shared_ptr<logger> stdout_logger_st(const std::string &logger_name) { | ||
|  |     return Factory::template create<sinks::stdout_sink_st>(logger_name); | ||
|  | } | ||
|  | 
 | ||
|  | template <typename Factory> | ||
|  | SPDLOG_INLINE std::shared_ptr<logger> stderr_logger_mt(const std::string &logger_name) { | ||
|  |     return Factory::template create<sinks::stderr_sink_mt>(logger_name); | ||
|  | } | ||
|  | 
 | ||
|  | template <typename Factory> | ||
|  | SPDLOG_INLINE std::shared_ptr<logger> stderr_logger_st(const std::string &logger_name) { | ||
|  |     return Factory::template create<sinks::stderr_sink_st>(logger_name); | ||
|  | } | ||
|  | }  // namespace spdlog
 |