23 #include "openPMD/backend/Attributable.hpp"
25 #include <initializer_list>
30 #include <type_traits>
34 #ifndef OPENPMD_protected
35 # define OPENPMD_protected protected
49 template<
typename U >
50 struct GenerationPolicy
52 template<
typename T >
75 template<
typename T >
76 std::vector< std::string >
77 keyAsString( T && key, std::vector< std::string >
const & parentKey )
80 return { std::to_string( std::forward< T >( key ) ) };
85 std::vector< std::string > keyAsString< std::string const & >(
86 std::string
const & key, std::vector< std::string >
const & parentKey );
89 std::vector< std::string > keyAsString< std::string >(
90 std::string && key, std::vector< std::string >
const & parentKey );
103 typename T_key = std::string,
104 typename T_container = std::map< T_key, T >
109 std::is_base_of< AttributableInterface, T >::value,
110 "Type of container element must be derived from Writable");
119 using InternalContainer = T_container;
122 using key_type =
typename InternalContainer::key_type;
123 using mapped_type =
typename InternalContainer::mapped_type;
124 using value_type =
typename InternalContainer::value_type;
125 using size_type =
typename InternalContainer::size_type;
126 using difference_type =
typename InternalContainer::difference_type;
127 using allocator_type =
typename InternalContainer::allocator_type;
128 using reference =
typename InternalContainer::reference;
129 using const_reference =
typename InternalContainer::const_reference;
130 using pointer =
typename InternalContainer::pointer;
131 using const_pointer =
typename InternalContainer::const_pointer;
132 using iterator =
typename InternalContainer::iterator;
133 using const_iterator =
typename InternalContainer::const_iterator;
138 iterator begin() noexcept {
return m_container->begin(); }
139 const_iterator begin()
const noexcept {
return m_container->begin(); }
140 const_iterator cbegin()
const noexcept {
return m_container->cbegin(); }
142 iterator end() noexcept {
return m_container->end(); }
143 const_iterator end()
const noexcept {
return m_container->end(); }
144 const_iterator cend()
const noexcept {
return m_container->cend(); }
146 bool empty()
const noexcept {
return m_container->empty(); }
148 size_type size()
const noexcept {
return m_container->size(); }
158 throw std::runtime_error(
"Can not clear a container in a read-only Series.");
163 std::pair< iterator, bool > insert(value_type
const& value) {
return m_container->insert(value); }
165 std::pair< iterator, bool > insert(P&& value) {
return m_container->insert(value); }
166 iterator insert(const_iterator hint, value_type
const& value) {
return m_container->insert(hint, value); }
168 iterator insert(const_iterator hint, P&& value) {
return m_container->insert(hint, value); }
169 template<
class InputIt >
170 void insert(InputIt first, InputIt last) { m_container->insert(first, last); }
171 void insert(std::initializer_list< value_type > ilist) { m_container->insert(ilist); }
173 void swap(Container & other) { m_container->swap(other.m_container); }
175 mapped_type& at(key_type
const& key) {
return m_container->at(key); }
176 mapped_type
const& at(key_type
const& key)
const {
return m_container->at(key); }
186 auto it = m_container->find(key);
187 if( it != m_container->end() )
194 throw std::out_of_range(out_of_range_msg(key));
198 t.linkHierarchy(writable());
199 auto& ret = m_container->insert({key, std::move(t)}).first->second;
200 ret.writable().ownKeyWithinParent =
201 detail::keyAsString( key, writable().ownKeyWithinParent );
215 auto it = m_container->find(key);
216 if( it != m_container->end() )
223 throw std::out_of_range(out_of_range_msg(key));
227 t.linkHierarchy(writable());
228 auto& ret = m_container->insert({key, std::move(t)}).first->second;
229 ret.writable().ownKeyWithinParent = detail::keyAsString(
230 std::move( key ), writable().ownKeyWithinParent );
237 iterator find(key_type
const& key) {
return m_container->find(key); }
238 const_iterator find(key_type
const& key)
const {
return m_container->find(key); }
245 size_type
count(key_type
const& key)
const {
return m_container->count(key); }
252 bool contains(key_type
const& key)
const {
return m_container->find(key) != m_container->end(); }
261 virtual size_type
erase(key_type
const& key)
264 throw std::runtime_error(
"Can not erase from a container in a read-only Series.");
266 auto res = m_container->find(key);
267 if( res != m_container->end() && res->second.written() )
272 IOHandler()->
flush();
274 return m_container->erase(key);
278 virtual iterator
erase(iterator res)
281 throw std::runtime_error(
"Can not erase from a container in a read-only Series.");
283 if( res != m_container->end() && res->second.written() )
288 IOHandler()->
flush();
290 return m_container->erase(res);
295 template <
class... Args>
297 -> decltype(InternalContainer().
emplace(std::forward<Args>(args)...))
299 return m_container->emplace(std::forward<Args>(args)...);
304 : m_container{std::make_shared< InternalContainer >()}
307 void clear_unchecked()
310 throw std::runtime_error(
"Clearing a written container not (yet) implemented.");
312 m_container->clear();
315 virtual void flush(std::string
const& path)
319 Parameter< Operation::CREATE_PATH > pCreate;
321 IOHandler()->
enqueue(IOTask(
this, pCreate));
327 std::shared_ptr< InternalContainer > m_container;
339 std::set< key_type > m_accessedKeys;
351 : m_originalContainer( container_in )
355 template<
typename K >
356 mapped_type & operator[]( K && k )
358 m_accessedKeys.insert( k );
359 return m_originalContainer[ std::forward< K >( k ) ];
362 template<
typename K >
363 mapped_type & at( K && k )
365 m_accessedKeys.insert( k );
366 return m_originalContainer.at( std::forward< K >( k ) );
371 auto & map = *m_originalContainer.m_container;
372 using iterator_t =
typename InternalContainer::const_iterator;
373 std::vector< iterator_t > deleteMe;
374 deleteMe.reserve( map.size() - m_accessedKeys.size() );
375 for( iterator_t it = map.begin(); it != map.end(); ++it )
377 auto lookup = m_accessedKeys.find( it->first );
378 if( lookup == m_accessedKeys.end() )
380 deleteMe.push_back( it );
383 for(
auto & it : deleteMe )