1 /* sane - Scanner Access Now Easy.
2 
3    Copyright (C) 2020 Povilas Kanapickas <povilas@radix.lt>
4 
5    This file is part of the SANE package.
6 
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 */
20 
21 #ifndef BACKEND_GENESYS_VALUE_FILTER_H
22 #define BACKEND_GENESYS_VALUE_FILTER_H
23 
24 #include <algorithm>
25 #include <initializer_list>
26 #include <iostream>
27 #include <vector>
28 
29 namespace genesys {
30 
31 struct AnyTag {};
32 constexpr AnyTag VALUE_FILTER_ANY{};
33 
34 template<class T>
35 class ValueFilterAny
36 {
37 public:
ValueFilterAny()38     ValueFilterAny() : matches_any_{false} {}
ValueFilterAny(AnyTag)39     ValueFilterAny(AnyTag) : matches_any_{true} {}
ValueFilterAny(std::initializer_list<T> values)40     ValueFilterAny(std::initializer_list<T> values) :
41         matches_any_{false},
42         values_{values}
43     {}
44 
matches(T value)45     bool matches(T value) const
46     {
47         if (matches_any_)
48             return true;
49         auto it = std::find(values_.begin(), values_.end(), value);
50         return it != values_.end();
51     }
52 
53     bool operator==(const ValueFilterAny& other) const
54     {
55         return matches_any_ == other.matches_any_ && values_ == other.values_;
56     }
57 
matches_any()58     bool matches_any() const { return matches_any_; }
values()59     const std::vector<T>& values() const { return values_; }
60 
61 private:
62     bool matches_any_ = false;
63     std::vector<T> values_;
64 
65     template<class Stream, class U>
66     friend void serialize(Stream& str, ValueFilterAny<U>& x);
67 };
68 
69 template<class T>
70 std::ostream& operator<<(std::ostream& out, const ValueFilterAny<T>& values)
71 {
72     if (values.matches_any()) {
73         out << "ANY";
74         return out;
75     }
76     out << format_vector_indent_braced(4, "", values.values());
77     return out;
78 }
79 
80 template<class Stream, class T>
serialize(Stream & str,ValueFilterAny<T> & x)81 void serialize(Stream& str, ValueFilterAny<T>& x)
82 {
83     serialize(str, x.matches_any_);
84     serialize_newline(str);
85     serialize(str, x.values_);
86 }
87 
88 
89 template<class T>
90 class ValueFilter
91 {
92 public:
93     ValueFilter() = default;
ValueFilter(std::initializer_list<T> values)94     ValueFilter(std::initializer_list<T> values) :
95         values_{values}
96     {}
97 
matches(T value)98     bool matches(T value) const
99     {
100         auto it = std::find(values_.begin(), values_.end(), value);
101         return it != values_.end();
102     }
103 
104     bool operator==(const ValueFilter& other) const
105     {
106         return values_ == other.values_;
107     }
108 
values()109     const std::vector<T>& values() const { return values_; }
110 
111 private:
112     std::vector<T> values_;
113 
114     template<class Stream, class U>
115     friend void serialize(Stream& str, ValueFilter<U>& x);
116 };
117 
118 template<class T>
119 std::ostream& operator<<(std::ostream& out, const ValueFilter<T>& values)
120 {
121     if (values.values().empty()) {
122         out << "(none)";
123         return out;
124     }
125     out << format_vector_indent_braced(4, "", values.values());
126     return out;
127 }
128 
129 template<class Stream, class T>
serialize(Stream & str,ValueFilter<T> & x)130 void serialize(Stream& str, ValueFilter<T>& x)
131 {
132     serialize_newline(str);
133     serialize(str, x.values_);
134 }
135 
136 } // namespace genesys
137 
138 #endif // BACKEND_GENESYS_VALUE_FILTER_H
139