diff --git a/common/cmdlib.cc b/common/cmdlib.cc index deed69db..0a966524 100644 --- a/common/cmdlib.cc +++ b/common/cmdlib.cc @@ -37,6 +37,8 @@ #include +#include + #define PATHSEPERATOR '/' /* set these before calling CheckParm */ @@ -763,15 +765,15 @@ DefaultPath(char *path, const char *basepath) strcat(path, temp); } -void -StripFilename(char *path) +std::string +StrippedFilename(const std::string& path) { - int length; - - length = strlen(path) - 1; - while (length > 0 && path[length] != PATHSEPERATOR) - length--; - path[length] = '\0'; + const size_t lastSlash = path.rfind(PATHSEPERATOR); + if (lastSlash == std::string::npos) { + return std::string(); + } + // excludes the trailing slash + return path.substr(0, lastSlash); } void diff --git a/include/common/cmdlib.hh b/include/common/cmdlib.hh index 72e9581d..d9316f7b 100644 --- a/include/common/cmdlib.hh +++ b/include/common/cmdlib.hh @@ -28,6 +28,7 @@ #include #include #include +#include #include #include // FIXME: For qmax/qmin @@ -95,7 +96,7 @@ void SaveFile(const char *filename, const void *buffer, int count); void DefaultExtension(char *path, const char *extension); void DefaultPath(char *path, const char *basepath); -void StripFilename(char *path); +std::string StrippedFilename(const std::string& path); void StripExtension(char *path); std::string StrippedExtension(const std::string& path); int IsAbsolutePath(const char *path); diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index 15bb4d2a..59df832b 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -371,11 +371,13 @@ public: float midsplitSurfFraction; char szMapName[512]; char szBSPName[512]; - struct - { - char *path; + + struct wadpath { + std::string path; bool external; //wads from this path are not to be embedded into the bsp, but will instead require the engine to load them from elsewhere. strongly recommended for eg halflife.wad - } wadPaths[16]; + }; + + std::vector wadPathsVec; vec_t on_epsilon; bool fObjExport; bool fOmitDetail; @@ -388,34 +390,47 @@ public: bool fContentHack; vec_t worldExtent; - - ~options_t() { - for (int i = 0; i < sizeof(wadPaths)/sizeof(wadPaths[0]); i++) - { - free(wadPaths[i].path); - wadPaths[i].path = nullptr; - } - } - options_t() { - memset(this, 0, sizeof(options_t)); - - // Initial values - this->dxLeakDist = 2; - this->dxSubdivide = 240; - this->fVerbose = true; - this->szMapName[0] = 0; - this->szBSPName[0] = 0; - - /* Default to the original Quake BSP Version... */ - this->BSPVersion = BSPVERSION; - this->fTranswater = true; - this->fixRotateObjTexture = true; - this->fOldaxis = true; - this->maxNodeSize = 1024; - this->midsplitSurfFraction = 0; - this->on_epsilon = 0.0001; - this->worldExtent = 65536; - } + options_t() : + fNofill(false), + fNoclip(false), + fNoskip(false), + fNodetail(false), + fOnlyents(false), + fConvertMapFormat(false), + convertMapFormat(conversion_t::quake), + fVerbose(true), + fAllverbose(false), + fSplitspecial(false), + fSplitturb(false), + fSplitsky(false), + fTranswater(true), + fTranssky(false), + fOldaxis(true), + fNoverbose(false), + fNopercent(false), + forceGoodTree(false), + fixRotateObjTexture(true), + fbspx_brushes(false), + fNoTextures(false), + hexen2(0), + BSPVersion(BSPVERSION), // Default to the original Quake BSP Version... + dxSubdivide(240), + dxLeakDist(2), + maxNodeSize(1024), + midsplitSurfFraction(0.0f), + szMapName{}, + szBSPName{}, + on_epsilon(0.0001), + fObjExport(false), + fOmitDetail(false), + fOmitDetailWall(false), + fOmitDetailIllusionary(false), + fOmitDetailFence(false), + fForcePRT1(false), + fTestExpand(false), + fLeakTest(false), + fContentHack(false), + worldExtent(65536.0f) {} }; extern options_t options; diff --git a/light/test_common.cc b/light/test_common.cc index bf1a4e09..0721fe86 100644 --- a/light/test_common.cc +++ b/light/test_common.cc @@ -4,15 +4,6 @@ #include TEST(common, StripFilename) { - char test[] = "/home/foo/bar.txt"; - StripFilename(test); - - ASSERT_EQ(std::string("/home/foo"), std::string(test)); -} - -TEST(common, StripFilenameFileOnly) { - char test[] = "bar.txt"; - StripFilename(test); - - ASSERT_EQ(std::string(""), std::string(test)); + ASSERT_EQ("/home/foo", StrippedFilename("/home/foo/bar.txt")); + ASSERT_EQ("", StrippedFilename("bar.txt")); } diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index c411049e..e47cc56a 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -863,20 +863,18 @@ ParseOptions(char *szOptions) szTok2 = GetTok(szTok + strlen(szTok) + 1, szEnd); if (!szTok2) Error("Invalid argument to option %s", szTok); - int i; - for (i = 0; i < sizeof(options.wadPaths)/sizeof(options.wadPaths[0]); i++) - { - if (options.wadPaths[i].path) - continue; - options.wadPaths[i].external = !!Q_strcasecmp(szTok, "wadpath"); - options.wadPaths[i].path = strdup(szTok2); - /* Remove trailing /, if any */ - if (options.wadPaths[i].path[strlen(options.wadPaths[i].path) - 1] == '/') - options.wadPaths[i].path[strlen(options.wadPaths[i].path) - 1] = 0; - break; + + std::string wadpath = szTok2; + /* Remove trailing /, if any */ + if (wadpath.size() > 0 && wadpath[wadpath.size() - 1] == '/') { + wadpath.resize(wadpath.size() - 1); } - if (i == sizeof(options.wadPaths)/sizeof(options.wadPaths[0])) - Error("too many -wadpath args"); + + options_t::wadpath wp; + wp.external = !!Q_strcasecmp(szTok, "wadpath"); + wp.path = wadpath; + options.wadPathsVec.push_back(wp); + szTok = szTok2; } else if (!Q_strcasecmp(szTok, "oldrottex")) { options.fixRotateObjTexture = false; @@ -1016,10 +1014,16 @@ InitQBSP(int argc, const char **argv) Message(msgFile, IntroString); /* If no wadpath given, default to the map directory */ - if (!options.wadPaths[0].path) { - options.wadPaths[0].external = false; - options.wadPaths[0].path = strdup(options.szMapName); - StripFilename(options.wadPaths[0].path); + if (options.wadPathsVec.empty()) { + options_t::wadpath wp; + wp.external = false; + wp.path = StrippedFilename(options.szMapName); + + // If options.szMapName is a relative path, StrippedFilename will return the empty string. + // In that case, don't add it as a wad path. + if (!wp.path.empty()) { + options.wadPathsVec.push_back(wp); + } } // Remove already existing files diff --git a/qbsp/wad.cc b/qbsp/wad.cc index f8187c9d..613bab71 100644 --- a/qbsp/wad.cc +++ b/qbsp/wad.cc @@ -133,37 +133,29 @@ wad_t *WADList_AddWad(const char *fpath, bool external, wad_t *current_wadlist) wad_t * WADList_Init(const char *wadstring) { - int len; - wad_t *wadlist; - const char *fname; - char *fpath; - const char *pos; - int pathlen; - if (!wadstring || !wadstring[0]) - return NULL; + return nullptr; - wadlist = NULL; - len = strlen(wadstring); - pos = wadstring; + wad_t *wadlist = nullptr; + const int len = strlen(wadstring); + const char *pos = wadstring; while (pos - wadstring < len) { - fname = pos; + // split string by ';' and copy the current component into fpath + const char *const fname = pos; while (*pos && *pos != ';') pos++; - if (!options.wadPaths[0].path || IsAbsolutePath(fname)) { - fpath = (char *)AllocMem(OTHER, (pos - fname) + 1, false); - q_snprintf(fpath, (pos - fname) + 1, "%s", fname); - wadlist = WADList_AddWad(fpath, false, wadlist); - FreeMem(fpath, OTHER, strlen(fpath) + 1); + const size_t fpathLen = pos - fname; + std::string fpath; + fpath.resize(fpathLen); + memcpy(&fpath[0], fname, fpathLen); + + if (options.wadPathsVec.empty() || IsAbsolutePath(fpath.c_str())) { + wadlist = WADList_AddWad(fpath.c_str(), false, wadlist); } else { - for (int i = 0; i < sizeof(options.wadPaths)/sizeof(options.wadPaths[0]) && options.wadPaths[i].path; i++) - { - pathlen = strlen(options.wadPaths[i].path) + 1 + (pos - fname); - fpath = (char *)AllocMem(OTHER, pathlen + 1, true); - q_snprintf(fpath, pathlen + 1, "%s/%s", options.wadPaths[i].path, fname); - wadlist = WADList_AddWad(fpath, options.wadPaths[i].external, wadlist); - FreeMem(fpath, OTHER, strlen(fpath) + 1); + for (const options_t::wadpath& wadpath : options.wadPathsVec) { + const std::string fullPath = wadpath.path + "/" + fpath; + wadlist = WADList_AddWad(fullPath.c_str(), wadpath.external, wadlist); } }