-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathattribute_selector.hpp
168 lines (135 loc) · 5.12 KB
/
attribute_selector.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Copyright Morten Bendiksen 2014 - 2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef MEDIASEQUENCER_PLUGIN_UTIL_XPATH_ATTRIBUTE_SELECTOR_HPP
#define MEDIASEQUENCER_PLUGIN_UTIL_XPATH_ATTRIBUTE_SELECTOR_HPP
#include "context.hpp"
#include "selector_common.hpp"
#include "attribute_iterator.hpp"
namespace mediasequencer { namespace plugin { namespace util { namespace xpath {
// Predicate that is used to filter out attributes which does not have
// the given name
struct filtered_attribute_name {
explicit filtered_attribute_name(std::string name): name(std::move(name)) {
}
filtered_attribute_name(filtered_attribute_name&& other)
: name(std::move(other.name)) {
}
filtered_attribute_name(filtered_attribute_name const& other)
: name(other.name) {
}
filtered_attribute_name& operator=(filtered_attribute_name const& other) {
name = other.name;
return *this;
}
typedef bool return_type;
bool operator()(std::pair<std::string, std::string> const& pair) const {
return pair.first == name;
}
std::string name;
};
// Predicate that is used to filter out attributes which does not have
// the given name and value
struct filtered_attribute_name_and_value {
filtered_attribute_name_and_value() {}
explicit filtered_attribute_name_and_value(std::string name, std::string value)
: name(std::move(name)), value(std::move(value)) {
}
filtered_attribute_name_and_value(filtered_attribute_name_and_value&& other)
: name(std::move(other.name)), value(std::move(other.value)) {
}
filtered_attribute_name_and_value(filtered_attribute_name_and_value const& other)
: name(other.name), value(other.value) {
}
filtered_attribute_name_and_value& operator=(filtered_attribute_name_and_value const& other) {
name = other.name;
value = other.value;
return *this;
}
typedef bool return_type;
template <typename C>
bool operator()(C const& s) const {
return s.attribute(name) == value;
}
std::string name;
std::string value;
};
// type for attribute selector
class _attribute {
public:
filtered_attribute_name operator()(std::string name) const {
return filtered_attribute_name(name);
}
filtered_attribute_name_and_value operator()(
std::string name, std::string value) const {
return filtered_attribute_name_and_value(name, value);
}
};
namespace {
/// selector object for attribute. Can be used as a function
/// taking a name of the target attribute, or the name and value.
/// 'range | attribute' gives all attributes defined on the
/// input range as pairs of strings
/// 'range | attribute("foo")' gives the values of the
/// attributes with the name 'foo'
/// 'range | attribute("foo", "bar")' gives the nodes that
/// have the attributes 'foo' set to the value 'bar'
const _attribute attribute;
}
// Implements the pipe operator for attributes. E.g.
// 'range | attributes'
template <typename Range>
boost::iterator_range<attribute_iterator<typename Range::iterator> >
operator|(Range const& range, _attribute)
{
return make_attributes(range);
}
// Used to transform a range of pairs of strings to a range of strings.
// The strings will be the second value from the pairs.
// Used to extract only the values of a range of attributes.
struct second_of_pair {
typedef std::string result_type;
std::string operator()(std::pair<std::string, std::string> const& pair) const{
return pair.second;
}
std::string operator()(std::pair<std::string, std::string>&& pair) const{
return std::move(pair.second);
}
};
// Implements the pipe operator for attributes filtered on name. E.g.
// 'range | attributes("foo")'
template <typename Range>
boost::range_detail::transformed_range
<second_of_pair,
const boost::range_detail::filtered_range
<filtered_attribute_name,
const boost::iterator_range<attribute_iterator<typename Range::iterator> > > >
operator|(Range const& range, filtered_attribute_name f)
{
return make_attributes(range) | boost::adaptors::filtered(f) |
boost::adaptors::transformed(second_of_pair());
}
// Implements the pipe operator for attributes filtered on name and value. E.g.
// 'range | attributes("foo", "bar")'
template <typename Range>
boost::range_detail::filtered_range<filtered_attribute_name_and_value,
const Range>
operator|(Range const& range, filtered_attribute_name_and_value f)
{
return range | boost::adaptors::filtered(f);
}
// enables the selector for attributes filtered on name and value
template <>
struct is_expr<filtered_attribute_name_and_value>: std::true_type {
};
// enables the selector for attributes filtered on name
template <>
struct is_expr<filtered_attribute_name>: std::true_type {
};
// enables the selector for attributes
template <>
struct is_expr<_attribute>: std::true_type {
};
}}}}
#endif // MEDIASEQUENCER_PLUGIN_UTIL_XPATH_ATTRIBUTE_SELECTOR_HPP