GEOS
MappedVector.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2024 Total, S.A
7  * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University
8  * Copyright (c) 2023-2024 Chevron
9  * Copyright (c) 2019- GEOS/GEOSX Contributors
10  * All rights reserved
11  *
12  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
13  * ------------------------------------------------------------------------------------------------------------
14  */
15 
20 #ifndef GEOS_DATAREPOSITORY_MAPPEDVECTOR_HPP_
21 #define GEOS_DATAREPOSITORY_MAPPEDVECTOR_HPP_
22 
23 // Source includes
24 #include "KeyIndexT.hpp"
25 #include "common/GeosxMacros.hpp"
26 #include "common/logger/Logger.hpp"
27 #include "LvArray/src/limits.hpp"
28 
29 // System includes
30 #include <vector>
31 
32 namespace geos
33 {
45 template< typename T,
46  typename T_PTR=T *,
47  typename KEY_TYPE=string,
48  typename INDEX_TYPE = int >
50 {
51 public:
52  static_assert( std::is_same< T_PTR, T * >::value || std::is_same< T_PTR, std::unique_ptr< T > >::value,
53  "invalid second template argument for MappedVector<T,T_PTR,KEY_TYPE,INDEX_TYPE>. Allowable types are T * and std::unique_ptr<T>." );
54 
56  using key_type = KEY_TYPE;
57 
59  using mapped_type = T_PTR;
60 
62  using LookupMapType = std::unordered_map< KEY_TYPE, INDEX_TYPE >;
63 
65  using value_type = typename std::pair< KEY_TYPE, T_PTR >;
66 
68  using const_key_value_type = typename std::pair< KEY_TYPE const, T * >;
69 
71  using const_value_type = typename std::pair< KEY_TYPE const, T const * >;
72 
74  using valueContainer = std::vector< value_type >;
75 
77  using constKeyValueContainer = std::vector< const_key_value_type >;
78 
80  using constValueContainer = std::vector< const_value_type >;
81 
83  using pointer = typename valueContainer::pointer;
84 
86  using const_pointer = typename valueContainer::const_pointer;
87 
89  using reference = typename valueContainer::reference;
90 
92  using const_reference = typename valueContainer::const_reference;
93 
95  using size_type = typename valueContainer::size_type;
96 
98  using iterator = typename constKeyValueContainer::iterator;
99 
101  using const_iterator = typename constValueContainer::const_iterator;
102 
104  using reverse_iterator = typename constKeyValueContainer::reverse_iterator;
105 
107  using const_reverse_iterator = typename constValueContainer::const_reverse_iterator;
108 
111 
112 
114  MappedVector() = default;
115 
118  {
119  clear();
120  }
121 
122 
123 
127  MappedVector( MappedVector const & ) = default;
128 
133  MappedVector & operator=( MappedVector const & ) = default;
134 
138  MappedVector( MappedVector && ) = default;
139 
145 
146 
147 
152 
153 
158  inline T const * operator[]( INDEX_TYPE index ) const
159  {
160  return ( index>KeyIndex::invalid_index &&
161  index<static_cast< INDEX_TYPE >( m_values.size() ) ) ? const_cast< T const * >(&(*(m_values[index].second))) : nullptr;
162  }
163 
169  inline T * operator[]( INDEX_TYPE index )
170  { return const_cast< T * >( const_cast< MappedVector< T, T_PTR, KEY_TYPE, INDEX_TYPE > const * >(this)->operator[]( index ) ); }
171 
177  inline T const * operator[]( KEY_TYPE const & keyName ) const
178  {
179  typename LookupMapType::const_iterator iter = m_keyLookup.find( keyName );
180  return ( iter!=m_keyLookup.end() ? this->operator[]( iter->second ) : nullptr );
181  }
182 
188  inline T * operator[]( KEY_TYPE const & keyName )
189  { return const_cast< T * >( const_cast< MappedVector< T, T_PTR, KEY_TYPE, INDEX_TYPE > const * >(this)->operator[]( keyName ) ); }
190 
196  inline T const * operator[]( KeyIndex const & keyIndex ) const
197  {
198  INDEX_TYPE index = keyIndex.index();
199 
200  if( index==KeyIndex::invalid_index )
201  {
202  index = getIndex( keyIndex.key() );
203  keyIndex.setIndex( index );
204  }
205 #ifdef MAPPED_VECTOR_RANGE_CHECKING
206  else if( m_values[index].first!=keyIndex.Key() )
207  {
208  index = getIndex( keyIndex.Key() );
209  keyIndex.setIndex( index );
210  }
211 #endif
212 
213  return this->operator[]( index );
214  }
215 
221  inline T * operator[]( KeyIndex const & keyIndex )
222  { return const_cast< T * >( const_cast< MappedVector< T, T_PTR, KEY_TYPE, INDEX_TYPE > const * >(this)->operator[]( keyIndex ) ); }
223 
225 
226 
231 
237  { return m_constKeyValues.begin(); }
238 
244  { return m_constValues.begin(); }
245 
251  { return m_constValues.begin(); }
252 
258  { return m_constKeyValues.end(); }
259 
265  { return m_constValues.end(); }
266 
272  { return m_constValues.end(); }
274 
275 
281  inline INDEX_TYPE getIndex( KEY_TYPE const & key ) const
282  {
283  typename LookupMapType::const_iterator iter = m_keyLookup.find( key );
284  return ( iter!=m_keyLookup.end() ? iter->second : KeyIndex::invalid_index );
285  }
286 
287 
292 
301  T * insert( KEY_TYPE const & keyName,
302  T_PTR source,
303  bool takeOwnership,
304  bool overwrite = false );
305 
306 
307 
315  void erase( INDEX_TYPE index )
316  {
317  // delete the pointed-to value, if owned
318  deleteValue( index );
319 
320  // delete lookup entry
321  m_keyLookup.erase( m_values[index].first );
322 
323  // delete and shift vector entries
324  m_values.erase( m_values.begin() + index );
325  m_ownsValues.erase( m_ownsValues.begin() + index );
326 
327  // rebuild parts of const key vectors after deleted entry
328  m_constKeyValues.resize( index );
329  m_constValues.resize( index );
330  for( typename valueContainer::size_type i = index; i < m_values.size(); ++i )
331  {
332  m_constKeyValues.emplace_back( m_values[i].first, rawPtr( i ) );
333  m_constValues.emplace_back( m_values[i].first, rawPtr( i ) );
334  }
335 
336  // adjust lookup map indices
337  for( typename valueContainer::size_type i = index; i < m_values.size(); ++i )
338  {
339  m_keyLookup[m_values[i].first] = i;
340  }
341  }
342 
349  void erase( KEY_TYPE const & key )
350  {
351  typename LookupMapType::const_iterator iter = m_keyLookup.find( key );
352  if( iter!=m_keyLookup.end() )
353  {
354  erase( iter->second );
355  }
356  }
357 
364  void erase( KeyIndex & keyIndex )
365  {
366  INDEX_TYPE index = keyIndex.Index();
367 
368  if( (index==KeyIndex::invalid_index) || (m_values[index].first!=keyIndex.Key()) )
369  {
370  index = getIndex( keyIndex.Key() );
371  keyIndex.setIndex( index );
372  }
373  erase( index );
374  }
375 
379  void clear()
380  {
381  for( typename valueContainer::size_type a = 0; a < m_values.size(); ++a )
382  {
383  deleteValue( LvArray::integerConversion< INDEX_TYPE >( a ) );
384  }
385  m_constKeyValues.clear();
386  m_constValues.clear();
387  m_values.clear();
388  m_ownsValues.clear();
389  m_keyLookup.clear();
390  }
391 
392 
394 
399  inline INDEX_TYPE size() const
400  {
401  return LvArray::integerConversion< INDEX_TYPE >( m_values.size() );
402  }
403 
408  inline valueContainer const & values()
409  { return this->m_values; }
410 
415  inline constValueContainer const & values() const
416  { return this->m_constValues; }
417 
422  inline LookupMapType const & keys() const
423  { return m_keyLookup; }
424 
425 
426 private:
427 
428  T * rawPtr( INDEX_TYPE index )
429  {
430  return &(*(m_values[index].second));
431  }
432 
433  template< typename U = T_PTR >
434  typename std::enable_if< std::is_same< U, T * >::value, void >::type
435  deleteValue( INDEX_TYPE index )
436  {
437  if( m_ownsValues[index] )
438  {
439  delete m_values[index].second;
440  }
441  }
442 
443  template< typename U = T_PTR >
444  typename std::enable_if< !std::is_same< U, T * >::value, void >::type
445  deleteValue( INDEX_TYPE GEOS_UNUSED_PARAM( index ) )
446  {}
447 
449  valueContainer m_values;
450 
452  constKeyValueContainer m_constKeyValues;
453 
455  constValueContainer m_constValues;
456 
458  LookupMapType m_keyLookup;
459 
461  std::vector< int > m_ownsValues;
462 };
463 
464 template< typename T, typename T_PTR, typename KEY_TYPE, typename INDEX_TYPE >
466  T_PTR source,
467  bool takeOwnership,
468  bool overwrite )
469 {
470  INDEX_TYPE index = KeyIndex::invalid_index;
471  typename LookupMapType::iterator iterKeyLookup = m_keyLookup.find( keyName );
472 
473 
474  // if the key was not found, make DataObject<T> and insert
475  if( iterKeyLookup == m_keyLookup.end() )
476  {
477  value_type newEntry = std::make_pair( keyName, std::move( source ) );
478  m_values.push_back( std::move( newEntry ) );
479  //TODO this needs to be a safe conversion
480  index = static_cast< INDEX_TYPE >(m_values.size()) - 1;
481  m_ownsValues.resize( index + 1 );
482  if( takeOwnership )
483  {
484  m_ownsValues[index] = true;
485  }
486 
487  m_keyLookup.insert( std::make_pair( keyName, index ) );
488  m_constKeyValues.emplace_back( keyName, rawPtr( index ) );
489  m_constValues.emplace_back( keyName, rawPtr( index ) );
490 
491  }
492  // if key was found
493  else
494  {
495  index = iterKeyLookup->second;
496 
497  if( takeOwnership )
498  {
499  m_ownsValues[index] = true;
500  }
501 
502  // if value is empty, then move source into value slot
503  if( m_values[index].second==nullptr )
504  {
505  m_values[index].second = std::move( source );
506  m_constKeyValues[index].second = rawPtr( index );
507  m_constValues[index].second = rawPtr( index );
508  }
509  else
510  {
511  if( overwrite )
512  {
513  deleteValue( index );
514  m_values[index].second = std::move( source );
515  m_constKeyValues[index].second = rawPtr( index );
516  m_constValues[index].second = rawPtr( index );
517  }
518  else if( typeid( source ) != typeid( m_values[index].second ) )
519  {
520  GEOS_ERROR( "MappedVector::insert(): Tried to insert existing key (" << keyName <<
521  ") with a different type without overwrite flag\n " << " " << LvArray::system::demangleType( source ) <<
522  " != " << LvArray::system::demangleType( m_values[ index ].second ) );
523  }
524  else
525  {
526  delete source;
527  }
528  }
529  }
530 
531  return &(*(m_values[index].second));
532 }
533 }
534 
535 #endif /* GEOS_DATAREPOSITORY_MAPPEDVECTOR_HPP_ */
#define GEOS_UNUSED_PARAM(X)
Mark an unused argument and silence compiler warnings.
Definition: GeosxMacros.hpp:72
#define GEOS_ERROR(msg)
Raise a hard error and terminate the program.
Definition: Logger.hpp:157
constexpr static INDEX_TYPE invalid_index
the value of an invalid index
Definition: KeyIndexT.hpp:51
void setIndex(INDEX_TYPE const &index) const
Set the index.
Definition: KeyIndexT.hpp:129
KEY_TYPE const & key() const
Access for the key.
Definition: KeyIndexT.hpp:106
INDEX_TYPE const & index() const
Access for the index.
Definition: KeyIndexT.hpp:113
void clear()
function to clear the MappedVector
T * operator[](KEY_TYPE const &keyName)
MappedVector()=default
deleted default constructor
T * operator[](INDEX_TYPE index)
constValueContainer const & values() const
access for value container
~MappedVector()
default destructor
const_iterator cend()
MappedVector & operator=(MappedVector const &)=default
Default copy assignment operator.
typename valueContainer::size_type size_type
the size_type of the value container
T const * operator[](KeyIndex const &keyIndex) const
typename std::pair< KEY_TYPE, T_PTR > value_type
the type of the values held in the vector
T * operator[](KeyIndex const &keyIndex)
MappedVector & operator=(MappedVector &&)=default
Default move assignment operator.
std::vector< value_type > valueContainer
the type of the vector container
INDEX_TYPE size() const
function to return the number of entries stored
typename std::pair< KEY_TYPE const, T * > const_key_value_type
the type of the values with const keys held in the vector
void erase(KEY_TYPE const &key)
Remove element at given key.
typename valueContainer::const_pointer const_pointer
the pointer to const type of the value container
void erase(INDEX_TYPE index)
Remove element at given index.
typename std::pair< KEY_TYPE const, T const * > const_value_type
a const type of the values held in the vector
typename valueContainer::pointer pointer
the pointer type of the value container
MappedVector(MappedVector &&)=default
Default move operator.
typename constValueContainer::const_reverse_iterator const_reverse_iterator
the reverse iterator to const type of the value container
T_PTR mapped_type
pointer to the value type
const_iterator end() const
valueContainer const & values()
access for value container
typename valueContainer::const_reference const_reference
reference to const type of the value container
MappedVector(MappedVector const &)=default
Default copy constructor.
std::vector< const_value_type > constValueContainer
a const type of the vector container
typename constKeyValueContainer::reverse_iterator reverse_iterator
the reverse iterator type of the value container
KEY_TYPE key_type
The type used for the key of the map.
std::unordered_map< KEY_TYPE, INDEX_TYPE > LookupMapType
the type of the lookup map
T const * operator[](KEY_TYPE const &keyName) const
typename valueContainer::reference reference
reference type of the value container
typename constKeyValueContainer::iterator iterator
the iterator type of the value container
void erase(KeyIndex &keyIndex)
Remove element at given key.
LookupMapType const & keys() const
access for key lookup
T * insert(KEY_TYPE const &keyName, T_PTR source, bool takeOwnership, bool overwrite=false)
insert new entry into MappedVector
const_iterator cbegin()
const_iterator begin() const
INDEX_TYPE getIndex(KEY_TYPE const &key) const
T const * operator[](INDEX_TYPE index) const
std::vector< const_key_value_type > constKeyValueContainer
a const type of the vector container
typename constValueContainer::const_iterator const_iterator
the iterator to const type of the value container
std::string string
String type.
Definition: DataTypes.hpp:91