Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions simplecpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2413,21 +2413,26 @@ namespace simplecpp {
return windowsPath;
}
#endif
}

bool isAbsolutePath(const std::string &path)
{
#ifdef SIMPLECPP_WINDOWS
static bool isAbsolutePath(const std::string &path)
{
if (path.length() >= 3 && path[0] > 0 && std::isalpha(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
return true;
return path.length() > 1U && (path[0] == '/' || path[0] == '\\');
}
// C:\\path\\file
// C:/path/file
if (path.length() >= 3 && std::isalpha(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
return true;

// \\host\path\file
// //host/path/file
if (path.length() >= 2 && (path[0] == '\\' || path[0] == '/') && (path[1] == '\\' || path[1] == '/'))
return true;

return false;
#else
static bool isAbsolutePath(const std::string &path)
{
return path.length() > 1U && path[0] == '/';
}
return !path.empty() && path[0] == '/';
#endif
}
}

namespace simplecpp {
/**
Expand Down Expand Up @@ -2988,7 +2993,7 @@ static std::string openHeaderDirect(std::ifstream &f, const std::string &path)

static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader)
{
if (isAbsolutePath(header))
if (simplecpp::isAbsolutePath(header))
return openHeaderDirect(f, simplecpp::simplifyPath(header));

// prefer first to search the header relatively to source file if found, when not a system header
Expand Down
3 changes: 3 additions & 0 deletions simplecpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,9 @@ namespace simplecpp {
/** Returns the __cplusplus value for a given standard */
SIMPLECPP_LIB std::string getCppStdString(const std::string &std);
SIMPLECPP_LIB std::string getCppStdString(cppstd_t std);

/** Checks if given path is absolute */
SIMPLECPP_LIB bool isAbsolutePath(const std::string &path);
}

#undef SIMPLECPP_TOKENLIST_ALLOW_PTR
Expand Down
37 changes: 36 additions & 1 deletion test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static int assertEquals(const std::string &expected, const std::string &actual,
if (expected != actual) {
numberOfFailedAssertions++;
std::cerr << "------ assertion failed ---------" << std::endl;
std::cerr << "line " << line << std::endl;
std::cerr << "line test.cpp:" << line << std::endl;
Copy link
Collaborator Author

@firewave firewave Sep 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows some IDEs to show a clickable link making it easier to navigate to the failure.

std::cerr << "expected:" << pprint(expected) << std::endl;
std::cerr << "actual:" << pprint(actual) << std::endl;
}
Expand Down Expand Up @@ -3231,6 +3231,39 @@ static void fuzz_crash()
}
}

static void isAbsolutePath() {
#ifdef _WIN32
ASSERT_EQUALS(true, simplecpp::isAbsolutePath("C:\\foo\\bar"));
ASSERT_EQUALS(true, simplecpp::isAbsolutePath("C:/foo/bar"));
ASSERT_EQUALS(true, simplecpp::isAbsolutePath("\\\\foo\\bar"));

ASSERT_EQUALS(false, simplecpp::isAbsolutePath("foo\\bar"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("foo/bar"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("foo.cpp"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("C:foo.cpp"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("C:foo\\bar.cpp"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("bar.cpp"));
//ASSERT_EQUALS(true, simplecpp::isAbsolutePath("\\")); // TODO
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("0:\\foo\\bar"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("0:/foo/bar"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("\\foo\\bar"));
//ASSERT_EQUALS(false, simplecpp::isAbsolutePath("\\\\")); // TODO
//ASSERT_EQUALS(false, simplecpp::isAbsolutePath("//")); // TODO
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("/foo/bar"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("/"));
#else
ASSERT_EQUALS(true, simplecpp::isAbsolutePath("/foo/bar"));
ASSERT_EQUALS(true, simplecpp::isAbsolutePath("/"));
ASSERT_EQUALS(true, simplecpp::isAbsolutePath("//host/foo/bar"));

ASSERT_EQUALS(false, simplecpp::isAbsolutePath("foo/bar"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("foo.cpp"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("C:\\foo\\bar"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("C:/foo/bar"));
ASSERT_EQUALS(false, simplecpp::isAbsolutePath("\\\\foo\\bar"));
#endif
}

int main(int argc, char **argv)
{
TEST_CASE(backslash);
Expand Down Expand Up @@ -3487,5 +3520,7 @@ int main(int argc, char **argv)

TEST_CASE(fuzz_crash);

TEST_CASE(isAbsolutePath);

return numberOfFailedAssertions > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}