diff --git a/src/game/game.cpp b/src/game/game.cpp index 17e4b9c654..8d19949983 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -325,7 +325,7 @@ static bool WriteMapSetup(const fs::path &mapSetup, CMap &map, int writeTerrain, f->printf("if CanAccessFile(__file__ .. \".preamble\") then Load(__file__ .. \".preamble\", Editor.Running == 0) end\n\n"); if (!Map.Info.Preamble.empty()) { std::unique_ptr preamble = CreateFileWriter(mapSetup.string() + ".preamble"); - preamble->write(Map.Info.Preamble.c_str(), Map.Info.Preamble.size()); + preamble->write(Map.Info.Preamble); } f->printf("-- player configuration\n"); @@ -480,7 +480,7 @@ static bool WriteMapSetup(const fs::path &mapSetup, CMap &map, int writeTerrain, f->printf("if CanAccessFile(__file__ .. \".postamble\") then Load(__file__ .. \".postamble\", Editor.Running == 0) end\n\n"); if (!Map.Info.Postamble.empty()) { std::unique_ptr postamble = CreateFileWriter(mapSetup.string() + ".postamble"); - postamble->write(Map.Info.Postamble.c_str(), Map.Info.Postamble.size()); + postamble->write(Map.Info.Postamble); } } catch (const FileException &) { diff --git a/src/include/iolib.h b/src/include/iolib.h index 16ca55fff1..9580c37dd7 100644 --- a/src/include/iolib.h +++ b/src/include/iolib.h @@ -41,6 +41,7 @@ #include #include +#include #include /*---------------------------------------------------------------------------- @@ -61,11 +62,15 @@ class FileException class FileWriter { public: - virtual ~FileWriter() {} + virtual ~FileWriter() = default; - void printf(const char *format, ...) PRINTF_VAARG_ATTRIBUTE(2, 3); // Don't forget to count this + template + void printf(const char *format, Ts... args) + { + write(Format(format, args...)); + } - virtual int write(const char *data, unsigned int size) = 0; + virtual int write(std::string_view data) = 0; }; @@ -119,7 +124,13 @@ class CFile long tell(); static SDL_RWops *to_SDL_RWops(std::unique_ptr file); - int printf(const char *format, ...) PRINTF_VAARG_ATTRIBUTE(2, 3); // Don't forget to count this + void write(std::string_view); + + template + void printf(const char* format, Ts... args) + { + write(Format(format, args...)); + } private: class PImpl; std::unique_ptr pimpl; diff --git a/src/include/stratagus.h b/src/include/stratagus.h index 50dfc884e4..a16a1f219f 100644 --- a/src/include/stratagus.h +++ b/src/include/stratagus.h @@ -108,7 +108,27 @@ extern bool EnableWallsInSinglePlayer; extern std::vector OriginalArgv; extern void AbortAt(const char *file, int line, const char *funcName, const char *conditionStr); -extern void PrintOnStdOut(const char *format, ...); + +template +std::string Format(const char *format, Ts... args) +{ + const auto len = snprintf(nullptr, 0, format, args...); + std::string res(len, '\0'); + snprintf(res.data(), res.size(), format, args...); + return res; +} + +inline void PrintOnStderr(std::string_view s) +{ + fwrite(s.data(), 1, s.size(), stderr); + fflush(stderr); +} + +inline void PrintOnStdOut(std::string_view s) +{ + fwrite(s.data(), 1, s.size(), stdout); + fflush(stdout); +} /** ** Assert a condition. If cond is not true abort with file,line. @@ -119,24 +139,24 @@ extern void PrintOnStdOut(const char *format, ...); /** ** Print debug information with function name. */ +#define LogPrint(format, ...) \ + do { \ + PrintFunction(); \ + PrintOnStdOut(Format(format, ##__VA_ARGS__)); \ + } while (0) + #define DebugPrint(format, ...) \ do { \ if (EnableDebugPrint) { \ - PrintFunction(); \ - PrintOnStdOut(format, ##__VA_ARGS__); \ + LogPrint(format, ##__VA_ARGS__); \ } \ } while (0) -#define LogPrint(format, ...) \ - do { \ - PrintFunction(); \ - PrintOnStdOut(format, ##__VA_ARGS__); \ - } while (0) #define ErrorPrint(format, ...) \ do { \ fprintf(stderr, "%s:%d: %s: ", __FILE__, __LINE__, __func__); \ - fprintf(stderr, format, ##__VA_ARGS__); \ + PrintOnStderr(Format(format, ##__VA_ARGS__)); \ } while (0) /*============================================================================ diff --git a/src/stratagus/iolib.cpp b/src/stratagus/iolib.cpp index c3a04b3608..972c59b0b6 100644 --- a/src/stratagus/iolib.cpp +++ b/src/stratagus/iolib.cpp @@ -69,7 +69,7 @@ enum class ClfType class CFile::PImpl { public: - PImpl(); + PImpl() = default; ~PImpl(); PImpl(const PImpl &) = delete; const PImpl &operator=(const PImpl &) = delete; @@ -83,13 +83,13 @@ class CFile::PImpl int write(const void *buf, size_t len); private: - ClfType cl_type; /// type of CFile - FILE *cl_plain; /// standard file pointer + ClfType cl_type = ClfType::Invalid; /// type of CFile + FILE *cl_plain = nullptr; /// standard file pointer #ifdef USE_ZLIB gzFile cl_gz; /// gzip file pointer #endif // !USE_ZLIB #ifdef USE_BZ2LIB - BZFILE *cl_bz; /// bzip2 file pointer + BZFILE *cl_bz = nullptr; /// bzip2 file pointer #endif // !USE_BZ2LIB }; @@ -158,33 +158,11 @@ long CFile::tell() /** ** CLprintf Library file write ** -** @param format String Format. -** @param ... Parameter List. +** @param data String to write. */ -int CFile::printf(const char *format, ...) -{ - std::vector p(500); - - while (true) { - // Try to print in the allocated space. - va_list ap; - va_start(ap, format); - const int n = vsnprintf(p.data(), p.size(), format, ap); - va_end(ap); - // If that worked, string was processed. - if (n > -1 && n < static_cast(p.size())) { - p.resize(n); - break; - } - // Else try again with more space. - if (n > -1) { // glibc 2.1 - p.resize(n + 1); // precisely what is needed - } else { /* glibc 2.0, vc++ */ - p.resize(p.size() * 2); // twice the old size - } - } - int ret = pimpl->write(p.data(), p.size()); - return ret; +void CFile::write(std::string_view data) +{ + pimpl->write(data.data(), data.size()); } static Sint64 sdl_size(SDL_RWops *context) @@ -240,11 +218,6 @@ SDL_RWops *CFile::to_SDL_RWops(std::unique_ptr file) // Implementation. // -CFile::PImpl::PImpl() -{ - cl_type = ClfType::Invalid; -} - CFile::PImpl::~PImpl() { if (cl_type != ClfType::Invalid) { @@ -712,20 +685,6 @@ std::vector ReadDataDirectory(const fs::path& directory) return files; } -void FileWriter::printf(const char *format, ...) -{ - // FIXME: hardcoded size - char buf[1024]; - - va_list ap; - va_start(ap, format); - buf[sizeof(buf) - 1] = '\0'; - vsnprintf(buf, sizeof(buf) - 1, format, ap); - va_end(ap); - write(buf, strlen(buf)); -} - - class RawFileWriter : public FileWriter { FILE *file; @@ -745,10 +704,7 @@ class RawFileWriter : public FileWriter if (file) { fclose(file); } } - int write(const char *data, unsigned int size) override - { - return fwrite(data, size, 1, file); - } + int write(std::string_view data) override { return fwrite(data.data(), data.size(), 1, file); } }; class GzFileWriter : public FileWriter @@ -770,9 +726,9 @@ class GzFileWriter : public FileWriter if (file) { gzclose(file); } } - int write(const char *data, unsigned int size) override + int write(std::string_view data) override { - return gzwrite(file, data, size); + return gzwrite(file, data.data(), data.size()); } }; diff --git a/src/stratagus/util.cpp b/src/stratagus/util.cpp index 8002530ed0..b4c4a141d8 100644 --- a/src/stratagus/util.cpp +++ b/src/stratagus/util.cpp @@ -518,15 +518,6 @@ void AbortAt(const char *file, int line, const char *funcName, const char *condi abort(); } -void PrintOnStdOut(const char *format, ...) -{ - va_list valist; - va_start(valist, format); - vprintf(format, valist); - va_end(valist); - fflush(stdout); -} - /*---------------------------------------------------------------------------- Check SSE/AVX support. This can detect the instruction support of diff --git a/src/video/graphic.cpp b/src/video/graphic.cpp index fd3c62017c..6164398e66 100644 --- a/src/video/graphic.cpp +++ b/src/video/graphic.cpp @@ -1065,18 +1065,19 @@ void CGraphic::OverlayGraphic(CGraphic *other, bool mask) this->Load(); other->Load(); if (!mSurface) { - PrintOnStdOut("ERROR: Graphic %s not loaded in call to OverlayGraphic", this->File.c_str()); + PrintOnStdOut( + Format("ERROR: Graphic %s not loaded in call to OverlayGraphic", this->File.c_str())); return; } if (!other->mSurface) { - PrintOnStdOut("ERROR: Graphic %s not loaded in call to OverlayGraphic", - other->File.c_str()); + PrintOnStdOut( + Format("ERROR: Graphic %s not loaded in call to OverlayGraphic", other->File.c_str())); return; } if (mSurface->w != other->mSurface->w || mSurface->h != other->mSurface->h) { - PrintOnStdOut("ERROR: Graphic %s has different size than %s OverlayGraphic", - File.c_str(), - other->File.c_str()); + PrintOnStdOut(Format("ERROR: Graphic %s has different size than %s OverlayGraphic", + File.c_str(), + other->File.c_str())); return; } @@ -1085,16 +1086,16 @@ void CGraphic::OverlayGraphic(CGraphic *other, bool mask) unsigned int dstColorKey; if (!((bpp == 1 && SDL_GetColorKey(other->mSurface, &srcColorKey) == 0 && SDL_GetColorKey(mSurface, &dstColorKey) == 0) || bpp == 4)) { - PrintOnStdOut("ERROR: OverlayGraphic only supported for 8-bit graphics with transparency " - "or RGBA graphics (%s)", - File.c_str()); + PrintOnStdOut(Format("ERROR: OverlayGraphic only supported for 8-bit graphics with " + "transparency or RGBA graphics (%s)", + File.c_str())); return; } if ((bpp != other->mSurface->format->BytesPerPixel)) { - PrintOnStdOut( + PrintOnStdOut(Format( "ERROR: OverlayGraphic only supported graphics with same depth (%s depth != %s depth)", File.c_str(), - other->File.c_str()); + other->File.c_str())); return; }