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_LABEL_PTR_H_
6#define TOOLS_GN_LABEL_PTR_H_
7
8#include <functional>
9
10#include "tools/gn/label.h"
11
12class Config;
13class ParseNode;
14class Target;
15
16// Structure that holds a labeled "thing". This is used for various places
17// where we need to store lists of targets or configs. We sometimes populate
18// the pointers on another thread from where we compute the labels, so this
19// structure lets us save them separately. This also allows us to store the
20// location of the thing that added this dependency.
21template<typename T>
22struct LabelPtrPair {
23  typedef T DestType;
24
25  LabelPtrPair() : label(), ptr(NULL), origin(NULL) {}
26
27  explicit LabelPtrPair(const Label& l) : label(l), ptr(NULL), origin(NULL) {
28  }
29
30  // This contructor is typically used in unit tests, it extracts the label
31  // automatically from a given pointer.
32  explicit LabelPtrPair(const T* p) : label(p->label()), ptr(p), origin(NULL) {
33  }
34
35  ~LabelPtrPair() {}
36
37  Label label;
38  const T* ptr;  // May be NULL.
39
40  // The origin of this dependency. This will be null for internally generated
41  // dependencies. This happens when a group is automatically expanded and that
42  // group's members are added to the target that depends on that group.
43  const ParseNode* origin;
44};
45
46typedef LabelPtrPair<Config> LabelConfigPair;
47typedef LabelPtrPair<Target> LabelTargetPair;
48
49typedef std::vector<LabelConfigPair> LabelConfigVector;
50typedef std::vector<LabelTargetPair> LabelTargetVector;
51
52// Comparison and search functions ---------------------------------------------
53
54// To do a brute-force search by label:
55// std::find_if(vect.begin(), vect.end(), LabelPtrLabelEquals<Config>(label));
56template<typename T>
57struct LabelPtrLabelEquals : public std::unary_function<Label, bool> {
58  explicit LabelPtrLabelEquals(const Label& l) : label(l) {}
59
60  bool operator()(const LabelPtrPair<T>& arg) const {
61    return arg.label == label;
62  }
63
64  const Label& label;
65};
66
67// To do a brute-force search by object pointer:
68// std::find_if(vect.begin(), vect.end(), LabelPtrPtrEquals<Config>(config));
69template<typename T>
70struct LabelPtrPtrEquals : public std::unary_function<T, bool> {
71  explicit LabelPtrPtrEquals(const T* p) : ptr(p) {}
72
73  bool operator()(const LabelPtrPair<T>& arg) const {
74    return arg.ptr == ptr;
75  }
76
77  const T* ptr;
78};
79
80// To sort by label:
81// std::sort(vect.begin(), vect.end(), LabelPtrLabelLess<Config>());
82template<typename T>
83struct LabelPtrLabelLess : public std::binary_function<LabelPtrPair<T>,
84                                                       LabelPtrPair<T>,
85                                                       bool> {
86  bool operator()(const LabelPtrPair<T>& a, const LabelPtrPair<T>& b) const {
87    return a.label < b.label;
88  }
89};
90
91// Default comparison operators -----------------------------------------------
92//
93// The default hash and comparison operators operate on the label, which should
94// always be valid, whereas the pointer is sometimes null.
95
96template<typename T> inline bool operator==(const LabelPtrPair<T>& a,
97                                            const LabelPtrPair<T>& b) {
98  return a.label == b.label;
99}
100
101template<typename T> inline bool operator<(const LabelPtrPair<T>& a,
102                                           const LabelPtrPair<T>& b) {
103  return a.label < b.label;
104}
105
106namespace BASE_HASH_NAMESPACE {
107
108#if defined(COMPILER_GCC)
109template<typename T> struct hash< LabelPtrPair<T> > {
110  std::size_t operator()(const LabelPtrPair<T>& v) const {
111    BASE_HASH_NAMESPACE::hash<Label> h;
112    return h(v.label);
113  }
114};
115#elif defined(COMPILER_MSVC)
116template<typename T>
117inline size_t hash_value(const LabelPtrPair<T>& v) {
118  return BASE_HASH_NAMESPACE::hash_value(v.label);
119}
120#endif  // COMPILER...
121
122}  // namespace BASE_HASH_NAMESPACE
123
124#endif  // TOOLS_GN_LABEL_PTR_H_
125