Index: tools/gn/value_extractors.cc |
diff --git a/tools/gn/value_extractors.cc b/tools/gn/value_extractors.cc |
index 372156eadbdc16932d86e3c62865f7a2c1bfbbe6..7927b83dfed63d8e8a909e354ca3d3576a0d6e23 100644 |
--- a/tools/gn/value_extractors.cc |
+++ b/tools/gn/value_extractors.cc |
@@ -9,9 +9,55 @@ |
#include "tools/gn/label.h" |
#include "tools/gn/source_dir.h" |
#include "tools/gn/source_file.h" |
+#include "tools/gn/target.h" |
+#include "tools/gn/value.h" |
namespace { |
+// Sets the error and returns false on failure. |
+template<typename T, class Converter> |
+bool ListValueExtractor(const Value& value, |
+ std::vector<T>* dest, |
+ Err* err, |
+ const Converter& converter) { |
+ if (!value.VerifyTypeIs(Value::LIST, err)) |
+ return false; |
+ const std::vector<Value>& input_list = value.list_value(); |
+ dest->resize(input_list.size()); |
+ for (size_t i = 0; i < input_list.size(); i++) { |
+ if (!converter(input_list[i], &(*dest)[i], err)) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+// Like the above version but extracts to a UniqueVector and sets the error if |
+// there are duplicates. |
+template<typename T, class Converter> |
+bool ListValueUniqueExtractor(const Value& value, |
+ UniqueVector<T>* dest, |
+ Err* err, |
+ const Converter& converter) { |
+ if (!value.VerifyTypeIs(Value::LIST, err)) |
+ return false; |
+ const std::vector<Value>& input_list = value.list_value(); |
+ |
+ for (size_t i = 0; i < input_list.size(); i++) { |
+ T new_one; |
+ if (!converter(input_list[i], &new_one, err)) |
+ return false; |
+ if (!dest->push_back(new_one)) { |
+ // Already in the list, throw error. |
+ *err = Err(input_list[i], "Duplicate item in list"); |
+ size_t previous_index = dest->IndexOf(new_one); |
+ err->AppendSubErr(Err(input_list[previous_index], |
+ "This was the previous definition.")); |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
// This extractor rejects files with system-absolute file paths. If we need |
// that in the future, we'll have to add some flag to control this. |
struct RelativeFileConverter { |
@@ -110,16 +156,6 @@ bool ExtractListOfRelativeDirs(const BuildSettings* build_settings, |
bool ExtractListOfLabels(const Value& value, |
const SourceDir& current_dir, |
const Label& current_toolchain, |
- LabelConfigVector* dest, |
- Err* err) { |
- return ListValueExtractor(value, dest, err, |
- LabelResolver<Config>(current_dir, |
- current_toolchain)); |
-} |
- |
-bool ExtractListOfLabels(const Value& value, |
- const SourceDir& current_dir, |
- const Label& current_toolchain, |
LabelTargetVector* dest, |
Err* err) { |
return ListValueExtractor(value, dest, err, |
@@ -127,6 +163,26 @@ bool ExtractListOfLabels(const Value& value, |
current_toolchain)); |
} |
+bool ExtractListOfUniqueLabels(const Value& value, |
+ const SourceDir& current_dir, |
+ const Label& current_toolchain, |
+ UniqueVector<LabelConfigPair>* dest, |
+ Err* err) { |
+ return ListValueUniqueExtractor(value, dest, err, |
+ LabelResolver<Config>(current_dir, |
+ current_toolchain)); |
+} |
+ |
+bool ExtractListOfUniqueLabels(const Value& value, |
+ const SourceDir& current_dir, |
+ const Label& current_toolchain, |
+ UniqueVector<LabelTargetPair>* dest, |
+ Err* err) { |
+ return ListValueUniqueExtractor(value, dest, err, |
+ LabelResolver<Target>(current_dir, |
+ current_toolchain)); |
+} |
+ |
bool ExtractRelativeFile(const BuildSettings* build_settings, |
const Value& value, |
const SourceDir& current_dir, |