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 #include "gn/value_extractors.h"
6
7 #include <stddef.h>
8
9 #include "gn/build_settings.h"
10 #include "gn/err.h"
11 #include "gn/label.h"
12 #include "gn/source_dir.h"
13 #include "gn/source_file.h"
14 #include "gn/target.h"
15 #include "gn/value.h"
16
17 namespace {
18
19 // Sets the error and returns false on failure.
20 template <typename T, class Converter>
ListValueExtractor(const Value & value,std::vector<T> * dest,Err * err,const Converter & converter)21 bool ListValueExtractor(const Value& value,
22 std::vector<T>* dest,
23 Err* err,
24 const Converter& converter) {
25 if (!value.VerifyTypeIs(Value::LIST, err))
26 return false;
27 const std::vector<Value>& input_list = value.list_value();
28 dest->resize(input_list.size());
29 for (size_t i = 0; i < input_list.size(); i++) {
30 if (!converter(input_list[i], &(*dest)[i], err))
31 return false;
32 }
33 return true;
34 }
35
36 // Like the above version but extracts to a UniqueVector and sets the error if
37 // there are duplicates.
38 template <typename T, class Converter>
ListValueUniqueExtractor(const Value & value,UniqueVector<T> * dest,Err * err,const Converter & converter)39 bool ListValueUniqueExtractor(const Value& value,
40 UniqueVector<T>* dest,
41 Err* err,
42 const Converter& converter) {
43 if (!value.VerifyTypeIs(Value::LIST, err))
44 return false;
45 const std::vector<Value>& input_list = value.list_value();
46
47 for (const auto& item : input_list) {
48 T new_one;
49 if (!converter(item, &new_one, err))
50 return false;
51 if (!dest->push_back(new_one)) {
52 // Already in the list, throw error.
53 *err = Err(item, "Duplicate item in list");
54 size_t previous_index = dest->IndexOf(new_one);
55 err->AppendSubErr(
56 Err(input_list[previous_index], "This was the previous definition."));
57 return false;
58 }
59 }
60 return true;
61 }
62
63 struct RelativeFileConverter {
RelativeFileConverter__anond5d651e50111::RelativeFileConverter64 RelativeFileConverter(const BuildSettings* build_settings_in,
65 const SourceDir& current_dir_in)
66 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anond5d651e50111::RelativeFileConverter67 bool operator()(const Value& v, SourceFile* out, Err* err) const {
68 *out = current_dir.ResolveRelativeFile(v, err,
69 build_settings->root_path_utf8());
70 return !err->has_error();
71 }
72 const BuildSettings* build_settings;
73 const SourceDir& current_dir;
74 };
75
76 struct LibFileConverter {
LibFileConverter__anond5d651e50111::LibFileConverter77 LibFileConverter(const BuildSettings* build_settings_in,
78 const SourceDir& current_dir_in)
79 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anond5d651e50111::LibFileConverter80 bool operator()(const Value& v, LibFile* out, Err* err) const {
81 if (!v.VerifyTypeIs(Value::STRING, err))
82 return false;
83 if (v.string_value().find('/') == std::string::npos) {
84 *out = LibFile(v.string_value());
85 } else {
86 *out = LibFile(current_dir.ResolveRelativeFile(
87 v, err, build_settings->root_path_utf8()));
88 }
89 return !err->has_error();
90 }
91 const BuildSettings* build_settings;
92 const SourceDir& current_dir;
93 };
94
95 struct RelativeDirConverter {
RelativeDirConverter__anond5d651e50111::RelativeDirConverter96 RelativeDirConverter(const BuildSettings* build_settings_in,
97 const SourceDir& current_dir_in)
98 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anond5d651e50111::RelativeDirConverter99 bool operator()(const Value& v, SourceDir* out, Err* err) const {
100 *out = current_dir.ResolveRelativeDir(v, err,
101 build_settings->root_path_utf8());
102 return true;
103 }
104 const BuildSettings* build_settings;
105 const SourceDir& current_dir;
106 };
107
108 struct ExternConverter {
ExternConverter__anond5d651e50111::ExternConverter109 ExternConverter(const BuildSettings* build_settings_in,
110 const SourceDir& current_dir_in)
111 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anond5d651e50111::ExternConverter112 bool operator()(const Value& v,
113 std::pair<std::string, LibFile>* out,
114 Err* err) const {
115 if (!v.VerifyTypeIs(Value::SCOPE, err))
116 return false;
117 Scope::KeyValueMap scope;
118 v.scope_value()->GetCurrentScopeValues(&scope);
119 std::string cratename;
120 if (auto it = scope.find("crate_name"); it != scope.end()) {
121 if (!it->second.VerifyTypeIs(Value::STRING, err))
122 return false;
123 cratename = it->second.string_value();
124 } else {
125 return false;
126 }
127 LibFile path;
128 if (auto it = scope.find("path"); it != scope.end()) {
129 if (!it->second.VerifyTypeIs(Value::STRING, err))
130 return false;
131 if (it->second.string_value().find('/') == std::string::npos) {
132 path = LibFile(it->second.string_value());
133 } else {
134 path = LibFile(current_dir.ResolveRelativeFile(
135 it->second, err, build_settings->root_path_utf8()));
136 }
137 } else {
138 return false;
139 }
140 *out = std::pair(cratename, path);
141 return !err->has_error();
142 }
143 const BuildSettings* build_settings;
144 const SourceDir& current_dir;
145 };
146
147 // Fills in a label.
148 template <typename T>
149 struct LabelResolver {
LabelResolver__anond5d651e50111::LabelResolver150 LabelResolver(const BuildSettings* build_settings_in,
151 const SourceDir& current_dir_in,
152 const Label& current_toolchain_in)
153 : build_settings(build_settings_in),
154 current_dir(current_dir_in),
155 current_toolchain(current_toolchain_in) {}
operator ()__anond5d651e50111::LabelResolver156 bool operator()(const Value& v, Label* out, Err* err) const {
157 if (!v.VerifyTypeIs(Value::STRING, err))
158 return false;
159 *out = Label::Resolve(current_dir, build_settings->root_path_utf8(),
160 current_toolchain, v, err);
161 return !err->has_error();
162 }
163 const BuildSettings* build_settings;
164 const SourceDir& current_dir;
165 const Label& current_toolchain;
166 };
167
168 // Fills the label part of a LabelPtrPair, leaving the pointer null.
169 template <typename T>
170 struct LabelPtrResolver {
LabelPtrResolver__anond5d651e50111::LabelPtrResolver171 LabelPtrResolver(const BuildSettings* build_settings_in,
172 const SourceDir& current_dir_in,
173 const Label& current_toolchain_in)
174 : build_settings(build_settings_in),
175 current_dir(current_dir_in),
176 current_toolchain(current_toolchain_in) {}
operator ()__anond5d651e50111::LabelPtrResolver177 bool operator()(const Value& v, LabelPtrPair<T>* out, Err* err) const {
178 if (!v.VerifyTypeIs(Value::STRING, err))
179 return false;
180 out->label = Label::Resolve(current_dir, build_settings->root_path_utf8(),
181 current_toolchain, v, err);
182 out->origin = v.origin();
183 return !err->has_error();
184 }
185 const BuildSettings* build_settings;
186 const SourceDir& current_dir;
187 const Label& current_toolchain;
188 };
189
190 struct LabelPatternResolver {
LabelPatternResolver__anond5d651e50111::LabelPatternResolver191 LabelPatternResolver(const BuildSettings* build_settings_in,
192 const SourceDir& current_dir_in)
193 : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anond5d651e50111::LabelPatternResolver194 bool operator()(const Value& v, LabelPattern* out, Err* err) const {
195 *out = LabelPattern::GetPattern(current_dir,
196 build_settings->root_path_utf8(), v, err);
197 return !err->has_error();
198 }
199
200 const BuildSettings* build_settings;
201 const SourceDir& current_dir;
202 };
203
204 } // namespace
205
ExtractListOfStringValues(const Value & value,std::vector<std::string> * dest,Err * err)206 bool ExtractListOfStringValues(const Value& value,
207 std::vector<std::string>* dest,
208 Err* err) {
209 if (!value.VerifyTypeIs(Value::LIST, err))
210 return false;
211 const std::vector<Value>& input_list = value.list_value();
212 dest->reserve(input_list.size());
213 for (const auto& item : input_list) {
214 if (!item.VerifyTypeIs(Value::STRING, err))
215 return false;
216 dest->push_back(item.string_value());
217 }
218 return true;
219 }
220
ExtractListOfRelativeFiles(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<SourceFile> * files,Err * err)221 bool ExtractListOfRelativeFiles(const BuildSettings* build_settings,
222 const Value& value,
223 const SourceDir& current_dir,
224 std::vector<SourceFile>* files,
225 Err* err) {
226 return ListValueExtractor(value, files, err,
227 RelativeFileConverter(build_settings, current_dir));
228 }
229
ExtractListOfLibs(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<LibFile> * libs,Err * err)230 bool ExtractListOfLibs(const BuildSettings* build_settings,
231 const Value& value,
232 const SourceDir& current_dir,
233 std::vector<LibFile>* libs,
234 Err* err) {
235 return ListValueExtractor(value, libs, err,
236 LibFileConverter(build_settings, current_dir));
237 }
238
ExtractListOfRelativeDirs(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<SourceDir> * dest,Err * err)239 bool ExtractListOfRelativeDirs(const BuildSettings* build_settings,
240 const Value& value,
241 const SourceDir& current_dir,
242 std::vector<SourceDir>* dest,
243 Err* err) {
244 return ListValueExtractor(value, dest, err,
245 RelativeDirConverter(build_settings, current_dir));
246 }
247
ExtractListOfLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,LabelTargetVector * dest,Err * err)248 bool ExtractListOfLabels(const BuildSettings* build_settings,
249 const Value& value,
250 const SourceDir& current_dir,
251 const Label& current_toolchain,
252 LabelTargetVector* dest,
253 Err* err) {
254 return ListValueExtractor(
255 value, dest, err,
256 LabelPtrResolver<Target>(build_settings, current_dir, current_toolchain));
257 }
258
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<Label> * dest,Err * err)259 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
260 const Value& value,
261 const SourceDir& current_dir,
262 const Label& current_toolchain,
263 UniqueVector<Label>* dest,
264 Err* err) {
265 return ListValueUniqueExtractor(
266 value, dest, err,
267 LabelResolver<Config>(build_settings, current_dir, current_toolchain));
268 }
269
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<LabelConfigPair> * dest,Err * err)270 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
271 const Value& value,
272 const SourceDir& current_dir,
273 const Label& current_toolchain,
274 UniqueVector<LabelConfigPair>* dest,
275 Err* err) {
276 return ListValueUniqueExtractor(
277 value, dest, err,
278 LabelPtrResolver<Config>(build_settings, current_dir, current_toolchain));
279 }
280
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<LabelTargetPair> * dest,Err * err)281 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
282 const Value& value,
283 const SourceDir& current_dir,
284 const Label& current_toolchain,
285 UniqueVector<LabelTargetPair>* dest,
286 Err* err) {
287 return ListValueUniqueExtractor(
288 value, dest, err,
289 LabelPtrResolver<Target>(build_settings, current_dir, current_toolchain));
290 }
291
ExtractRelativeFile(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,SourceFile * file,Err * err)292 bool ExtractRelativeFile(const BuildSettings* build_settings,
293 const Value& value,
294 const SourceDir& current_dir,
295 SourceFile* file,
296 Err* err) {
297 RelativeFileConverter converter(build_settings, current_dir);
298 return converter(value, file, err);
299 }
300
ExtractListOfLabelPatterns(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<LabelPattern> * patterns,Err * err)301 bool ExtractListOfLabelPatterns(const BuildSettings* build_settings,
302 const Value& value,
303 const SourceDir& current_dir,
304 std::vector<LabelPattern>* patterns,
305 Err* err) {
306 return ListValueExtractor(value, patterns, err,
307 LabelPatternResolver(build_settings, current_dir));
308 }
309
ExtractListOfExterns(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<std::pair<std::string,LibFile>> * externs,Err * err)310 bool ExtractListOfExterns(const BuildSettings* build_settings,
311 const Value& value,
312 const SourceDir& current_dir,
313 std::vector<std::pair<std::string, LibFile>>* externs,
314 Err* err) {
315 return ListValueExtractor(value, externs, err,
316 ExternConverter(build_settings, current_dir));
317 }
318