file_helper.cpp and filename_t fix
This commit is contained in:
		@@ -69,6 +69,15 @@
 | 
				
			|||||||
#define SPDLOG_FUNCTION __FUNCTION__
 | 
					#define SPDLOG_FUNCTION __FUNCTION__
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace spdlog {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class formatter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace sinks {
 | 
				
			||||||
 | 
					class sink;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
 | 
					#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
 | 
				
			||||||
using filename_t = std::wstring;
 | 
					using filename_t = std::wstring;
 | 
				
			||||||
#define SPDLOG_FILENAME_T(s) L##s
 | 
					#define SPDLOG_FILENAME_T(s) L##s
 | 
				
			||||||
@@ -82,14 +91,6 @@ using filename_t = std::string;
 | 
				
			|||||||
#define SPDLOG_FILENAME_T(s) s
 | 
					#define SPDLOG_FILENAME_T(s) s
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace spdlog {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class formatter;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace sinks {
 | 
					 | 
				
			||||||
class sink;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using log_clock = std::chrono::system_clock;
 | 
					using log_clock = std::chrono::system_clock;
 | 
				
			||||||
using sink_ptr = std::shared_ptr<sinks::sink>;
 | 
					using sink_ptr = std::shared_ptr<sinks::sink>;
 | 
				
			||||||
using sinks_init_list = std::initializer_list<sink_ptr>;
 | 
					using sinks_init_list = std::initializer_list<sink_ptr>;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,109 +5,35 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Helper class for file sinks.
 | 
					#include "spdlog/common.h"
 | 
				
			||||||
// When failing to open a file, retry several times(5) with a delay interval(10 ms).
 | 
					 | 
				
			||||||
// Throw spdlog_ex exception on errors.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "spdlog/details/log_msg.h"
 | 
					 | 
				
			||||||
#include "spdlog/details/os.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <cerrno>
 | 
					 | 
				
			||||||
#include <chrono>
 | 
					 | 
				
			||||||
#include <cstdio>
 | 
					 | 
				
			||||||
#include <string>
 | 
					 | 
				
			||||||
#include <thread>
 | 
					 | 
				
			||||||
#include <tuple>
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace spdlog {
 | 
					namespace spdlog {
 | 
				
			||||||
namespace details {
 | 
					namespace details {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Helper class for file sinks.
 | 
				
			||||||
 | 
					// When failing to open a file, retry several times(5) with a delay interval(10 ms).
 | 
				
			||||||
 | 
					// Throw spdlog_ex exception on errors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class file_helper
 | 
					class file_helper
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    const int open_tries = 5;
 | 
					    const int open_tries = 5;
 | 
				
			||||||
    const int open_interval = 10;
 | 
					    const int open_interval = 10;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    explicit file_helper() = default;
 | 
					    explicit file_helper() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    file_helper(const file_helper &) = delete;
 | 
					    file_helper(const file_helper &) = delete;
 | 
				
			||||||
    file_helper &operator=(const file_helper &) = delete;
 | 
					    file_helper &operator=(const file_helper &) = delete;
 | 
				
			||||||
 | 
					    ~file_helper();    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ~file_helper()
 | 
					    void open(const filename_t &fname, bool truncate = false);    
 | 
				
			||||||
    {
 | 
					    void reopen(bool truncate);    
 | 
				
			||||||
        close();
 | 
					    void flush();    
 | 
				
			||||||
    }
 | 
					    void close();    
 | 
				
			||||||
 | 
					    void write(const fmt::memory_buffer &buf);
 | 
				
			||||||
    void open(const filename_t &fname, bool truncate = false)
 | 
					    size_t size() const;    
 | 
				
			||||||
    {
 | 
					    const filename_t &filename() const;
 | 
				
			||||||
        close();
 | 
					    static bool file_exists(const filename_t &fname);
 | 
				
			||||||
        auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
 | 
					 | 
				
			||||||
        _filename = fname;
 | 
					 | 
				
			||||||
        for (int tries = 0; tries < open_tries; ++tries)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (!os::fopen_s(&fd_, fname, mode))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            details::os::sleep_for_millis(open_interval);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void reopen(bool truncate)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (_filename.empty())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            throw spdlog_ex("Failed re opening file - was not opened before");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        open(_filename, truncate);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void flush()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::fflush(fd_);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void close()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (fd_ != nullptr)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            std::fclose(fd_);
 | 
					 | 
				
			||||||
            fd_ = nullptr;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void write(const fmt::memory_buffer &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 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 &filename() const
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return _filename;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static bool file_exists(const filename_t &fname)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return os::file_exists(fname);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    // return file path and its extension:
 | 
					    // return file path and its extension:
 | 
				
			||||||
@@ -122,27 +48,7 @@ public:
 | 
				
			|||||||
    // ".mylog" => (".mylog". "")
 | 
					    // ".mylog" => (".mylog". "")
 | 
				
			||||||
    // "my_folder/.mylog" => ("my_folder/.mylog", "")
 | 
					    // "my_folder/.mylog" => ("my_folder/.mylog", "")
 | 
				
			||||||
    // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
 | 
					    // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
 | 
				
			||||||
    static std::tuple<filename_t, filename_t> split_by_extension(const spdlog::filename_t &fname)
 | 
					    static std::tuple<filename_t, filename_t> 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, spdlog::filename_t());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // treat casese like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
 | 
					 | 
				
			||||||
        auto folder_index = fname.rfind(details::os::folder_sep);
 | 
					 | 
				
			||||||
        if (folder_index != filename_t::npos && folder_index >= ext_index - 1)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return std::make_tuple(fname, spdlog::filename_t());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // finally - return a valid base and extension tuple
 | 
					 | 
				
			||||||
        return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    std::FILE *fd_{nullptr};
 | 
					    std::FILE *fd_{nullptr};
 | 
				
			||||||
@@ -150,3 +56,7 @@ private:
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
} // namespace details
 | 
					} // namespace details
 | 
				
			||||||
} // namespace spdlog
 | 
					} // namespace spdlog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef  SPDLOG_HEADER_ONLY
 | 
				
			||||||
 | 
					#include "../../../src/file_helper.cpp"
 | 
				
			||||||
 | 
					#endif // ! SPDLOG_HEADER_ONLY
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										132
									
								
								src/file_helper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/file_helper.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright(c) 2015 Gabi Melman.
 | 
				
			||||||
 | 
					// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SPDLOG_HEADER_ONLY
 | 
				
			||||||
 | 
					#include "spdlog/details/file_helper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#include "spdlog/details/os.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cerrno>
 | 
				
			||||||
 | 
					#include <chrono>
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <thread>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace spdlog {
 | 
				
			||||||
 | 
					namespace details 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SPDLOG_INLINE file_helper::~file_helper()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        close();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        close();
 | 
				
			||||||
 | 
					        auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
 | 
				
			||||||
 | 
					        _filename = fname;
 | 
				
			||||||
 | 
					        for (int tries = 0; tries < open_tries; ++tries)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!os::fopen_s(&fd_, fname, mode))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            details::os::sleep_for_millis(open_interval);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPDLOG_INLINE void file_helper::reopen(bool truncate)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (_filename.empty())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw spdlog_ex("Failed re opening file - was not opened before");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        open(_filename, truncate);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPDLOG_INLINE void file_helper::flush()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::fflush(fd_);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPDLOG_INLINE void file_helper::close()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (fd_ != nullptr)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::fclose(fd_);
 | 
				
			||||||
 | 
					            fd_ = nullptr;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPDLOG_INLINE void file_helper::write(const fmt::memory_buffer &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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPDLOG_INLINE 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_);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPDLOG_INLINE const filename_t &file_helper::filename() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return _filename;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPDLOG_INLINE bool file_helper::file_exists(const filename_t &fname)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return os::file_exists(fname);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // 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")
 | 
				
			||||||
 | 
					    SPDLOG_INLINE std::tuple<filename_t, filename_t> 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 casese like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
 | 
				
			||||||
 | 
					        auto folder_index = fname.rfind(details::os::folder_sep);
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
		Reference in New Issue
	
	Block a user