GEOSX
MappedVector.hpp
Go to the documentation of this file.
1 /*
2  * ------------------------------------------------------------------------------------------------------------
3  * SPDX-License-Identifier: LGPL-2.1-only
4  *
5  * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC
6  * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University
7  * Copyright (c) 2018-2020 Total, S.A
8  * Copyright (c) 2019- GEOSX Contributors
9  * All rights reserved
10  *
11  * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
12  * ------------------------------------------------------------------------------------------------------------
13  */
14 
19 #ifndef GEOSX_DATAREPOSITORY_MAPPEDVECTOR_HPP_
20 #define GEOSX_DATAREPOSITORY_MAPPEDVECTOR_HPP_
21 
22 // Source includes
23 #include "KeyIndexT.hpp"
24 #include "common/GeosxMacros.hpp"
25 #include "common/Logger.hpp"
26 #include "LvArray/src/limits.hpp"
27 
28 // System includes
29 #include <vector>
30 
31 namespace geosx
32 {
44 template< typename T,
45  typename T_PTR=T *,
46  typename KEY_TYPE=std::string,
47  typename INDEX_TYPE = int >
49 {
50 public:
51  static_assert( std::is_same< T_PTR, T * >::value || std::is_same< T_PTR, std::unique_ptr< T > >::value,
52  "invalid second template argument for MappedVector<T,T_PTR,KEY_TYPE,INDEX_TYPE>. Allowable types are T * and std::unique_ptr<T>." );
53 
55  using key_type = KEY_TYPE;
56 
58  using mapped_type = T_PTR;
59 
61  using LookupMapType = std::unordered_map< KEY_TYPE, INDEX_TYPE >;
62 
64  using value_type = typename std::pair< KEY_TYPE, T_PTR >;
65 
67  using const_key_value_type = typename std::pair< KEY_TYPE const, T * >;
68 
70  using const_value_type = typename std::pair< KEY_TYPE const, T const * >;
71 
73  using valueContainer = std::vector< value_type >;
74 
76  using constKeyValueContainer = std::vector< const_key_value_type >;
77 
79  using constValueContainer = std::vector< const_value_type >;
80 
82  using pointer = typename valueContainer::pointer;
83 
85  using const_pointer = typename valueContainer::const_pointer;
86 
88  using reference = typename valueContainer::reference;
89 
91  using const_reference = typename valueContainer::const_reference;
92 
94  using size_type = typename valueContainer::size_type;
95 
97  using iterator = typename constKeyValueContainer::iterator;
98 
100  using const_iterator = typename constValueContainer::const_iterator;
101 
103  using reverse_iterator = typename constKeyValueContainer::reverse_iterator;
104 
106  using const_reverse_iterator = typename constValueContainer::const_reverse_iterator;
107 
110 
111 
113  MappedVector() = default;
114 
117  {
118  clear();
119  }
120 
121 
122 
126  MappedVector( MappedVector const & ) = default;
127 
132  MappedVector & operator=( MappedVector const & ) = default;
133 
137  MappedVector( MappedVector && ) = default;
138 
143  MappedVector & operator=( MappedVector && ) = default;
144 
145 
146 
150 
152 
157  inline T const * operator[]( INDEX_TYPE index ) const
158  {
159  return ( index>KeyIndex::invalid_index &&
160  index<static_cast< INDEX_TYPE >( m_values.size() ) ) ? const_cast< T const * >(&(*(m_values[index].second))) : nullptr;
161  }
162 
168  inline T * operator[]( INDEX_TYPE index )
169  { return const_cast< T * >( const_cast< MappedVector< T, T_PTR, KEY_TYPE, INDEX_TYPE > const * >(this)->operator[]( index ) ); }
170 
176  inline T const * operator[]( KEY_TYPE const & keyName ) const
177  {
178  typename LookupMapType::const_iterator iter = m_keyLookup.find( keyName );
179  return ( iter!=m_keyLookup.end() ? this->operator[]( iter->second ) : nullptr );
180  }
181 
187  inline T * operator[]( KEY_TYPE const & keyName )
188  { return const_cast< T * >( const_cast< MappedVector< T, T_PTR, KEY_TYPE, INDEX_TYPE > const * >(this)->operator[]( keyName ) ); }
189 
195  inline T const * operator[]( KeyIndex const & keyIndex ) const
196  {
197  INDEX_TYPE index = keyIndex.Index();
198 
199  if( index==KeyIndex::invalid_index )
200  {
201  index = getIndex( keyIndex.Key() );
202  keyIndex.setIndex( index );
203  }
204 #ifdef MAPPED_VECTOR_RANGE_CHECKING
205  else if( m_values[index].first!=keyIndex.Key() )
206  {
207  index = getIndex( keyIndex.Key() );
208  keyIndex.setIndex( index );
209  }
210 #endif
211 
212  return this->operator[]( index );
213  }
214 
220  inline T * operator[]( KeyIndex const & keyIndex )
221  { return const_cast< T * >( const_cast< MappedVector< T, T_PTR, KEY_TYPE, INDEX_TYPE > const * >(this)->operator[]( keyIndex ) ); }
222 
224 
225 
229 
236  { return m_constKeyValues.begin(); }
237 
243  { return m_constValues.begin(); }
244 
250  { return m_constValues.begin(); }
251 
257  { return m_constKeyValues.end(); }
258 
264  { return m_constValues.end(); }
265 
271  { return m_constValues.end(); }
273 
274 
280  inline INDEX_TYPE getIndex( KEY_TYPE const & key ) const
281  {
282  typename LookupMapType::const_iterator iter = m_keyLookup.find( key );
283  return ( iter!=m_keyLookup.end() ? iter->second : KeyIndex::invalid_index );
284  }
285 
286 
290 
300  T * insert( KEY_TYPE const & keyName,
301  T_PTR source,
302  bool takeOwnership,
303  bool overwrite = false );
304 
305 
306 
314  void erase( INDEX_TYPE index )
315  {
316  // delete the pointed-to value, if owned
317  deleteValue( index );
318 
319  // delete lookup entry
320  m_keyLookup.erase( m_values[index].first );
321 
322  // delete and shift vector entries
323  m_values.erase( m_values.begin() + index );
324  m_ownsValues.erase( m_ownsValues.begin() + index );
325 
326  // rebuild parts of const key vectors after deleted entry
327  m_constKeyValues.resize( index );
328  m_constValues.resize( index );
329  for( typename valueContainer::size_type i = index; i < m_values.size(); ++i )
330  {
331  m_constKeyValues.emplace_back( m_values[i].first, rawPtr( index ) );
332  m_constValues.emplace_back( m_values[i].first, rawPtr( index ) );
333  }
334 
335  // adjust lookup map indices
336  for( typename valueContainer::size_type i = index; i < m_values.size(); ++i )
337  {
338  m_keyLookup[m_values[i].first] = i;
339  }
340  }
341 
348  void erase( KEY_TYPE const & key )
349  {
350  typename LookupMapType::const_iterator iter = m_keyLookup.find( key );
351  if( iter!=m_keyLookup.end() )
352  {
353  erase( iter->second );
354  }
355  }
356 
363  void erase( KeyIndex & keyIndex )
364  {
365  INDEX_TYPE index = keyIndex.Index();
366 
367  if( (index==KeyIndex::invalid_index) || (m_values[index].first!=keyIndex.Key()) )
368  {
369  index = getIndex( keyIndex.Key() );
370  keyIndex.setIndex( index );
371  }
372  erase( index );
373  }
374 
378  void clear()
379  {
380  for( typename valueContainer::size_type a = 0; a < m_values.size(); ++a )
381  {
382  deleteValue( LvArray::integerConversion< INDEX_TYPE >( a ) );
383  }
384  m_constKeyValues.clear();
385  m_constValues.clear();
386  m_values.clear();
387  m_ownsValues.clear();
388  m_keyLookup.clear();
389  }
390 
391 
393 
398  inline INDEX_TYPE size() const
399  {
400  return LvArray::integerConversion< INDEX_TYPE >( m_values.size() );
401  }
402 
407  inline valueContainer const & values()
408  { return this->m_values; }
409 
414  inline constValueContainer const & values() const
415  { return this->m_constValues; }
416 
421  inline LookupMapType const & keys() const
422  { return m_keyLookup; }
423 
424 
425 private:
426 
427  T * rawPtr( INDEX_TYPE index )
428  {
429  return &(*(m_values[index].second));
430  }
431 
432  template< typename U = T_PTR >
433  typename std::enable_if< std::is_same< U, T * >::value, void >::type
434  deleteValue( INDEX_TYPE index )
435  {
436  if( m_ownsValues[index] )
437  {
438  delete m_values[index].second;
439  }
440  }
441 
442  template< typename U = T_PTR >
443  typename std::enable_if< !std::is_same< U, T * >::value, void >::type
444  deleteValue( INDEX_TYPE GEOSX_UNUSED_PARAM( index ) )
445  {}
446 
448  valueContainer m_values;
449 
451  constKeyValueContainer m_constKeyValues;
452 
454  constValueContainer m_constValues;
455 
457  LookupMapType m_keyLookup;
458 
460  std::vector< int > m_ownsValues;
461 };
462 
463 template< typename T, typename T_PTR, typename KEY_TYPE, typename INDEX_TYPE >
465  T_PTR source,
466  bool takeOwnership,
467  bool overwrite )
468 {
469  INDEX_TYPE index = KeyIndex::invalid_index;
470  typename LookupMapType::iterator iterKeyLookup = m_keyLookup.find( keyName );
471 
472 
473  // if the key was not found, make DataObject<T> and insert
474  if( iterKeyLookup == m_keyLookup.end() )
475  {
476  value_type newEntry = std::make_pair( keyName, std::move( source ) );
477  m_values.push_back( std::move( newEntry ) );
478  //TODO this needs to be a safe conversion
479  index = static_cast< INDEX_TYPE >(m_values.size()) - 1;
480  m_ownsValues.resize( index + 1 );
481  if( takeOwnership )
482  {
483  m_ownsValues[index] = true;
484  }
485 
486  m_keyLookup.insert( std::make_pair( keyName, index ) );
487  m_constKeyValues.emplace_back( keyName, rawPtr( index ) );
488  m_constValues.emplace_back( keyName, rawPtr( index ) );
489 
490  }
491  // if key was found
492  else
493  {
494  index = iterKeyLookup->second;
495 
496  if( takeOwnership )
497  {
498  m_ownsValues[index] = true;
499  }
500 
501  // if value is empty, then move source into value slot
502  if( m_values[index].second==nullptr )
503  {
504  m_values[index].second = std::move( source );
505  m_constKeyValues[index].second = rawPtr( index );
506  m_constValues[index].second = rawPtr( index );
507  }
508  else
509  {
510  if( overwrite )
511  {
512  deleteValue( index );
513  m_values[index].second = std::move( source );
514  m_constKeyValues[index].second = rawPtr( index );
515  m_constValues[index].second = rawPtr( index );
516  }
517  else if( source->get_typeid() != m_values[index].second->get_typeid() )
518  {
519  GEOSX_ERROR( "MappedVector::insert(): Tried to insert existing key ("<<keyName<<
520  ") with a different type without overwrite flag\n"<<" "<<source->get_typeid().name()<<" != "<<
521  m_values[index].second->get_typeid().name() );
522  }
523  else
524  {
525  delete source;
526  }
527  }
528  }
529 
530  return &(*(m_values[index].second));
531 }
532 }
533 
534 #endif /* GEOSX_DATAREPOSITORY_MAPPEDVECTOR_HPP_ */
void setIndex(INDEX_TYPE const &index) const
Set the index.
Definition: KeyIndexT.hpp:128
typename constValueContainer::const_iterator const_iterator
the iterator to const type of the value container
T const * operator[](INDEX_TYPE index) const
typename valueContainer::pointer pointer
the pointer type of the value container
void clear()
function to clear the MappedVector
const_iterator cend()
typename constValueContainer::const_reverse_iterator const_reverse_iterator
the reverse iterator to const type of the value container
typename constKeyValueContainer::reverse_iterator reverse_iterator
the reverse iterator type of the value container
std::vector< const_value_type > constValueContainer
a const type of the vector container
keyType key_type
The type used for the key of the map.
typename valueContainer::const_pointer const_pointer
the pointer to const type of the value container
Contains portable access to std::numeric_limits and functions for converting between integral types...
typename std::pair< keyType const, Group * > const_key_value_type
the type of the values with const keys held in the vector
MappedVector & operator=(MappedVector const &)=default
Default copy assignment operator.
T * insert(KEY_TYPE const &keyName, T_PTR source, bool takeOwnership, bool overwrite=false)
insert new entry into MappedVector
const_iterator begin() const
std::unordered_map< keyType, indexType > LookupMapType
the type of the lookup map
MappedVector()=default
deleted default constructor
LookupMapType const & keys() const
access for key lookup
typename valueContainer::reference reference
reference type of the value container
typename std::pair< keyType, Group * > value_type
the type of the values held in the vector
std::vector< const_key_value_type > constKeyValueContainer
a const type of the vector container
~MappedVector()
default destructor
typename valueContainer::size_type size_type
the size_type of the value container
void erase(INDEX_TYPE index)
Remove element at given index.
typename std::pair< keyType const, Group const * > const_value_type
a const type of the values held in the vector
static constexpr INDEX_TYPE invalid_index
the value of an invalid index
Definition: KeyIndexT.hpp:50
T const * operator[](KeyIndex const &keyIndex) const
const_iterator cbegin()
#define GEOSX_ERROR(msg)
Raise a hard error and terminate the program.
Definition: Logger.hpp:110
valueContainer const & values()
access for value container
void erase(KEY_TYPE const &key)
Remove element at given key.
KEY_TYPE const & Key() const
Access for the key.
Definition: KeyIndexT.hpp:105
void erase(KeyIndex &keyIndex)
Remove element at given key.
constValueContainer const & values() const
access for value container
T const * operator[](KEY_TYPE const &keyName) const
T * operator[](INDEX_TYPE index)
const_iterator end() const
typename valueContainer::const_reference const_reference
reference to const type of the value container
std::string string
String type.
Definition: DataTypes.hpp:131
std::vector< value_type > valueContainer
the type of the vector container
INDEX_TYPE getIndex(KEY_TYPE const &key) const
INDEX_TYPE size() const
function to return the number of entries stored
#define GEOSX_UNUSED_PARAM(X)
Mark an unused argument and silence compiler warnings.
Definition: GeosxMacros.hpp:66
typename constKeyValueContainer::iterator iterator
the iterator type of the value container
T * operator[](KeyIndex const &keyIndex)
INDEX_TYPE const & Index() const
Access for the index.
Definition: KeyIndexT.hpp:112
T * operator[](KEY_TYPE const &keyName)