23 #include "openPMD/Error.hpp" 24 #include "openPMD/backend/Attributable.hpp" 26 #include <initializer_list> 31 #include <type_traits> 35 #ifndef OPENPMD_protected 36 #define OPENPMD_protected protected: 50 struct GenerationPolicy
66 typename T_key = std::string,
67 typename T_container = std::map<T_key, T> >
71 using InternalContainer = T_container;
100 std::vector<std::string>
101 keyAsString(
T &&key, std::vector<std::string>
const &parentKey)
104 return {std::to_string(std::forward<T>(key))};
110 std::vector<std::string> keyAsString<std::string const &>(
111 std::string
const &key, std::vector<std::string>
const &parentKey);
114 std::vector<std::string> keyAsString<std::string>(
115 std::string &&key, std::vector<std::string>
const &parentKey);
129 typename T_key = std::string,
130 typename T_container = std::map<T_key, T> >
134 std::is_base_of<Attributable, T>::value,
135 "Type of container element must be derived from Writable");
148 using InternalContainer = T_container;
150 std::shared_ptr<ContainerData> m_containerData{
new ContainerData()};
152 inline void setData(std::shared_ptr<ContainerData> containerData)
154 m_containerData = std::move(containerData);
155 Attributable::setData(m_containerData);
158 inline InternalContainer
const &container()
const 160 return m_containerData->m_container;
163 inline InternalContainer &container()
165 return m_containerData->m_container;
169 using key_type =
typename InternalContainer::key_type;
170 using mapped_type =
typename InternalContainer::mapped_type;
171 using value_type =
typename InternalContainer::value_type;
172 using size_type =
typename InternalContainer::size_type;
173 using difference_type =
typename InternalContainer::difference_type;
174 using allocator_type =
typename InternalContainer::allocator_type;
175 using reference =
typename InternalContainer::reference;
176 using const_reference =
typename InternalContainer::const_reference;
177 using pointer =
typename InternalContainer::pointer;
178 using const_pointer =
typename InternalContainer::const_pointer;
179 using iterator =
typename InternalContainer::iterator;
180 using const_iterator =
typename InternalContainer::const_iterator;
182 iterator begin() noexcept
184 return container().begin();
186 const_iterator begin()
const noexcept
188 return container().begin();
190 const_iterator cbegin()
const noexcept
192 return container().cbegin();
195 iterator end() noexcept
197 return container().end();
199 const_iterator end()
const noexcept
201 return container().end();
203 const_iterator cend()
const noexcept
205 return container().cend();
208 bool empty()
const noexcept
210 return container().empty();
213 size_type size()
const noexcept
215 return container().size();
227 throw std::runtime_error(
228 "Can not clear a container in a read-only Series.");
233 std::pair<iterator, bool> insert(value_type
const &value)
235 return container().insert(value);
238 std::pair<iterator, bool> insert(P &&value)
240 return container().insert(value);
242 iterator insert(const_iterator hint, value_type
const &value)
244 return container().insert(hint, value);
247 iterator insert(const_iterator hint, P &&value)
249 return container().insert(hint, value);
251 template <
class InputIt>
252 void insert(InputIt first, InputIt last)
254 container().insert(first, last);
256 void insert(std::initializer_list<value_type> ilist)
258 container().insert(ilist);
263 container().swap(other.m_container);
266 mapped_type &at(key_type
const &key)
268 return container().at(key);
270 mapped_type
const &at(key_type
const &key)
const 272 return container().at(key);
287 auto it = container().find(key);
288 if (it != container().end())
292 if (IOHandler()->m_seriesStatus !=
297 throw std::out_of_range(out_of_range_msg(key));
301 t.linkHierarchy(writable());
302 auto &ret = container().insert({key, std::move(t)}).first->second;
303 ret.writable().ownKeyWithinParent =
304 detail::keyAsString(key, writable().ownKeyWithinParent);
322 auto it = container().find(key);
323 if (it != container().end())
327 if (IOHandler()->m_seriesStatus !=
332 throw std::out_of_range(out_of_range_msg(key));
336 t.linkHierarchy(writable());
337 auto &ret = container().insert({key, std::move(t)}).first->second;
338 ret.writable().ownKeyWithinParent = detail::keyAsString(
339 std::move(key), writable().ownKeyWithinParent);
346 iterator find(key_type
const &key)
348 return container().find(key);
350 const_iterator find(key_type
const &key)
const 352 return container().find(key);
360 size_type
count(key_type
const &key)
const 362 return container().count(key);
373 return container().find(key) != container().end();
384 virtual size_type
erase(key_type
const &key)
387 throw std::runtime_error(
388 "Can not erase from a container in a read-only Series.");
390 auto res = container().find(key);
391 if (res != container().end() && res->second.written())
395 IOHandler()->enqueue(
IOTask(&res->second, pDelete));
396 IOHandler()->flush(internal::defaultFlushParams);
398 return container().erase(key);
402 virtual iterator
erase(iterator res)
405 throw std::runtime_error(
406 "Can not erase from a container in a read-only Series.");
408 if (res != container().end() && res->second.written())
412 IOHandler()->enqueue(
IOTask(&res->second, pDelete));
413 IOHandler()->flush(internal::defaultFlushParams);
415 return container().erase(res);
420 template <
class... Args>
422 -> decltype(InternalContainer().emplace(std::forward<Args>(args)...))
424 return container().emplace(std::forward<Args>(args)...);
431 Container(std::shared_ptr<ContainerData> containerData)
432 :
Attributable{containerData}, m_containerData{std::move(containerData)}
435 void clear_unchecked()
438 throw std::runtime_error(
439 "Clearing a written container not (yet) implemented.");
451 IOHandler()->enqueue(
IOTask(
this, pCreate));
454 flushAttributes(flushParams);
463 Attributable::setData(m_containerData);
478 template <
typename Container_t>
479 class EraseStaleEntries
481 using BareContainer_t =
482 typename std::remove_reference<Container_t>::type;
483 using key_type =
typename BareContainer_t::key_type;
484 using mapped_type =
typename BareContainer_t::mapped_type;
485 std::set<key_type> m_accessedKeys;
493 Container_t m_originalContainer;
496 explicit EraseStaleEntries(Container_t &container_in)
497 : m_originalContainer(container_in)
500 explicit EraseStaleEntries(BareContainer_t &&container_in)
501 : m_originalContainer(std::move(container_in))
504 EraseStaleEntries(EraseStaleEntries &&) =
default;
505 EraseStaleEntries &operator=(EraseStaleEntries &&) =
default;
507 template <
typename K>
508 mapped_type &operator[](K &&k)
510 m_accessedKeys.insert(k);
511 return m_originalContainer[std::forward<K>(k)];
514 template <
typename K>
515 mapped_type &at(K &&k)
517 m_accessedKeys.insert(k);
518 return m_originalContainer.at(std::forward<K>(k));
526 template <
typename K>
529 m_accessedKeys.erase(std::forward<K>(k));
534 auto &map = m_originalContainer.container();
535 using iterator_t =
typename BareContainer_t::const_iterator;
536 std::vector<iterator_t> deleteMe;
537 deleteMe.reserve(map.size() - m_accessedKeys.size());
538 for (iterator_t it = map.begin(); it != map.end(); ++it)
540 auto lookup = m_accessedKeys.find(it->first);
541 if (lookup == m_accessedKeys.end())
543 deleteMe.push_back(it);
546 for (
auto &it : deleteMe)
Return an error string for read-only access.
Definition: OutOfRangeMsg.hpp:36
Definition: ParticlePatches.hpp:31
Self-contained description of a single IO operation.
Definition: IOTask.hpp:695
virtual mapped_type & operator[](key_type const &key)
Access the value that is mapped to a key equivalent to key, creating it if such key does not exist al...
Definition: Container.hpp:285
Container Element Creation Policy.
Definition: Attributable.hpp:47
Logical compilation of data from one snapshot (e.g.
Definition: Iteration.hpp:126
auto emplace(Args &&...args) -> decltype(InternalContainer().emplace(std::forward< Args >(args)...))
Definition: Container.hpp:421
bool contains(key_type const &key) const
Checks if there is an element with a key equivalent to an exiting key in the container.
Definition: Container.hpp:371
Definition: IOTask.hpp:294
virtual size_type erase(key_type const &key)
Remove a single element from the container and (if written) from disk.
Definition: Container.hpp:384
Implementation for the root level of the openPMD hierarchy.
Definition: Series.hpp:186
Definition: Container.hpp:68
Definition: Container.cpp:51
Public definitions of openPMD-api.
void clear()
Remove all objects from the container and (if written) from disk.
Definition: Container.hpp:224
void forget(K &&k)
Remove key from the list of accessed keys.
Definition: Container.hpp:527
Data members for Series.
Definition: Series.hpp:67
Definition: Attributable.hpp:56
Definition: ReadIterations.hpp:54
All objects in the openPMD object model are temporarily mutable to allow inserting newly-parsed data...
InternalContainer m_container
The wrapped container holding all the actual data, e.g.
Definition: Container.hpp:76
Parameters recursively passed through the openPMD hierarchy when flushing.
Definition: AbstractIOHandler.hpp:84
size_type count(key_type const &key) const
This returns either 1 if the key is found in the container of 0 if not.
Definition: Container.hpp:360
virtual iterator erase(iterator res)
Definition: Container.hpp:402
Definition: ParticleSpecies.hpp:33
This class wraps a Container and forwards operator[]() and at() to it.
Definition: Container.hpp:62
Definition: IOTask.hpp:239
Map-like container that enforces openPMD requirements and handles IO.
Definition: Container.hpp:131
Open Series as read-only, fails if Series is not found.
virtual mapped_type & operator[](key_type &&key)
Access the value that is mapped to a key equivalent to key, creating it if such key does not exist al...
Definition: Container.hpp:320
Layer to manage storage of attributes associated with file objects.
Definition: Attributable.hpp:93