source: src/Common/ScopedMap.hpp@ b28ce93

Last change on this file since b28ce93 was 6b33e89, checked in by Peter A. Buhr <pabuhr@…>, 5 months ago

change backquote call to regular call

  • Property mode set to 100644
File size: 11.5 KB
RevLine 
[e491159]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[c92bdcc]7// ScopedMap.hpp --
[e491159]8//
9// Author : Aaron B. Moss
10// Created On : Wed Dec 2 11:37:00 2015
[6b0b624]11// Last Modified By : Peter A. Buhr
[6b33e89]12// Last Modified On : Mon May 13 07:32:09 2024
13// Update Count : 6
[e491159]14//
15
[6b0b624]16#pragma once
[e491159]17
18#include <cassert>
19#include <iterator>
20#include <map>
21#include <utility>
22#include <vector>
23
[6253fc3]24/// Default (empty) ScopedMap note type
25struct EmptyNote {};
26
[e491159]27/// A map where the items are placed into nested scopes;
[6253fc3]28/// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward.
29/// Scopes may be annotated with a value; the annotation defaults to empty
30template<typename Key, typename Value, typename Note = EmptyNote>
[e491159]31class ScopedMap {
[6253fc3]32 typedef std::map< Key, Value > MapType;
[6b33e89]33public:
[6253fc3]34 struct Scope {
35 MapType map;
[4612bb0]36 Note note;
37
38 template<typename N>
[df00c78]39 Scope(N && n) : map(), note(std::forward<N>(n)) {}
[98a2b1dc]40
[4612bb0]41 Scope() = default;
[df00c78]42 Scope(const Scope &) = default;
43 Scope(Scope &&) = default;
44 Scope & operator= (const Scope &) = default;
45 Scope & operator= (Scope &&) = default;
[6253fc3]46 };
[6b33e89]47 private:
[e491159]48 typedef std::vector< Scope > ScopeList;
49
[db9d7a9]50 /// Scoped list of maps.
51 ScopeList scopes;
[e491159]52public:
[6253fc3]53 typedef typename MapType::key_type key_type;
54 typedef typename MapType::mapped_type mapped_type;
55 typedef typename MapType::value_type value_type;
[e491159]56 typedef typename ScopeList::size_type size_type;
57 typedef typename ScopeList::difference_type difference_type;
[6253fc3]58 typedef typename MapType::reference reference;
59 typedef typename MapType::const_reference const_reference;
60 typedef typename MapType::pointer pointer;
61 typedef typename MapType::const_pointer const_pointer;
[e491159]62
[98a2b1dc]63 // Both iterator types are complete bidrectional iterators, see below.
64 class iterator;
65 class const_iterator;
[e491159]66
67 /// Starts a new scope
68 void beginScope() {
69 scopes.emplace_back();
70 }
71
[4612bb0]72 // Starts a new scope with the given note
73 template<typename N>
[df00c78]74 void beginScope( N && n ) {
[4612bb0]75 scopes.emplace_back( std::forward<N>(n) );
76 }
77
[e491159]78 /// Ends a scope; invalidates any iterators pointing to elements of that scope
79 void endScope() {
80 scopes.pop_back();
81 assert( ! scopes.empty() );
82 }
83
84 /// Default constructor initializes with one scope
[4612bb0]85 ScopedMap() : scopes() { beginScope(); }
86
87 /// Constructs with a given note on the outermost scope
88 template<typename N>
[df00c78]89 ScopedMap( N && n ) : scopes() { beginScope(std::forward<N>(n)); }
[e491159]90
[6253fc3]91 iterator begin() { return iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
92 const_iterator begin() const { return const_iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
93 const_iterator cbegin() const { return const_iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
94 iterator end() { return iterator(scopes, scopes[0].map.end(), 0); }
95 const_iterator end() const { return const_iterator(scopes, scopes[0].map.end(), 0); }
96 const_iterator cend() const { return const_iterator(scopes, scopes[0].map.end(), 0); }
[e491159]97
98 /// Gets the index of the current scope (counted from 1)
[1f75e2d]99 size_type currentScope() const { return scopes.size() - 1; }
[e491159]100
[6253fc3]101 /// Gets the note at the given scope
[df00c78]102 Note & getNote() { return scopes.back().note; }
103 const Note & getNote() const { return scopes.back().note; }
104 Note & getNote( size_type i ) { return scopes[i].note; }
105 const Note & getNote( size_type i ) const { return scopes[i].note; }
[6253fc3]106
[e491159]107 /// Finds the given key in the outermost scope it occurs; returns end() for none such
[df00c78]108 iterator find( const Key & key ) {
[e491159]109 for ( size_type i = scopes.size() - 1; ; --i ) {
[6253fc3]110 typename MapType::iterator val = scopes[i].map.find( key );
111 if ( val != scopes[i].map.end() ) return iterator( scopes, val, i );
[e491159]112 if ( i == 0 ) break;
113 }
114 return end();
115 }
[df00c78]116 const_iterator find( const Key & key ) const {
[6253fc3]117 return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->find( key ) );
[e491159]118 }
119
[e58dfb9]120 /// Finds the given key in the provided scope; returns end() for none such
[df00c78]121 iterator findAt( size_type scope, const Key & key ) {
[6253fc3]122 typename MapType::iterator val = scopes[scope].map.find( key );
123 if ( val != scopes[scope].map.end() ) return iterator( scopes, val, scope );
[e58dfb9]124 return end();
125 }
[df00c78]126 const_iterator findAt( size_type scope, const Key & key ) const {
[6253fc3]127 return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findAt( scope, key ) );
[e58dfb9]128 }
129
[e491159]130 /// Finds the given key in the outermost scope inside the given scope where it occurs
[df00c78]131 iterator findNext( const_iterator & it, const Key & key ) {
[1f75e2d]132 if ( it.level == 0 ) return end();
133 for ( size_type i = it.level - 1; ; --i ) {
[6253fc3]134 typename MapType::iterator val = scopes[i].map.find( key );
135 if ( val != scopes[i].map.end() ) return iterator( scopes, val, i );
[e491159]136 if ( i == 0 ) break;
137 }
138 return end();
139 }
[df00c78]140 const_iterator findNext( const_iterator & it, const Key & key ) const {
[6253fc3]141 return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findNext( it, key ) );
[e491159]142 }
143
144 /// Inserts the given key-value pair into the outermost scope
[1f75e2d]145 template< typename value_type_t >
[df00c78]146 std::pair< iterator, bool > insert( value_type_t && value ) {
[6253fc3]147 std::pair< typename MapType::iterator, bool > res = scopes.back().map.insert( std::forward<value_type_t>( value ) );
[1f75e2d]148 return std::make_pair( iterator(scopes, std::move( res.first ), scopes.size()-1), std::move( res.second ) );
[e491159]149 }
150
[1f75e2d]151 template< typename value_t >
[df00c78]152 std::pair< iterator, bool > insert( const Key & key, value_t && value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); }
[1f75e2d]153
154 template< typename value_type_t >
[df00c78]155 std::pair< iterator, bool > insertAt( size_type scope, value_type_t && value ) {
[6253fc3]156 std::pair< typename MapType::iterator, bool > res = scopes.at(scope).map.insert( std::forward<value_type_t>( value ) );
[1f75e2d]157 return std::make_pair( iterator(scopes, std::move( res.first ), scope), std::move( res.second ) );
158 }
[e491159]159
[b12c036]160 template< typename value_t >
[df00c78]161 std::pair< iterator, bool > insertAt( size_type scope, const Key & key, value_t && value ) {
[b12c036]162 return insertAt( scope, std::make_pair( key, std::forward<value_t>( value ) ) );
163 }
164
[df00c78]165 Value & operator[] ( const Key & key ) {
[e491159]166 iterator slot = find( key );
167 if ( slot != end() ) return slot->second;
168 return insert( key, Value() ).first->second;
169 }
170
[21a2a7d]171 /// Erases element with key in the innermost scope that has it.
172 size_type erase( const Key & key ) {
173 for ( auto it = scopes.rbegin() ; it != scopes.rend() ; ++it ) {
[ccb29b4]174 size_type i = it->map.erase( key );
175 if ( 0 != i ) return i;
[21a2a7d]176 }
177 return 0;
178 }
[e491159]179
[df00c78]180 size_type count( const Key & key ) const {
[e491159]181 size_type c = 0;
182 auto it = find( key );
183 auto end = cend();
184
185 while(it != end) {
186 c++;
187 it = findNext(it, key);
188 }
189
190 return c;
191 }
[e9b5043]192
193 bool contains( const Key & key ) const {
194 return find( key ) != cend();
195 }
[e491159]196};
197
[98a2b1dc]198template<typename Key, typename Value, typename Note>
199class ScopedMap<Key, Value, Note>::iterator :
200 public std::iterator< std::bidirectional_iterator_tag, value_type > {
201 friend class ScopedMap;
202 friend class const_iterator;
[7f1be01]203 typedef typename MapType::iterator wrapped_iterator;
204 typedef typename ScopeList::size_type size_type;
[98a2b1dc]205
206 /// Checks if this iterator points to a valid item
207 bool is_valid() const {
208 return it != (*scopes)[level].map.end();
209 }
210
211 /// Increments on invalid
212 iterator & next_valid() {
213 if ( ! is_valid() ) { ++(*this); }
214 return *this;
215 }
216
217 /// Decrements on invalid
218 iterator & prev_valid() {
219 if ( ! is_valid() ) { --(*this); }
220 return *this;
221 }
222
[7f1be01]223 iterator(ScopeList & _scopes, const wrapped_iterator & _it, size_type inLevel)
[98a2b1dc]224 : scopes(&_scopes), it(_it), level(inLevel) {}
225public:
226 iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
227 iterator & operator= (const iterator & that) {
228 scopes = that.scopes; level = that.level; it = that.it;
229 return *this;
230 }
231
232 reference operator* () { return *it; }
233 pointer operator-> () const { return it.operator->(); }
234
235 iterator & operator++ () {
236 if ( it == (*scopes)[level].map.end() ) {
237 if ( level == 0 ) return *this;
238 --level;
239 it = (*scopes)[level].map.begin();
240 } else {
241 ++it;
242 }
243 return next_valid();
244 }
245 iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
246
247 iterator & operator-- () {
248 // may fail if this is the begin iterator; allowed by STL spec
249 if ( it == (*scopes)[level].map.begin() ) {
250 ++level;
251 it = (*scopes)[level].map.end();
252 }
253 --it;
254 return prev_valid();
255 }
256 iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
257
258 bool operator== (const iterator & that) const {
259 return scopes == that.scopes && level == that.level && it == that.it;
260 }
261 bool operator!= (const iterator & that) const { return !( *this == that ); }
262
263 size_type get_level() const { return level; }
264
265 Note & get_note() { return (*scopes)[level].note; }
266 const Note & get_note() const { return (*scopes)[level].note; }
267
268private:
[7f1be01]269 ScopeList *scopes;
[98a2b1dc]270 wrapped_iterator it;
271 size_type level;
272};
273
274template<typename Key, typename Value, typename Note>
275class ScopedMap<Key, Value, Note>::const_iterator :
276 public std::iterator< std::bidirectional_iterator_tag, value_type > {
277 friend class ScopedMap;
278 typedef typename ScopedMap::MapType::iterator wrapped_iterator;
279 typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
280 typedef typename ScopedMap::ScopeList scope_list;
281 typedef typename scope_list::size_type size_type;
282
283 /// Checks if this iterator points to a valid item
284 bool is_valid() const {
285 return it != (*scopes)[level].map.end();
286 }
287
288 /// Increments on invalid
289 const_iterator & next_valid() {
290 if ( ! is_valid() ) { ++(*this); }
291 return *this;
292 }
293
294 /// Decrements on invalid
295 const_iterator & prev_valid() {
296 if ( ! is_valid() ) { --(*this); }
297 return *this;
298 }
299
300 const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
301 : scopes(&_scopes), it(_it), level(inLevel) {}
302public:
303 const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
304 const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
305 const_iterator & operator= (const iterator & that) {
306 scopes = that.scopes; level = that.level; it = that.it;
307 return *this;
308 }
309 const_iterator & operator= (const const_iterator & that) {
310 scopes = that.scopes; level = that.level; it = that.it;
311 return *this;
312 }
313
314 const_reference operator* () { return *it; }
315 const_pointer operator-> () { return it.operator->(); }
316
317 const_iterator & operator++ () {
318 if ( it == (*scopes)[level].map.end() ) {
319 if ( level == 0 ) return *this;
320 --level;
321 it = (*scopes)[level].map.begin();
322 } else {
323 ++it;
324 }
325 return next_valid();
326 }
327 const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
328
329 const_iterator & operator-- () {
330 // may fail if this is the begin iterator; allowed by STL spec
331 if ( it == (*scopes)[level].map.begin() ) {
332 ++level;
333 it = (*scopes)[level].map.end();
334 }
335 --it;
336 return prev_valid();
337 }
338 const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
339
340 bool operator== (const const_iterator & that) const {
341 return scopes == that.scopes && level == that.level && it == that.it;
342 }
343 bool operator!= (const const_iterator & that) const { return !( *this == that ); }
344
345 size_type get_level() const { return level; }
346
347 const Note & get_note() const { return (*scopes)[level].note; }
348
349private:
350 scope_list const *scopes;
351 wrapped_const_iterator it;
352 size_type level;
353};
354
[e491159]355// Local Variables: //
356// tab-width: 4 //
357// mode: c++ //
358// compile-command: "make install" //
359// End: //
Note: See TracBrowser for help on using the repository browser.