BLI Path: add function BLI_path_contains()
Add function `BLI_path_contains(container, containee)` that returns true if and only `container` contains `containee`. Paths are normalised and converted to native path separators before comparing. Relative paths are *not* made absolute, to simplify the function call; if this is necessary the caller has to do this conversion first.
This commit is contained in:
@@ -55,6 +55,10 @@ bool BLI_path_name_at_index(const char *__restrict path,
|
||||
int *__restrict r_offset,
|
||||
int *__restrict r_len) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/** Return true only if #containee_path is contained in #container_path. */
|
||||
bool BLI_path_contains(const char *container_path,
|
||||
const char *containee_path) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
const char *BLI_path_slash_rfind(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
|
||||
int BLI_path_slash_ensure(char *string) ATTR_NONNULL();
|
||||
void BLI_path_slash_rstrip(char *string) ATTR_NONNULL();
|
||||
|
||||
@@ -1935,6 +1935,34 @@ bool BLI_path_name_at_index(const char *__restrict path,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BLI_path_contains(const char *container_path, const char *containee_path)
|
||||
{
|
||||
char container_native[PATH_MAX];
|
||||
char containee_native[PATH_MAX];
|
||||
|
||||
/* Keep space for a trailing slash. If the path is truncated by this, the containee path is
|
||||
* longer than PATH_MAX and the result is ill-defined. */
|
||||
BLI_strncpy(container_native, container_path, PATH_MAX - 1);
|
||||
BLI_strncpy(containee_native, containee_path, PATH_MAX);
|
||||
|
||||
BLI_path_slash_native(container_native);
|
||||
BLI_path_slash_native(containee_native);
|
||||
|
||||
BLI_path_normalize(NULL, container_native);
|
||||
BLI_path_normalize(NULL, containee_native);
|
||||
|
||||
if (STREQ(container_native, containee_native)) {
|
||||
/* The paths are equal, they contain each other. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Add a trailing slash to prevent same-prefix directories from matching.
|
||||
* e.g. "/some/path" doesn't contain "/some/pathlib". */
|
||||
BLI_path_slash_ensure(container_native);
|
||||
|
||||
return BLI_str_startswith(containee_native, container_native);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pointer to the leftmost path separator in string. Not actually used anywhere.
|
||||
*/
|
||||
|
||||
@@ -655,3 +655,26 @@ TEST(path_util, PathRelPath)
|
||||
# undef PATH_REL
|
||||
|
||||
#endif
|
||||
|
||||
/* BLI_path_contains */
|
||||
TEST(path_util, PathContains)
|
||||
{
|
||||
EXPECT_TRUE(BLI_path_contains("/some/path", "/some/path")) << "A path contains itself";
|
||||
EXPECT_TRUE(BLI_path_contains("/some/path", "/some/path/inside"))
|
||||
<< "A path contains its subdirectory";
|
||||
EXPECT_TRUE(BLI_path_contains("/some/path", "/some/path/../path/inside"))
|
||||
<< "Paths should be normalised";
|
||||
EXPECT_TRUE(BLI_path_contains("C:\\some\\path", "C:\\some\\path\\inside"))
|
||||
<< "Windows paths should be supported as well";
|
||||
|
||||
EXPECT_FALSE(BLI_path_contains("C:\\some\\path", "C:\\some\\other\\path"))
|
||||
<< "Windows paths should be supported as well";
|
||||
EXPECT_FALSE(BLI_path_contains("/some/path", "/"))
|
||||
<< "Root directory not be contained in a subdirectory";
|
||||
EXPECT_FALSE(BLI_path_contains("/some/path", "/some/path/../outside"))
|
||||
<< "Paths should be normalised";
|
||||
EXPECT_FALSE(BLI_path_contains("/some/path", "/some/path_library"))
|
||||
<< "Just sharing a suffix is not enough, path semantics should be followed";
|
||||
EXPECT_FALSE(BLI_path_contains("/some/path", "./contents"))
|
||||
<< "Relative paths are not supported";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user