Fix handling input file path separator (#4515) (#4516)

This commit is contained in:
Anthony Donlon
2023-09-26 15:42:15 -04:00
committed by GitHub
parent be45a9b7d5
commit 229ce1aecf
22 changed files with 335 additions and 206 deletions
+67 -8
View File
@@ -124,15 +124,46 @@ void V3Os::setenvStr(const string& envvar, const string& value, const string& wh
//######################################################################
// Generic filename utilities
static bool isSlash(char ch) VL_PURE { return ch == '/' || ch == '\\'; }
#if defined(_WIN32) || defined(__MINGW32__)
static constexpr char V3OS_SLASH = '\\';
#else
static constexpr char V3OS_SLASH = '/';
#endif
string V3Os::filenameFromDirBase(const string& dir, const string& basename) VL_PURE {
// Don't return ./{filename} because if filename was absolute, that makes it relative
if (dir.empty() || dir == ".") {
return basename;
} else {
return dir + "/" + basename;
static bool isSlash(char ch) VL_PURE {
#if defined(_WIN32) || defined(__MINGW32__)
return ch == '/' || ch == '\\';
#else
return ch == '/';
#endif
}
string V3Os::filenameCleanup(const string& filename) VL_PURE {
string str;
str.reserve(filename.length());
bool lastIsSlash = false;
for (const char ch : filename) {
const bool lastIsSlashOld = lastIsSlash;
lastIsSlash = isSlash(ch);
if (lastIsSlash && lastIsSlashOld) continue;
str += ch;
}
if (str.size() > 1 && isSlash(str.back())) str.pop_back();
while (str.size() > 2 && str[0] == '.' && isSlash(str[1])) str.erase(0, 2);
return str;
}
string V3Os::filenameJoin(std::initializer_list<const std::string> paths) VL_PURE {
string fullpath;
for (const auto& item : paths) {
if (item.empty() || item == ".") {
continue;
} else {
if (!fullpath.empty()) fullpath += V3OS_SLASH;
fullpath += item;
}
}
return fullpath;
}
string V3Os::filenameDir(const string& filename) VL_PURE {
@@ -144,7 +175,7 @@ string V3Os::filenameDir(const string& filename) VL_PURE {
if (it.base() == filename.begin()) {
return ".";
} else {
return {filename.begin(), (++it).base()};
return string{filename.begin(), (++it).base()};
}
}
@@ -164,6 +195,10 @@ string V3Os::filenameNonExt(const string& filename) VL_PURE {
return base;
}
string V3Os::filenameNonDirExt(const string& filename) VL_PURE {
return filenameNonExt(filenameNonDir(filename));
}
string V3Os::filenameSubstitute(const string& filename) {
string result;
// cppcheck-has-bug-suppress unusedLabel
@@ -392,3 +427,27 @@ int V3Os::system(const string& command) {
return exit_code;
}
}
void V3Os::selfTest() {
#ifdef VL_DEBUG
UASSERT_SELFTEST(string, filenameCleanup(""), "");
UASSERT_SELFTEST(string, filenameCleanup("."), ".");
UASSERT_SELFTEST(string, filenameCleanup(".."), "..");
UASSERT_SELFTEST(string, filenameCleanup("/"), "/");
UASSERT_SELFTEST(string, filenameCleanup("../"), "..");
UASSERT_SELFTEST(string, filenameCleanup("//"), "/");
UASSERT_SELFTEST(string, filenameCleanup("//."), "/.");
UASSERT_SELFTEST(string, filenameCleanup("./"), ".");
UASSERT_SELFTEST(string, filenameCleanup("././"), ".");
UASSERT_SELFTEST(string, filenameCleanup(".///"), ".");
UASSERT_SELFTEST(string, filenameCleanup("a"), "a");
UASSERT_SELFTEST(string, filenameCleanup("a/"), "a");
UASSERT_SELFTEST(string, filenameCleanup("a/b"), "a/b");
UASSERT_SELFTEST(string, filenameCleanup("././//./a/b"), "a/b");
UASSERT_SELFTEST(string, filenameCleanup(".//./a///"), "a");
UASSERT_SELFTEST(string, filenameCleanup("///a/./b///."), "/a/./b/.");
UASSERT_SELFTEST(string, filenameCleanup("aaa/bbb/ccc/"), "aaa/bbb/ccc");
UASSERT_SELFTEST(string, filenameCleanup("./aaa/bbb/ccc/"), "aaa/bbb/ccc");
UASSERT_SELFTEST(string, filenameCleanup("../aaa/bbb/ccc/"), "../aaa/bbb/ccc");
#endif
}