| // Copyright 2022 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_RESOLVED_TARGET_DEPS_H_ |
| #define TOOLS_GN_RESOLVED_TARGET_DEPS_H_ |
| |
| #include "base/containers/span.h" |
| #include "gn/label_ptr.h" |
| |
| #include <memory> |
| |
| // A class used to record the dependencies of a given Target in |
| // a way that is much more efficient to iterate over than having three |
| // separate LabelTargetVector instances. Technically equivalent to |
| // DepsIterator, but profiling shows that this class is much faster |
| // to use during graph-traversal heavy operations. |
| // |
| // Usage is: |
| // 1) Create instance, passing const references to the LabelTargetVector |
| // instances for the private, public and data deps for the target. |
| // |
| // 2) Use private_deps(), public_deps(), data_deps(), linked_deps() |
| // and all_deps() to retrieve spans that cover various subsets of |
| // interests. These can be used directly in for-range loops as in: |
| // |
| // for (const Target* target : resolved.linked_deps()) { |
| // .. |
| // } |
| // |
| class ResolvedTargetDeps { |
| public: |
| ResolvedTargetDeps() = default; |
| |
| ResolvedTargetDeps(const LabelTargetVector& public_deps, |
| const LabelTargetVector& private_deps, |
| const LabelTargetVector& data_deps) |
| : public_count_(static_cast<uint32_t>(public_deps.size())), |
| private_count_(static_cast<uint32_t>(private_deps.size())), |
| data_count_(static_cast<uint32_t>(data_deps.size())), |
| deps_(Allocate(public_deps, private_deps, data_deps)) {} |
| |
| size_t size() const { return private_count_ + public_count_ + data_count_; } |
| |
| base::span<const Target*> public_deps() const { |
| return {deps_.get(), public_count_}; |
| } |
| |
| base::span<const Target*> private_deps() const { |
| return {deps_.get() + public_count_, private_count_}; |
| } |
| |
| base::span<const Target*> data_deps() const { |
| return {deps_.get() + private_count_ + public_count_, data_count_}; |
| } |
| |
| base::span<const Target*> linked_deps() const { |
| return {deps_.get(), private_count_ + public_count_}; |
| } |
| |
| base::span<const Target*> all_deps() const { |
| return {deps_.get(), private_count_ + public_count_ + data_count_}; |
| } |
| |
| static std::unique_ptr<const Target*[]> Allocate( |
| const LabelTargetVector& public_deps, |
| const LabelTargetVector& private_deps, |
| const LabelTargetVector& data_deps) { |
| size_t total_size = |
| private_deps.size() + public_deps.size() + data_deps.size(); |
| auto result = std::make_unique<const Target*[]>(total_size); |
| const Target** ptr = result.get(); |
| for (const auto& pair : public_deps) |
| *ptr++ = pair.ptr; |
| for (const auto& pair : private_deps) |
| *ptr++ = pair.ptr; |
| for (const auto& pair : data_deps) |
| *ptr++ = pair.ptr; |
| return result; |
| } |
| |
| private: |
| uint32_t public_count_ = 0; |
| uint32_t private_count_ = 0; |
| uint32_t data_count_ = 0; |
| // Store the pointers in the following order: public, private, data. |
| std::unique_ptr<const Target*[]> deps_; |
| }; |
| |
| #endif // TOOLS_GN_RESOLVED_TARGET_DEPS_H_ |