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 *out
= current_dir
.ResolveRelativeFile(v
, err
,
69 build_settings
->root_path_utf8());
70 return !err
->has_error();
72 const BuildSettings
* build_settings
;
73 const SourceDir
& current_dir
;
76 struct RelativeDirConverter
{
77 RelativeDirConverter(const BuildSettings
* build_settings_in
,
78 const SourceDir
& current_dir_in
)
79 : build_settings(build_settings_in
),
80 current_dir(current_dir_in
) {
82 bool operator()(const Value
& v
, SourceDir
* out
, Err
* err
) const {
83 *out
= current_dir
.ResolveRelativeDir(v
, err
,
84 build_settings
->root_path_utf8());
87 const BuildSettings
* build_settings
;
88 const SourceDir
& current_dir
;
92 template<typename T
> struct LabelResolver
{
93 LabelResolver(const SourceDir
& current_dir_in
,
94 const Label
& current_toolchain_in
)
95 : current_dir(current_dir_in
),
96 current_toolchain(current_toolchain_in
) {}
97 bool operator()(const Value
& v
, Label
* out
, Err
* err
) const {
98 if (!v
.VerifyTypeIs(Value::STRING
, err
))
100 *out
= Label::Resolve(current_dir
, current_toolchain
, v
, err
);
101 return !err
->has_error();
103 const SourceDir
& current_dir
;
104 const Label
& current_toolchain
;
107 // Fills the label part of a LabelPtrPair, leaving the pointer null.
108 template<typename T
> struct LabelPtrResolver
{
109 LabelPtrResolver(const SourceDir
& current_dir_in
,
110 const Label
& current_toolchain_in
)
111 : current_dir(current_dir_in
),
112 current_toolchain(current_toolchain_in
) {}
113 bool operator()(const Value
& v
, LabelPtrPair
<T
>* out
, Err
* err
) const {
114 if (!v
.VerifyTypeIs(Value::STRING
, err
))
116 out
->label
= Label::Resolve(current_dir
, current_toolchain
, v
, err
);
117 out
->origin
= v
.origin();
118 return !err
->has_error();
120 const SourceDir
& current_dir
;
121 const Label
& current_toolchain
;
126 bool ExtractListOfStringValues(const Value
& value
,
127 std::vector
<std::string
>* dest
,
129 if (!value
.VerifyTypeIs(Value::LIST
, err
))
131 const std::vector
<Value
>& input_list
= value
.list_value();
132 dest
->reserve(input_list
.size());
133 for (const auto& item
: input_list
) {
134 if (!item
.VerifyTypeIs(Value::STRING
, err
))
136 dest
->push_back(item
.string_value());
141 bool ExtractListOfRelativeFiles(const BuildSettings
* build_settings
,
143 const SourceDir
& current_dir
,
144 std::vector
<SourceFile
>* files
,
146 return ListValueExtractor(value
, files
, err
,
147 RelativeFileConverter(build_settings
, current_dir
));
150 bool ExtractListOfRelativeDirs(const BuildSettings
* build_settings
,
152 const SourceDir
& current_dir
,
153 std::vector
<SourceDir
>* dest
,
155 return ListValueExtractor(value
, dest
, err
,
156 RelativeDirConverter(build_settings
, current_dir
));
159 bool ExtractListOfLabels(const Value
& value
,
160 const SourceDir
& current_dir
,
161 const Label
& current_toolchain
,
162 LabelTargetVector
* dest
,
164 return ListValueExtractor(value
, dest
, err
,
165 LabelPtrResolver
<Target
>(current_dir
,
169 bool ExtractListOfUniqueLabels(const Value
& value
,
170 const SourceDir
& current_dir
,
171 const Label
& current_toolchain
,
172 UniqueVector
<Label
>* dest
,
174 return ListValueUniqueExtractor(value
, dest
, err
,
175 LabelResolver
<Config
>(current_dir
,
179 bool ExtractListOfUniqueLabels(const Value
& value
,
180 const SourceDir
& current_dir
,
181 const Label
& current_toolchain
,
182 UniqueVector
<LabelConfigPair
>* dest
,
184 return ListValueUniqueExtractor(value
, dest
, err
,
185 LabelPtrResolver
<Config
>(current_dir
,
189 bool ExtractListOfUniqueLabels(const Value
& value
,
190 const SourceDir
& current_dir
,
191 const Label
& current_toolchain
,
192 UniqueVector
<LabelTargetPair
>* dest
,
194 return ListValueUniqueExtractor(value
, dest
, err
,
195 LabelPtrResolver
<Target
>(current_dir
,
199 bool ExtractRelativeFile(const BuildSettings
* build_settings
,
201 const SourceDir
& current_dir
,
204 RelativeFileConverter
converter(build_settings
, current_dir
);
205 return converter(value
, file
, err
);