Adds support for alternate path separator on Windows, and make all tests pass with CMake and VC++ 9 (by Manuel Klimek).
This commit is contained in:
@@ -63,8 +63,14 @@ namespace testing {
|
||||
namespace internal {
|
||||
|
||||
#if GTEST_OS_WINDOWS
|
||||
// On Windows, '\\' is the standard path separator, but many tools and the
|
||||
// Windows API also accept '/' as an alternate path separator. Unless otherwise
|
||||
// noted, a file path can contain either kind of path separators, or a mixture
|
||||
// of them.
|
||||
const char kPathSeparator = '\\';
|
||||
const char kAlternatePathSeparator = '/';
|
||||
const char kPathSeparatorString[] = "\\";
|
||||
const char kAlternatePathSeparatorString[] = "/";
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
// Windows CE doesn't have a current directory. You should not use
|
||||
// the current directory in tests on Windows CE, but this at least
|
||||
@@ -81,6 +87,15 @@ const char kPathSeparatorString[] = "/";
|
||||
const char kCurrentDirectoryString[] = "./";
|
||||
#endif // GTEST_OS_WINDOWS
|
||||
|
||||
// Returns whether the given character is a valid path separator.
|
||||
static bool IsPathSeparator(char c) {
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
return (c == kPathSeparator) || (c == kAlternatePathSeparator);
|
||||
#else
|
||||
return c == kPathSeparator;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the current working directory, or "" if unsuccessful.
|
||||
FilePath FilePath::GetCurrentDir() {
|
||||
#if GTEST_OS_WINDOWS_MOBILE
|
||||
@@ -108,6 +123,22 @@ FilePath FilePath::RemoveExtension(const char* extension) const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Returns a pointer to the last occurence of a valid path separator in
|
||||
// the FilePath. On Windows, for example, both '/' and '\' are valid path
|
||||
// separators. Returns NULL if no path separator was found.
|
||||
const char* FilePath::FindLastPathSeparator() const {
|
||||
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
|
||||
// Comparing two pointers of which only one is NULL is undefined.
|
||||
if (last_alt_sep != NULL &&
|
||||
(last_sep == NULL || last_alt_sep > last_sep)) {
|
||||
return last_alt_sep;
|
||||
}
|
||||
#endif
|
||||
return last_sep;
|
||||
}
|
||||
|
||||
// Returns a copy of the FilePath with the directory part removed.
|
||||
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
|
||||
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
|
||||
@@ -115,7 +146,7 @@ FilePath FilePath::RemoveExtension(const char* extension) const {
|
||||
// returns an empty FilePath ("").
|
||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||
FilePath FilePath::RemoveDirectoryName() const {
|
||||
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
||||
const char* const last_sep = FindLastPathSeparator();
|
||||
return last_sep ? FilePath(String(last_sep + 1)) : *this;
|
||||
}
|
||||
|
||||
@@ -126,7 +157,7 @@ FilePath FilePath::RemoveDirectoryName() const {
|
||||
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
|
||||
// On Windows platform, '\' is the path separator, otherwise it is '/'.
|
||||
FilePath FilePath::RemoveFileName() const {
|
||||
const char* const last_sep = strrchr(c_str(), kPathSeparator);
|
||||
const char* const last_sep = FindLastPathSeparator();
|
||||
String dir;
|
||||
if (last_sep) {
|
||||
dir = String(c_str(), last_sep + 1 - c_str());
|
||||
@@ -219,7 +250,7 @@ bool FilePath::IsRootDirectory() const {
|
||||
// current directory. Handle this properly.
|
||||
return pathname_.length() == 3 && IsAbsolutePath();
|
||||
#else
|
||||
return pathname_ == kPathSeparatorString;
|
||||
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -231,9 +262,9 @@ bool FilePath::IsAbsolutePath() const {
|
||||
((name[0] >= 'a' && name[0] <= 'z') ||
|
||||
(name[0] >= 'A' && name[0] <= 'Z')) &&
|
||||
name[1] == ':' &&
|
||||
name[2] == kPathSeparator;
|
||||
IsPathSeparator(name[2]);
|
||||
#else
|
||||
return name[0] == kPathSeparator;
|
||||
return IsPathSeparator(name[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -260,7 +291,8 @@ FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
|
||||
// it is intended to represent a directory. Returns false otherwise.
|
||||
// This does NOT check that a directory (or file) actually exists.
|
||||
bool FilePath::IsDirectory() const {
|
||||
return pathname_.EndsWith(kPathSeparatorString);
|
||||
return !pathname_.empty() &&
|
||||
IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
|
||||
}
|
||||
|
||||
// Create directories so that path exists. Returns true if successful or if
|
||||
@@ -305,7 +337,7 @@ bool FilePath::CreateFolder() const {
|
||||
// name, otherwise return the name string unmodified.
|
||||
// On Windows platform, uses \ as the separator, other platforms use /.
|
||||
FilePath FilePath::RemoveTrailingPathSeparator() const {
|
||||
return pathname_.EndsWith(kPathSeparatorString)
|
||||
return IsDirectory()
|
||||
? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
|
||||
: *this;
|
||||
}
|
||||
@@ -324,12 +356,19 @@ void FilePath::Normalize() {
|
||||
memset(dest_ptr, 0, pathname_.length() + 1);
|
||||
|
||||
while (*src != '\0') {
|
||||
*dest_ptr++ = *src;
|
||||
if (*src != kPathSeparator)
|
||||
*dest_ptr = *src;
|
||||
if (!IsPathSeparator(*src)) {
|
||||
src++;
|
||||
else
|
||||
while (*src == kPathSeparator)
|
||||
} else {
|
||||
#if GTEST_HAS_ALT_PATH_SEP_
|
||||
if (*dest_ptr == kAlternatePathSeparator) {
|
||||
*dest_ptr = kPathSeparator;
|
||||
}
|
||||
#endif
|
||||
while (IsPathSeparator(*src))
|
||||
src++;
|
||||
}
|
||||
dest_ptr++;
|
||||
}
|
||||
*dest_ptr = '\0';
|
||||
pathname_ = dest;
|
||||
|
||||
Reference in New Issue
Block a user