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_CONFIG_VALUES_EXTRACTORS_H_
6 #define TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_
7
8 #include <stddef.h>
9
10 #include <ostream>
11 #include <string>
12 #include <vector>
13
14 #include "gn/config.h"
15 #include "gn/config_values.h"
16 #include "gn/target.h"
17
18 struct EscapeOptions;
19
20 // Provides a way to iterate through all ConfigValues applying to a given
21 // target. This is more complicated than normal because the target has a list
22 // of configs applying to it, and also config values on the target itself.
23 //
24 // This iterator allows one to iterate through all of these in a defined order
25 // in one convenient loop. The order is defined to be the ConfigValues on the
26 // target itself first, then the applying configs, in order.
27 //
28 // Example:
29 // for (ConfigValueIterator iter(target); !iter.done(); iter.Next())
30 // DoSomething(iter.cur());
31 class ConfigValuesIterator {
32 public:
ConfigValuesIterator(const Target * target)33 explicit ConfigValuesIterator(const Target* target) : target_(target) {
34 // If the target doesn't have its own config_values()
35 if (!target->has_config_values()) {
36 cur_index_ = 0;
37 }
38 }
39
done()40 bool done() const {
41 return cur_index_ >= static_cast<int>(target_->configs().size());
42 }
43
cur()44 const ConfigValues& cur() const {
45 if (cur_index_ == -1)
46 return target_->config_values();
47 return target_->configs()[cur_index_].ptr->resolved_values();
48 }
49
50 // Returns the origin of who added this config, if any. This will always be
51 // null for the config values of a target itself.
origin()52 const ParseNode* origin() const {
53 if (cur_index_ == -1)
54 return nullptr;
55 return target_->configs()[cur_index_].origin;
56 }
57
Next()58 void Next() { cur_index_++; }
59
60 // Returns the config holding the current config values, or NULL for those
61 // config values associated with the target itself.
GetCurrentConfig()62 const Config* GetCurrentConfig() const {
63 if (cur_index_ == -1)
64 return nullptr;
65 return target_->configs()[cur_index_].ptr;
66 }
67
68 private:
69 const Target* target_;
70
71 // Represents an index into the target_'s configs() or, when -1, the config
72 // values on the target itself.
73 int cur_index_ = -1;
74 };
75
76 enum RecursiveWriterConfig {
77 kRecursiveWriterKeepDuplicates,
78 kRecursiveWriterSkipDuplicates,
79 };
80
81 // Writes a given config value that applies to a given target. This collects
82 // all values from the target itself and all configs that apply, and writes
83 // then in order.
84 template <typename T, class Writer>
RecursiveTargetConfigToStream(RecursiveWriterConfig config,const Target * target,const std::vector<T> & (ConfigValues::* getter)()const,const Writer & writer,std::ostream & out)85 inline void RecursiveTargetConfigToStream(
86 RecursiveWriterConfig config,
87 const Target* target,
88 const std::vector<T>& (ConfigValues::*getter)() const,
89 const Writer& writer,
90 std::ostream& out) {
91 std::set<T> seen;
92 for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
93 const std::vector<T>& values = ((iter.cur()).*getter)();
94 for (size_t i = 0; i < values.size(); i++) {
95 switch (config) {
96 case kRecursiveWriterKeepDuplicates:
97 writer(values[i], out);
98 break;
99
100 case kRecursiveWriterSkipDuplicates:
101 if (seen.find(values[i]) == seen.end()) {
102 seen.insert(values[i]);
103 writer(values[i], out);
104 }
105 }
106 }
107 }
108 }
109
110 // Writes the values out as strings with no transformation.
111 void RecursiveTargetConfigStringsToStream(
112 RecursiveWriterConfig config,
113 const Target* target,
114 const std::vector<std::string>& (ConfigValues::*getter)() const,
115 const EscapeOptions& escape_options,
116 std::ostream& out);
117
118 #endif // TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_
119