36#if GTEST_OS_WINDOWS_MOBILE
49# define GTEST_PATH_MAX_ _MAX_PATH
50#elif defined(PATH_MAX)
51# define GTEST_PATH_MAX_ PATH_MAX
52#elif defined(_XOPEN_PATH_MAX)
53# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
55# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
67const char kAlternatePathSeparator =
'/';
68const char kAlternatePathSeparatorString[] =
"/";
69# if GTEST_OS_WINDOWS_MOBILE
75const DWORD kInvalidFileAttributes = 0xffffffff;
85static bool IsPathSeparator(
char c) {
86#if GTEST_HAS_ALT_PATH_SEP_
94FilePath FilePath::GetCurrentDir() {
95#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
96 GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32 || \
101#elif GTEST_OS_WINDOWS
103 return FilePath(_getcwd(cwd,
sizeof(cwd)) ==
nullptr ?
"" : cwd);
106 char* result = getcwd(cwd,
sizeof(cwd));
113 return FilePath(result ==
nullptr ?
"" : cwd);
121FilePath FilePath::RemoveExtension(
const char* extension)
const {
122 const std::string dot_extension = std::string(
".") + extension;
124 return FilePath(pathname_.substr(
125 0, pathname_.length() - dot_extension.length()));
133const char* FilePath::FindLastPathSeparator()
const {
135#if GTEST_HAS_ALT_PATH_SEP_
136 const char*
const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
138 if (last_alt_sep !=
nullptr &&
139 (last_sep ==
nullptr || last_alt_sep > last_sep)) {
152FilePath FilePath::RemoveDirectoryName()
const {
153 const char*
const last_sep = FindLastPathSeparator();
154 return last_sep ? FilePath(last_sep + 1) : *this;
163FilePath FilePath::RemoveFileName()
const {
164 const char*
const last_sep = FindLastPathSeparator();
167 dir = std::string(c_str(),
static_cast<size_t>(last_sep + 1 - c_str()));
171 return FilePath(dir);
180FilePath FilePath::MakeFileName(
const FilePath& directory,
181 const FilePath& base_name,
183 const char* extension) {
186 file = base_name.string() +
"." + extension;
191 return ConcatPaths(directory, FilePath(
file));
196FilePath FilePath::ConcatPaths(
const FilePath& directory,
197 const FilePath& relative_path) {
198 if (directory.IsEmpty())
199 return relative_path;
200 const FilePath dir(directory.RemoveTrailingPathSeparator());
201 return FilePath(dir.string() +
kPathSeparator + relative_path.string());
206bool FilePath::FileOrDirectoryExists()
const {
207#if GTEST_OS_WINDOWS_MOBILE
208 LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
209 const DWORD attributes = GetFileAttributes(unicode);
211 return attributes != kInvalidFileAttributes;
214 return posix::Stat(pathname_.c_str(), &file_stat) == 0;
220bool FilePath::DirectoryExists()
const {
225 const FilePath& path(IsRootDirectory() ? *
this :
226 RemoveTrailingPathSeparator());
228 const FilePath& path(*
this);
231#if GTEST_OS_WINDOWS_MOBILE
232 LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
233 const DWORD attributes = GetFileAttributes(unicode);
235 if ((attributes != kInvalidFileAttributes) &&
236 (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
241 result =
posix::Stat(path.c_str(), &file_stat) == 0 &&
250bool FilePath::IsRootDirectory()
const {
252 return pathname_.length() == 3 && IsAbsolutePath();
254 return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
259bool FilePath::IsAbsolutePath()
const {
260 const char*
const name = pathname_.c_str();
262 return pathname_.length() >= 3 &&
263 ((name[0] >=
'a' && name[0] <=
'z') ||
264 (name[0] >=
'A' && name[0] <=
'Z')) &&
266 IsPathSeparator(name[2]);
268 return IsPathSeparator(name[0]);
280FilePath FilePath::GenerateUniqueFileName(
const FilePath& directory,
281 const FilePath& base_name,
282 const char* extension) {
283 FilePath full_pathname;
286 full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
287 }
while (full_pathname.FileOrDirectoryExists());
288 return full_pathname;
294bool FilePath::IsDirectory()
const {
295 return !pathname_.empty() &&
296 IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
302bool FilePath::CreateDirectoriesRecursively()
const {
303 if (!this->IsDirectory()) {
307 if (pathname_.length() == 0 || this->DirectoryExists()) {
311 const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
312 return parent.CreateDirectoriesRecursively() && this->CreateFolder();
319bool FilePath::CreateFolder()
const {
320#if GTEST_OS_WINDOWS_MOBILE
321 FilePath removed_sep(this->RemoveTrailingPathSeparator());
322 LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
323 int result = CreateDirectory(unicode,
nullptr) ? 0 : -1;
325#elif GTEST_OS_WINDOWS
326 int result = _mkdir(pathname_.c_str());
327#elif GTEST_OS_ESP8266 || GTEST_OS_XTENSA
331 int result = mkdir(pathname_.c_str(), 0777);
335 return this->DirectoryExists();
343FilePath FilePath::RemoveTrailingPathSeparator()
const {
345 ? FilePath(pathname_.substr(0, pathname_.length() - 1))
353 auto out = pathname_.begin();
358 }
else if (out == pathname_.begin() || *std::prev(out) !=
kPathSeparator) {
365 pathname_.erase(out, pathname_.end());
void Normalize(float *Values)
const char kCurrentDirectoryString[]
std::string StreamableToString(const T &streamable)
const char kPathSeparator
int Stat(const char *path, StatStruct *buf)
bool IsDir(const StatStruct &st)
static bool EndsWithCaseInsensitive(const std::string &str, const std::string &suffix)