Skip to content

Commit eff31dc

Browse files
committed
Fixed cppcheck-opensource#80 (Cannot find include files with relative paths on Windows)
1 parent 5f2cd06 commit eff31dc

2 files changed

Lines changed: 106 additions & 9 deletions

File tree

simplecpp.cpp

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,14 @@ namespace simplecpp {
17461746
// replace backslash separators
17471747
std::replace(path.begin(), path.end(), '\\', '/');
17481748

1749+
const bool unc(path.compare(0,2,"//") == 0);
1750+
1751+
// replace "//" with "/"
1752+
pos = 0;
1753+
while ((pos = path.find("//",pos)) != std::string::npos) {
1754+
path.erase(pos,1);
1755+
}
1756+
17491757
// remove "./"
17501758
pos = 0;
17511759
while ((pos = path.find("./",pos)) != std::string::npos) {
@@ -1755,19 +1763,41 @@ namespace simplecpp {
17551763
pos += 2;
17561764
}
17571765

1758-
// remove "xyz/../"
1759-
pos = 1U;
1760-
while ((pos = path.find("/../", pos)) != std::string::npos) {
1761-
const std::string::size_type pos1 = path.rfind('/', pos - 1U);
1762-
if (pos1 == std::string::npos) {
1763-
path.erase(0,pos+4);
1764-
pos = 0;
1766+
// remove trailing dot if path ends with "/."
1767+
if (endsWith(path,"/."))
1768+
path.erase(path.size()-1);
1769+
1770+
// simplify ".."
1771+
pos = 1; // don't simplify ".." if path starts with that
1772+
while ((pos = path.find("/..", pos)) != std::string::npos) {
1773+
// not end of path, then string must be "/../"
1774+
if (pos + 3 < path.size() && path[pos + 3] != '/') {
1775+
++pos;
1776+
continue;
1777+
}
1778+
// get previous subpath
1779+
const std::string::size_type pos1 = path.rfind('/', pos - 1U) + 1U;
1780+
const std::string previousSubPath = path.substr(pos1, pos-pos1);
1781+
if (previousSubPath == "..") {
1782+
// don't simplify
1783+
++pos;
17651784
} else {
1766-
path.erase(pos1,pos-pos1+3);
1767-
pos = std::min((std::string::size_type)1, pos1);
1785+
// remove previous subpath and ".."
1786+
path.erase(pos1,pos-pos1+4);
1787+
if (path.empty())
1788+
path = ".";
1789+
// update pos
1790+
pos = (pos1 == 0) ? 1 : (pos1 - 1);
17681791
}
17691792
}
17701793

1794+
// Remove trailing '/'?
1795+
//if (path.size() > 1 && endsWith(path, "/"))
1796+
// path.erase(path.size()-1);
1797+
1798+
if (unc)
1799+
path = '/' + path;
1800+
17711801
return realFilename(path);
17721802
}
17731803
}

test.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,71 @@ void simplifyPath()
12561256
ASSERT_EQUALS("../1.c", simplecpp::simplifyPath("../a/../1.c"));
12571257
ASSERT_EQUALS("/../1.c", simplecpp::simplifyPath("/../1.c"));
12581258
ASSERT_EQUALS("/../1.c", simplecpp::simplifyPath("/../a/../1.c"));
1259+
1260+
ASSERT_EQUALS("a/..b/1.c", simplecpp::simplifyPath("a/..b/1.c"));
1261+
ASSERT_EQUALS("../../1.c", simplecpp::simplifyPath("../../1.c"));
1262+
ASSERT_EQUALS("../../../1.c", simplecpp::simplifyPath("../../../1.c"));
1263+
ASSERT_EQUALS("../../../1.c", simplecpp::simplifyPath("../../../a/../1.c"));
1264+
ASSERT_EQUALS("../../1.c", simplecpp::simplifyPath("a/../../../1.c"));
1265+
}
1266+
1267+
// tests transferred from cppcheck
1268+
// https://github.com/danmar/cppcheck/blob/d3e79b71b5ec6e641ca3e516cfced623b27988af/test/testpath.cpp#L43
1269+
void simplifyPath_cppcheck()
1270+
{
1271+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("index.h"));
1272+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./index.h"));
1273+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath(".//index.h"));
1274+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath(".///index.h"));
1275+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/index.h"));
1276+
ASSERT_EQUALS("/path/", simplecpp::simplifyPath("/path/"));
1277+
ASSERT_EQUALS("/", simplecpp::simplifyPath("/"));
1278+
ASSERT_EQUALS("/", simplecpp::simplifyPath("/."));
1279+
ASSERT_EQUALS("/", simplecpp::simplifyPath("/./"));
1280+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/./index.h"));
1281+
ASSERT_EQUALS("/", simplecpp::simplifyPath("/.//"));
1282+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/.//index.h"));
1283+
ASSERT_EQUALS("../index.h", simplecpp::simplifyPath("../index.h"));
1284+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../index.h"));
1285+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./path/../index.h"));
1286+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("path/../index.h"));
1287+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path//../index.h"));
1288+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./path//../index.h"));
1289+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("path//../index.h"));
1290+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/..//index.h"));
1291+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./path/..//index.h"));
1292+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("path/..//index.h"));
1293+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path//..//index.h"));
1294+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("./path//..//index.h"));
1295+
ASSERT_EQUALS("index.h", simplecpp::simplifyPath("path//..//index.h"));
1296+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../other/../index.h"));
1297+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../other///././../index.h"));
1298+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../other/././..///index.h"));
1299+
ASSERT_EQUALS("/index.h", simplecpp::simplifyPath("/path/../other///././..///index.h"));
1300+
ASSERT_EQUALS("../path/index.h", simplecpp::simplifyPath("../path/other/../index.h"));
1301+
ASSERT_EQUALS("a/index.h", simplecpp::simplifyPath("a/../a/index.h"));
1302+
ASSERT_EQUALS(".", simplecpp::simplifyPath("a/.."));
1303+
ASSERT_EQUALS(".", simplecpp::simplifyPath("./a/.."));
1304+
ASSERT_EQUALS("../../src/test.cpp", simplecpp::simplifyPath("../../src/test.cpp"));
1305+
ASSERT_EQUALS("../../../src/test.cpp", simplecpp::simplifyPath("../../../src/test.cpp"));
1306+
ASSERT_EQUALS("src/test.cpp", simplecpp::simplifyPath(".//src/test.cpp"));
1307+
ASSERT_EQUALS("src/test.cpp", simplecpp::simplifyPath(".///src/test.cpp"));
1308+
ASSERT_EQUALS("test.cpp", simplecpp::simplifyPath("./././././test.cpp"));
1309+
ASSERT_EQUALS("src/", simplecpp::simplifyPath("src/abc/.."));
1310+
ASSERT_EQUALS("src/", simplecpp::simplifyPath("src/abc/../"));
1311+
1312+
// Handling of UNC paths on Windows
1313+
ASSERT_EQUALS("//src/test.cpp", simplecpp::simplifyPath("//src/test.cpp"));
1314+
ASSERT_EQUALS("//src/test.cpp", simplecpp::simplifyPath("///src/test.cpp"));
1315+
}
1316+
1317+
void simplifyPath_New()
1318+
{
1319+
ASSERT_EQUALS("", simplecpp::simplifyPath(""));
1320+
ASSERT_EQUALS("/", simplecpp::simplifyPath("/"));
1321+
ASSERT_EQUALS("//", simplecpp::simplifyPath("//"));
1322+
ASSERT_EQUALS("//", simplecpp::simplifyPath("///"));
1323+
ASSERT_EQUALS("/", simplecpp::simplifyPath("\\"));
12591324
}
12601325

12611326

@@ -1379,6 +1444,8 @@ int main(int argc, char **argv)
13791444

13801445
// utility functions.
13811446
TEST_CASE(simplifyPath);
1447+
TEST_CASE(simplifyPath_cppcheck);
1448+
TEST_CASE(simplifyPath_New);
13821449

13831450
return numberOfFailedAssertions > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
13841451
}

0 commit comments

Comments
 (0)