Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for wchar_t on Windows #111

Merged
merged 8 commits into from
Jul 26, 2015
9 changes: 9 additions & 0 deletions include/spdlog/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@
#define SPDLOG_NOEXCEPT throw()
#endif

#if defined(WIN32) && defined(SPDLOG_USE_WCHAR)
typedef std::wstring tstring;
typedef wchar_t tchar;
#define S(s) L ## s
#else
#define S(s) s
typedef std::string tstring;
typedef char tchar;
#endif

namespace spdlog
{
Expand Down
16 changes: 8 additions & 8 deletions include/spdlog/details/file_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ class file_helper
}


void open(const std::string& fname, bool truncate=false)
void open(const tstring& fname, bool truncate=false)
{

close();
const char* mode = truncate ? "wb" : "ab";
const tchar* mode = truncate ? S("wb") : S("ab");
_filename = fname;
for (int tries = 0; tries < open_tries; ++tries)
{
Expand All @@ -76,7 +76,7 @@ class file_helper
std::this_thread::sleep_for(std::chrono::milliseconds(open_interval));
}

throw spdlog_ex("Failed opening file " + fname + " for writing");
throw spdlog_ex("Failed opening file for writing");
}

void reopen(bool truncate)
Expand Down Expand Up @@ -106,22 +106,22 @@ class file_helper
size_t size = msg.formatted.size();
auto data = msg.formatted.data();
if(std::fwrite(data, 1, size, _fd) != size)
throw spdlog_ex("Failed writing to file " + _filename);
throw spdlog_ex("Failed writing to file");

if(_force_flush)
std::fflush(_fd);

}

const std::string& filename() const
const tstring& filename() const
{
return _filename;
}

