~thopiekar/zypper/libzypp-manual-import

« back to all changes in this revision

Viewing changes to zypp/base/SetTracker.h

  • Committer: Thomas-Karl Pietrowski
  • Date: 2015-08-15 15:59:50 UTC
  • Revision ID: thopiekar@googlemail.com-20150815155950-j66qn38efmvn289t
syncing with "changes 15.13.0 (11)"  #9a0aca7e3a21d768491b141a8ae86ef0c3fbc227
* https://github.com/openSUSE/libzypp/commit/9a0aca7e3a21d768491b141a8ae86ef0c3fbc227

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*---------------------------------------------------------------------\
 
2
|                          ____ _   __ __ ___                          |
 
3
|                         |__  / \ / / . \ . \                         |
 
4
|                           / / \ V /|  _/  _/                         |
 
5
|                          / /__ | | | | | |                           |
 
6
|                         /_____||_| |_| |_|                           |
 
7
|                                                                      |
 
8
\---------------------------------------------------------------------*/
 
9
/** \file       zypp/base/SetTracker.h
 
10
 */
 
11
#ifndef ZYPP_BASE_SETTRACKER_H
 
12
#define ZYPP_BASE_SETTRACKER_H
 
13
 
 
14
#include <iosfwd>
 
15
#include <utility>
 
16
#include <algorithm>
 
17
 
 
18
///////////////////////////////////////////////////////////////////
 
19
namespace zypp
 
20
{
 
21
  ///////////////////////////////////////////////////////////////////
 
22
  namespace base
 
23
  {
 
24
    ///////////////////////////////////////////////////////////////////
 
25
    /// \class SetTracker
 
26
    /// \brief Track added/removed set items based on an initial set.
 
27
    ///
 
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.
 
31
    ///
 
32
    /// It is also possible to directly manipulate the three sets.
 
33
    ///
 
34
    /// \note The tracking API expects the template arg to have set semantic.
 
35
    ///////////////////////////////////////////////////////////////////
 
36
    template <class _Set>
 
37
    struct SetTracker
 
38
    {
 
39
      typedef  _Set                     set_type;
 
40
      typedef typename _Set::key_type   key_type;
 
41
      typedef typename _Set::value_type value_type;
 
42
 
 
43
      /** Default Ctor: empty set */
 
44
      SetTracker()
 
45
      {}
 
46
 
 
47
      /** Ctor taking an initial set */
 
48
      SetTracker( set_type initial_r )
 
49
      : _current( std::move(initial_r) )
 
50
      {}
 
51
 
 
52
      /// \name Tracking API
 
53
      //@{
 
54
      /** (Re-)Start tracking the current set (discards previously tracked changes).
 
55
       * \return \c False (set did not change)
 
56
       */
 
57
      bool setInitial()
 
58
      { _added.clear(); _removed.clear(); return false; }
 
59
 
 
60
      /** Start tracking a new set (discards previously tracked changes).
 
61
       * \return Whether the set did change (new!=current)
 
62
       */
 
63
      bool setInitial( set_type new_r )
 
64
      {
 
65
        setInitial();
 
66
        bool changed = ( new_r != _current );
 
67
        if ( changed )
 
68
        {
 
69
          _current = std::move(new_r);
 
70
        }
 
71
        return changed;
 
72
      }
 
73
 
 
74
 
 
75
      /** Set a \a new_r set and track changes.
 
76
       * \return Whether the set has changed
 
77
       */
 
78
      bool set( set_type new_r )
 
79
      {
 
80
        bool changed = ( new_r != _current );
 
81
        if ( changed )
 
82
        {
 
83
          setInitial(); // clear added/removed
 
84
          if ( new_r.empty() )
 
85
          {
 
86
            _removed.swap( _current );
 
87
          }
 
88
          else if ( _current.empty() )
 
89
          {
 
90
            _added.swap( _current );
 
91
          }
 
92
          else
 
93
          {
 
94
            setDifference( new_r, _current, _added );
 
95
            setDifference( _current, new_r, _removed );
 
96
            _current = std::move(new_r);
 
97
          }
 
98
        }
 
99
        return changed;
 
100
      }
 
101
 
 
102
      /** Add an element to the set and track changes.
 
103
       * \return Whether the set has changed
 
104
       */
 
105
      bool add( const value_type & val_r )
 
106
      {
 
107
        bool done = _current.insert( val_r ).second;
 
108
        if ( done )
 
109
        {
 
110
          _added.insert( val_r );
 
111
          _removed.erase( val_r );
 
112
        }
 
113
        return done;
 
114
      }
 
115
 
 
116
      /** Remove an element from the set and track changes.
 
117
       * \return Whether the set has changed
 
118
       */
 
119
      bool remove( const value_type & val_r )
 
120
      {
 
121
        bool done = _current.erase( val_r );
 
122
        if ( done )
 
123
        {
 
124
          _added.erase( val_r );
 
125
          _removed.insert( val_r );
 
126
        }
 
127
        return done;
 
128
      }
 
129
      //@}
 
130
 
 
131
      /// \name Query and retrieval
 
132
      //@{
 
133
      /** Whether \a val_r is in the set. */
 
134
      bool contains( const key_type & key_r ) const     { return find( _current, key_r ); }
 
135
 
 
136
      /** Whether \a val_r is tracked as added. */
 
137
      bool wasAdded( const key_type & key_r ) const     { return find( _added, key_r ); }
 
138
 
 
139
      /** Whether \a val_r is tracked as removed. */
 
140
      bool wasRemoved( const key_type & key_r ) const   { return find( _removed, key_r ); }
 
141
 
 
142
 
 
143
      /** Return the current set. */
 
144
      const set_type & current() const                  { return _current; }
 
145
 
 
146
      /** Return the set of added items. */
 
147
      const set_type & added() const                    { return _added; }
 
148
 
 
149
      /** Return the set of removed items. */
 
150
      const set_type & removed() const                  { return _removed; }
 
151
      //@}
 
152
 
 
153
      /// \name Direct manipulation
 
154
      //@{
 
155
      /** Return the current set. */
 
156
      set_type & current()                              { return _current; }
 
157
 
 
158
      /** Return the set of added items. */
 
159
      set_type & added()                                { return _added; }
 
160
 
 
161
      /** Return the set of removed items. */
 
162
      set_type & removed()                              { return _removed; }
 
163
      //@}
 
164
 
 
165
    private:
 
166
      static bool find( const set_type & set_r, const key_type & key_r )
 
167
      { return set_r.find( key_r ) != set_r.end(); }
 
168
 
 
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 )
 
171
      {
 
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() );
 
176
      }
 
177
 
 
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 )
 
180
      {
 
181
        // std::set_difference requires ordered sets!
 
182
        for ( const auto & l : lhs )
 
183
        { if ( rhs.find( l ) == rhs.end() ) result_r.insert( l ); }
 
184
      }
 
185
 
 
186
    private:
 
187
      set_type _current;
 
188
      set_type _added;
 
189
      set_type _removed;
 
190
    };
 
191
 
 
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() << ')'; }
 
196
 
 
197
  } // namespace base
 
198
  ///////////////////////////////////////////////////////////////////
 
199
} // namespace zypp
 
200
///////////////////////////////////////////////////////////////////
 
201
#endif // ZYPP_BASE_SETTRACKER_H