| // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef TOOLS_GN_FILESYSTEM_UTILS_H_ | 
 | #define TOOLS_GN_FILESYSTEM_UTILS_H_ | 
 |  | 
 | #include <stddef.h> | 
 |  | 
 | #include <string> | 
 |  | 
 | #include "base/files/file_path.h" | 
 | #include "base/strings/string_piece.h" | 
 | #include "tools/gn/settings.h" | 
 | #include "tools/gn/target.h" | 
 |  | 
 | class Err; | 
 |  | 
 | std::string FilePathToUTF8(const base::FilePath::StringType& str); | 
 | inline std::string FilePathToUTF8(const base::FilePath& path) { | 
 |   return FilePathToUTF8(path.value()); | 
 | } | 
 | base::FilePath UTF8ToFilePath(const base::StringPiece& sp); | 
 |  | 
 | // Extensions ----------------------------------------------------------------- | 
 |  | 
 | // Returns the index of the extension (character after the last dot not after a | 
 | // slash). Returns std::string::npos if not found. Returns path.size() if the | 
 | // file ends with a dot. | 
 | size_t FindExtensionOffset(const std::string& path); | 
 |  | 
 | // Returns a string piece pointing into the input string identifying the | 
 | // extension. Note that the input pointer must outlive the output. | 
 | base::StringPiece FindExtension(const std::string* path); | 
 |  | 
 | // Filename parts ------------------------------------------------------------- | 
 |  | 
 | // Returns the offset of the character following the last slash, or | 
 | // 0 if no slash was found. Returns path.size() if the path ends with a slash. | 
 | // Note that the input pointer must outlive the output. | 
 | size_t FindFilenameOffset(const std::string& path); | 
 |  | 
 | // Returns a string piece pointing into the input string identifying the | 
 | // file name (following the last slash, including the extension). Note that the | 
 | // input pointer must outlive the output. | 
 | base::StringPiece FindFilename(const std::string* path); | 
 |  | 
 | // Like FindFilename but does not include the extension. | 
 | base::StringPiece FindFilenameNoExtension(const std::string* path); | 
 |  | 
 | // Removes everything after the last slash. The last slash, if any, will be | 
 | // preserved. | 
 | void RemoveFilename(std::string* path); | 
 |  | 
 | // Returns if the given character is a slash. This allows both slashes and | 
 | // backslashes for consistency between Posix and Windows (as opposed to | 
 | // FilePath::IsSeparator which is based on the current platform). | 
 | inline bool IsSlash(const char ch) { | 
 |   return ch == '/' || ch == '\\'; | 
 | } | 
 |  | 
 | // Returns true if the given path ends with a slash. | 
 | bool EndsWithSlash(const std::string& s); | 
 |  | 
 | // Path parts ----------------------------------------------------------------- | 
 |  | 
 | // Returns a string piece pointing into the input string identifying the | 
 | // directory name of the given path, including the last slash. Note that the | 
 | // input pointer must outlive the output. | 
 | base::StringPiece FindDir(const std::string* path); | 
 |  | 
 | // Returns the substring identifying the last component of the dir, or the | 
 | // empty substring if none. For example "//foo/bar/" -> "bar". | 
 | base::StringPiece FindLastDirComponent(const SourceDir& dir); | 
 |  | 
 | // Returns true if the given string is in the given output dir. This is pretty | 
 | // stupid and doesn't handle "." and "..", etc., it is designed for a sanity | 
 | // check to keep people from writing output files to the source directory | 
 | // accidentally. | 
 | bool IsStringInOutputDir(const SourceDir& output_dir, const std::string& str); | 
 |  | 
 | // Verifies that the given string references a file inside of the given | 
 | // directory. This just uses IsStringInOutputDir above. | 
 | // | 
 | // The origin will be blamed in the error. | 
 | // | 
 | // If the file isn't in the dir, returns false and sets the error. Otherwise | 
 | // returns true and leaves the error untouched. | 
 | bool EnsureStringIsInOutputDir(const SourceDir& output_dir, | 
 |                                const std::string& str, | 
 |                                const ParseNode* origin, | 
 |                                Err* err); | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 |  | 
 | // Returns true if the input string is absolute. Double-slashes at the | 
 | // beginning are treated as source-relative paths. On Windows, this handles | 
 | // paths of both the native format: "C:/foo" and ours "/C:/foo" | 
 | bool IsPathAbsolute(const base::StringPiece& path); | 
 |  | 
 | // Returns true if the input string is source-absolute. Source-absolute | 
 | // paths begin with two forward slashes and resolve as if they are | 
 | // relative to the source root. | 
 | bool IsPathSourceAbsolute(const base::StringPiece& path); | 
 |  | 
 | // Given an absolute path, checks to see if is it is inside the source root. | 
 | // If it is, fills a source-absolute path into the given output and returns | 
 | // true. If it isn't, clears the dest and returns false. | 
 | // | 
 | // The source_root should be a base::FilePath converted to UTF-8. On Windows, | 
 | // it should begin with a "C:/" rather than being our SourceFile's style | 
 | // ("/C:/"). The source root can end with a slash or not. | 
 | // | 
 | // Note that this does not attempt to normalize slashes in the output. | 
 | bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root, | 
 |                                         const base::StringPiece& path, | 
 |                                         std::string* dest); | 
 |  | 
 | // Given two absolute paths |base| and |target|, returns a relative path to | 
 | // |target| as if the current directory was |base|.  The relative path returned | 
 | // is minimal.  For example, if "../../a/b/" and "../b" are both valid, then the | 
 | // latter will be returned.  On Windows, it's impossible to have a relative path | 
 | // from C:\foo to D:\bar, so the absolute path |target| is returned instead for | 
 | // this case. | 
 | base::FilePath MakeAbsoluteFilePathRelativeIfPossible( | 
 |     const base::FilePath& base, | 
 |     const base::FilePath& target); | 
 |  | 
 | // Collapses "." and sequential "/"s and evaluates "..". |path| may be | 
 | // system-absolute, source-absolute, or relative. If |path| is source-absolute | 
 | // and |source_root| is non-empty, |path| may be system absolute after this | 
 | // function returns, if |path| references the filesystem outside of | 
 | // |source_root| (ex. path = "//.."). In this case on Windows, |path| will have | 
 | // a leading slash. Otherwise, |path| will retain its relativity. |source_root| | 
 | // must not end with a slash. | 
 | void NormalizePath(std::string* path, | 
 |                    const base::StringPiece& source_root = base::StringPiece()); | 
 |  | 
 | // Converts slashes to backslashes for Windows. Keeps the string unchanged | 
 | // for other systems. | 
 | void ConvertPathToSystem(std::string* path); | 
 |  | 
 | // Takes a path, |input|, and makes it relative to the given directory | 
 | // |dest_dir|. Both inputs may be source-relative (e.g. begins with | 
 | // with "//") or may be absolute. | 
 | // | 
 | // If supplied, the |source_root| parameter is the absolute path to | 
 | // the source root and not end in a slash. Unless you know that the | 
 | // inputs are always source relative, this should be supplied. | 
 | std::string RebasePath( | 
 |     const std::string& input, | 
 |     const SourceDir& dest_dir, | 
 |     const base::StringPiece& source_root = base::StringPiece()); | 
 |  | 
 | // Resolves a file or dir name (parameter input) relative to | 
 | // value directory. Will return an empty SourceDir/File on error | 
 | // and set the give *err pointer (required). Empty input is always an error. | 
 | // Returned value can be used to set value in either SourceFile or SourceDir | 
 | // (based on as_file parameter). | 
 | // | 
 | // Parameter as_file defines whether result path will look like a file path | 
 | // or it should be treated as a directory (contains "/" and the end | 
 | // of the string). | 
 | // | 
 | // If source_root is supplied, these functions will additionally handle the | 
 | // case where the input is a system-absolute but still inside the source | 
 | // tree. This is the case for some external tools. | 
 | template <typename StringType> | 
 | std::string ResolveRelative(const StringType& input, | 
 |                             const std::string& value, | 
 |                             bool as_file, | 
 |                             const base::StringPiece& source_root); | 
 |  | 
 | // Resolves source file or directory relative to some given source root. Returns | 
 | // an empty file path on error. | 
 | base::FilePath ResolvePath(const std::string& value, | 
 |                            bool as_file, | 
 |                            const base::FilePath& source_root); | 
 |  | 
 | // Returns the given directory with no terminating slash at the end, such that | 
 | // appending a slash and more stuff will produce a valid path. | 
 | // | 
 | // If the directory refers to either the source or system root, we'll append | 
 | // a "." so this remains valid. | 
 | std::string DirectoryWithNoLastSlash(const SourceDir& dir); | 
 |  | 
 | // Returns the "best" SourceDir representing the given path. If it's inside the | 
 | // given source_root, a source-relative directory will be returned (e.g. | 
 | // "//foo/bar.cc". If it's outside of the source root or the source root is | 
 | // empty, a system-absolute directory will be returned. | 
 | SourceDir SourceDirForPath(const base::FilePath& source_root, | 
 |                            const base::FilePath& path); | 
 |  | 
 | // Like SourceDirForPath but returns the SourceDir representing the current | 
 | // directory. | 
 | SourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root); | 
 |  | 
 | // Given the label of a toolchain and whether that toolchain is the default | 
 | // toolchain, returns the name of the subdirectory for that toolchain's | 
 | // output. This will be the empty string to indicate that the toolchain outputs | 
 | // go in the root build directory. Otherwise, the result will end in a slash. | 
 | std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default); | 
 |  | 
 | // Returns true if the contents of the file and stream given are equal, false | 
 | // otherwise. | 
 | bool ContentsEqual(const base::FilePath& file_path, const std::string& data); | 
 |  | 
 | // Writes given stream contents to the given file if it differs from existing | 
 | // file contents. Returns true if new contents was successfully written or | 
 | // existing file contents doesn't need updating, false on write error. |err| is | 
 | // set on write error if not nullptr. | 
 | bool WriteFileIfChanged(const base::FilePath& file_path, | 
 |                         const std::string& data, | 
 |                         Err* err); | 
 |  | 
 | // Writes given stream contents to the given file. Returns true if data was | 
 | // successfully written, false otherwise. |err| is set on error if not nullptr. | 
 | bool WriteFile(const base::FilePath& file_path, | 
 |                const std::string& data, | 
 |                Err* err); | 
 |  | 
 | // ----------------------------------------------------------------------------- | 
 |  | 
 | enum class BuildDirType { | 
 |   // Returns the root toolchain dir rather than the generated or output | 
 |   // subdirectories. This is valid only for the toolchain directory getters. | 
 |   // Asking for this for a target or source dir makes no sense. | 
 |   TOOLCHAIN_ROOT, | 
 |  | 
 |   // Generated file directory. | 
 |   GEN, | 
 |  | 
 |   // Output file directory. | 
 |   OBJ, | 
 | }; | 
 |  | 
 | // In different contexts, different information is known about the toolchain in | 
 | // question. If you have a Target or settings object, everything can be | 
 | // extracted from there. But when querying label information on something in | 
 | // another toolchain, for example, the only thing known (it may not even exist) | 
 | // is the toolchain label string and whether it matches the default toolchain. | 
 | // | 
 | // This object extracts the relevant information from a variety of input | 
 | // types for the convenience of the caller. | 
 | class BuildDirContext { | 
 |  public: | 
 |   // Extracts toolchain information associated with the given target. | 
 |   explicit BuildDirContext(const Target* target); | 
 |  | 
 |   // Extracts toolchain information associated with the given settings object. | 
 |   explicit BuildDirContext(const Settings* settings); | 
 |  | 
 |   // Extrats toolchain information from the current toolchain of the scope. | 
 |   explicit BuildDirContext(const Scope* execution_scope); | 
 |  | 
 |   // Extracts the default toolchain information from the given execution | 
 |   // scope. The toolchain you want to query must be passed in. This doesn't | 
 |   // use the settings object from the Scope so one can query other toolchains. | 
 |   // If you want to use the scope's current toolchain, use the version above. | 
 |   BuildDirContext(const Scope* execution_scope, const Label& toolchain_label); | 
 |  | 
 |   // Specify all information manually. | 
 |   BuildDirContext(const BuildSettings* build_settings, | 
 |                   const Label& toolchain_label, | 
 |                   bool is_default_toolchain); | 
 |  | 
 |   const BuildSettings* build_settings; | 
 |   const Label& toolchain_label; | 
 |   bool is_default_toolchain; | 
 | }; | 
 |  | 
 | // Returns the root, object, or generated file directory for the toolchain. | 
 | // | 
 | // The toolchain object file root is never exposed in GN (there is no | 
 | // root_obj_dir variable) so BuildDirType::OBJ would normally never be passed | 
 | // to this function except when it's called by one of the variants below that | 
 | // append paths to it. | 
 | SourceDir GetBuildDirAsSourceDir(const BuildDirContext& context, | 
 |                                  BuildDirType type); | 
 | OutputFile GetBuildDirAsOutputFile(const BuildDirContext& context, | 
 |                                    BuildDirType type); | 
 |  | 
 | // Returns the output or generated file directory corresponding to the given | 
 | // source directory. | 
 | SourceDir GetSubBuildDirAsSourceDir(const BuildDirContext& context, | 
 |                                     const SourceDir& source_dir, | 
 |                                     BuildDirType type); | 
 | OutputFile GetSubBuildDirAsOutputFile(const BuildDirContext& context, | 
 |                                       const SourceDir& source_dir, | 
 |                                       BuildDirType type); | 
 |  | 
 | // Returns the output or generated file directory corresponding to the given | 
 | // target. | 
 | SourceDir GetBuildDirForTargetAsSourceDir(const Target* target, | 
 |                                           BuildDirType type); | 
 | OutputFile GetBuildDirForTargetAsOutputFile(const Target* target, | 
 |                                             BuildDirType type); | 
 |  | 
 | // Returns the scope's current directory. | 
 | SourceDir GetScopeCurrentBuildDirAsSourceDir(const Scope* scope, | 
 |                                              BuildDirType type); | 
 | // Lack of OutputDir version is due only to it not currently being needed, | 
 | // please add one if you need it. | 
 |  | 
 | #endif  // TOOLS_GN_FILESYSTEM_UTILS_H_ |