Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "gtest/internal/gtest-filepath.h"
00033 #include "gtest/internal/gtest-port.h"
00034
00035 #include <stdlib.h>
00036
00037 #if GTEST_OS_WINDOWS_MOBILE
00038 # include <windows.h>
00039 #elif GTEST_OS_WINDOWS
00040 # include <direct.h>
00041 # include <io.h>
00042 #elif GTEST_OS_SYMBIAN || GTEST_OS_NACL
00043
00044 # include <sys/syslimits.h>
00045 #else
00046 # include <limits.h>
00047 # include <climits>
00048 #endif // GTEST_OS_WINDOWS_MOBILE
00049
00050 #if GTEST_OS_WINDOWS
00051 # define GTEST_PATH_MAX_ _MAX_PATH
00052 #elif defined(PATH_MAX)
00053 # define GTEST_PATH_MAX_ PATH_MAX
00054 #elif defined(_XOPEN_PATH_MAX)
00055 # define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
00056 #else
00057 # define GTEST_PATH_MAX_ _POSIX_PATH_MAX
00058 #endif // GTEST_OS_WINDOWS
00059
00060 #include "gtest/internal/gtest-string.h"
00061
00062 namespace testing {
00063 namespace internal {
00064
00065 #if GTEST_OS_WINDOWS
00066
00067
00068
00069
00070 const char kPathSeparator = '\\';
00071 const char kAlternatePathSeparator = '/';
00072 const char kPathSeparatorString[] = "\\";
00073 const char kAlternatePathSeparatorString[] = "/";
00074 # if GTEST_OS_WINDOWS_MOBILE
00075
00076
00077
00078 const char kCurrentDirectoryString[] = "\\";
00079
00080 const DWORD kInvalidFileAttributes = 0xffffffff;
00081 # else
00082 const char kCurrentDirectoryString[] = ".\\";
00083 # endif // GTEST_OS_WINDOWS_MOBILE
00084 #else
00085 const char kPathSeparator = '/';
00086 const char kPathSeparatorString[] = "/";
00087 const char kCurrentDirectoryString[] = "./";
00088 #endif // GTEST_OS_WINDOWS
00089
00090
00091 static bool IsPathSeparator(char c) {
00092 #if GTEST_HAS_ALT_PATH_SEP_
00093 return (c == kPathSeparator) || (c == kAlternatePathSeparator);
00094 #else
00095 return c == kPathSeparator;
00096 #endif
00097 }
00098
00099
00100 FilePath FilePath::GetCurrentDir() {
00101 #if GTEST_OS_WINDOWS_MOBILE
00102
00103
00104 return FilePath(kCurrentDirectoryString);
00105 #elif GTEST_OS_WINDOWS
00106 char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
00107 return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
00108 #else
00109 char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
00110 return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
00111 #endif // GTEST_OS_WINDOWS_MOBILE
00112 }
00113
00114
00115
00116
00117
00118 FilePath FilePath::RemoveExtension(const char* extension) const {
00119 String dot_extension(String::Format(".%s", extension));
00120 if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
00121 return FilePath(String(pathname_.c_str(), pathname_.length() - 4));
00122 }
00123 return *this;
00124 }
00125
00126
00127
00128
00129 const char* FilePath::FindLastPathSeparator() const {
00130 const char* const last_sep = strrchr(c_str(), kPathSeparator);
00131 #if GTEST_HAS_ALT_PATH_SEP_
00132 const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
00133
00134 if (last_alt_sep != NULL &&
00135 (last_sep == NULL || last_alt_sep > last_sep)) {
00136 return last_alt_sep;
00137 }
00138 #endif
00139 return last_sep;
00140 }
00141
00142
00143
00144
00145
00146
00147
00148 FilePath FilePath::RemoveDirectoryName() const {
00149 const char* const last_sep = FindLastPathSeparator();
00150 return last_sep ? FilePath(String(last_sep + 1)) : *this;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 FilePath FilePath::RemoveFileName() const {
00160 const char* const last_sep = FindLastPathSeparator();
00161 String dir;
00162 if (last_sep) {
00163 dir = String(c_str(), last_sep + 1 - c_str());
00164 } else {
00165 dir = kCurrentDirectoryString;
00166 }
00167 return FilePath(dir);
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 FilePath FilePath::MakeFileName(const FilePath& directory,
00177 const FilePath& base_name,
00178 int number,
00179 const char* extension) {
00180 String file;
00181 if (number == 0) {
00182 file = String::Format("%s.%s", base_name.c_str(), extension);
00183 } else {
00184 file = String::Format("%s_%d.%s", base_name.c_str(), number, extension);
00185 }
00186 return ConcatPaths(directory, FilePath(file));
00187 }
00188
00189
00190
00191 FilePath FilePath::ConcatPaths(const FilePath& directory,
00192 const FilePath& relative_path) {
00193 if (directory.IsEmpty())
00194 return relative_path;
00195 const FilePath dir(directory.RemoveTrailingPathSeparator());
00196 return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator,
00197 relative_path.c_str()));
00198 }
00199
00200
00201
00202 bool FilePath::FileOrDirectoryExists() const {
00203 #if GTEST_OS_WINDOWS_MOBILE
00204 LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
00205 const DWORD attributes = GetFileAttributes(unicode);
00206 delete [] unicode;
00207 return attributes != kInvalidFileAttributes;
00208 #else
00209 posix::StatStruct file_stat;
00210 return posix::Stat(pathname_.c_str(), &file_stat) == 0;
00211 #endif // GTEST_OS_WINDOWS_MOBILE
00212 }
00213
00214
00215
00216 bool FilePath::DirectoryExists() const {
00217 bool result = false;
00218 #if GTEST_OS_WINDOWS
00219
00220
00221 const FilePath& path(IsRootDirectory() ? *this :
00222 RemoveTrailingPathSeparator());
00223 #else
00224 const FilePath& path(*this);
00225 #endif
00226
00227 #if GTEST_OS_WINDOWS_MOBILE
00228 LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
00229 const DWORD attributes = GetFileAttributes(unicode);
00230 delete [] unicode;
00231 if ((attributes != kInvalidFileAttributes) &&
00232 (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
00233 result = true;
00234 }
00235 #else
00236 posix::StatStruct file_stat;
00237 result = posix::Stat(path.c_str(), &file_stat) == 0 &&
00238 posix::IsDir(file_stat);
00239 #endif // GTEST_OS_WINDOWS_MOBILE
00240
00241 return result;
00242 }
00243
00244
00245
00246 bool FilePath::IsRootDirectory() const {
00247 #if GTEST_OS_WINDOWS
00248
00249
00250
00251 return pathname_.length() == 3 && IsAbsolutePath();
00252 #else
00253 return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
00254 #endif
00255 }
00256
00257
00258 bool FilePath::IsAbsolutePath() const {
00259 const char* const name = pathname_.c_str();
00260 #if GTEST_OS_WINDOWS
00261 return pathname_.length() >= 3 &&
00262 ((name[0] >= 'a' && name[0] <= 'z') ||
00263 (name[0] >= 'A' && name[0] <= 'Z')) &&
00264 name[1] == ':' &&
00265 IsPathSeparator(name[2]);
00266 #else
00267 return IsPathSeparator(name[0]);
00268 #endif
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
00280 const FilePath& base_name,
00281 const char* extension) {
00282 FilePath full_pathname;
00283 int number = 0;
00284 do {
00285 full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
00286 } while (full_pathname.FileOrDirectoryExists());
00287 return full_pathname;
00288 }
00289
00290
00291
00292
00293 bool FilePath::IsDirectory() const {
00294 return !pathname_.empty() &&
00295 IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
00296 }
00297
00298
00299
00300
00301 bool FilePath::CreateDirectoriesRecursively() const {
00302 if (!this->IsDirectory()) {
00303 return false;
00304 }
00305
00306 if (pathname_.length() == 0 || this->DirectoryExists()) {
00307 return true;
00308 }
00309
00310 const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
00311 return parent.CreateDirectoriesRecursively() && this->CreateFolder();
00312 }
00313
00314
00315
00316
00317
00318 bool FilePath::CreateFolder() const {
00319 #if GTEST_OS_WINDOWS_MOBILE
00320 FilePath removed_sep(this->RemoveTrailingPathSeparator());
00321 LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
00322 int result = CreateDirectory(unicode, NULL) ? 0 : -1;
00323 delete [] unicode;
00324 #elif GTEST_OS_WINDOWS
00325 int result = _mkdir(pathname_.c_str());
00326 #else
00327 int result = mkdir(pathname_.c_str(), 0777);
00328 #endif // GTEST_OS_WINDOWS_MOBILE
00329
00330 if (result == -1) {
00331 return this->DirectoryExists();
00332 }
00333 return true;
00334 }
00335
00336
00337
00338
00339 FilePath FilePath::RemoveTrailingPathSeparator() const {
00340 return IsDirectory()
00341 ? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
00342 : *this;
00343 }
00344
00345
00346
00347
00348
00349 void FilePath::Normalize() {
00350 if (pathname_.c_str() == NULL) {
00351 pathname_ = "";
00352 return;
00353 }
00354 const char* src = pathname_.c_str();
00355 char* const dest = new char[pathname_.length() + 1];
00356 char* dest_ptr = dest;
00357 memset(dest_ptr, 0, pathname_.length() + 1);
00358
00359 while (*src != '\0') {
00360 *dest_ptr = *src;
00361 if (!IsPathSeparator(*src)) {
00362 src++;
00363 } else {
00364 #if GTEST_HAS_ALT_PATH_SEP_
00365 if (*dest_ptr == kAlternatePathSeparator) {
00366 *dest_ptr = kPathSeparator;
00367 }
00368 #endif
00369 while (IsPathSeparator(*src))
00370 src++;
00371 }
00372 dest_ptr++;
00373 }
00374 *dest_ptr = '\0';
00375 pathname_ = dest;
00376 delete[] dest;
00377 }
00378
00379 }
00380 }