media/webrtc/trunk/testing/gtest/src/gtest-filepath.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/webrtc/trunk/testing/gtest/src/gtest-filepath.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,380 @@
     1.4 +// Copyright 2008, Google Inc.
     1.5 +// All rights reserved.
     1.6 +//
     1.7 +// Redistribution and use in source and binary forms, with or without
     1.8 +// modification, are permitted provided that the following conditions are
     1.9 +// met:
    1.10 +//
    1.11 +//     * Redistributions of source code must retain the above copyright
    1.12 +// notice, this list of conditions and the following disclaimer.
    1.13 +//     * Redistributions in binary form must reproduce the above
    1.14 +// copyright notice, this list of conditions and the following disclaimer
    1.15 +// in the documentation and/or other materials provided with the
    1.16 +// distribution.
    1.17 +//     * Neither the name of Google Inc. nor the names of its
    1.18 +// contributors may be used to endorse or promote products derived from
    1.19 +// this software without specific prior written permission.
    1.20 +//
    1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.32 +//
    1.33 +// Authors: keith.ray@gmail.com (Keith Ray)
    1.34 +
    1.35 +#include "gtest/internal/gtest-filepath.h"
    1.36 +#include "gtest/internal/gtest-port.h"
    1.37 +
    1.38 +#include <stdlib.h>
    1.39 +
    1.40 +#if GTEST_OS_WINDOWS_MOBILE
    1.41 +# include <windows.h>
    1.42 +#elif GTEST_OS_WINDOWS
    1.43 +# include <direct.h>
    1.44 +# include <io.h>
    1.45 +#elif GTEST_OS_SYMBIAN
    1.46 +// Symbian OpenC has PATH_MAX in sys/syslimits.h
    1.47 +# include <sys/syslimits.h>
    1.48 +#else
    1.49 +# include <limits.h>
    1.50 +# include <climits>  // Some Linux distributions define PATH_MAX here.
    1.51 +#endif  // GTEST_OS_WINDOWS_MOBILE
    1.52 +
    1.53 +#if GTEST_OS_WINDOWS
    1.54 +# define GTEST_PATH_MAX_ _MAX_PATH
    1.55 +#elif defined(PATH_MAX)
    1.56 +# define GTEST_PATH_MAX_ PATH_MAX
    1.57 +#elif defined(_XOPEN_PATH_MAX)
    1.58 +# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
    1.59 +#else
    1.60 +# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
    1.61 +#endif  // GTEST_OS_WINDOWS
    1.62 +
    1.63 +#include "gtest/internal/gtest-string.h"
    1.64 +
    1.65 +namespace testing {
    1.66 +namespace internal {
    1.67 +
    1.68 +#if GTEST_OS_WINDOWS
    1.69 +// On Windows, '\\' is the standard path separator, but many tools and the
    1.70 +// Windows API also accept '/' as an alternate path separator. Unless otherwise
    1.71 +// noted, a file path can contain either kind of path separators, or a mixture
    1.72 +// of them.
    1.73 +const char kPathSeparator = '\\';
    1.74 +const char kAlternatePathSeparator = '/';
    1.75 +const char kPathSeparatorString[] = "\\";
    1.76 +const char kAlternatePathSeparatorString[] = "/";
    1.77 +# if GTEST_OS_WINDOWS_MOBILE
    1.78 +// Windows CE doesn't have a current directory. You should not use
    1.79 +// the current directory in tests on Windows CE, but this at least
    1.80 +// provides a reasonable fallback.
    1.81 +const char kCurrentDirectoryString[] = "\\";
    1.82 +// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
    1.83 +const DWORD kInvalidFileAttributes = 0xffffffff;
    1.84 +# else
    1.85 +const char kCurrentDirectoryString[] = ".\\";
    1.86 +# endif  // GTEST_OS_WINDOWS_MOBILE
    1.87 +#else
    1.88 +const char kPathSeparator = '/';
    1.89 +const char kPathSeparatorString[] = "/";
    1.90 +const char kCurrentDirectoryString[] = "./";
    1.91 +#endif  // GTEST_OS_WINDOWS
    1.92 +
    1.93 +// Returns whether the given character is a valid path separator.
    1.94 +static bool IsPathSeparator(char c) {
    1.95 +#if GTEST_HAS_ALT_PATH_SEP_
    1.96 +  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
    1.97 +#else
    1.98 +  return c == kPathSeparator;
    1.99 +#endif
   1.100 +}
   1.101 +
   1.102 +// Returns the current working directory, or "" if unsuccessful.
   1.103 +FilePath FilePath::GetCurrentDir() {
   1.104 +#if GTEST_OS_WINDOWS_MOBILE
   1.105 +  // Windows CE doesn't have a current directory, so we just return
   1.106 +  // something reasonable.
   1.107 +  return FilePath(kCurrentDirectoryString);
   1.108 +#elif GTEST_OS_WINDOWS
   1.109 +  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
   1.110 +  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
   1.111 +#else
   1.112 +  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
   1.113 +  return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
   1.114 +#endif  // GTEST_OS_WINDOWS_MOBILE
   1.115 +}
   1.116 +
   1.117 +// Returns a copy of the FilePath with the case-insensitive extension removed.
   1.118 +// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
   1.119 +// FilePath("dir/file"). If a case-insensitive extension is not
   1.120 +// found, returns a copy of the original FilePath.
   1.121 +FilePath FilePath::RemoveExtension(const char* extension) const {
   1.122 +  String dot_extension(String::Format(".%s", extension));
   1.123 +  if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
   1.124 +    return FilePath(String(pathname_.c_str(), pathname_.length() - 4));
   1.125 +  }
   1.126 +  return *this;
   1.127 +}
   1.128 +
   1.129 +// Returns a pointer to the last occurence of a valid path separator in
   1.130 +// the FilePath. On Windows, for example, both '/' and '\' are valid path
   1.131 +// separators. Returns NULL if no path separator was found.
   1.132 +const char* FilePath::FindLastPathSeparator() const {
   1.133 +  const char* const last_sep = strrchr(c_str(), kPathSeparator);
   1.134 +#if GTEST_HAS_ALT_PATH_SEP_
   1.135 +  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
   1.136 +  // Comparing two pointers of which only one is NULL is undefined.
   1.137 +  if (last_alt_sep != NULL &&
   1.138 +      (last_sep == NULL || last_alt_sep > last_sep)) {
   1.139 +    return last_alt_sep;
   1.140 +  }
   1.141 +#endif
   1.142 +  return last_sep;
   1.143 +}
   1.144 +
   1.145 +// Returns a copy of the FilePath with the directory part removed.
   1.146 +// Example: FilePath("path/to/file").RemoveDirectoryName() returns
   1.147 +// FilePath("file"). If there is no directory part ("just_a_file"), it returns
   1.148 +// the FilePath unmodified. If there is no file part ("just_a_dir/") it
   1.149 +// returns an empty FilePath ("").
   1.150 +// On Windows platform, '\' is the path separator, otherwise it is '/'.
   1.151 +FilePath FilePath::RemoveDirectoryName() const {
   1.152 +  const char* const last_sep = FindLastPathSeparator();
   1.153 +  return last_sep ? FilePath(String(last_sep + 1)) : *this;
   1.154 +}
   1.155 +
   1.156 +// RemoveFileName returns the directory path with the filename removed.
   1.157 +// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
   1.158 +// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
   1.159 +// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
   1.160 +// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
   1.161 +// On Windows platform, '\' is the path separator, otherwise it is '/'.
   1.162 +FilePath FilePath::RemoveFileName() const {
   1.163 +  const char* const last_sep = FindLastPathSeparator();
   1.164 +  String dir;
   1.165 +  if (last_sep) {
   1.166 +    dir = String(c_str(), last_sep + 1 - c_str());
   1.167 +  } else {
   1.168 +    dir = kCurrentDirectoryString;
   1.169 +  }
   1.170 +  return FilePath(dir);
   1.171 +}
   1.172 +
   1.173 +// Helper functions for naming files in a directory for xml output.
   1.174 +
   1.175 +// Given directory = "dir", base_name = "test", number = 0,
   1.176 +// extension = "xml", returns "dir/test.xml". If number is greater
   1.177 +// than zero (e.g., 12), returns "dir/test_12.xml".
   1.178 +// On Windows platform, uses \ as the separator rather than /.
   1.179 +FilePath FilePath::MakeFileName(const FilePath& directory,
   1.180 +                                const FilePath& base_name,
   1.181 +                                int number,
   1.182 +                                const char* extension) {
   1.183 +  String file;
   1.184 +  if (number == 0) {
   1.185 +    file = String::Format("%s.%s", base_name.c_str(), extension);
   1.186 +  } else {
   1.187 +    file = String::Format("%s_%d.%s", base_name.c_str(), number, extension);
   1.188 +  }
   1.189 +  return ConcatPaths(directory, FilePath(file));
   1.190 +}
   1.191 +
   1.192 +// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
   1.193 +// On Windows, uses \ as the separator rather than /.
   1.194 +FilePath FilePath::ConcatPaths(const FilePath& directory,
   1.195 +                               const FilePath& relative_path) {
   1.196 +  if (directory.IsEmpty())
   1.197 +    return relative_path;
   1.198 +  const FilePath dir(directory.RemoveTrailingPathSeparator());
   1.199 +  return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator,
   1.200 +                                 relative_path.c_str()));
   1.201 +}
   1.202 +
   1.203 +// Returns true if pathname describes something findable in the file-system,
   1.204 +// either a file, directory, or whatever.
   1.205 +bool FilePath::FileOrDirectoryExists() const {
   1.206 +#if GTEST_OS_WINDOWS_MOBILE
   1.207 +  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
   1.208 +  const DWORD attributes = GetFileAttributes(unicode);
   1.209 +  delete [] unicode;
   1.210 +  return attributes != kInvalidFileAttributes;
   1.211 +#else
   1.212 +  posix::StatStruct file_stat;
   1.213 +  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
   1.214 +#endif  // GTEST_OS_WINDOWS_MOBILE
   1.215 +}
   1.216 +
   1.217 +// Returns true if pathname describes a directory in the file-system
   1.218 +// that exists.
   1.219 +bool FilePath::DirectoryExists() const {
   1.220 +  bool result = false;
   1.221 +#if GTEST_OS_WINDOWS
   1.222 +  // Don't strip off trailing separator if path is a root directory on
   1.223 +  // Windows (like "C:\\").
   1.224 +  const FilePath& path(IsRootDirectory() ? *this :
   1.225 +                                           RemoveTrailingPathSeparator());
   1.226 +#else
   1.227 +  const FilePath& path(*this);
   1.228 +#endif
   1.229 +
   1.230 +#if GTEST_OS_WINDOWS_MOBILE
   1.231 +  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
   1.232 +  const DWORD attributes = GetFileAttributes(unicode);
   1.233 +  delete [] unicode;
   1.234 +  if ((attributes != kInvalidFileAttributes) &&
   1.235 +      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
   1.236 +    result = true;
   1.237 +  }
   1.238 +#else
   1.239 +  posix::StatStruct file_stat;
   1.240 +  result = posix::Stat(path.c_str(), &file_stat) == 0 &&
   1.241 +      posix::IsDir(file_stat);
   1.242 +#endif  // GTEST_OS_WINDOWS_MOBILE
   1.243 +
   1.244 +  return result;
   1.245 +}
   1.246 +
   1.247 +// Returns true if pathname describes a root directory. (Windows has one
   1.248 +// root directory per disk drive.)
   1.249 +bool FilePath::IsRootDirectory() const {
   1.250 +#if GTEST_OS_WINDOWS
   1.251 +  // TODO(wan@google.com): on Windows a network share like
   1.252 +  // \\server\share can be a root directory, although it cannot be the
   1.253 +  // current directory.  Handle this properly.
   1.254 +  return pathname_.length() == 3 && IsAbsolutePath();
   1.255 +#else
   1.256 +  return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
   1.257 +#endif
   1.258 +}
   1.259 +
   1.260 +// Returns true if pathname describes an absolute path.
   1.261 +bool FilePath::IsAbsolutePath() const {
   1.262 +  const char* const name = pathname_.c_str();
   1.263 +#if GTEST_OS_WINDOWS
   1.264 +  return pathname_.length() >= 3 &&
   1.265 +     ((name[0] >= 'a' && name[0] <= 'z') ||
   1.266 +      (name[0] >= 'A' && name[0] <= 'Z')) &&
   1.267 +     name[1] == ':' &&
   1.268 +     IsPathSeparator(name[2]);
   1.269 +#else
   1.270 +  return IsPathSeparator(name[0]);
   1.271 +#endif
   1.272 +}
   1.273 +
   1.274 +// Returns a pathname for a file that does not currently exist. The pathname
   1.275 +// will be directory/base_name.extension or
   1.276 +// directory/base_name_<number>.extension if directory/base_name.extension
   1.277 +// already exists. The number will be incremented until a pathname is found
   1.278 +// that does not already exist.
   1.279 +// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
   1.280 +// There could be a race condition if two or more processes are calling this
   1.281 +// function at the same time -- they could both pick the same filename.
   1.282 +FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
   1.283 +                                          const FilePath& base_name,
   1.284 +                                          const char* extension) {
   1.285 +  FilePath full_pathname;
   1.286 +  int number = 0;
   1.287 +  do {
   1.288 +    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
   1.289 +  } while (full_pathname.FileOrDirectoryExists());
   1.290 +  return full_pathname;
   1.291 +}
   1.292 +
   1.293 +// Returns true if FilePath ends with a path separator, which indicates that
   1.294 +// it is intended to represent a directory. Returns false otherwise.
   1.295 +// This does NOT check that a directory (or file) actually exists.
   1.296 +bool FilePath::IsDirectory() const {
   1.297 +  return !pathname_.empty() &&
   1.298 +         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
   1.299 +}
   1.300 +
   1.301 +// Create directories so that path exists. Returns true if successful or if
   1.302 +// the directories already exist; returns false if unable to create directories
   1.303 +// for any reason.
   1.304 +bool FilePath::CreateDirectoriesRecursively() const {
   1.305 +  if (!this->IsDirectory()) {
   1.306 +    return false;
   1.307 +  }
   1.308 +
   1.309 +  if (pathname_.length() == 0 || this->DirectoryExists()) {
   1.310 +    return true;
   1.311 +  }
   1.312 +
   1.313 +  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
   1.314 +  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
   1.315 +}
   1.316 +
   1.317 +// Create the directory so that path exists. Returns true if successful or
   1.318 +// if the directory already exists; returns false if unable to create the
   1.319 +// directory for any reason, including if the parent directory does not
   1.320 +// exist. Not named "CreateDirectory" because that's a macro on Windows.
   1.321 +bool FilePath::CreateFolder() const {
   1.322 +#if GTEST_OS_WINDOWS_MOBILE
   1.323 +  FilePath removed_sep(this->RemoveTrailingPathSeparator());
   1.324 +  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
   1.325 +  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
   1.326 +  delete [] unicode;
   1.327 +#elif GTEST_OS_WINDOWS
   1.328 +  int result = _mkdir(pathname_.c_str());
   1.329 +#else
   1.330 +  int result = mkdir(pathname_.c_str(), 0777);
   1.331 +#endif  // GTEST_OS_WINDOWS_MOBILE
   1.332 +
   1.333 +  if (result == -1) {
   1.334 +    return this->DirectoryExists();  // An error is OK if the directory exists.
   1.335 +  }
   1.336 +  return true;  // No error.
   1.337 +}
   1.338 +
   1.339 +// If input name has a trailing separator character, remove it and return the
   1.340 +// name, otherwise return the name string unmodified.
   1.341 +// On Windows platform, uses \ as the separator, other platforms use /.
   1.342 +FilePath FilePath::RemoveTrailingPathSeparator() const {
   1.343 +  return IsDirectory()
   1.344 +      ? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
   1.345 +      : *this;
   1.346 +}
   1.347 +
   1.348 +// Removes any redundant separators that might be in the pathname.
   1.349 +// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
   1.350 +// redundancies that might be in a pathname involving "." or "..".
   1.351 +// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
   1.352 +void FilePath::Normalize() {
   1.353 +  if (pathname_.c_str() == NULL) {
   1.354 +    pathname_ = "";
   1.355 +    return;
   1.356 +  }
   1.357 +  const char* src = pathname_.c_str();
   1.358 +  char* const dest = new char[pathname_.length() + 1];
   1.359 +  char* dest_ptr = dest;
   1.360 +  memset(dest_ptr, 0, pathname_.length() + 1);
   1.361 +
   1.362 +  while (*src != '\0') {
   1.363 +    *dest_ptr = *src;
   1.364 +    if (!IsPathSeparator(*src)) {
   1.365 +      src++;
   1.366 +    } else {
   1.367 +#if GTEST_HAS_ALT_PATH_SEP_
   1.368 +      if (*dest_ptr == kAlternatePathSeparator) {
   1.369 +        *dest_ptr = kPathSeparator;
   1.370 +      }
   1.371 +#endif
   1.372 +      while (IsPathSeparator(*src))
   1.373 +        src++;
   1.374 +    }
   1.375 +    dest_ptr++;
   1.376 +  }
   1.377 +  *dest_ptr = '\0';
   1.378 +  pathname_ = dest;
   1.379 +  delete[] dest;
   1.380 +}
   1.381 +
   1.382 +}  // namespace internal
   1.383 +}  // namespace testing

mercurial