• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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_TARGET_PUBLIC_PAIR_H_
6 #define TOOLS_GN_TARGET_PUBLIC_PAIR_H_
7 
8 #include "gn/immutable_vector.h"
9 #include "gn/tagged_pointer.h"
10 #include "gn/unique_vector.h"
11 
12 class Target;
13 
14 // A Compact encoding for a (target_ptr, is_public_flag) pair.
15 class TargetPublicPair {
16  public:
17   TargetPublicPair() = default;
TargetPublicPair(const Target * target,bool is_public)18   TargetPublicPair(const Target* target, bool is_public)
19       : pair_(target, static_cast<unsigned>(is_public)) {}
TargetPublicPair(std::pair<const Target *,bool> pair)20   TargetPublicPair(std::pair<const Target*, bool> pair)
21       : pair_(pair.first, static_cast<unsigned>(pair.second)) {}
22 
target()23   const Target* target() const { return pair_.ptr(); }
set_target(const Target * target)24   void set_target(const Target* target) { pair_.set_ptr(target); }
25 
is_public()26   bool is_public() const { return pair_.tag() != 0; }
set_is_public(bool is_public)27   void set_is_public(bool is_public) { pair_.set_tag(is_public ? 1 : 0); }
28 
29   // Utility structs that can be used to instantiante containers
30   // that only use the target for lookups / comparisons. E.g.
31   //
32   //   std::unordered_set<TargetPublicPair,
33   //                      TargetPublicPair::TargetHash,
34   //                      TargetPublicPair::TargetEqualTo>
35   //
36   //   std::set<TargetPublicPair, TargetPublicPair::TargetLess>
37   //
38   struct TargetHash {
operatorTargetHash39     size_t operator()(TargetPublicPair p) const noexcept {
40       return std::hash<const Target*>()(p.target());
41     }
42   };
43 
44   struct TargetEqualTo {
operatorTargetEqualTo45     bool operator()(TargetPublicPair a, TargetPublicPair b) const noexcept {
46       return a.target() == b.target();
47     }
48   };
49 
50   struct TargetLess {
operatorTargetLess51     bool operator()(TargetPublicPair a, TargetPublicPair b) const noexcept {
52       return a.target() < b.target();
53     }
54   };
55 
56  private:
57   TaggedPointer<const Target, 1> pair_;
58 };
59 
60 // A helper type to build a list of (target, is_public) pairs, where target
61 // pointers are unique. Usage is:
62 //
63 //   1) Create builder instance.
64 //   2) Call Append() or AppendInherited() as many times as necessary.
65 //   3) Call Build() to retrieve final list as an immutable vector.
66 //
67 class TargetPublicPairListBuilder
68     : public UniqueVector<TargetPublicPair,
69                           TargetPublicPair::TargetHash,
70                           TargetPublicPair::TargetEqualTo> {
71  public:
72   // Add (target, is_public) to the list being constructed. If the target
73   // was not already in the list, recorded the |is_public| flag as is,
74   // otherwise, set the recorded flag to true only if |is_public| is true, or
75   // don't do anything otherwise.
Append(const Target * target,bool is_public)76   void Append(const Target* target, bool is_public) {
77     auto ret = EmplaceBackWithIndex(target, is_public);
78     if (!ret.first && is_public) {
79       // UniqueVector<T>::operator[]() always returns a const reference
80       // because the returned values are lookup keys in its set-like data
81       // structure (thus modifying them would break its internal consistency).
82       // However, because TargetHash and TargetEqualTo are being used to
83       // instantiate this template, only the target() part of the value must
84       // remain constant, and it is possible to modify the is_public() part
85       // in-place safely.
86       auto* pair = const_cast<TargetPublicPair*>(&(*this)[ret.second]);
87       pair->set_is_public(true);
88     }
89   }
90 
91   // Append all pairs from any container with begin() and end() iterators
92   // that dereference to values that convert to a TargetPublicPair value.
93   // If |is_public| is false, the input pair will be appended with the
94   // value of the public flag to false.
95   template <
96       typename C,
97       typename = std::void_t<
98           decltype(static_cast<TargetPublicPair>(*std::declval<C>().begin())),
99           decltype(static_cast<TargetPublicPair>(*std::declval<C>().end()))>>
AppendInherited(const C & other,bool is_public)100   void AppendInherited(const C& other, bool is_public) {
101     for (const auto& pair : other) {
102       Append(pair.target(), is_public && pair.is_public());
103     }
104   }
105 
Build()106   ImmutableVector<TargetPublicPair> Build() {
107     return ImmutableVector<TargetPublicPair>(release());
108   }
109 };
110 
111 #endif  // TOOLS_GN_TARGET_PUBLIC_PAIR_H_
112