1 // Copyright 2014 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 <stddef.h>
6
7 #include "gn/err.h"
8 #include "gn/filesystem_utils.h"
9 #include "gn/functions.h"
10 #include "gn/parse_tree.h"
11 #include "gn/scope.h"
12 #include "gn/value.h"
13
14 namespace functions {
15
16 const char kFilterExclude[] = "filter_exclude";
17 const char kFilterExclude_HelpShort[] =
18 "filter_exclude: Remove values that match a set of patterns.";
19 const char kFilterExclude_Help[] =
20 R"(filter_exclude: Remove values that match a set of patterns.
21
22 filter_exclude(values, exclude_patterns)
23
24 The argument values must be a list of strings.
25
26 The argument exclude_patterns must be a list of file patterns (see
27 "gn help file_pattern"). Any elements in values matching at least one
28 of those patterns will be excluded.
29
30 Examples
31 values = [ "foo.cc", "foo.h", "foo.proto" ]
32 result = filter_exclude(values, [ "*.proto" ])
33 # result will be [ "foo.cc", "foo.h" ]
34 )";
35
36 const char kFilterInclude[] = "filter_include";
37 const char kFilterInclude_HelpShort[] =
38 "filter_include: Remove values that do not match a set of patterns.";
39 const char kFilterInclude_Help[] =
40 R"(filter_include: Remove values that do not match a set of patterns.
41
42 filter_include(values, include_patterns)
43
44 The argument values must be a list of strings.
45
46 The argument include_patterns must be a list of file patterns (see
47 "gn help file_pattern"). Only elements from values matching at least
48 one of the pattern will be included.
49
50 Examples
51 values = [ "foo.cc", "foo.h", "foo.proto" ]
52 result = filter_include(values, [ "*.proto" ])
53 # result will be [ "foo.proto" ]
54 )";
55
56 namespace {
57
58 enum FilterSelection {
59 kExcludeFilter,
60 kIncludeFilter,
61 };
62
RunFilter(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,FilterSelection selection,Err * err)63 Value RunFilter(Scope* scope,
64 const FunctionCallNode* function,
65 const std::vector<Value>& args,
66 FilterSelection selection,
67 Err* err) {
68 if (args.size() != 2) {
69 *err = Err(function, "Expecting exactly two arguments.");
70 return Value();
71 }
72
73 // Extract "values".
74 if (args[0].type() != Value::LIST) {
75 *err = Err(args[0], "First argument must be a list of strings.");
76 return Value();
77 }
78
79 // Extract "patterns".
80 PatternList patterns;
81 patterns.SetFromValue(args[1], err);
82 if (err->has_error())
83 return Value();
84
85 Value result(function, Value::LIST);
86 for (const auto& value : args[0].list_value()) {
87 if (value.type() != Value::STRING) {
88 *err = Err(args[0], "First argument must be a list of strings.");
89 return Value();
90 }
91
92 const bool matches_pattern = patterns.MatchesValue(value);
93 switch (selection) {
94 case kIncludeFilter:
95 if (matches_pattern)
96 result.list_value().push_back(value);
97 break;
98
99 case kExcludeFilter:
100 if (!matches_pattern)
101 result.list_value().push_back(value);
102 break;
103 }
104 }
105 return result;
106 }
107
108 } // anonymous namespace
109
RunFilterExclude(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,Err * err)110 Value RunFilterExclude(Scope* scope,
111 const FunctionCallNode* function,
112 const std::vector<Value>& args,
113 Err* err) {
114 return RunFilter(scope, function, args, kExcludeFilter, err);
115 }
116
RunFilterInclude(Scope * scope,const FunctionCallNode * function,const std::vector<Value> & args,Err * err)117 Value RunFilterInclude(Scope* scope,
118 const FunctionCallNode* function,
119 const std::vector<Value>& args,
120 Err* err) {
121 return RunFilter(scope, function, args, kIncludeFilter, err);
122 }
123
124 } // namespace functions
125