Add ICU message format support
[chromium-blink-merge.git] / tools / gn / value_extractors.cc
blob365c5342779c841b79e34337ff6cc4a93c7a1add
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"
15 namespace {
17 // Sets the error and returns false on failure.
18 template<typename T, class Converter>
19 bool ListValueExtractor(const Value& value,
20 std::vector<T>* dest,
21 Err* err,
22 const Converter& converter) {
23 if (!value.VerifyTypeIs(Value::LIST, err))
24 return false;
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))
29 return false;
31 return true;
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,
39 Err* err,
40 const Converter& converter) {
41 if (!value.VerifyTypeIs(Value::LIST, err))
42 return false;
43 const std::vector<Value>& input_list = value.list_value();
45 for (const auto& item : input_list) {
46 T new_one;
47 if (!converter(item, &new_one, err))
48 return false;
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."));
55 return false;
58 return true;
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());
85 return true;
87 const BuildSettings* build_settings;
88 const SourceDir& current_dir;
91 // Fills in a label.
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))
99 return false;
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))
115 return false;
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;
124 } // namespace
126 bool ExtractListOfStringValues(const Value& value,
127 std::vector<std::string>* dest,
128 Err* err) {
129 if (!value.VerifyTypeIs(Value::LIST, err))
130 return false;
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))
135 return false;
136 dest->push_back(item.string_value());
138 return true;
141 bool ExtractListOfRelativeFiles(const BuildSettings* build_settings,
142 const Value& value,
143 const SourceDir& current_dir,
144 std::vector<SourceFile>* files,
145 Err* err) {
146 return ListValueExtractor(value, files, err,
147 RelativeFileConverter(build_settings, current_dir));
150 bool ExtractListOfRelativeDirs(const BuildSettings* build_settings,
151 const Value& value,
152 const SourceDir& current_dir,
153 std::vector<SourceDir>* dest,
154 Err* err) {
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,
163 Err* err) {
164 return ListValueExtractor(value, dest, err,
165 LabelPtrResolver<Target>(current_dir,
166 current_toolchain));
169 bool ExtractListOfUniqueLabels(const Value& value,
170 const SourceDir& current_dir,
171 const Label& current_toolchain,
172 UniqueVector<Label>* dest,
173 Err* err) {
174 return ListValueUniqueExtractor(value, dest, err,
175 LabelResolver<Config>(current_dir,
176 current_toolchain));
179 bool ExtractListOfUniqueLabels(const Value& value,
180 const SourceDir& current_dir,
181 const Label& current_toolchain,
182 UniqueVector<LabelConfigPair>* dest,
183 Err* err) {
184 return ListValueUniqueExtractor(value, dest, err,
185 LabelPtrResolver<Config>(current_dir,
186 current_toolchain));
189 bool ExtractListOfUniqueLabels(const Value& value,
190 const SourceDir& current_dir,
191 const Label& current_toolchain,
192 UniqueVector<LabelTargetPair>* dest,
193 Err* err) {
194 return ListValueUniqueExtractor(value, dest, err,
195 LabelPtrResolver<Target>(current_dir,
196 current_toolchain));
199 bool ExtractRelativeFile(const BuildSettings* build_settings,
200 const Value& value,
201 const SourceDir& current_dir,
202 SourceFile* file,
203 Err* err) {
204 RelativeFileConverter converter(build_settings, current_dir);
205 return converter(value, file, err);