1
/*---------------------------------------------------------------------\
3
| |__ / \ / / . \ . \ |
8
\---------------------------------------------------------------------*/
9
/** \file zypp/base/SetTracker.h
11
#ifndef ZYPP_BASE_SETTRACKER_H
12
#define ZYPP_BASE_SETTRACKER_H
18
///////////////////////////////////////////////////////////////////
21
///////////////////////////////////////////////////////////////////
24
///////////////////////////////////////////////////////////////////
26
/// \brief Track added/removed set items based on an initial set.
28
/// The class maintains the \ref current set of items and also records
29
/// the changes compared to the initial set (\ref added and \ref removed
30
/// items) if you use the tracking API.
32
/// It is also possible to directly manipulate the three sets.
34
/// \note The tracking API expects the template arg to have set semantic.
35
///////////////////////////////////////////////////////////////////
39
typedef _Set set_type;
40
typedef typename _Set::key_type key_type;
41
typedef typename _Set::value_type value_type;
43
/** Default Ctor: empty set */
47
/** Ctor taking an initial set */
48
SetTracker( set_type initial_r )
49
: _current( std::move(initial_r) )
52
/// \name Tracking API
54
/** (Re-)Start tracking the current set (discards previously tracked changes).
55
* \return \c False (set did not change)
58
{ _added.clear(); _removed.clear(); return false; }
60
/** Start tracking a new set (discards previously tracked changes).
61
* \return Whether the set did change (new!=current)
63
bool setInitial( set_type new_r )
66
bool changed = ( new_r != _current );
69
_current = std::move(new_r);
75
/** Set a \a new_r set and track changes.
76
* \return Whether the set has changed
78
bool set( set_type new_r )
80
bool changed = ( new_r != _current );
83
setInitial(); // clear added/removed
86
_removed.swap( _current );
88
else if ( _current.empty() )
90
_added.swap( _current );
94
setDifference( new_r, _current, _added );
95
setDifference( _current, new_r, _removed );
96
_current = std::move(new_r);
102
/** Add an element to the set and track changes.
103
* \return Whether the set has changed
105
bool add( const value_type & val_r )
107
bool done = _current.insert( val_r ).second;
110
_added.insert( val_r );
111
_removed.erase( val_r );
116
/** Remove an element from the set and track changes.
117
* \return Whether the set has changed
119
bool remove( const value_type & val_r )
121
bool done = _current.erase( val_r );
124
_added.erase( val_r );
125
_removed.insert( val_r );
131
/// \name Query and retrieval
133
/** Whether \a val_r is in the set. */
134
bool contains( const key_type & key_r ) const { return find( _current, key_r ); }
136
/** Whether \a val_r is tracked as added. */
137
bool wasAdded( const key_type & key_r ) const { return find( _added, key_r ); }
139
/** Whether \a val_r is tracked as removed. */
140
bool wasRemoved( const key_type & key_r ) const { return find( _removed, key_r ); }
143
/** Return the current set. */
144
const set_type & current() const { return _current; }
146
/** Return the set of added items. */
147
const set_type & added() const { return _added; }
149
/** Return the set of removed items. */
150
const set_type & removed() const { return _removed; }
153
/// \name Direct manipulation
155
/** Return the current set. */
156
set_type & current() { return _current; }
158
/** Return the set of added items. */
159
set_type & added() { return _added; }
161
/** Return the set of removed items. */
162
set_type & removed() { return _removed; }
166
static bool find( const set_type & set_r, const key_type & key_r )
167
{ return set_r.find( key_r ) != set_r.end(); }
169
template <class _ORDERED_SET, typename enable_if = typename _ORDERED_SET::key_compare>
170
static void setDifference( const _ORDERED_SET & lhs, const _ORDERED_SET & rhs, _ORDERED_SET & result_r )
172
// std::set_difference requires ordered sets!
173
std::set_difference( lhs.begin(), lhs.end(), rhs.begin(), rhs.end(),
174
std::inserter( result_r, result_r.end() ),
175
typename _ORDERED_SET::key_compare() );
178
template <class _UNORDERED_SET, typename enable_if = typename _UNORDERED_SET::hasher, typename = void>
179
static void setDifference( const _UNORDERED_SET & lhs, const _UNORDERED_SET & rhs, _UNORDERED_SET & result_r )
181
// std::set_difference requires ordered sets!
182
for ( const auto & l : lhs )
183
{ if ( rhs.find( l ) == rhs.end() ) result_r.insert( l ); }
192
/** \relates SetTracker Stream output */
193
template <class _Set>
194
std::ostream & operator<<( std::ostream & str, const SetTracker<_Set> & obj )
195
{ return str << "set(" << obj.current().size() << "|+" << obj.added().size() << "|-" << obj.removed().size() << ')'; }
198
///////////////////////////////////////////////////////////////////
200
///////////////////////////////////////////////////////////////////
201
#endif // ZYPP_BASE_SETTRACKER_H