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.
5 #include "tools/gn/value_extractors.h"
7 #include "tools/gn/build_settings.h"
8 #include "tools/gn/err.h"
9 #include "tools/gn/label.h"
10 #include "tools/gn/source_dir.h"
11 #include "tools/gn/source_file.h"
12 #include "tools/gn/target.h"
13 #include "tools/gn/value.h"
17 // Sets the error and returns false on failure.
18 template<typename T
, class Converter
>
19 bool ListValueExtractor(const Value
& value
,
22 const Converter
& converter
) {
23 if (!value
.VerifyTypeIs(Value::LIST
, err
))
25 const std::vector
<Value
>& input_list
= value
.list_value();
26 dest
->resize(input_list
.size());
27 for (size_t i
= 0; i
< input_list
.size(); i
++) {
28 if (!converter(input_list
[i
], &(*dest
)[i
], err
))
34 // Like the above version but extracts to a UniqueVector and sets the error if
35 // there are duplicates.
36 template<typename T
, class Converter
>
37 bool ListValueUniqueExtractor(const Value
& value
,
38 UniqueVector
<T
>* dest
,
40 const Converter
& converter
) {
41 if (!value
.VerifyTypeIs(Value::LIST
, err
))
43 const std::vector
<Value
>& input_list
= value
.list_value();
45 for (const auto& item
: input_list
) {
47 if (!converter(item
, &new_one
, err
))
49 if (!dest
->push_back(new_one
)) {
50 // Already in the list, throw error.
51 *err
= Err(item
, "Duplicate item in list");
52 size_t previous_index
= dest
->IndexOf(new_one
);
53 err
->AppendSubErr(Err(input_list
[previous_index
],
54 "This was the previous definition."));
61 // This extractor rejects files with system-absolute file paths. If we need
62 // that in the future, we'll have to add some flag to control this.
63 struct RelativeFileConverter
{
64 RelativeFileConverter(const BuildSettings
* build_settings_in
,
65 const SourceDir
& current_dir_in
)
66 : build_settings(build_settings_in
),
67 current_dir(current_dir_in
) {
69 bool operator()(const Value
& v
, SourceFile
* out
, Err
* err
) const {
70 if (!v
.VerifyTypeIs(Value::STRING
, err
))
72 *out
= current_dir
.ResolveRelativeFile(v
.string_value(),
73 build_settings
->root_path_utf8());
74 if (out
->is_system_absolute()) {
75 *err
= Err(v
, "System-absolute file path.",
76 "You can't list a system-absolute file path here. Please include "
77 "only files in\nthe source tree. Maybe you meant to begin with two "
78 "slashes to indicate an\nabsolute path in the source tree?");
83 const BuildSettings
* build_settings
;
84 const SourceDir
& current_dir
;
87 struct RelativeDirConverter
{
88 RelativeDirConverter(const BuildSettings
* build_settings_in
,
89 const SourceDir
& current_dir_in
)
90 : build_settings(build_settings_in
),
91 current_dir(current_dir_in
) {
93 bool operator()(const Value
& v
, SourceDir
* out
, Err
* err
) const {
94 if (!v
.VerifyTypeIs(Value::STRING
, err
))
96 *out
= current_dir
.ResolveRelativeDir(v
.string_value(),
97 build_settings
->root_path_utf8());
100 const BuildSettings
* build_settings
;
101 const SourceDir
& current_dir
;
105 template<typename T
> struct LabelResolver
{
106 LabelResolver(const SourceDir
& current_dir_in
,
107 const Label
& current_toolchain_in
)
108 : current_dir(current_dir_in
),
109 current_toolchain(current_toolchain_in
) {}
110 bool operator()(const Value
& v
, Label
* out
, Err
* err
) const {
111 if (!v
.VerifyTypeIs(Value::STRING
, err
))
113 *out
= Label::Resolve(current_dir
, current_toolchain
, v
, err
);
114 return !err
->has_error();
116 const SourceDir
& current_dir
;
117 const Label
& current_toolchain
;
120 // Fills the label part of a LabelPtrPair, leaving the pointer null.
121 template<typename T
> struct LabelPtrResolver
{
122 LabelPtrResolver(const SourceDir
& current_dir_in
,
123 const Label
& current_toolchain_in
)
124 : current_dir(current_dir_in
),
125 current_toolchain(current_toolchain_in
) {}
126 bool operator()(const Value
& v
, LabelPtrPair
<T
>* out
, Err
* err
) const {
127 if (!v
.VerifyTypeIs(Value::STRING
, err
))
129 out
->label
= Label::Resolve(current_dir
, current_toolchain
, v
, err
);
130 out
->origin
= v
.origin();
131 return !err
->has_error();
133 const SourceDir
& current_dir
;
134 const Label
& current_toolchain
;
139 bool ExtractListOfStringValues(const Value
& value
,
140 std::vector
<std::string
>* dest
,
142 if (!value
.VerifyTypeIs(Value::LIST
, err
))
144 const std::vector
<Value
>& input_list
= value
.list_value();
145 dest
->reserve(input_list
.size());
146 for (const auto& item
: input_list
) {
147 if (!item
.VerifyTypeIs(Value::STRING
, err
))
149 dest
->push_back(item
.string_value());
154 bool ExtractListOfRelativeFiles(const BuildSettings
* build_settings
,
156 const SourceDir
& current_dir
,
157 std::vector
<SourceFile
>* files
,
159 return ListValueExtractor(value
, files
, err
,
160 RelativeFileConverter(build_settings
, current_dir
));
163 bool ExtractListOfRelativeDirs(const BuildSettings
* build_settings
,
165 const SourceDir
& current_dir
,
166 std::vector
<SourceDir
>* dest
,
168 return ListValueExtractor(value
, dest
, err
,
169 RelativeDirConverter(build_settings
, current_dir
));
172 bool ExtractListOfLabels(const Value
& value
,
173 const SourceDir
& current_dir
,
174 const Label
& current_toolchain
,
175 LabelTargetVector
* dest
,
177 return ListValueExtractor(value
, dest
, err
,
178 LabelPtrResolver
<Target
>(current_dir
,
182 bool ExtractListOfUniqueLabels(const Value
& value
,
183 const SourceDir
& current_dir
,
184 const Label
& current_toolchain
,
185 UniqueVector
<Label
>* dest
,
187 return ListValueUniqueExtractor(value
, dest
, err
,
188 LabelResolver
<Config
>(current_dir
,
192 bool ExtractListOfUniqueLabels(const Value
& value
,
193 const SourceDir
& current_dir
,
194 const Label
& current_toolchain
,
195 UniqueVector
<LabelConfigPair
>* dest
,
197 return ListValueUniqueExtractor(value
, dest
, err
,
198 LabelPtrResolver
<Config
>(current_dir
,
202 bool ExtractListOfUniqueLabels(const Value
& value
,
203 const SourceDir
& current_dir
,
204 const Label
& current_toolchain
,
205 UniqueVector
<LabelTargetPair
>* dest
,
207 return ListValueUniqueExtractor(value
, dest
, err
,
208 LabelPtrResolver
<Target
>(current_dir
,
212 bool ExtractRelativeFile(const BuildSettings
* build_settings
,
214 const SourceDir
& current_dir
,
217 RelativeFileConverter
converter(build_settings
, current_dir
);
218 return converter(value
, file
, err
);