From 70546016cd4bafddd1658c2fb3f5d92b3c257fe8 Mon Sep 17 00:00:00 2001 From: Argent77 Date: Tue, 7 Jul 2015 14:26:25 +0200 Subject: [PATCH 1/3] Added check for equal file paths and fixed a bug in output filename generation --- tileconv/fileio.cpp | 234 ++++++++++++++++++++++++++++++++++++++---- tileconv/fileio.h | 37 ++++++- tileconv/options.cpp | 108 ++++++++----------- tileconv/options.h | 14 ++- tileconv/tileconv.cpp | 139 +++++++++---------------- tileconv/types.h | 1 - 6 files changed, 353 insertions(+), 180 deletions(-) diff --git a/tileconv/fileio.cpp b/tileconv/fileio.cpp index f02027f..e4b5b50 100644 --- a/tileconv/fileio.cpp +++ b/tileconv/fileio.cpp @@ -20,54 +20,250 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "fileio.h" -#include -#include -#include +#ifdef _WIN32 +# include +#else +# include +# include +# include +#endif namespace tc { -bool File::IsDirectory(const char *fileName) noexcept +#ifdef _WIN32 +const char File::PATH_SEPARATOR = '\\'; +#else +const char File::PATH_SEPARATOR = '/'; +#endif + + +std::string File::ExtractFilePath(const std::string &fileName) noexcept +{ + std::string retVal; + if (!fileName.empty()) { + if (IsPathSeparator(fileName.at(fileName.size() - 1))) { + retVal = fileName; + } else { + std::string::size_type pos = fileName.find_last_of(PATH_SEPARATOR); + if (pos == std::string::npos) { + pos = fileName.find_last_of('/'); + } + if (pos != std::string::npos) { + retVal = fileName.substr(0, pos); + } + } + } + return retVal; +} + +std::string File::ExtractFileName(const std::string &fileName) noexcept +{ + std::string retVal; + if (!fileName.empty() && !IsPathSeparator(fileName.at(fileName.size() - 1))) { + std::string::size_type pos = fileName.find_last_of(PATH_SEPARATOR); + if (pos == std::string::npos) { + pos = fileName.find_last_of('/'); + } + if (pos != std::string::npos) { + retVal = fileName.substr(pos+1); + } else { + retVal = fileName; + } + } + return retVal; +} + +std::string File::ExtractFileBase(const std::string &fileName) noexcept +{ + std::string retVal = ExtractFileName(fileName); + if (!retVal.empty()) { + std::string::size_type pos = retVal.find_last_of('.'); + if (pos != std::string::npos) { + retVal = retVal.substr(0, pos); + } + } + return retVal; +} + +std::string File::ExtractFileExt(const std::string &fileName) noexcept +{ + std::string retVal = ExtractFileName(fileName); + std::string::size_type pos = retVal.find_last_of('.'); + if (pos != std::string::npos) { + retVal = retVal.substr(pos); + } else { + retVal.clear(); + } + return retVal; +} + +std::string File::CreateFileName(const std::string &path, const std::string &file) noexcept { - if (fileName != nullptr) { + std::string retVal; + if (!path.empty()) { + retVal += path; + if (!IsPathSeparator(path.at(path.size() - 1))) { + retVal += PATH_SEPARATOR; + } + } + if (!file.empty()) { + retVal += file; + } + return retVal; +} + +std::string File::ChangeFileExt(const std::string &fileName, const std::string &fileExt) noexcept +{ + std::string retVal; + if (!fileName.empty()) { + std::string path = ExtractFilePath(fileName); + std::string name = ExtractFileBase(fileName); + if (!name.empty()) { + if (!fileExt.empty() && fileExt.at(0) != '.') { + name += '.'; + } + name += fileExt; + retVal = CreateFileName(path, name); + } else { + retVal = fileName; + } + } + return retVal; +} + +bool File::IsPathSeparator(char ch) noexcept +{ + // Note: '/' is always valid + return (ch == PATH_SEPARATOR || ch == '/'); +} + +bool File::IsDirectory(const std::string &fileName) noexcept +{ + bool retVal = false; + if (!fileName.empty()) { +#ifdef _WIN32 + DWORD flags = ::GetFileAttributes(fileName.c_str()); + if (flags != INVALID_FILE_ATTRIBUTES) { + retVal = (flags & FILE_ATTRIBUTE_DIRECTORY) != 0; + } +#else struct stat s; - if (stat(fileName, &s) != -1) { + if (::stat(fileName.c_str(), &s) != -1) { return S_ISDIR(s.st_mode); } +#endif } - return false; + return retVal; } +bool File::Exists(const std::string &path) noexcept +{ + bool retVal = false; + if (!path.empty()) { +#ifdef _WIN32 + retVal = (::GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES); +#else + struct stat s; + retVal = (::stat(path.c_str(), &s) == 0); +#endif + } + return retVal; +} -long File::GetFileSize(const char *fileName) noexcept +long File::GetFileSize(const std::string &fileName) noexcept { - if (fileName != nullptr) { + if (!fileName.empty()) { +#ifdef _WIN32 + HANDLE h = ::CreateFile(fileName.c_str(), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + if (h != INVALID_HANDLE_VALUE) { + DWORD size = ::GetFileSize(h, NULL); + ::CloseHandle(h); + if (size != INVALID_FILE_SIZE) { + return size; + } + } +#else struct stat s; - if (stat(fileName, &s) != -1) { + if (::stat(fileName.c_str(), &s) != -1) { return s.st_size; } +#endif } return -1L; } - -bool File::RemoveFile(const char *fileName) noexcept +bool File::RemoveFile(const std::string &fileName) noexcept { - if (fileName != nullptr) { - return (std::remove(fileName) == 0); + if (!fileName.empty()) { + return (std::remove(fileName.c_str()) == 0); } return false; } - -bool File::RenameFile(const char *oldFileName, const char *newFileName) noexcept +bool File::RenameFile(const std::string &oldFileName, const std::string &newFileName) noexcept { - if (oldFileName != nullptr && *oldFileName != 0 && - newFileName != nullptr && *newFileName != 0) { - return (std::rename(oldFileName, newFileName) == 0); + if (!oldFileName.empty() && !newFileName.empty()) { + return (std::rename(oldFileName.c_str(), newFileName.c_str()) == 0); } return false; } +bool File::IsEqual(const std::string &path1, const std::string &path2) noexcept +{ + bool retVal = false; + + if (!path1.empty() && !path2.empty()) { +#ifdef _WIN32 + HANDLE h2 = ::CreateFile(path2.c_str(), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + HANDLE h1 = ::CreateFile(path1.c_str(), 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + if (h1 == INVALID_HANDLE_VALUE || h2 == INVALID_HANDLE_VALUE) { + if (h2 != INVALID_HANDLE_VALUE) { + ::CloseHandle(h2); + } + if (h1 != INVALID_HANDLE_VALUE) { + ::CloseHandle(h1); + } + return retVal; + } + + BY_HANDLE_FILE_INFORMATION info1, info2; + bool b1 = ::GetFileInformationByHandle(h1, &info1); + bool b2 = ::GetFileInformationByHandle(h2, &info2); + if (!b1 || !b2) { + ::CloseHandle(h2); + ::CloseHandle(h1); + return retVal; + } + + retVal = (info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber) && + (info1.nFileIndexHigh == info2.nFileIndexHigh) && + (info1.nFileIndexLow == info2.nFileIndexLow) && + (info1.nFileSizeHigh == info2.nFileSizeHigh) && + (info1.nFileSizeLow == info2.nFileSizeLow) && + (info1.ftLastWriteTime.dwLowDateTime == info2.ftLastWriteTime.dwLowDateTime) && + (info1.ftLastWriteTime.dwHighDateTime == info2.ftLastWriteTime.dwHighDateTime); + + ::CloseHandle(h2); + ::CloseHandle(h1); + +#else + struct stat s1, s2; + int e2 = ::stat(path2.c_str(), &s2); + int e1 = ::stat(path1.c_str(), &s1); + if (e1 == 0 && e2 == 0) { + retVal = (s1.st_dev == s2.st_dev) && + (s1.st_ino == s2.st_ino) && + (s1.st_size == s2.st_size) && + (s1.st_mtime == s2.st_mtime); + } + +#endif + } + return retVal; +} File::File(const char *fileName, const char *mode) noexcept : m_file(0) diff --git a/tileconv/fileio.h b/tileconv/fileio.h index 89a8197..f09dbb3 100644 --- a/tileconv/fileio.h +++ b/tileconv/fileio.h @@ -33,17 +33,44 @@ namespace tc { class File { public: + /** Extracts the full path component of the given file name. */ + static std::string ExtractFilePath(const std::string &fileName) noexcept; + /** Extracts the top-level path component of the given file name which can be filename or folder. */ + static std::string ExtractFileName(const std::string &fileName) noexcept; + /** Extracts the top-level path component without extension. */ + static std::string ExtractFileBase(const std::string &fileName) noexcept; + /** Extracts the file extension of the top-level path component. */ + static std::string ExtractFileExt(const std::string &fileName) noexcept; + + /** Concatenates path and file and returns the result. */ + static std::string CreateFileName(const std::string &path, const std::string &file) noexcept; + + /** Changes the file extension of the specified filename. */ + static std::string ChangeFileExt(const std::string &fileName, const std::string &fileExt) noexcept; + + /** Returns true if the specified character is a path separator. */ + static bool IsPathSeparator(char ch) noexcept; + /** Returns true only if the given path is a directory. */ - static bool IsDirectory(const char *fileName) noexcept; + static bool IsDirectory(const std::string &fileName) noexcept; + + /** + * Returns true only if the given path exists (can be regular file, folder + * or any other kind of file type). + */ + static bool Exists(const std::string &path) noexcept; /** Returns size of the given file in bytes. Returns -1 on error. */ - static long GetFileSize(const char *fileName) noexcept; + static long GetFileSize(const std::string &fileName) noexcept; /** Deletes the file identified by the given name. */ - static bool RemoveFile(const char *fileName) noexcept; + static bool RemoveFile(const std::string &fileName) noexcept; /** Changes the name of a file. */ - static bool RenameFile(const char *oldFileName, const char *newFileName) noexcept; + static bool RenameFile(const std::string &oldFileName, const std::string &newFileName) noexcept; + + /** Returns whether the two specified path strings are pointing to the same file. */ + static bool IsEqual(const std::string &path1, const std::string &path2) noexcept; public: /** Opens a file in the specified mode. */ @@ -142,6 +169,8 @@ class File File& operator=(const File &) = delete; private: + static const char PATH_SEPARATOR; // OS-specific path separator character (either '\' or '/') + std::FILE *m_file; // current file handle std::string m_fileName; // filename std::string m_mode; // current file mode diff --git a/tileconv/options.cpp b/tileconv/options.cpp index 6530b99..2bb7ed9 100644 --- a/tileconv/options.cpp +++ b/tileconv/options.cpp @@ -296,31 +296,12 @@ const std::string& Options::getInput(int idx) const noexcept bool Options::setOutput(const std::string &outFile) noexcept { if (!outFile.empty()) { - // determining if outFile contains filename - std::size_t pos = 0, size = outFile.size(); - if (!File::IsDirectory(outFile.c_str())) { - // splitting file name from path - pos = std::max(outFile.find_last_of('/'), outFile.find_last_of('\\')); - if (pos != std::string::npos) { - size = outFile.size() - pos - 1; - m_outFile.assign(outFile.substr(pos + 1, size)); - size = pos; - pos = 0; - } else { - m_outFile.assign(outFile); - pos = size = 0; - } - } else { + if (File::IsDirectory(outFile.c_str())) { + m_outPath.assign(outFile); m_outFile.clear(); - } - - // setting path - m_outPath.assign(outFile.substr(pos, size)); - if (!m_outPath.empty()) { - char ch = m_outPath.back(); - if (ch != '/' && ch != '\\') { - m_outPath.append("/"); - } + } else { + m_outPath.assign(File::ExtractFilePath(outFile)); + m_outFile.assign(File::ExtractFileName(outFile)); } return true; } @@ -399,7 +380,7 @@ FileType Options::GetFileType(const std::string &fileName, bool assumeTis) noexc } else { if (assumeTis) { long size = f.getsize(); - if ((size % 5120) == 0) { + if ((size % 0x1400) == 0) { return FileType::TIS; } else { return FileType::UNKNOWN; @@ -414,42 +395,51 @@ FileType Options::GetFileType(const std::string &fileName, bool assumeTis) noexc return FileType::UNKNOWN; } +std::string Options::GetFileExt(FileType type) noexcept +{ + switch (type) { + case FileType::TIS: return std::string(".tis"); + case FileType::MOS: return std::string(".mos"); + case FileType::TBC: return std::string(".tbc"); + case FileType::MBC: return std::string(".mbc"); + case FileType::TIZ: return std::string(".tiz"); + case FileType::MOZ: return std::string(".moz"); + default: return std::string(); + } +} -std::string Options::SetFileExt(const std::string &fileName, FileType type) noexcept +std::string Options::GetOutputFileName(const std::string &path, const std::string inputFile, + FileType type, bool overwrite) noexcept { - std::string retVal; - if (!fileName.empty() && type != FileType::UNKNOWN) { - uint32_t pos = fileName.find_last_of('.', fileName.size()); - if (pos != std::string::npos) { - retVal.assign(fileName.substr(0, pos)); + static const std::string defString; // empty default string + + if (!inputFile.empty() && type != FileType::UNKNOWN) { + std::string outFileBase, outFileExt, outPath; + + // getting path + if (path.empty()) { + // using input file and path + outPath = File::ExtractFilePath(inputFile); + } else { + // using separate path with input file + outPath = path; } - switch (type) { - case FileType::TIS: - retVal.append(".tis"); - break; - case FileType::MOS: - retVal.append(".mos"); - break; - case FileType::TBC: - retVal.append(".tbc"); - break; - case FileType::MBC: - retVal.append(".mbc"); - break; - case FileType::TIZ: - retVal.append(".tiz"); - break; - case FileType::MOZ: - retVal.append(".moz"); - break; - default: - break; + + // getting filename + outFileBase = File::ExtractFileBase(inputFile); + outFileExt = GetFileExt(type); + + // making output file unique if necessary + std::string output(File::CreateFileName(outPath, outFileBase + outFileExt)); + for (int idx = 0; !overwrite && File::Exists(output); idx++) { + std::string suffix("-" + std::to_string(idx)); + output = File::CreateFileName(outPath, outFileBase + outFileExt + suffix); } + return output; } - return retVal; + return defString; } - Encoding Options::GetEncodingType(int code) noexcept { switch (code & 0xff) { @@ -463,14 +453,11 @@ Encoding Options::GetEncodingType(int code) noexcept } } - - bool Options::IsTileDeflated(int code) noexcept { return (code & DEFLATE) == 0; } - unsigned Options::GetEncodingCode(Encoding type, bool deflate) noexcept { unsigned retVal = deflate ? 0 : DEFLATE; @@ -487,9 +474,6 @@ unsigned Options::GetEncodingCode(Encoding type, bool deflate) noexcept case Encoding::BC3: retVal |= ENCODE_DXT5; break; -// case Encoding::WEBP: -// retVal |= ENCODE_WEBP; -// break; case Encoding::Z: retVal |= ENCODE_Z; break; @@ -500,7 +484,6 @@ unsigned Options::GetEncodingCode(Encoding type, bool deflate) noexcept return retVal; } - const std::string& Options::GetEncodingName(int code) noexcept { static const std::string descUnk("Unknown (unknown)"); @@ -508,13 +491,11 @@ const std::string& Options::GetEncodingName(int code) noexcept static const std::string descDxt1Def("BC1/DXT1 (zlib-compressed)"); static const std::string descDxt3Def("BC2/DXT3 (zlib-compressed)"); static const std::string descDxt5Def("BC3/DXT5 (zlib-compressed)"); -// static const std::string descWebPDef("WebP (zlib-compressed)"); static const std::string descZ("JPEG compressed TIZ/MOZ"); static const std::string descRaw("Not encoded (uncompressed)"); static const std::string descDxt1("BC1/DXT1 (uncompressed)"); static const std::string descDxt3("BC2/DXT3 (uncompressed)"); static const std::string descDxt5("BC3/DXT5 (uncompressed)"); -// static const std::string descWebP("WebP (uncompressed)"); switch (code) { case ENCODE_RAW: return descRawDef; @@ -531,7 +512,6 @@ const std::string& Options::GetEncodingName(int code) noexcept } } - std::string Options::getOptionsSummary(bool complete) const noexcept { std::string sum; diff --git a/tileconv/options.h b/tileconv/options.h index 431f2e5..f15afdf 100644 --- a/tileconv/options.h +++ b/tileconv/options.h @@ -40,8 +40,18 @@ class Options */ static FileType GetFileType(const std::string &fileName, bool assumeTis) noexcept; - /** Returns the given input filename with the new file extension as specified by type. */ - static std::string SetFileExt(const std::string &fileName, FileType type) noexcept; + /** Returns the file extension based on the specified type. Returns empty string on error. */ + static std::string GetFileExt(FileType type) noexcept; + + /** + * Returns a filename for the output file based on the specified parameters. + * Appends output file by a number if filename already exists (e.g. foo.bar-0, foo.bar-1, ...). + * \param path Output path. + * \param inputFile Input file with path. + * \return Full path to output filename or empty string on error. + */ + static std::string GetOutputFileName(const std::string &path, const std::string inputFile, + FileType type, bool overwrite) noexcept; /** Returns the encoding type for the given numeric code. Returns Encoding::UNKNOWN on error. */ static Encoding GetEncodingType(int code) noexcept; diff --git a/tileconv/tileconv.cpp b/tileconv/tileconv.cpp index 8b472fe..9b59931 100644 --- a/tileconv/tileconv.cpp +++ b/tileconv/tileconv.cpp @@ -94,25 +94,59 @@ bool TileConv::execute() noexcept std::printf("\nProcessing file %d of %d\n", i+1, getOptions().getInputCount()); } const std::string &inputFile = getOptions().getInput(i); + if (!File::Exists(inputFile)) { + retVal = false; + std::printf("File does not exist: \"%s\"\n", inputFile.c_str()); + if (getOptions().isHaltOnError()) { + return retVal; + } else { + continue; + } + } + + FileType fileType = Options::GetFileType(inputFile, getOptions().assumeTis()); + std::string outputFile; + // generating output filename + if (getOptions().isOutFile()) { + outputFile = File::CreateFileName(getOptions().getOutPath(), getOptions().getOutFile()); + } else { + switch (fileType) { + case FileType::TIS: + outputFile = Options::GetOutputFileName(getOptions().getOutPath(), inputFile, FileType::TBC, false); + break; + case FileType::MOS: + outputFile = Options::GetOutputFileName(getOptions().getOutPath(), inputFile, FileType::MBC, false); + break; + case FileType::TBC: + case FileType::TIZ: + outputFile = Options::GetOutputFileName(getOptions().getOutPath(), inputFile, FileType::TIS, false); + break; + case FileType::MBC: + case FileType::MOZ: + outputFile = Options::GetOutputFileName(getOptions().getOutPath(), inputFile, FileType::MOS, false); + break; + default: + outputFile.clear(); + break; + } + } + if (outputFile.empty()) { + retVal = false; + std::printf("Error creating output filename\n"); + if (getOptions().isHaltOnError()) { + return retVal; + } + } else if (File::IsEqual(inputFile, outputFile)) { + std::printf("Error: Input file and output file are equal: %s\n", inputFile.c_str()); + if (getOptions().isHaltOnError()) { + return retVal; + } + } + if (!inputFile.empty()) { switch (Options::GetFileType(inputFile, getOptions().assumeTis())) { case FileType::TIS: - // generating output filename - if (getOptions().isOutFile()) { - outputFile = getOptions().getOutPath() + getOptions().getOutFile(); - } else { - outputFile = getOptions().getOutPath() + Options::SetFileExt(inputFile, FileType::TBC); - } - if (outputFile.empty()) { - retVal = false; - std::printf("Error creating output filename\n"); - if (getOptions().isHaltOnError()) { - return retVal; - } else { - break; - } - } // converting if (!getOptions().isSilent()) { std::printf("Converting TIS -> TBC\n"); @@ -127,21 +161,6 @@ bool TileConv::execute() noexcept } break; case FileType::MOS: - // generating output filename - if (getOptions().isOutFile()) { - outputFile = getOptions().getOutPath() + getOptions().getOutFile(); - } else { - outputFile = getOptions().getOutPath() + Options::SetFileExt(inputFile, FileType::MBC); - } - if (outputFile.empty()) { - retVal = false; - std::printf("Error creating output filename\n"); - if (getOptions().isHaltOnError()) { - return retVal; - } else { - break; - } - } // converting if (!getOptions().isSilent()) { std::printf("Converting MOS -> MBC\n"); @@ -156,21 +175,6 @@ bool TileConv::execute() noexcept } break; case FileType::TBC: - // generating output filename - if (getOptions().isOutFile()) { - outputFile = getOptions().getOutPath() + getOptions().getOutFile(); - } else { - outputFile = getOptions().getOutPath() + Options::SetFileExt(inputFile, FileType::TIS); - } - if (outputFile.empty()) { - retVal = false; - std::printf("Error creating output filename\n"); - if (getOptions().isHaltOnError()) { - return retVal; - } else { - break; - } - } // converting if (!getOptions().isSilent()) { std::printf("Converting TBC -> TIS\n"); @@ -185,21 +189,6 @@ bool TileConv::execute() noexcept } break; case FileType::MBC: - // generating output filename - if (getOptions().isOutFile()) { - outputFile = getOptions().getOutPath() + getOptions().getOutFile(); - } else { - outputFile = getOptions().getOutPath() + Options::SetFileExt(inputFile, FileType::MOS); - } - if (outputFile.empty()) { - retVal = false; - std::printf("Error creating output filename\n"); - if (getOptions().isHaltOnError()) { - return retVal; - } else { - break; - } - } // converting if (!getOptions().isSilent()) { std::printf("Converting MBC -> MOS\n"); @@ -214,21 +203,6 @@ bool TileConv::execute() noexcept } break; case FileType::TIZ: - // generating output filename - if (getOptions().isOutFile()) { - outputFile = getOptions().getOutPath() + getOptions().getOutFile(); - } else { - outputFile = getOptions().getOutPath() + Options::SetFileExt(inputFile, FileType::TIS); - } - if (outputFile.empty()) { - retVal = false; - std::printf("Error creating output filename\n"); - if (getOptions().isHaltOnError()) { - return retVal; - } else { - break; - } - } // converting if (!getOptions().isSilent()) { std::printf("Converting TIZ -> TIS\n"); @@ -243,21 +217,6 @@ bool TileConv::execute() noexcept } break; case FileType::MOZ: - // generating output filename - if (getOptions().isOutFile()) { - outputFile = getOptions().getOutPath() + getOptions().getOutFile(); - } else { - outputFile = getOptions().getOutPath() + Options::SetFileExt(inputFile, FileType::MOS); - } - if (outputFile.empty()) { - retVal = false; - std::printf("Error creating output filename\n"); - if (getOptions().isHaltOnError()) { - return retVal; - } else { - break; - } - } // converting if (!getOptions().isSilent()) { std::printf("Converting MOZ -> MOS\n"); diff --git a/tileconv/types.h b/tileconv/types.h index 6ac88e5..26af3d7 100644 --- a/tileconv/types.h +++ b/tileconv/types.h @@ -32,7 +32,6 @@ namespace tc { #define ENCODE_DXT1 1 #define ENCODE_DXT3 2 #define ENCODE_DXT5 3 -//#define ENCODE_WEBP 4 #define ENCODE_Z 255 /** From e1e7e3cdce7d1d2831942c6875f8eeca1d3dd4da Mon Sep 17 00:00:00 2001 From: Argent77 Date: Tue, 7 Jul 2015 14:36:11 +0200 Subject: [PATCH 2/3] Improved version information --- tileconv/options.cpp | 10 +++++++++- tileconv/version.cpp | 3 +++ tileconv/version.h | 6 ++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tileconv/options.cpp b/tileconv/options.cpp index 2bb7ed9..7880d1c 100644 --- a/tileconv/options.cpp +++ b/tileconv/options.cpp @@ -166,7 +166,15 @@ bool Options::init(int argc, char *argv[]) noexcept setShowInfo(true); break; case 'V': - std::printf("%s %d.%d.%d by %s\n", prog_name, vers_major, vers_minor, vers_patch, author); + if (std::strlen(vers_suffix)) { + std::printf("%s %d.%d.%d (%s) by %s\n", prog_name, vers_major, vers_minor, vers_patch, vers_suffix, author); + } else { + if (vers_patch != 0) { + std::printf("%s %d.%d.%d by %s\n", prog_name, vers_major, vers_minor, vers_patch, author); + } else { + std::printf("%s %d.%d by %s\n", prog_name, vers_major, vers_minor, author); + } + } return false; default: std::printf("Unrecognized parameter \"-%c\"\n", optopt); diff --git a/tileconv/version.cpp b/tileconv/version.cpp index 9556123..e492c9b 100644 --- a/tileconv/version.cpp +++ b/tileconv/version.cpp @@ -19,8 +19,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "version.h" + int vers_major = 0; int vers_minor = 5; int vers_patch = 1; +char vers_suffix[] = ""; char prog_name[] = "tileconv"; char author[] = "Argent77"; diff --git a/tileconv/version.h b/tileconv/version.h index fa1341b..594fdf8 100644 --- a/tileconv/version.h +++ b/tileconv/version.h @@ -19,8 +19,14 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifndef _VERSION_H_ +#define _VERSION_H_ + extern int vers_major; extern int vers_minor; extern int vers_patch; +extern char vers_suffix[]; extern char prog_name[]; extern char author[]; + +#endif // _VERSION_H_ From 878dda67f67512cb10e69c61762e58ddc152b2bf Mon Sep 17 00:00:00 2001 From: Argent77 Date: Tue, 7 Jul 2015 14:45:45 +0200 Subject: [PATCH 3/3] Version 0.6 --- tileconv/version.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tileconv/version.cpp b/tileconv/version.cpp index e492c9b..c300a67 100644 --- a/tileconv/version.cpp +++ b/tileconv/version.cpp @@ -22,8 +22,8 @@ THE SOFTWARE. #include "version.h" int vers_major = 0; -int vers_minor = 5; -int vers_patch = 1; +int vers_minor = 6; +int vers_patch = 0; char vers_suffix[] = ""; char prog_name[] = "tileconv"; char author[] = "Argent77";