19 #include <lunchbox/debug.h> 21 #include <boost/iterator/iterator_facade.hpp> 27 template<
typename T >
28 class IntervalSet< T >::const_iterator :
29 public boost::iterator_facade< typename IntervalSet< T >::const_iterator,
30 T, std::forward_iterator_tag, T >
38 friend class boost::iterator_core_access;
41 typedef typename IntervalSet< T >::EdgeSet::const_iterator
44 const_iterator(
const IntervalSet&
set,
const edge_iterator& interval )
45 : _intervalIteratorEnd( set._intervals.
end( ))
46 , _startEdge( interval )
48 if (_startEdge != _intervalIteratorEnd )
49 _value = _startEdge->first;
52 const_iterator(
const IntervalSet &
set,
const edge_iterator & interval,
55 , _intervalIteratorEnd( set._intervals.
end( ))
56 , _startEdge( interval )
61 if( _startEdge == _intervalIteratorEnd )
64 edge_iterator endEdge = _startEdge;
67 if( _value >= _startEdge->first && _value < endEdge->first )
73 if( _startEdge != _intervalIteratorEnd )
74 _value = _startEdge->first;
78 bool equal(
const const_iterator& rhs )
const 80 return (_startEdge == _intervalIteratorEnd &&
81 rhs._startEdge == _intervalIteratorEnd) ||
82 (_startEdge == rhs._startEdge && _value == rhs._value );
91 edge_iterator _intervalIteratorEnd;
92 edge_iterator _startEdge;
101 insert( element, element );
106 erase( element, element );
110 const T& endElement )
112 LBASSERT( startElement <= endElement );
114 Edge startValue( startElement,
true );
115 Edge endValue( endElement,
false );
117 if( _intervals.empty( ))
119 _intervals.insert( startValue );
120 _intervals.insert( endValue );
121 _size = endElement - startElement + 1;
126 typename EdgeSet::iterator previous_to_start =
127 _intervals.lower_bound( startValue );
128 if( previous_to_start != _intervals.end( ))
130 if( previous_to_start == _intervals.begin( ))
132 if( startValue.first < previous_to_start->first )
133 previous_to_start = _intervals.end();
139 previous_to_start = (++_intervals.rbegin()).base();
142 typename EdgeSet::iterator position;
144 size_t overlappingPortion = 0;
145 T overlappingStart = T();
147 if( previous_to_start == _intervals.end( ))
152 position = _intervals.insert( startValue );
155 else if( !previous_to_start->second )
158 if( previous_to_start->first + 1 == startElement )
162 position = previous_to_start;
164 _intervals.erase( previous_to_start );
168 position = _intervals.insert( previous_to_start, startValue );
174 position = previous_to_start;
176 overlappingStart = startElement;
181 while( position != _intervals.end() && position->first <= endElement )
188 LBASSERT( !position->second );
189 overlappingPortion += position->first - overlappingStart + 1;
192 overlappingStart = position->first;
194 fallsInside = position->second;
199 _intervals.erase( position++ );
202 if( position != _intervals.end() &&
203 position->second && position->first == endElement + 1 )
208 _intervals.erase(position);
210 else if( !fallsInside )
214 _intervals.insert(position, endValue);
217 overlappingPortion += endElement - overlappingStart + 1;
219 _size += size_t(endElement - startElement + 1) - overlappingPortion;
220 LBASSERT( _intervals.size() % 2 == 0 );
224 const T& endElement )
226 LBASSERT( startElement <= endElement );
228 if( _intervals.empty( ))
232 typename EdgeSet::iterator nextToStart =
233 _intervals.lower_bound( std::make_pair( startElement,
true ));
234 typename EdgeSet::iterator previousToStart = nextToStart;
235 if( nextToStart == _intervals.begin( ))
236 previousToStart = _intervals.end();
237 else if( nextToStart == _intervals.end( ))
243 typename EdgeSet::iterator position;
245 T overlappingStart = 0;
246 size_t overlapping_portion = 0;
248 if( previousToStart != _intervals.end( ))
251 if( previousToStart->second )
256 _intervals.insert( std::make_pair( startElement - 1,
false ));
258 overlappingStart = startElement;
262 position = previousToStart;
271 position = _intervals.begin();
272 overlappingStart = position->first;
277 while( position != _intervals.end() && position->first <= endElement )
280 overlapping_portion += position->first - overlappingStart + 1;
282 overlappingStart = position->first;
284 inside = position->second;
289 _intervals.erase( position++ );
294 LBASSERT( position != _intervals.end( ));
297 _intervals.insert (std::make_pair( endElement + 1,
true ));
298 overlapping_portion += endElement - overlappingStart + 1;
301 _size -= overlapping_portion;
302 LBASSERT( _intervals.size() % 2 == 0 );
307 for(
typename EdgeSet::const_iterator i = rhs._intervals.begin();
308 i != rhs._intervals.end(); ++i )
310 insert( i->first, i->second );
322 return find( element ) !=
end();
325 template <
typename T >
typename IntervalSet< T >::const_iterator
328 if( _intervals.empty( ))
331 typename EdgeSet::const_iterator next =
332 _intervals.lower_bound( std::make_pair( element,
false ));
336 if( next == _intervals.end() || next == _intervals.begin( ))
340 typename EdgeSet::const_iterator previous = next;
342 if( previous->second )
343 return const_iterator( *
this, previous, element );
347 template <
typename T >
typename IntervalSet< T >::const_iterator
350 if( _intervals.empty( ))
352 return const_iterator( *
this, _intervals.begin( ));
355 template <
typename T >
typename IntervalSet< T >::const_iterator
358 return const_iterator( *
this, _intervals.end());
373 _intervals.swap( rhs._intervals );
const_iterator find(const T &element) const
bool exists(const T &element) const
IntervalSet()
Construct a new interval set.
void erase(const T &element)
Remove the given element.
void swap(IntervalSet &rhs)
Swap this container with another one.
void insert(const T &element)
Insert a new element.
const_iterator begin() const
Abstraction layer and common utilities for multi-threaded programming.
const_iterator end() const
void clear()
Remove all stored elements.