13d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// Copyright 2008, Google Inc. 23d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// All rights reserved. 33d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// 43d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// Redistribution and use in source and binary forms, with or without 53d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// modification, are permitted provided that the following conditions are 63d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// met: 73d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// 83d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// * Redistributions of source code must retain the above copyright 93d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// notice, this list of conditions and the following disclaimer. 103d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// * Redistributions in binary form must reproduce the above 113d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// copyright notice, this list of conditions and the following disclaimer 123d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// in the documentation and/or other materials provided with the 133d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// distribution. 143d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// * Neither the name of Google Inc. nor the names of its 153d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// contributors may be used to endorse or promote products derived from 163d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// this software without specific prior written permission. 173d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// 183d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 193d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 203d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 213d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 223d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 233d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 243d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 253d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 263d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 273d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 283d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 293d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// 303d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// Author: keith.ray@gmail.com (Keith Ray) 313d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// 323d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// Google Test filepath utilities 333d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// 343d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// This header file declares classes and functions used internally by 353d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// Google Test. They are subject to change without notice. 363d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// 373d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// This file is #included in <gtest/internal/gtest-internal.h>. 383d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// Do not include this header file separately! 393d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 403d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 413d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 423d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 433d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick#include "gtest/internal/gtest-string.h" 443d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 453d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanicknamespace testing { 463d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanicknamespace internal { 473d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 483d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// FilePath - a class for file and directory pathname manipulation which 493d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// handles platform-specific conventions (like the pathname separator). 503d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// Used for helper functions for naming files in a directory for xml output. 513d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// Except for Set methods, all methods are const or static, which provides an 523d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// "immutable value object" -- useful for peace of mind. 533d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// A FilePath with a value ending in a path separator ("like/this/") represents 543d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// a directory, otherwise it is assumed to represent a file. In either case, 553d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// it may or may not represent an actual file or directory in the file system. 563d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// Names are NOT checked for syntax correctness -- no checking for illegal 573d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick// characters, malformed paths, etc. 583d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 593d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanickclass GTEST_API_ FilePath { 603d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick public: 613d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick FilePath() : pathname_("") { } 623d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } 633d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 643d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick explicit FilePath(const char* pathname) : pathname_(pathname) { 653d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick Normalize(); 663d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick } 673d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 683d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick explicit FilePath(const String& pathname) : pathname_(pathname) { 693d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick Normalize(); 703d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick } 713d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 723d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick FilePath& operator=(const FilePath& rhs) { 733d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick Set(rhs); 743d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick return *this; 753d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick } 763d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 773d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick void Set(const FilePath& rhs) { 783d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick pathname_ = rhs.pathname_; 793d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick } 803d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 813d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick String ToString() const { return pathname_; } 823d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick const char* c_str() const { return pathname_.c_str(); } 833d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 843d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns the current working directory, or "" if unsuccessful. 853d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick static FilePath GetCurrentDir(); 863d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 873d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Given directory = "dir", base_name = "test", number = 0, 883d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // extension = "xml", returns "dir/test.xml". If number is greater 893d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // than zero (e.g., 12), returns "dir/test_12.xml". 903d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // On Windows platform, uses \ as the separator rather than /. 913d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick static FilePath MakeFileName(const FilePath& directory, 923d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick const FilePath& base_name, 933d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick int number, 943d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick const char* extension); 953d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 963d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Given directory = "dir", relative_path = "test.xml", 973d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // returns "dir/test.xml". 983d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // On Windows, uses \ as the separator rather than /. 993d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick static FilePath ConcatPaths(const FilePath& directory, 1003d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick const FilePath& relative_path); 1013d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1023d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns a pathname for a file that does not currently exist. The pathname 1033d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // will be directory/base_name.extension or 1043d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // directory/base_name_<number>.extension if directory/base_name.extension 1053d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // already exists. The number will be incremented until a pathname is found 1063d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // that does not already exist. 1073d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. 1083d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // There could be a race condition if two or more processes are calling this 1093d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // function at the same time -- they could both pick the same filename. 1103d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick static FilePath GenerateUniqueFileName(const FilePath& directory, 1113d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick const FilePath& base_name, 1123d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick const char* extension); 1133d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1143d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns true iff the path is NULL or "". 1153d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick bool IsEmpty() const { return c_str() == NULL || *c_str() == '\0'; } 1163d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1173d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // If input name has a trailing separator character, removes it and returns 1183d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // the name, otherwise return the name string unmodified. 1193d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // On Windows platform, uses \ as the separator, other platforms use /. 1203d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick FilePath RemoveTrailingPathSeparator() const; 1213d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1223d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns a copy of the FilePath with the directory part removed. 1233d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Example: FilePath("path/to/file").RemoveDirectoryName() returns 1243d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // FilePath("file"). If there is no directory part ("just_a_file"), it returns 1253d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // the FilePath unmodified. If there is no file part ("just_a_dir/") it 1263d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // returns an empty FilePath (""). 1273d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // On Windows platform, '\' is the path separator, otherwise it is '/'. 1283d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick FilePath RemoveDirectoryName() const; 1293d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1303d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // RemoveFileName returns the directory path with the filename removed. 1313d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". 1323d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // If the FilePath is "a_file" or "/a_file", RemoveFileName returns 1333d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does 1343d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // not have a file, like "just/a/dir/", it returns the FilePath unmodified. 1353d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // On Windows platform, '\' is the path separator, otherwise it is '/'. 1363d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick FilePath RemoveFileName() const; 1373d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1383d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns a copy of the FilePath with the case-insensitive extension removed. 1393d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns 1403d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // FilePath("dir/file"). If a case-insensitive extension is not 1413d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // found, returns a copy of the original FilePath. 1423d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick FilePath RemoveExtension(const char* extension) const; 1433d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1443d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Creates directories so that path exists. Returns true if successful or if 1453d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // the directories already exist; returns false if unable to create 1463d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // directories for any reason. Will also return false if the FilePath does 1473d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // not represent a directory (that is, it doesn't end with a path separator). 1483d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick bool CreateDirectoriesRecursively() const; 1493d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1503d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Create the directory so that path exists. Returns true if successful or 1513d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // if the directory already exists; returns false if unable to create the 1523d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // directory for any reason, including if the parent directory does not 1533d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // exist. Not named "CreateDirectory" because that's a macro on Windows. 1543d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick bool CreateFolder() const; 1553d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1563d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns true if FilePath describes something in the file-system, 1573d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // either a file, directory, or whatever, and that something exists. 1583d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick bool FileOrDirectoryExists() const; 1593d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1603d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns true if pathname describes a directory in the file-system 1613d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // that exists. 1623d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick bool DirectoryExists() const; 1633d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1643d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns true if FilePath ends with a path separator, which indicates that 1653d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // it is intended to represent a directory. Returns false otherwise. 1663d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // This does NOT check that a directory (or file) actually exists. 1673d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick bool IsDirectory() const; 1683d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1693d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns true if pathname describes a root directory. (Windows has one 1703d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // root directory per disk drive.) 1713d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick bool IsRootDirectory() const; 1723d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1733d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns true if pathname describes an absolute path. 1743d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick bool IsAbsolutePath() const; 1753d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1763d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick private: 1773d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Replaces multiple consecutive separators with a single separator. 1783d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // For example, "bar///foo" becomes "bar/foo". Does not eliminate other 1793d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // redundancies that might be in a pathname involving "." or "..". 1803d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // 1813d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // A pathname with multiple consecutive separators may occur either through 1823d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // user error or as a result of some scripts or APIs that generate a pathname 1833d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // with a trailing separator. On other platforms the same API or script 1843d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // may NOT generate a pathname with a trailing "/". Then elsewhere that 1853d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // pathname may have another "/" and pathname components added to it, 1863d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // without checking for the separator already being there. 1873d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // The script language and operating system may allow paths like "foo//bar" 1883d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // but some of the functions in FilePath will not handle that correctly. In 1893d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // particular, RemoveTrailingPathSeparator() only removes one separator, and 1903d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // it is called in CreateDirectoriesRecursively() assuming that it will change 1913d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // a pathname from directory syntax (trailing separator) to filename syntax. 1923d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // 1933d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // On Windows this method also replaces the alternate path separator '/' with 1943d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // the primary path separator '\\', so that for example "bar\\/\\foo" becomes 1953d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // "bar\\foo". 1963d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1973d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick void Normalize(); 1983d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 1993d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // Returns a pointer to the last occurence of a valid path separator in 2003d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // the FilePath. On Windows, for example, both '/' and '\' are valid path 2013d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick // separators. Returns NULL if no path separator was found. 2023d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick const char* FindLastPathSeparator() const; 2033d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 2043d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick String pathname_; 2053d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick}; // class FilePath 2063d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 2073d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick} // namespace internal 2083d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick} // namespace testing 2093d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick 2103d000e7dd14c3185b9e27a6c38a67288b4d10431Ian Romanick#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 211