• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/frameworks_utils.h"
12 #include "gn/label.h"
13 #include "gn/source_dir.h"
14 #include "gn/source_file.h"
15 #include "gn/target.h"
16 #include "gn/value.h"
17 
18 namespace {
19 
20 // Sets the error and returns false on failure.
21 template <typename T, class Converter>
ListValueExtractor(const Value & value,std::vector<T> * dest,Err * err,const Converter & converter)22 bool ListValueExtractor(const Value& value,
23                         std::vector<T>* dest,
24                         Err* err,
25                         const Converter& converter) {
26   if (!value.VerifyTypeIs(Value::LIST, err))
27     return false;
28   const std::vector<Value>& input_list = value.list_value();
29   dest->resize(input_list.size());
30   for (size_t i = 0; i < input_list.size(); i++) {
31     if (!converter(input_list[i], &(*dest)[i], err))
32       return false;
33   }
34   return true;
35 }
36 
37 // Sets the error and returns false on failure.
38 template <typename T, class Converter>
ListValueAppender(const Value & value,std::vector<T> * dest,Err * err,const Converter & converter)39 bool ListValueAppender(const Value& value,
40                        std::vector<T>* dest,
41                        Err* err,
42                        const Converter& converter)
43 {
44   if (!value.VerifyTypeIs(Value::LIST, err))
45     return false;
46   const std::vector<Value>& input_list = value.list_value();
47   for (const auto& item : input_list) {
48     T new_one;
49     if (!converter(item, &new_one, err))
50       return false;
51     dest->push_back(new_one);
52   }
53   return true;
54 }
55 
56 // Like the above version but extracts to a UniqueVector and sets the error if
57 // there are duplicates.
58 template <typename T, class Converter>
ListValueUniqueExtractor(const Value & value,UniqueVector<T> * dest,Err * err,const Converter & converter)59 bool ListValueUniqueExtractor(const Value& value,
60                               UniqueVector<T>* dest,
61                               Err* err,
62                               const Converter& converter) {
63   if (!value.VerifyTypeIs(Value::LIST, err))
64     return false;
65   const std::vector<Value>& input_list = value.list_value();
66 
67   for (const auto& item : input_list) {
68     T new_one;
69     if (!converter(item, &new_one, err))
70       return false;
71     if (!dest->push_back(new_one)) {
72       // Already in the list, throw error.
73       *err = Err(item, "Duplicate item in list");
74       size_t previous_index = dest->IndexOf(new_one);
75       err->AppendSubErr(
76           Err(input_list[previous_index], "This was the previous definition."));
77       return false;
78     }
79   }
80   return true;
81 }
82 
83 struct RelativeFileConverter {
RelativeFileConverter__anonda75a4010111::RelativeFileConverter84   RelativeFileConverter(const BuildSettings* build_settings_in,
85                         const SourceDir& current_dir_in)
86       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonda75a4010111::RelativeFileConverter87   bool operator()(const Value& v, SourceFile* out, Err* err) const {
88     *out = current_dir.ResolveRelativeFile(v, err,
89                                            build_settings->root_path_utf8());
90     return !err->has_error();
91   }
92   const BuildSettings* build_settings;
93   const SourceDir& current_dir;
94 };
95 
96 struct LibFileConverter {
LibFileConverter__anonda75a4010111::LibFileConverter97   LibFileConverter(const BuildSettings* build_settings_in,
98                    const SourceDir& current_dir_in)
99       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonda75a4010111::LibFileConverter100   bool operator()(const Value& v, LibFile* out, Err* err) const {
101     if (!v.VerifyTypeIs(Value::STRING, err))
102       return false;
103     if (!GetFrameworkName(v.string_value()).empty()) {
104       *err = Err(v, "Unsupported value in libs.",
105                  "Use frameworks to list framework dependencies.");
106       return false;
107     }
108     if (v.string_value().find('/') == std::string::npos) {
109       *out = LibFile(v.string_value());
110     } else {
111       *out = LibFile(current_dir.ResolveRelativeFile(
112           v, err, build_settings->root_path_utf8()));
113     }
114     return !err->has_error();
115   }
116   const BuildSettings* build_settings;
117   const SourceDir& current_dir;
118 };
119 
120 struct RelativeDirConverter {
RelativeDirConverter__anonda75a4010111::RelativeDirConverter121   RelativeDirConverter(const BuildSettings* build_settings_in,
122                        const SourceDir& current_dir_in)
123       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonda75a4010111::RelativeDirConverter124   bool operator()(const Value& v, SourceDir* out, Err* err) const {
125     *out = current_dir.ResolveRelativeDir(v, err,
126                                           build_settings->root_path_utf8());
127     return true;
128   }
129   const BuildSettings* build_settings;
130   const SourceDir& current_dir;
131 };
132 
133 struct ExternConverter {
ExternConverter__anonda75a4010111::ExternConverter134   ExternConverter(const BuildSettings* build_settings_in,
135                   const SourceDir& current_dir_in)
136       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonda75a4010111::ExternConverter137   bool operator()(const Value& v,
138                   std::pair<std::string, LibFile>* out,
139                   Err* err) const {
140     if (!v.VerifyTypeIs(Value::SCOPE, err))
141       return false;
142     Scope::KeyValueMap scope;
143     v.scope_value()->GetCurrentScopeValues(&scope);
144     std::string cratename;
145     if (auto it = scope.find("crate_name"); it != scope.end()) {
146       if (!it->second.VerifyTypeIs(Value::STRING, err))
147         return false;
148       cratename = it->second.string_value();
149     } else {
150       return false;
151     }
152     LibFile path;
153     if (auto it = scope.find("path"); it != scope.end()) {
154       if (!it->second.VerifyTypeIs(Value::STRING, err))
155         return false;
156       if (it->second.string_value().find('/') == std::string::npos) {
157         path = LibFile(it->second.string_value());
158       } else {
159         path = LibFile(current_dir.ResolveRelativeFile(
160             it->second, err, build_settings->root_path_utf8()));
161       }
162     } else {
163       return false;
164     }
165     *out = std::pair(cratename, path);
166     return !err->has_error();
167   }
168   const BuildSettings* build_settings;
169   const SourceDir& current_dir;
170 };
171 
172 // Fills in a label.
173 template <typename T>
174 struct LabelResolver {
LabelResolver__anonda75a4010111::LabelResolver175   LabelResolver(const BuildSettings* build_settings_in,
176                 const SourceDir& current_dir_in,
177                 const Label& current_toolchain_in)
178       : build_settings(build_settings_in),
179         current_dir(current_dir_in),
180         current_toolchain(current_toolchain_in) {}
operator ()__anonda75a4010111::LabelResolver181   bool operator()(const Value& v, Label* out, Err* err) const {
182     if (!v.VerifyTypeIs(Value::STRING, err))
183       return false;
184     *out = Label::Resolve(current_dir, build_settings->root_path_utf8(),
185                           current_toolchain, v, err);
186     return !err->has_error();
187   }
188   const BuildSettings* build_settings;
189   const SourceDir& current_dir;
190   const Label& current_toolchain;
191 };
192 
193 // Fills the label part of a LabelPtrPair, leaving the pointer null.
194 template <typename T>
195 struct LabelPtrResolver {
LabelPtrResolver__anonda75a4010111::LabelPtrResolver196   LabelPtrResolver(const BuildSettings* build_settings_in,
197                    const SourceDir& current_dir_in,
198                    const Label& current_toolchain_in)
199       : build_settings(build_settings_in),
200         current_dir(current_dir_in),
201         current_toolchain(current_toolchain_in) {}
operator ()__anonda75a4010111::LabelPtrResolver202   bool operator()(const Value& v, LabelPtrPair<T>* out, Err* err) const {
203     if (!v.VerifyTypeIs(Value::STRING, err))
204       return false;
205     out->label = Label::Resolve(current_dir, build_settings->root_path_utf8(),
206                                 current_toolchain, v, err);
207     out->origin = v.origin();
208     return !err->has_error();
209   }
210   const BuildSettings* build_settings;
211   const SourceDir& current_dir;
212   const Label& current_toolchain;
213 };
214 
215 // Fills the label part of a LabelPtrPair, leaving the pointer null.
216 template <typename T>
217 struct ExternalDepPtrResolver {
ExternalDepPtrResolver__anonda75a4010111::ExternalDepPtrResolver218   ExternalDepPtrResolver(const BuildSettings* build_settings_in,
219                          const SourceDir& current_dir_in,
220                          const Label& current_toolchain_in)
221       : build_settings(build_settings_in),
222         current_dir(current_dir_in),
223         current_toolchain(current_toolchain_in) {}
operator ()__anonda75a4010111::ExternalDepPtrResolver224   bool operator()(const Value& v, LabelPtrPair<T>* out, Err* err) const
225   {
226     if (!v.VerifyTypeIs(Value::STRING, err)) {
227       return false;
228     }
229     std::string label;
230     if (!build_settings->GetExternalDepsLabel(v, label, err)) {
231       return false;
232     }
233     Value external_dep(v.origin(), label);
234     out->label = Label::Resolve(current_dir, build_settings->root_path_utf8(),
235                                 current_toolchain, external_dep, err);
236     out->origin = v.origin();
237     out->is_external_deps = true;
238     return !err->has_error();
239   }
240   const BuildSettings* build_settings;
241   const SourceDir& current_dir;
242   const Label& current_toolchain;
243 };
244 
245 struct LabelPatternResolver {
LabelPatternResolver__anonda75a4010111::LabelPatternResolver246   LabelPatternResolver(const BuildSettings* build_settings_in,
247                        const SourceDir& current_dir_in)
248       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonda75a4010111::LabelPatternResolver249   bool operator()(const Value& v, LabelPattern* out, Err* err) const {
250     *out = LabelPattern::GetPattern(current_dir,
251                                     build_settings->root_path_utf8(), v, err);
252     return !err->has_error();
253   }
254 
255   const BuildSettings* build_settings;
256   const SourceDir& current_dir;
257 };
258 
259 }  // namespace
260 
ExtractListOfStringValues(const Value & value,std::vector<std::string> * dest,Err * err)261 bool ExtractListOfStringValues(const Value& value,
262                                std::vector<std::string>* dest,
263                                Err* err) {
264   if (!value.VerifyTypeIs(Value::LIST, err))
265     return false;
266   const std::vector<Value>& input_list = value.list_value();
267   dest->reserve(input_list.size());
268   for (const auto& item : input_list) {
269     if (!item.VerifyTypeIs(Value::STRING, err))
270       return false;
271     dest->push_back(item.string_value());
272   }
273   return true;
274 }
275 
ExtractListOfRelativeFiles(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<SourceFile> * files,Err * err)276 bool ExtractListOfRelativeFiles(const BuildSettings* build_settings,
277                                 const Value& value,
278                                 const SourceDir& current_dir,
279                                 std::vector<SourceFile>* files,
280                                 Err* err) {
281   return ListValueExtractor(value, files, err,
282                             RelativeFileConverter(build_settings, current_dir));
283 }
284 
ExtractListOfLibs(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<LibFile> * libs,Err * err)285 bool ExtractListOfLibs(const BuildSettings* build_settings,
286                        const Value& value,
287                        const SourceDir& current_dir,
288                        std::vector<LibFile>* libs,
289                        Err* err) {
290   return ListValueExtractor(value, libs, err,
291                             LibFileConverter(build_settings, current_dir));
292 }
293 
ExtractListOfRelativeDirs(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<SourceDir> * dest,Err * err)294 bool ExtractListOfRelativeDirs(const BuildSettings* build_settings,
295                                const Value& value,
296                                const SourceDir& current_dir,
297                                std::vector<SourceDir>* dest,
298                                Err* err) {
299   return ListValueExtractor(value, dest, err,
300                             RelativeDirConverter(build_settings, current_dir));
301 }
302 
ExtractListOfLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,LabelTargetVector * dest,Err * err)303 bool ExtractListOfLabels(const BuildSettings* build_settings,
304                          const Value& value,
305                          const SourceDir& current_dir,
306                          const Label& current_toolchain,
307                          LabelTargetVector* dest,
308                          Err* err) {
309   return ListValueExtractor(
310       value, dest, err,
311       LabelPtrResolver<Target>(build_settings, current_dir, current_toolchain));
312 }
313 
ExtractListOfExternalDeps(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,LabelTargetVector * dest,Err * err)314 bool ExtractListOfExternalDeps(const BuildSettings* build_settings,
315                                const Value& value,
316                                const SourceDir& current_dir,
317                                const Label& current_toolchain,
318                                LabelTargetVector* dest,
319                                Err* err) {
320   return ListValueAppender(
321       value, dest, err,
322       ExternalDepPtrResolver<Target>(build_settings, current_dir, current_toolchain));
323 }
324 
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<Label> * dest,Err * err)325 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
326                                const Value& value,
327                                const SourceDir& current_dir,
328                                const Label& current_toolchain,
329                                UniqueVector<Label>* dest,
330                                Err* err) {
331   return ListValueUniqueExtractor(
332       value, dest, err,
333       LabelResolver<Config>(build_settings, current_dir, current_toolchain));
334 }
335 
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<LabelConfigPair> * dest,Err * err)336 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
337                                const Value& value,
338                                const SourceDir& current_dir,
339                                const Label& current_toolchain,
340                                UniqueVector<LabelConfigPair>* dest,
341                                Err* err) {
342   return ListValueUniqueExtractor(
343       value, dest, err,
344       LabelPtrResolver<Config>(build_settings, current_dir, current_toolchain));
345 }
346 
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<LabelTargetPair> * dest,Err * err)347 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
348                                const Value& value,
349                                const SourceDir& current_dir,
350                                const Label& current_toolchain,
351                                UniqueVector<LabelTargetPair>* dest,
352                                Err* err) {
353   return ListValueUniqueExtractor(
354       value, dest, err,
355       LabelPtrResolver<Target>(build_settings, current_dir, current_toolchain));
356 }
357 
ExtractRelativeFile(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,SourceFile * file,Err * err)358 bool ExtractRelativeFile(const BuildSettings* build_settings,
359                          const Value& value,
360                          const SourceDir& current_dir,
361                          SourceFile* file,
362                          Err* err) {
363   RelativeFileConverter converter(build_settings, current_dir);
364   return converter(value, file, err);
365 }
366 
ExtractListOfLabelPatterns(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<LabelPattern> * patterns,Err * err)367 bool ExtractListOfLabelPatterns(const BuildSettings* build_settings,
368                                 const Value& value,
369                                 const SourceDir& current_dir,
370                                 std::vector<LabelPattern>* patterns,
371                                 Err* err) {
372   return ListValueExtractor(value, patterns, err,
373                             LabelPatternResolver(build_settings, current_dir));
374 }
375 
ExtractListOfExterns(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<std::pair<std::string,LibFile>> * externs,Err * err)376 bool ExtractListOfExterns(const BuildSettings* build_settings,
377                           const Value& value,
378                           const SourceDir& current_dir,
379                           std::vector<std::pair<std::string, LibFile>>* externs,
380                           Err* err) {
381   return ListValueExtractor(value, externs, err,
382                             ExternConverter(build_settings, current_dir));
383 }
384