File src/ItemFilter.cpp changed (mode: 100644) (index 46c3eff..56abf20) |
... |
... |
ItemFilter::~ItemFilter() |
53 |
53 |
bool |
bool |
54 |
54 |
ItemFilter::passes(Item &item) const |
ItemFilter::passes(Item &item) const |
55 |
55 |
{ |
{ |
56 |
|
return passes([&item](const std::string &f) { return item.getValue(f); }); |
|
|
56 |
|
return passes([&item](const std::string &f) { |
|
57 |
|
return std::vector<std::string>{ item.getValue(f) }; |
|
58 |
|
}); |
57 |
59 |
} |
} |
58 |
60 |
|
|
59 |
61 |
bool |
bool |
60 |
|
ItemFilter::passes(std::function<std::string(const std::string &)> accessor) |
|
61 |
|
const |
|
|
62 |
|
ItemFilter::passes(std::function<accessor_f> accessor) const |
62 |
63 |
{ |
{ |
63 |
64 |
std::string error; |
std::string error; |
64 |
65 |
return passes(accessor, error); |
return passes(accessor, error); |
65 |
66 |
} |
} |
66 |
67 |
|
|
67 |
68 |
bool |
bool |
68 |
|
ItemFilter::passes(std::function<std::string(const std::string &)> accessor, |
|
69 |
|
std::string &error) const |
|
|
69 |
|
ItemFilter::passes(std::function<accessor_f> accessor, std::string &error) const |
70 |
70 |
{ |
{ |
71 |
71 |
error.clear(); |
error.clear(); |
72 |
72 |
|
|
|
... |
... |
ItemFilter::passes(std::function<std::string(const std::string &)> accessor, |
89 |
89 |
}; |
}; |
90 |
90 |
|
|
91 |
91 |
for (const Cond &cond : conds) { |
for (const Cond &cond : conds) { |
92 |
|
if (!test(cond, accessor(cond.key))) { |
|
|
92 |
|
bool matched = false; |
|
93 |
|
for (const std::string &val : accessor(cond.key)) { |
|
94 |
|
if (test(cond, val)) { |
|
95 |
|
matched = true; |
|
96 |
|
break; |
|
97 |
|
} |
|
98 |
|
} |
|
99 |
|
if (!matched) { |
93 |
100 |
err(cond); |
err(cond); |
94 |
101 |
} |
} |
95 |
102 |
} |
} |
File src/ItemFilter.hpp changed (mode: 100644) (index d1f6836..b8c716b) |
... |
... |
class Item; |
34 |
34 |
*/ |
*/ |
35 |
35 |
class ItemFilter |
class ItemFilter |
36 |
36 |
{ |
{ |
|
37 |
|
/** |
|
38 |
|
* @brief Type of function that is used to query field value. |
|
39 |
|
* |
|
40 |
|
* A field can be expanded to zero, one or multiple values and each value |
|
41 |
|
* will be matched individually. |
|
42 |
|
*/ |
|
43 |
|
using accessor_f = std::vector<std::string>(const std::string &key); |
|
44 |
|
|
37 |
45 |
public: |
public: |
38 |
46 |
/** |
/** |
39 |
47 |
* @brief Constructs the filter out of conditions in textual form. |
* @brief Constructs the filter out of conditions in textual form. |
|
... |
... |
public: |
72 |
80 |
* |
* |
73 |
81 |
* @returns @c true if it passes, and @c false otherwise. |
* @returns @c true if it passes, and @c false otherwise. |
74 |
82 |
*/ |
*/ |
75 |
|
bool passes(std::function<std::string(const std::string &)> accessor) const; |
|
|
83 |
|
bool passes(std::function<accessor_f> accessor) const; |
76 |
84 |
|
|
77 |
85 |
/** |
/** |
78 |
86 |
* @brief Checks whether item represented by its fields passes the filter. |
* @brief Checks whether item represented by its fields passes the filter. |
|
... |
... |
public: |
82 |
90 |
* |
* |
83 |
91 |
* @returns @c true if it passes, and @c false otherwise. |
* @returns @c true if it passes, and @c false otherwise. |
84 |
92 |
*/ |
*/ |
85 |
|
bool passes(std::function<std::string(const std::string &)> accessor, |
|
86 |
|
std::string &error) const; |
|
|
93 |
|
bool passes(std::function<accessor_f> accessor, std::string &error) const; |
87 |
94 |
|
|
88 |
95 |
private: |
private: |
89 |
96 |
/** |
/** |
File src/cmds/AddCmd.cpp changed (mode: 100644) (index 0ee0412..ffdf63d) |
... |
... |
AddCmd::run(Project &project, const std::vector<std::string> &args) |
125 |
125 |
|
|
126 |
126 |
std::string guard = cfg.get("guards.newitem", std::string()); |
std::string guard = cfg.get("guards.newitem", std::string()); |
127 |
127 |
auto accessor = [&fields](const std::string &f) { |
auto accessor = [&fields](const std::string &f) { |
|
128 |
|
using return_t = std::vector<std::string>; |
128 |
129 |
auto it = fields.find(f); |
auto it = fields.find(f); |
129 |
|
return (it == fields.cend()) ? std::string() : it->second; |
|
|
130 |
|
return (it == fields.cend()) ? return_t{} : return_t{ it->second }; |
130 |
131 |
}; |
}; |
131 |
132 |
std::string error; |
std::string error; |
132 |
133 |
if (!ItemFilter(breakIntoArgs(guard)).passes(accessor, error)) { |
if (!ItemFilter(breakIntoArgs(guard)).passes(accessor, error)) { |
File tests/ItemFilter.cpp changed (mode: 100644) (index a180990..1c3b2f1) |
... |
... |
TEST_CASE("Error messages add up", "[item-filter]") |
40 |
40 |
ItemFilter filter({ "_id==notid", "title!=title", "_id!/ID", "title/xy" }); |
ItemFilter filter({ "_id==notid", "title!=title", "_id!/ID", "title/xy" }); |
41 |
41 |
|
|
42 |
42 |
std::string error; |
std::string error; |
43 |
|
auto accessor = [&item](const std::string &f) { return item.getValue(f); }; |
|
|
43 |
|
auto accessor = [&item](const std::string &f) { |
|
44 |
|
return std::vector<std::string>{ item.getValue(f) }; |
|
45 |
|
}; |
44 |
46 |
REQUIRE(!filter.passes(accessor, error)); |
REQUIRE(!filter.passes(accessor, error)); |
45 |
47 |
|
|
46 |
48 |
REQUIRE(split(error, '\n').size() == 4); |
REQUIRE(split(error, '\n').size() == 4); |