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_S, 37 SOURCE_RC, 38 SOURCE_O, // Object files can be inputs, too. Also counts .obj. 39 SOURCE_DEF, 40 41 SOURCE_RS, 42 SOURCE_GO, 43 44 // Must be last. 45 SOURCE_NUMTYPES, 46 }; 47 48 SourceFile() = default; 49 50 // Takes a known absolute source file. Always begins in a slash. 51 explicit SourceFile(const std::string& value); 52 explicit SourceFile(std::string&& value); 53 explicit SourceFile(StringAtom value); 54 55 ~SourceFile() = default; 56 is_null()57 bool is_null() const { return value_.empty(); } value()58 const std::string& value() const { return value_.str(); } type()59 Type type() const { return type_; } 60 61 // Returns everything after the last slash. 62 std::string GetName() const; 63 SourceDir GetDir() const; 64 65 // Resolves this source file relative to some given source root. Returns 66 // an empty file path on error. 67 base::FilePath Resolve(const base::FilePath& source_root) const; 68 69 // Returns true if this file starts with a "//" which indicates a path 70 // from the source root. is_source_absolute()71 bool is_source_absolute() const { 72 return value().size() >= 2 && value()[0] == '/' && value()[1] == '/'; 73 } 74 75 // Returns true if this file starts with a single slash which indicates a 76 // system-absolute path. is_system_absolute()77 bool is_system_absolute() const { return !is_source_absolute(); } 78 79 // Returns a source-absolute path starting with only one slash at the 80 // beginning (normally source-absolute paths start with two slashes to mark 81 // them as such). This is normally used when concatenating names together. 82 // 83 // This function asserts that the file is actually source-absolute. The 84 // return value points into our buffer. SourceAbsoluteWithOneSlash()85 std::string_view SourceAbsoluteWithOneSlash() const { 86 CHECK(is_source_absolute()); 87 return std::string_view(&value()[1], value().size() - 1); 88 } 89 90 bool operator==(const SourceFile& other) const { 91 return value_ == other.value_; 92 } 93 bool operator!=(const SourceFile& other) const { return !operator==(other); } 94 bool operator<(const SourceFile& other) const { 95 return value_ < other.value_; 96 } 97 98 struct PtrCompare { operatorPtrCompare99 bool operator()(const SourceFile& a, const SourceFile& b) const noexcept { 100 return StringAtom::PtrCompare()(a.value_, b.value_); 101 } 102 }; 103 struct PtrHash { operatorPtrHash104 size_t operator()(const SourceFile& s) const noexcept { 105 return StringAtom::PtrHash()(s.value_); 106 } 107 }; 108 109 struct PtrEqual { operatorPtrEqual110 bool operator()(const SourceFile& a, const SourceFile& b) const noexcept { 111 return StringAtom::PtrEqual()(a.value_, b.value_); 112 } 113 }; 114 115 private: 116 friend class SourceDir; 117 118 void SetValue(const std::string& value); 119 120 StringAtom value_; 121 Type type_ = SOURCE_UNKNOWN; 122 }; 123 124 namespace std { 125 126 template <> 127 struct hash<SourceFile> { 128 std::size_t operator()(const SourceFile& v) const { 129 hash<std::string> h; 130 return h(v.value()); 131 } 132 }; 133 134 } // namespace std 135 136 // Represents a set of source files. 137 // NOTE: In practice, this is much faster than using an std::set<> or 138 // std::unordered_set<> container. E.g. for the Fuchsia Zircon build, the 139 // overall difference in "gn gen" time is about 10%. 140 using SourceFileSet = base::flat_set<SourceFile, SourceFile::PtrCompare>; 141 142 // Represents a set of tool types. 143 class SourceFileTypeSet { 144 public: 145 SourceFileTypeSet(); 146 147 void Set(SourceFile::Type type) { 148 flags_[static_cast<int>(type)] = true; 149 empty_ = false; 150 } 151 bool Get(SourceFile::Type type) const { 152 return flags_[static_cast<int>(type)]; 153 } 154 155 bool empty() const { return empty_; } 156 157 bool CSourceUsed() const; 158 bool RustSourceUsed() const; 159 bool GoSourceUsed() const; 160 161 bool MixedSourceUsed() const; 162 163 private: 164 bool empty_; 165 bool flags_[static_cast<int>(SourceFile::SOURCE_NUMTYPES)]; 166 }; 167 168 #endif // TOOLS_GN_SOURCE_FILE_H_ 169