static bool file_exists(const std::string& name)
static bool file_exists(const tstring& name)
{
FILE* file;
if (!os::fopen_s(&file, name.c_str(), "r"))
if (!os::fopen_s(&file, name.c_str(), S("r")))
{
fclose(file);
return true;
Expand All @@ -134,7 +134,7 @@ class file_helper

private:
FILE* _fd;
std::string _filename;
tstring _filename;
bool _force_flush;


Expand Down
8 changes: 7 additions & 1 deletion include/spdlog/details/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -2638,6 +2638,12 @@ class BasicMemoryWriter : public BasicWriter<Char> {
typedef BasicMemoryWriter<char> MemoryWriter;
typedef BasicMemoryWriter<wchar_t> WMemoryWriter;

#if defined(WIN32) && defined(SPDLOG_USE_WCHAR)
#define TMemoryWriter WMemoryWriter
#else
#define TMemoryWriter MemoryWriter
#endif

/**
\rst
This class template provides operations for formatting and writing data
Expand Down Expand Up @@ -3152,4 +3158,4 @@ FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
# include "format.cc"
#endif

#endif // FMT_FORMAT_H_
#endif // FMT_FORMAT_H_
24 changes: 22 additions & 2 deletions include/spdlog/details/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,37 @@ constexpr inline unsigned short eol_size()
#endif

//fopen_s on non windows for writing
inline int fopen_s(FILE** fp, const std::string& filename, const char* mode)
inline int fopen_s(FILE** fp, const tstring& filename, const tchar* mode)
{
#ifdef _WIN32
#if defined(WIN32)
#if defined(SPDLOG_USE_WCHAR)
*fp = _wfsopen((filename.c_str()), mode, _SH_DENYWR);
#else
*fp = _fsopen((filename.c_str()), mode, _SH_DENYWR);
#endif
return *fp == nullptr;
#else
*fp = fopen((filename.c_str()), mode);
return *fp == nullptr;
#endif
}

inline int remove(const tchar* filename)
{
#if defined(WIN32) && defined(SPDLOG_USE_WCHAR)
return _wremove(filename);
#else
return std::remove(filename);
#endif
}

inline int rename(const tchar* filename1, const tchar* filename2)
{
#if defined(WIN32) && defined(SPDLOG_USE_WCHAR)
return _wrename(filename1, filename2);
#else
return std::rename(filename1, filename2);
#endif
}

//Return utc offset in minutes or -1 on failure
Expand Down
16 changes: 8 additions & 8 deletions include/spdlog/details/spdlog_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,24 +48,24 @@ inline void spdlog::drop(const std::string &name)
}

// Create multi/single threaded rotating file logger
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const tstring& filename, size_t max_file_size, size_t max_files, bool force_flush)
{
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, S("txt"), max_file_size, max_files, force_flush);
}

inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const tstring& filename, size_t max_file_size, size_t max_files, bool force_flush)
{
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, S("txt"), max_file_size, max_files, force_flush);
}

// Create file logger which creates new file at midnight):
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const tstring& filename, int hour, int minute, bool force_flush)
{
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, "txt", hour, minute, force_flush);
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, S("txt"), hour, minute, force_flush);
}
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const tstring& filename, int hour, int minute, bool force_flush)
{
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, "txt", hour, minute, force_flush);
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, S("txt"), hour, minute, force_flush);
}


Expand Down
41 changes: 21 additions & 20 deletions include/spdlog/sinks/file_sinks.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "../details/null_mutex.h"
#include "../details/file_helper.h"
#include "../details/format.h"
#include "../details/os.h"

namespace spdlog
{
Expand Down Expand Up @@ -71,7 +72,7 @@ template<class Mutex>
class rotating_file_sink : public base_sink < Mutex >
{
public:
rotating_file_sink(const std::string &base_filename, const std::string &extension,
rotating_file_sink(const tstring &base_filename, const tstring &extension,
std::size_t max_size, std::size_t max_files,
bool force_flush = false) :
_base_filename(base_filename),
Expand Down Expand Up @@ -102,13 +103,13 @@ class rotating_file_sink : public base_sink < Mutex >
}

private:
static std::string calc_filename(const std::string& filename, std::size_t index, const std::string& extension)
static tstring calc_filename(const tstring& filename, std::size_t index, const tstring& extension)
{
fmt::MemoryWriter w;
fmt::TMemoryWriter w;
if (index)
w.write("{}.{}.{}", filename, index, extension);
w.write(S("{}.{}.{}"), filename, index, extension);
else
w.write("{}.{}", filename, extension);
w.write(S("{}.{}"), filename, extension);
return w.str();
}

Expand All @@ -123,25 +124,25 @@ class rotating_file_sink : public base_sink < Mutex >
_file_helper.close();
for (auto i = _max_files; i > 0; --i)
{
std::string src = calc_filename(_base_filename, i - 1, _extension);
std::string target = calc_filename(_base_filename, i, _extension);
tstring src = calc_filename(_base_filename, i - 1, _extension);
tstring target = calc_filename(_base_filename, i, _extension);

if (details::file_helper::file_exists(target))
{
if (std::remove(target.c_str()) != 0)
if (details::os::remove(target.c_str()) != 0)
{
throw spdlog_ex("rotating_file_sink: failed removing " + target);
throw spdlog_ex("rotating_file_sink: failed removing");
}
}
if (details::file_helper::file_exists(src) && std::rename(src.c_str(), target.c_str()))
if (details::file_helper::file_exists(src) && details::os::rename(src.c_str(), target.c_str()))
{
throw spdlog_ex("rotating_file_sink: failed renaming " + src + " to " + target);
throw spdlog_ex("rotating_file_sink: failed renaming");
}
}
_file_helper.reopen(true);
}
std::string _base_filename;
std::string _extension;
tstring _base_filename;
tstring _extension;
std::size_t _max_size;
std::size_t _max_files;
std::size_t _current_size;
Expand All @@ -160,8 +161,8 @@ class daily_file_sink :public base_sink < Mutex >
public:
//create daily file sink which rotates on given time
daily_file_sink(
const std::string& base_filename,
const std::string& extension,
const tstring& base_filename,
const tstring& extension,
int rotation_hour,
int rotation_minute,
bool force_flush = false) : _base_filename(base_filename),
Expand Down Expand Up @@ -210,16 +211,16 @@ class daily_file_sink :public base_sink < Mutex >
}

//Create filename for the form basename.YYYY-MM-DD.extension
static std::string calc_filename(const std::string& basename, const std::string& extension)
static tstring calc_filename(const tstring& basename, const tstring& extension)
{
std::tm tm = spdlog::details::os::localtime();
fmt::MemoryWriter w;
w.write("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension);
fmt::TMemoryWriter w;
w.write(S("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension);
return w.str();
}

std::string _base_filename;
std::string _extension;
tstring _base_filename;
tstring _extension;
int _rotation_h;
int _rotation_m;
std::chrono::system_clock::time_point _rotation_tp;
Expand Down
8 changes: 4 additions & 4 deletions include/spdlog/spdlog.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ void set_sync_mode();
//
// Create and register multi/single threaded rotating file logger
//
std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush = false);
std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush = false);
std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const tstring& filename, size_t max_file_size, size_t max_files, bool force_flush = false);
std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const tstring& filename, size_t max_file_size, size_t max_files, bool force_flush = false);

//
// Create file logger which creates new file on the given time (default in midnight):
//
std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour=0, int minute=0, bool force_flush = false);
std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const std::string& filename, int hour=0, int minute=0, bool force_flush = false);
std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const tstring& filename, int hour=0, int minute=0, bool force_flush = false);
std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const tstring& filename, int hour=0, int minute=0, bool force_flush = false);


//
Expand Down
6 changes: 6 additions & 0 deletions include/spdlog/tweakme.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,9 @@
// Note that upon creating a logger the registry is modified by spdlog..
// #define SPDLOG_NO_REGISTRY_MUTEX
///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////
// Uncomment to enable usage of wchar_t for file names on Windows.
// #define SPDLOG_USE_WCHAR
///////////////////////////////////////////////////////////////////////////////