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 "tools/gn/value_extractors.h" 6 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" 14 15 namespace { 16 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; 30 } 31 return true; 32 } 33 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(); 44 45 for (size_t i = 0; i < input_list.size(); i++) { 46 T new_one; 47 if (!converter(input_list[i], &new_one, err)) 48 return false; 49 if (!dest->push_back(new_one)) { 50 // Already in the list, throw error. 51 *err = Err(input_list[i], "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; 56 } 57 } 58 return true; 59 } 60 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) { 68 } 69 bool operator()(const Value& v, SourceFile* out, Err* err) const { 70 if (!v.VerifyTypeIs(Value::STRING, err)) 71 return false; 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?"); 79 return false; 80 } 81 return true; 82 } 83 const BuildSettings* build_settings; 84 const SourceDir& current_dir; 85 }; 86 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) { 92 } 93 bool operator()(const Value& v, SourceDir* out, Err* err) const { 94 if (!v.VerifyTypeIs(Value::STRING, err)) 95 return false; 96 *out = current_dir.ResolveRelativeDir(v.string_value(), 97 build_settings->root_path_utf8()); 98 return true; 99 } 100 const BuildSettings* build_settings; 101 const SourceDir& current_dir; 102 }; 103 104 // Fills in a label. 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)) 112 return false; 113 *out = Label::Resolve(current_dir, current_toolchain, v, err); 114 return !err->has_error(); 115 } 116 const SourceDir& current_dir; 117 const Label& current_toolchain; 118 }; 119 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)) 128 return false; 129 out->label = Label::Resolve(current_dir, current_toolchain, v, err); 130 out->origin = v.origin(); 131 return !err->has_error(); 132 } 133 const SourceDir& current_dir; 134 const Label& current_toolchain; 135 }; 136 137 } // namespace 138 139 bool ExtractListOfStringValues(const Value& value, 140 std::vector<std::string>* dest, 141 Err* err) { 142 if (!value.VerifyTypeIs(Value::LIST, err)) 143 return false; 144 const std::vector<Value>& input_list = value.list_value(); 145 dest->reserve(input_list.size()); 146 for (size_t i = 0; i < input_list.size(); i++) { 147 if (!input_list[i].VerifyTypeIs(Value::STRING, err)) 148 return false; 149 dest->push_back(input_list[i].string_value()); 150 } 151 return true; 152 } 153 154 bool ExtractListOfRelativeFiles(const BuildSettings* build_settings, 155 const Value& value, 156 const SourceDir& current_dir, 157 std::vector<SourceFile>* files, 158 Err* err) { 159 return ListValueExtractor(value, files, err, 160 RelativeFileConverter(build_settings, current_dir)); 161 } 162 163 bool ExtractListOfRelativeDirs(const BuildSettings* build_settings, 164 const Value& value, 165 const SourceDir& current_dir, 166 std::vector<SourceDir>* dest, 167 Err* err) { 168 return ListValueExtractor(value, dest, err, 169 RelativeDirConverter(build_settings, current_dir)); 170 } 171 172 bool ExtractListOfLabels(const Value& value, 173 const SourceDir& current_dir, 174 const Label& current_toolchain, 175 LabelTargetVector* dest, 176 Err* err) { 177 return ListValueExtractor(value, dest, err, 178 LabelPtrResolver<Target>(current_dir, 179 current_toolchain)); 180 } 181 182 bool ExtractListOfUniqueLabels(const Value& value, 183 const SourceDir& current_dir, 184 const Label& current_toolchain, 185 UniqueVector<Label>* dest, 186 Err* err) { 187 return ListValueUniqueExtractor(value, dest, err, 188 LabelResolver<Config>(current_dir, 189 current_toolchain)); 190 } 191 192 bool ExtractListOfUniqueLabels(const Value& value, 193 const SourceDir& current_dir, 194 const Label& current_toolchain, 195 UniqueVector<LabelConfigPair>* dest, 196 Err* err) { 197 return ListValueUniqueExtractor(value, dest, err, 198 LabelPtrResolver<Config>(current_dir, 199 current_toolchain)); 200 } 201 202 bool ExtractListOfUniqueLabels(const Value& value, 203 const SourceDir& current_dir, 204 const Label& current_toolchain, 205 UniqueVector<LabelTargetPair>* dest, 206 Err* err) { 207 return ListValueUniqueExtractor(value, dest, err, 208 LabelPtrResolver<Target>(current_dir, 209 current_toolchain)); 210 } 211 212 bool ExtractRelativeFile(const BuildSettings* build_settings, 213 const Value& value, 214 const SourceDir& current_dir, 215 SourceFile* file, 216 Err* err) { 217 RelativeFileConverter converter(build_settings, current_dir); 218 return converter(value, file, err); 219 } 220