• 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/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