1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef TOOLS_GN_SOURCE_FILE_H_ 6 #define TOOLS_GN_SOURCE_FILE_H_ 7 8 #include <stddef.h> 9 10 #include <algorithm> 11 #include <string> 12 #include <string_view> 13 14 #include "base/containers/flat_set.h" 15 #include "base/files/file_path.h" 16 #include "base/logging.h" 17 18 #include "gn/string_atom.h" 19 20 class SourceDir; 21 22 // Represents a file within the source tree. Always begins in a slash, never 23 // ends in one. 24 class SourceFile { 25 public: 26 // This should be sequential integers starting from 0 so they can be used as 27 // array indices. 28 enum Type { 29 SOURCE_UNKNOWN = 0, 30 SOURCE_ASM, 31 SOURCE_C, 32 SOURCE_CPP, 33 SOURCE_H, 34 SOURCE_M, 35 SOURCE_MM, 36 SOURCE_MODULEMAP, 37 SOURCE_S, 38 SOURCE_RC, 39 SOURCE_O, // Object files can be inputs, too. Also counts .obj. 40 SOURCE_DEF, 41 42 SOURCE_RS, 43 SOURCE_GO, 44 SOURCE_SWIFT, 45 SOURCE_SWIFTMODULE, 46 47 // Must be last. 48 SOURCE_NUMTYPES, 49 }; 50 51 SourceFile() = default; 52 53 // Takes a known absolute source file. Always begins in a slash. 54 explicit SourceFile(const std::string& value); 55 explicit SourceFile(std::string&& value); 56 explicit SourceFile(StringAtom value); 57 58 ~SourceFile() = default; 59 is_null()60 bool is_null() const { return value_.empty(); } value()61 const std::string& value() const { return value_.str(); } 62 Type GetType() const; 63 64 // Optimized implementation of GetType() == SOURCE_XXX 65 bool IsDefType() const; // SOURCE_DEF 66 bool IsModuleMapType() const; // SOURCE_MODULEMAP 67 bool IsObjectType() const; // SOURCE_O 68 bool IsSwiftType() const; // SOURCE_SWIFT 69 bool IsSwiftModuleType() const; // SOURCE_SWIFTMODULE 70 71 // Returns everything after the last slash. 72 std::string GetName() const; 73 SourceDir GetDir() const; 74 75 // Resolves this source file relative to some given source root. Returns 76 // an empty file path on error. 77 base::FilePath Resolve(const base::FilePath& source_root) const; 78 79 // Returns true if this file starts with a "//" which indicates a path 80 // from the source root. is_source_absolute()81 bool is_source_absolute() const { 82 return value().size() >= 2 && value()[0] == '/' && value()[1] == '/'; 83 } 84 85 // Returns true if this file starts with a single slash which indicates a 86 // system-absolute path. is_system_absolute()87 bool is_system_absolute() const { return !is_source_absolute(); } 88 89 // Returns a source-absolute path starting with only one slash at the 90 // beginning (normally source-absolute paths start with two slashes to mark 91 // them as such). This is normally used when concatenating names together. 92 // 93 // This function asserts that the file is actually source-absolute. The 94 // return value points into our buffer. SourceAbsoluteWithOneSlash()95 std::string_view SourceAbsoluteWithOneSlash() const { 96 CHECK(is_source_absolute()); 97 return std::string_view(&value()[1], value().size() - 1); 98 } 99 100 bool operator==(const SourceFile& other) const { 101 return value_.SameAs(other.value_); 102 } 103 bool operator!=(const SourceFile& other) const { return !operator==(other); } 104 bool operator<(const SourceFile& other) const { 105 return value_ < other.value_; 106 } 107 108 struct PtrCompare { operatorPtrCompare109 bool operator()(const SourceFile& a, const SourceFile& b) const noexcept { 110 return StringAtom::PtrCompare()(a.value_, b.value_); 111 } 112 }; 113 struct PtrHash { operatorPtrHash114 size_t operator()(const SourceFile& s) const noexcept { 115 return StringAtom::PtrHash()(s.value_); 116 } 117 }; 118 119 struct PtrEqual { operatorPtrEqual120 bool operator()(const SourceFile& a, const SourceFile& b) const noexcept { 121 return StringAtom::PtrEqual()(a.value_, b.value_); 122 } 123 }; 124 125 private: 126 friend class SourceDir; 127 128 void SetValue(const std::string& value); 129 130 StringAtom value_; 131 }; 132 133 namespace std { 134 135 template <> 136 struct hash<SourceFile> { 137 std::size_t operator()(const SourceFile& v) const { 138 return SourceFile::PtrHash()(v); 139 } 140 }; 141 142 } // namespace std 143 144 // Represents a set of source files. 145 // NOTE: In practice, this is much faster than using an std::set<> or 146 // std::unordered_set<> container. E.g. for the Fuchsia Zircon build, the 147 // overall difference in "gn gen" time is about 10%. 148 using SourceFileSet = base::flat_set<SourceFile, SourceFile::PtrCompare>; 149 150 // Represents a set of tool types. 151 class SourceFileTypeSet { 152 public: 153 SourceFileTypeSet(); 154 155 void Set(SourceFile::Type type) { 156 flags_[static_cast<int>(type)] = true; 157 empty_ = false; 158 } 159 bool Get(SourceFile::Type type) const { 160 return flags_[static_cast<int>(type)]; 161 } 162 163 bool empty() const { return empty_; } 164 165 bool CSourceUsed() const; 166 bool RustSourceUsed() const; 167 bool GoSourceUsed() const; 168 bool SwiftSourceUsed() const; 169 170 bool MixedSourceUsed() const; 171 172 private: 173 bool empty_; 174 bool flags_[static_cast<int>(SourceFile::SOURCE_NUMTYPES)]; 175 }; 176 177 #endif // TOOLS_GN_SOURCE_FILE_H_ 178