/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ #pragma once #include //#include #include #include #include #include #include #include #include #include #include #include #include #include // FIXME: For qmax/qmin #define stringify__(x) #x #define stringify(x) stringify__(x) #ifndef __GNUC__ #define __attribute__(x) #endif #ifdef _MSC_VER #define unlink _unlink #endif /* set these before calling CheckParm */ extern int myargc; extern char **myargv; char *Q_strupr(char *start); char *Q_strlower(char *start); int Q_strncasecmp(const char *s1, const char *s2, int n); int Q_strcasecmp(const char *s1, const char *s2); extern std::filesystem::path qdir, // c:/Quake/, c:/Hexen II/ etc. gamedir, // c:/Quake/mymod/ basedir; // c:/Quake/ID1/, c:/Quake 2/BASEQ2/ etc. bool string_iequals(const std::string &a, const std::string &b); // mxd struct case_insensitive_hash { std::size_t operator()(const std::string &s) const noexcept { std::size_t hash = 0x811c9dc5; constexpr std::size_t prime = 0x1000193; for (auto &c : s) { hash ^= tolower(c); hash *= prime; } return hash; } }; struct case_insensitive_equal { bool operator()(const std::string &l, const std::string &r) const noexcept { return Q_strcasecmp(l.c_str(), r.c_str()) == 0; } }; struct case_insensitive_less { bool operator()(const std::string &l, const std::string &r) const noexcept { return Q_strcasecmp(l.c_str(), r.c_str()) < 0; } }; void SetQdirFromPath(const std::string &basedirname, std::filesystem::path path); // Returns the path itself if it has an extension already, otherwise // returns the path with extension replaced with `extension`. inline std::filesystem::path DefaultExtension(const std::filesystem::path &path, const std::filesystem::path &extension) { if (path.has_extension()) return path; return std::filesystem::path(path).replace_extension(extension); } #include using qclock = std::chrono::high_resolution_clock; using duration = std::chrono::duration; using time_point = std::chrono::time_point; inline time_point I_FloatTime() { return qclock::now(); } template inline void Print(const char *fmt, const Args &...args) { fmt::print(fmt, std::forward(args)...); } [[noreturn]] void Error(const char *error) __attribute__((noreturn)); template [[noreturn]] inline void Error(const char *fmt, const Args &...args) { auto formatted = fmt::format(fmt, std::forward(args)...); Error(formatted.c_str()); } #define FError(fmt, ...) \ Error("{}: " fmt, __func__, __VA_ARGS__) int CheckParm(const char *check); using qfile_t = std::unique_ptr; qfile_t SafeOpenWrite(const std::filesystem::path &filename); qfile_t SafeOpenRead(const std::filesystem::path &filename, bool must_exist = false); size_t SafeRead(const qfile_t &f, void *buffer, size_t count); size_t SafeWrite(const qfile_t &f, const void *buffer, size_t count); void SafeSeek(const qfile_t &f, long offset, int32_t origin); long SafeTell(const qfile_t &f); long LoadFilePak(std::filesystem::path &filename, void *destptr); long LoadFile(const std::filesystem::path &filename, void *destptr); int ParseNum(char *str); short BigShort(short l); short LittleShort(short l); int BigLong(int l); int LittleLong(int l); float BigFloat(float l); float LittleFloat(float l); // temporary #ifdef _WIN32 #define copystring _strdup #else #define copystring strdup #endif inline void Q_assert_(bool success, const char *expr, const char *file, int line) { if (!success) { LogPrint("{}:{}: Q_assert({}) failed.\n", file, line, expr); assert(0); exit(1); } } /** * assertion macro that is used in all builds (debug/release) */ #define Q_assert(x) Q_assert_((x), stringify(x), __FILE__, __LINE__) #define Q_assert_unreachable() Q_assert(false)