• 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 // Like the above version but extracts to a UniqueVector and sets the error if
38 // there are duplicates.
39 template <typename T, class Converter>
ListValueUniqueExtractor(const Value & value,UniqueVector<T> * dest,Err * err,const Converter & converter)40 bool ListValueUniqueExtractor(const Value& value,
41                               UniqueVector<T>* dest,
42                               Err* err,
43                               const Converter& converter) {
44   if (!value.VerifyTypeIs(Value::LIST, err))
45     return false;
46   const std::vector<Value>& input_list = value.list_value();
47 
48   for (const auto& item : input_list) {
49     T new_one;
50     if (!converter(item, &new_one, err))
51       return false;
52     if (!dest->push_back(new_one)) {
53       // Already in the list, throw error.
54       *err = Err(item, "Duplicate item in list");
55       size_t previous_index = dest->IndexOf(new_one);
56       err->AppendSubErr(
57           Err(input_list[previous_index], "This was the previous definition."));
58       return false;
59     }
60   }
61   return true;
62 }
63 
64 struct RelativeFileConverter {
RelativeFileConverter__anonb8f867620111::RelativeFileConverter65   RelativeFileConverter(const BuildSettings* build_settings_in,
66                         const SourceDir& current_dir_in)
67       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonb8f867620111::RelativeFileConverter68   bool operator()(const Value& v, SourceFile* out, Err* err) const {
69     *out = current_dir.ResolveRelativeFile(v, err,
70                                            build_settings->root_path_utf8());
71     return !err->has_error();
72   }
73   const BuildSettings* build_settings;
74   const SourceDir& current_dir;
75 };
76 
77 struct LibFileConverter {
LibFileConverter__anonb8f867620111::LibFileConverter78   LibFileConverter(const BuildSettings* build_settings_in,
79                    const SourceDir& current_dir_in)
80       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonb8f867620111::LibFileConverter81   bool operator()(const Value& v, LibFile* out, Err* err) const {
82     if (!v.VerifyTypeIs(Value::STRING, err))
83       return false;
84     if (!GetFrameworkName(v.string_value()).empty()) {
85       *err = Err(v, "Unsupported value in libs.",
86                  "Use frameworks to list framework dependencies.");
87       return false;
88     }
89     if (v.string_value().find('/') == std::string::npos) {
90       *out = LibFile(v.string_value());
91     } else {
92       *out = LibFile(current_dir.ResolveRelativeFile(
93           v, err, build_settings->root_path_utf8()));
94     }
95     return !err->has_error();
96   }
97   const BuildSettings* build_settings;
98   const SourceDir& current_dir;
99 };
100 
101 struct RelativeDirConverter {
RelativeDirConverter__anonb8f867620111::RelativeDirConverter102   RelativeDirConverter(const BuildSettings* build_settings_in,
103                        const SourceDir& current_dir_in)
104       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonb8f867620111::RelativeDirConverter105   bool operator()(const Value& v, SourceDir* out, Err* err) const {
106     *out = current_dir.ResolveRelativeDir(v, err,
107                                           build_settings->root_path_utf8());
108     return true;
109   }
110   const BuildSettings* build_settings;
111   const SourceDir& current_dir;
112 };
113 
114 struct ExternConverter {
ExternConverter__anonb8f867620111::ExternConverter115   ExternConverter(const BuildSettings* build_settings_in,
116                   const SourceDir& current_dir_in)
117       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonb8f867620111::ExternConverter118   bool operator()(const Value& v,
119                   std::pair<std::string, LibFile>* out,
120                   Err* err) const {
121     if (!v.VerifyTypeIs(Value::SCOPE, err))
122       return false;
123     Scope::KeyValueMap scope;
124     v.scope_value()->GetCurrentScopeValues(&scope);
125     std::string cratename;
126     if (auto it = scope.find("crate_name"); it != scope.end()) {
127       if (!it->second.VerifyTypeIs(Value::STRING, err))
128         return false;
129       cratename = it->second.string_value();
130     } else {
131       return false;
132     }
133     LibFile path;
134     if (auto it = scope.find("path"); it != scope.end()) {
135       if (!it->second.VerifyTypeIs(Value::STRING, err))
136         return false;
137       if (it->second.string_value().find('/') == std::string::npos) {
138         path = LibFile(it->second.string_value());
139       } else {
140         path = LibFile(current_dir.ResolveRelativeFile(
141             it->second, err, build_settings->root_path_utf8()));
142       }
143     } else {
144       return false;
145     }
146     *out = std::pair(cratename, path);
147     return !err->has_error();
148   }
149   const BuildSettings* build_settings;
150   const SourceDir& current_dir;
151 };
152 
153 // Fills in a label.
154 template <typename T>
155 struct LabelResolver {
LabelResolver__anonb8f867620111::LabelResolver156   LabelResolver(const BuildSettings* build_settings_in,
157                 const SourceDir& current_dir_in,
158                 const Label& current_toolchain_in)
159       : build_settings(build_settings_in),
160         current_dir(current_dir_in),
161         current_toolchain(current_toolchain_in) {}
operator ()__anonb8f867620111::LabelResolver162   bool operator()(const Value& v, Label* out, Err* err) const {
163     if (!v.VerifyTypeIs(Value::STRING, err))
164       return false;
165     *out = Label::Resolve(current_dir, build_settings->root_path_utf8(),
166                           current_toolchain, v, err);
167     return !err->has_error();
168   }
169   const BuildSettings* build_settings;
170   const SourceDir& current_dir;
171   const Label& current_toolchain;
172 };
173 
174 // Fills the label part of a LabelPtrPair, leaving the pointer null.
175 template <typename T>
176 struct LabelPtrResolver {
LabelPtrResolver__anonb8f867620111::LabelPtrResolver177   LabelPtrResolver(const BuildSettings* build_settings_in,
178                    const SourceDir& current_dir_in,
179                    const Label& current_toolchain_in)
180       : build_settings(build_settings_in),
181         current_dir(current_dir_in),
182         current_toolchain(current_toolchain_in) {}
operator ()__anonb8f867620111::LabelPtrResolver183   bool operator()(const Value& v, LabelPtrPair<T>* out, Err* err) const {
184     if (!v.VerifyTypeIs(Value::STRING, err))
185       return false;
186     out->label = Label::Resolve(current_dir, build_settings->root_path_utf8(),
187                                 current_toolchain, v, err);
188     out->origin = v.origin();
189     return !err->has_error();
190   }
191   const BuildSettings* build_settings;
192   const SourceDir& current_dir;
193   const Label& current_toolchain;
194 };
195 
196 struct LabelPatternResolver {
LabelPatternResolver__anonb8f867620111::LabelPatternResolver197   LabelPatternResolver(const BuildSettings* build_settings_in,
198                        const SourceDir& current_dir_in)
199       : build_settings(build_settings_in), current_dir(current_dir_in) {}
operator ()__anonb8f867620111::LabelPatternResolver200   bool operator()(const Value& v, LabelPattern* out, Err* err) const {
201     *out = LabelPattern::GetPattern(current_dir,
202                                     build_settings->root_path_utf8(), v, err);
203     return !err->has_error();
204   }
205 
206   const BuildSettings* build_settings;
207   const SourceDir& current_dir;
208 };
209 
210 }  // namespace
211 
ExtractListOfStringValues(const Value & value,std::vector<std::string> * dest,Err * err)212 bool ExtractListOfStringValues(const Value& value,
213                                std::vector<std::string>* dest,
214                                Err* err) {
215   if (!value.VerifyTypeIs(Value::LIST, err))
216     return false;
217   const std::vector<Value>& input_list = value.list_value();
218   dest->reserve(input_list.size());
219   for (const auto& item : input_list) {
220     if (!item.VerifyTypeIs(Value::STRING, err))
221       return false;
222     dest->push_back(item.string_value());
223   }
224   return true;
225 }
226 
ExtractListOfRelativeFiles(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<SourceFile> * files,Err * err)227 bool ExtractListOfRelativeFiles(const BuildSettings* build_settings,
228                                 const Value& value,
229                                 const SourceDir& current_dir,
230                                 std::vector<SourceFile>* files,
231                                 Err* err) {
232   return ListValueExtractor(value, files, err,
233                             RelativeFileConverter(build_settings, current_dir));
234 }
235 
ExtractListOfLibs(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<LibFile> * libs,Err * err)236 bool ExtractListOfLibs(const BuildSettings* build_settings,
237                        const Value& value,
238                        const SourceDir& current_dir,
239                        std::vector<LibFile>* libs,
240                        Err* err) {
241   return ListValueExtractor(value, libs, err,
242                             LibFileConverter(build_settings, current_dir));
243 }
244 
ExtractListOfRelativeDirs(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<SourceDir> * dest,Err * err)245 bool ExtractListOfRelativeDirs(const BuildSettings* build_settings,
246                                const Value& value,
247                                const SourceDir& current_dir,
248                                std::vector<SourceDir>* dest,
249                                Err* err) {
250   return ListValueExtractor(value, dest, err,
251                             RelativeDirConverter(build_settings, current_dir));
252 }
253 
ExtractListOfLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,LabelTargetVector * dest,Err * err)254 bool ExtractListOfLabels(const BuildSettings* build_settings,
255                          const Value& value,
256                          const SourceDir& current_dir,
257                          const Label& current_toolchain,
258                          LabelTargetVector* dest,
259                          Err* err) {
260   return ListValueExtractor(
261       value, dest, err,
262       LabelPtrResolver<Target>(build_settings, current_dir, current_toolchain));
263 }
264 
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<Label> * dest,Err * err)265 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
266                                const Value& value,
267                                const SourceDir& current_dir,
268                                const Label& current_toolchain,
269                                UniqueVector<Label>* dest,
270                                Err* err) {
271   return ListValueUniqueExtractor(
272       value, dest, err,
273       LabelResolver<Config>(build_settings, current_dir, current_toolchain));
274 }
275 
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<LabelConfigPair> * dest,Err * err)276 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
277                                const Value& value,
278                                const SourceDir& current_dir,
279                                const Label& current_toolchain,
280                                UniqueVector<LabelConfigPair>* dest,
281                                Err* err) {
282   return ListValueUniqueExtractor(
283       value, dest, err,
284       LabelPtrResolver<Config>(build_settings, current_dir, current_toolchain));
285 }
286 
ExtractListOfUniqueLabels(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,const Label & current_toolchain,UniqueVector<LabelTargetPair> * dest,Err * err)287 bool ExtractListOfUniqueLabels(const BuildSettings* build_settings,
288                                const Value& value,
289                                const SourceDir& current_dir,
290                                const Label& current_toolchain,
291                                UniqueVector<LabelTargetPair>* dest,
292                                Err* err) {
293   return ListValueUniqueExtractor(
294       value, dest, err,
295       LabelPtrResolver<Target>(build_settings, current_dir, current_toolchain));
296 }
297 
ExtractRelativeFile(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,SourceFile * file,Err * err)298 bool ExtractRelativeFile(const BuildSettings* build_settings,
299                          const Value& value,
300                          const SourceDir& current_dir,
301                          SourceFile* file,
302                          Err* err) {
303   RelativeFileConverter converter(build_settings, current_dir);
304   return converter(value, file, err);
305 }
306 
ExtractListOfLabelPatterns(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<LabelPattern> * patterns,Err * err)307 bool ExtractListOfLabelPatterns(const BuildSettings* build_settings,
308                                 const Value& value,
309                                 const SourceDir& current_dir,
310                                 std::vector<LabelPattern>* patterns,
311                                 Err* err) {
312   return ListValueExtractor(value, patterns, err,
313                             LabelPatternResolver(build_settings, current_dir));
314 }
315 
ExtractListOfExterns(const BuildSettings * build_settings,const Value & value,const SourceDir & current_dir,std::vector<std::pair<std::string,LibFile>> * externs,Err * err)316 bool ExtractListOfExterns(const BuildSettings* build_settings,
317                           const Value& value,
318                           const SourceDir& current_dir,
319                           std::vector<std::pair<std::string, LibFile>>* externs,
320                           Err* err) {
321   return ListValueExtractor(value, externs, err,
322                             ExternConverter(build_settings, current_dir));
323 }
324