openPMD-api
 
Loading...
Searching...
No Matches
Container.hpp
1/* Copyright 2017-2025 Fabian Koller and Franz Poeschel, Axel Huebl
2 *
3 * This file is part of openPMD-api.
4 *
5 * openPMD-api is free software: you can redistribute it and/or modify
6 * it under the terms of of either the GNU General Public License or
7 * the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * openPMD-api is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License and the GNU Lesser General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * and the GNU Lesser General Public License along with openPMD-api.
19 * If not, see <http://www.gnu.org/licenses/>.
20 */
21#pragma once
22
23#include "openPMD/Error.hpp"
24#include "openPMD/IO/Access.hpp"
25#include "openPMD/backend/Attributable.hpp"
26
27#include <initializer_list>
28#include <map>
29#include <set>
30#include <stdexcept>
31#include <string>
32#include <type_traits>
33#include <utility>
34
35// expose private and protected members for invasive testing
36#ifndef OPENPMD_protected
37#define OPENPMD_protected protected:
38#endif
39
40namespace openPMD
41{
42namespace traits
43{
50 template <typename U>
52 {
53 constexpr static bool is_noop = true;
54 template <typename T>
55 void operator()(T &)
56 {}
57 };
58} // namespace traits
59
60namespace internal
61{
62 class SeriesData;
63 template <typename>
64 class EraseStaleEntries;
65
66 template <
67 typename T,
68 typename T_key = std::string,
69 typename T_container = std::map<T_key, T>>
70 class ContainerData : virtual public AttributableData
71 {
72 public:
73 using InternalContainer = T_container;
74
78 InternalContainer m_container;
79
80 ContainerData() = default;
81
82 ContainerData(ContainerData const &) = delete;
83 ContainerData(ContainerData &&) = delete;
84
85 ContainerData &operator=(ContainerData const &) = delete;
86 ContainerData &operator=(ContainerData &&) = delete;
87 };
88} // namespace internal
89
99template <
100 typename T,
101 typename T_key = std::string,
102 typename T_container = std::map<T_key, T>>
103class Container : virtual public Attributable
104{
105 static_assert(
106 std::is_base_of<Attributable, T>::value,
107 "Type of container element must be derived from Writable");
108
109 friend class Iteration;
110 friend class ParticleSpecies;
111 friend class ParticlePatches;
112 friend class internal::SeriesData;
113 friend class Series;
114 template <typename>
115 friend class internal::EraseStaleEntries;
116 friend class StatefulIterator;
117
118protected:
120 using InternalContainer = T_container;
121
122 std::shared_ptr<ContainerData> m_containerData;
123
124 inline void setData(std::shared_ptr<ContainerData> containerData)
125 {
126 m_containerData = std::move(containerData);
127 Attributable::setData(m_containerData);
128 }
129
130 inline InternalContainer const &container() const
131 {
132 return m_containerData->m_container;
133 }
134
135 inline InternalContainer &container()
136 {
137 return m_containerData->m_container;
138 }
139
140public:
141 using key_type = typename InternalContainer::key_type;
142 using mapped_type = typename InternalContainer::mapped_type;
143 using value_type = typename InternalContainer::value_type;
144 using size_type = typename InternalContainer::size_type;
145 using difference_type = typename InternalContainer::difference_type;
146 using allocator_type = typename InternalContainer::allocator_type;
147 using reference = typename InternalContainer::reference;
148 using const_reference = typename InternalContainer::const_reference;
149 using pointer = typename InternalContainer::pointer;
150 using const_pointer = typename InternalContainer::const_pointer;
151 using iterator = typename InternalContainer::iterator;
152 using const_iterator = typename InternalContainer::const_iterator;
153 using reverse_iterator = typename InternalContainer::reverse_iterator;
154 using const_reverse_iterator =
155 typename InternalContainer::const_reverse_iterator;
156
157 iterator begin() noexcept;
158 const_iterator begin() const noexcept;
159 const_iterator cbegin() const noexcept;
160
161 iterator end() noexcept;
162 const_iterator end() const noexcept;
163 const_iterator cend() const noexcept;
164
165 reverse_iterator rbegin() noexcept;
166 const_reverse_iterator rbegin() const noexcept;
167 const_reverse_iterator crbegin() const noexcept;
168
169 reverse_iterator rend() noexcept;
170 const_reverse_iterator rend() const noexcept;
171 const_reverse_iterator crend() const noexcept;
172
173 bool empty() const noexcept;
174
175 size_type size() const noexcept;
176
183 void clear();
184
185 std::pair<iterator, bool> insert(value_type const &value);
186 std::pair<iterator, bool> insert(value_type &&value);
187 iterator insert(const_iterator hint, value_type const &value);
188 iterator insert(const_iterator hint, value_type &&value);
189 template <class InputIt>
190 void insert(InputIt first, InputIt last)
191 {
192 container().insert(first, last);
193 }
194 void insert(std::initializer_list<value_type> ilist);
195
196 void swap(Container &other);
197
198 mapped_type &at(key_type const &key);
199 mapped_type const &at(key_type const &key) const;
200
211 mapped_type &operator[](key_type const &key);
222 mapped_type &operator[](key_type &&key);
223
224 iterator find(key_type const &key);
225 const_iterator find(key_type const &key) const;
226
232 size_type count(key_type const &key) const;
233
240 bool contains(key_type const &key) const;
241
250 size_type erase(key_type const &key);
251
253 iterator erase(iterator res);
255 // virtual iterator erase(const_iterator first, const_iterator last)
256
257 template <class... Args>
258 auto emplace(Args &&...args)
259 -> decltype(InternalContainer().emplace(std::forward<Args>(args)...))
260 {
261 return container().emplace(std::forward<Args>(args)...);
262 }
263
264 // clang-format off
265OPENPMD_protected
266 // clang-format on
267
268 void clear_unchecked();
269
270 virtual void
271 flush(std::string const &path, internal::FlushParams const &flushParams);
272
273 Container();
274
275 Container(NoInit);
276
277public:
278 /*
279 * Need to define these manually due to the virtual inheritance from
280 * Attributable.
281 * Otherwise, they would only run from the most derived class
282 * if explicitly called.
283 * If not defining these, a user could destroy copy/move constructors/
284 * assignment operators by deriving from any class that has a virtual
285 * Attributable somewhere.
286 * Care must be taken in move constructors/assignment operators to not move
287 * multiple times (which could happen in diamond inheritance situations).
288 */
289
290 Container(Container const &other);
291
292 Container(Container &&other) noexcept;
293
294 Container &operator=(Container const &other);
295
296 Container &operator=(Container &&other) noexcept;
297};
298
299namespace internal
300{
310 template <typename Container_t>
311 class EraseStaleEntries
312 {
313 static_assert(
314 std::is_same_v<Container_t, std::remove_reference_t<Container_t>>);
315 using key_type = typename Container_t::key_type;
316 using mapped_type = typename Container_t::mapped_type;
317 std::set<key_type> m_accessedKeys;
318 /*
319 * Note: Putting a copy here leads to weird bugs due to destructors
320 * being called too eagerly upon destruction.
321 * Should be avoidable by extending the frontend redesign to the
322 * Container class template
323 * (https://github.com/openPMD/openPMD-api/pull/886)
324 */
325 Container_t &m_originalContainer;
326
327 public:
328 explicit EraseStaleEntries(Container_t &container_in);
329
330 EraseStaleEntries(EraseStaleEntries &&) = delete;
331 EraseStaleEntries &operator=(EraseStaleEntries &&) = delete;
332
333 mapped_type &operator[](typename Container_t::key_type const &k);
334
335 mapped_type &at(typename Container_t::key_type const &k);
336
342 void forget(typename Container_t::key_type const &k);
343
344 ~EraseStaleEntries();
345 };
346} // namespace internal
347} // namespace openPMD
Map-like container that enforces openPMD requirements and handles IO.
Definition Container.hpp:104
void clear()
Remove all objects from the container and (if written) from disk.
size_type erase(key_type const &key)
Remove a single element from the container and (if written) from disk.
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...
size_type count(key_type const &key) const
This returns either 1 if the key is found in the container of 0 if not.
bool contains(key_type const &key) const
Checks if there is an element with a key equivalent to an exiting key in the container.
iterator erase(iterator res)
auto emplace(Args &&...args) -> decltype(InternalContainer().emplace(std::forward< Args >(args)...))
Definition Container.hpp:258
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:71
InternalContainer m_container
Definition Container.hpp:78
This class wraps a Container and forwards operator[]() and at() to it.
Definition Container.hpp:312
void forget(typename Container_t::key_type const &k)
Remove key from the list of accessed keys.
Data members for Series.
Definition Series.hpp:90
Public definitions of openPMD-api.
Definition Date.cpp:29
@ T
time
Definition UnitDimension.hpp:41
Parameters recursively passed through the openPMD hierarchy when flushing.
Definition AbstractIOHandler.hpp:106
Container Element Creation Policy.
Definition Container.hpp:52