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 struct RelativeFileConverter
{
62 RelativeFileConverter(const BuildSettings
* build_settings_in
,
63 const SourceDir
& current_dir_in
)
64 : build_settings(build_settings_in
),
65 current_dir(current_dir_in
) {
67 bool operator()(const Value
& v
, SourceFile
* out
, Err
* err
) const {
68 if (!v
.VerifyTypeIs(Value::STRING
, err
))
70 *out
= current_dir
.ResolveRelativeFile(v
.string_value(),
71 build_settings
->root_path_utf8());
74 const BuildSettings
* build_settings
;
75 const SourceDir
& current_dir
;
78 struct RelativeDirConverter
{
79 RelativeDirConverter(const BuildSettings
* build_settings_in
,
80 const SourceDir
& current_dir_in
)
81 : build_settings(build_settings_in
),
82 current_dir(current_dir_in
) {
84 bool operator()(const Value
& v
, SourceDir
* out
, Err
* err
) const {
85 if (!v
.VerifyTypeIs(Value::STRING
, err
))
87 *out
= current_dir
.ResolveRelativeDir(v
.string_value(),
88 build_settings
->root_path_utf8());
91 const BuildSettings
* build_settings
;
92 const SourceDir
& current_dir
;
96 template<typename T
> struct LabelResolver
{
97 LabelResolver(const SourceDir
& current_dir_in
,
98 const Label
& current_toolchain_in
)
99 : current_dir(current_dir_in
),
100 current_toolchain(current_toolchain_in
) {}
101 bool operator()(const Value
& v
, Label
* out
, Err
* err
) const {
102 if (!v
.VerifyTypeIs(Value::STRING
, err
))
104 *out
= Label::Resolve(current_dir
, current_toolchain
, v
, err
);
105 return !err
->has_error();
107 const SourceDir
& current_dir
;
108 const Label
& current_toolchain
;
111 // Fills the label part of a LabelPtrPair, leaving the pointer null.
112 template<typename T
> struct LabelPtrResolver
{
113 LabelPtrResolver(const SourceDir
& current_dir_in
,
114 const Label
& current_toolchain_in
)
115 : current_dir(current_dir_in
),
116 current_toolchain(current_toolchain_in
) {}
117 bool operator()(const Value
& v
, LabelPtrPair
<T
>* out
, Err
* err
) const {
118 if (!v
.VerifyTypeIs(Value::STRING
, err
))
120 out
->label
= Label::Resolve(current_dir
, current_toolchain
, v
, err
);
121 out
->origin
= v
.origin();
122 return !err
->has_error();
124 const SourceDir
& current_dir
;
125 const Label
& current_toolchain
;
130 bool ExtractListOfStringValues(const Value
& value
,
131 std::vector
<std::string
>* dest
,
133 if (!value
.VerifyTypeIs(Value::LIST
, err
))
135 const std::vector
<Value
>& input_list
= value
.list_value();
136 dest
->reserve(input_list
.size());
137 for (const auto& item
: input_list
) {
138 if (!item
.VerifyTypeIs(Value::STRING
, err
))
140 dest
->push_back(item
.string_value());
145 bool ExtractListOfRelativeFiles(const BuildSettings
* build_settings
,
147 const SourceDir
& current_dir
,
148 std::vector
<SourceFile
>* files
,
150 return ListValueExtractor(value
, files
, err
,
151 RelativeFileConverter(build_settings
, current_dir
));
154 bool ExtractListOfRelativeDirs(const BuildSettings
* build_settings
,
156 const SourceDir
& current_dir
,
157 std::vector
<SourceDir
>* dest
,
159 return ListValueExtractor(value
, dest
, err
,
160 RelativeDirConverter(build_settings
, current_dir
));
163 bool ExtractListOfLabels(const Value
& value
,
164 const SourceDir
& current_dir
,
165 const Label
& current_toolchain
,
166 LabelTargetVector
* dest
,
168 return ListValueExtractor(value
, dest
, err
,
169 LabelPtrResolver
<Target
>(current_dir
,
173 bool ExtractListOfUniqueLabels(const Value
& value
,
174 const SourceDir
& current_dir
,
175 const Label
& current_toolchain
,
176 UniqueVector
<Label
>* dest
,
178 return ListValueUniqueExtractor(value
, dest
, err
,
179 LabelResolver
<Config
>(current_dir
,
183 bool ExtractListOfUniqueLabels(const Value
& value
,
184 const SourceDir
& current_dir
,
185 const Label
& current_toolchain
,
186 UniqueVector
<LabelConfigPair
>* dest
,
188 return ListValueUniqueExtractor(value
, dest
, err
,
189 LabelPtrResolver
<Config
>(current_dir
,
193 bool ExtractListOfUniqueLabels(const Value
& value
,
194 const SourceDir
& current_dir
,
195 const Label
& current_toolchain
,
196 UniqueVector
<LabelTargetPair
>* dest
,
198 return ListValueUniqueExtractor(value
, dest
, err
,
199 LabelPtrResolver
<Target
>(current_dir
,
203 bool ExtractRelativeFile(const BuildSettings
* build_settings
,
205 const SourceDir
& current_dir
,
208 RelativeFileConverter
converter(build_settings
, current_dir
);
209 return converter(value
, file
, err
);