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 TSet set_type;
40 typedef typename TSet::key_type key_type;
41 typedef typename TSet::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 // build the initial (cur-add+rem) set in _current
84 setDifference( _current, _added, _removed );
85 _current.swap( _removed );
89 const set_type & initial( _current );
90 setDifference( initial, new_r, _removed );
91 setDifference( new_r, initial, _added );
92 _current.swap( new_r );
97 /** Add an element to the set and track changes.
98 * \return Whether the set has changed
100 bool add( const value_type & val_r )
102 bool done = _current.insert( val_r ).second;
105 if ( ! _removed.erase( val_r ) )
106 _added.insert( val_r );
111 /** Remove an element from the set and track changes.
112 * \return Whether the set has changed
114 bool remove( const value_type & val_r )
116 bool done = _current.erase( val_r );
119 if ( ! _added.erase( val_r ) )
120 _removed.insert( val_r );
126 /// \name Query and retrieval
128 /** Whether \a val_r is in the set. */
129 bool contains( const key_type & key_r ) const { return find( _current, key_r ); }
131 /** Whether \a val_r is tracked as added. */
132 bool wasAdded( const key_type & key_r ) const { return find( _added, key_r ); }
134 /** Whether \a val_r is tracked as removed. */
135 bool wasRemoved( const key_type & key_r ) const { return find( _removed, key_r ); }
138 /** Return the current set. */
139 const set_type & current() const { return _current; }
141 /** Return the set of added items. */
142 const set_type & added() const { return _added; }
144 /** Return the set of removed items. */
145 const set_type & removed() const { return _removed; }
148 /// \name Direct manipulation
150 /** Return the current set. */
151 set_type & current() { return _current; }
153 /** Return the set of added items. */
154 set_type & added() { return _added; }
156 /** Return the set of removed items. */
157 set_type & removed() { return _removed; }
162 static bool find( const set_type & set_r, const key_type & key_r )
163 { return set_r.find( key_r ) != set_r.end(); }
165 template <class TORDERED_SET, typename enable_if = typename TORDERED_SET::key_compare>
166 static void setDifference( const TORDERED_SET & lhs, const TORDERED_SET & rhs, TORDERED_SET & result_r )
168 // std::set_difference requires ordered sets!
169 std::set_difference( lhs.begin(), lhs.end(), rhs.begin(), rhs.end(),
170 std::inserter( result_r, result_r.end() ),
171 typename TORDERED_SET::key_compare() );
174 template <class TUNORDERED_SET, typename enable_if = typename TUNORDERED_SET::hasher, typename = void>
175 static void setDifference( const TUNORDERED_SET & lhs, const TUNORDERED_SET & rhs, TUNORDERED_SET & result_r )
177 // std::set_difference requires ordered sets!
178 for ( const auto & l : lhs )
179 { if ( rhs.find( l ) == rhs.end() ) result_r.insert( l ); }
188 /** \relates SetTracker Stream output */
189 template <class TSet>
190 std::ostream & operator<<( std::ostream & str, const SetTracker<TSet> & obj )
191 { return str << "set(" << obj.current().size() << "|+" << obj.added().size() << "|-" << obj.removed().size() << ')'; }
194 ///////////////////////////////////////////////////////////////////
196 ///////////////////////////////////////////////////////////////////
197 #endif // ZYPP_BASE_SETTRACKER_H