openPMD-api
BaseRecordComponent.hpp
1 /* Copyright 2017-2021 Fabian Koller
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/Dataset.hpp"
24 #include "openPMD/Error.hpp"
25 #include "openPMD/backend/Attributable.hpp"
26 
27 #include <optional>
28 
29 // expose private and protected members for invasive testing
30 #ifndef OPENPMD_protected
31 #define OPENPMD_protected protected:
32 #endif
33 
34 namespace openPMD
35 {
36 namespace internal
37 {
39  {
40  public:
44  std::optional<Dataset> m_dataset;
51  bool m_isConstant = false;
58  bool m_datasetDefined = false;
59 
63  operator=(BaseRecordComponentData const &) = delete;
64  BaseRecordComponentData &operator=(BaseRecordComponentData &&) = delete;
65 
66  BaseRecordComponentData() = default;
67 
68  virtual void reset()
69  {
70  m_dataset = std::nullopt;
71  m_isConstant = false;
72  m_datasetDefined = false;
73  }
74  };
75 } // namespace internal
76 
77 template <typename>
78 class BaseRecord;
79 
80 class BaseRecordComponent : virtual public Attributable
81 {
82  template <typename T, typename T_key, typename T_container>
83  friend class Container;
84 
85 public:
86  /*
87  * Need to define these manually due to the virtual inheritance from
88  * Attributable.
89  * Otherwise, they would only run from the most derived class
90  * if explicitly called.
91  * If not defining these, a user could destroy copy/move constructors/
92  * assignment operators by deriving from any class that has a virtual
93  * Attributable somewhere.
94  * Care must be taken in move constructors/assignment operators to not move
95  * multiple times (which could happen in diamond inheritance situations).
96  */
97 
99  : Attributable(NoInit())
100  {
101  m_attri = other.m_attri;
102  m_baseRecordComponentData = other.m_baseRecordComponentData;
103  }
104 
106  {
107  if (other.m_attri)
108  {
109  m_attri = std::move(other.m_attri);
110  }
111  m_baseRecordComponentData = std::move(other.m_baseRecordComponentData);
112  }
113 
114  BaseRecordComponent &operator=(BaseRecordComponent const &other)
115  {
116  m_attri = other.m_attri;
117  m_baseRecordComponentData = other.m_baseRecordComponentData;
118  return *this;
119  }
120 
121  BaseRecordComponent &operator=(BaseRecordComponent &&other)
122  {
123  if (other.m_attri)
124  {
125  m_attri = std::move(other.m_attri);
126  }
127  m_baseRecordComponentData = std::move(other.m_baseRecordComponentData);
128  return *this;
129  }
130 
131  double unitSI() const;
132 
133  BaseRecordComponent &resetDatatype(Datatype);
134 
135  Datatype getDatatype() const;
136 
144  bool constant() const;
145 
146  std::optional<size_t> joinedDimension() const;
147 
165  ChunkTable availableChunks();
166 
167 protected:
169  std::shared_ptr<Data_t> m_baseRecordComponentData;
170 
171  inline Data_t const &get() const
172  {
173  return *m_baseRecordComponentData;
174  }
175 
176  inline Data_t &get()
177  {
178  return *m_baseRecordComponentData;
179  }
180 
181  inline void setData(std::shared_ptr<Data_t> data)
182  {
183  m_baseRecordComponentData = std::move(data);
184  Attributable::setData(m_baseRecordComponentData);
185  }
186 
187  virtual void setDatasetDefined(Data_t &);
188 
189  bool datasetDefined() const;
190 
193 }; // BaseRecordComponent
194 
195 namespace detail
196 {
205  template <typename T_RecordComponent>
207  {
208  template <typename T>
209  static void call(T_RecordComponent &rc)
210  {
211  rc.makeConstant(T());
212  }
213 
214  template <unsigned n, typename... Args>
215  static void call(Args &&...)
216  {
217  throw std::runtime_error(
218  "makeEmpty: Datatype not supported by openPMD.");
219  }
220  };
221 } // namespace detail
222 } // namespace openPMD
Layer to manage storage of attributes associated with file objects.
Definition: Attributable.hpp:101
Definition: BaseRecordComponent.hpp:81
bool constant() const
Returns true if this is a constant record component.
Definition: BaseRecordComponent.cpp:63
ChunkTable availableChunks()
Get data chunks that are available to be loaded from the backend.
Definition: BaseRecordComponent.cpp:81
Map-like container that enforces openPMD requirements and handles IO.
Definition: Container.hpp:104
Definition: Attributable.hpp:57
Definition: BaseRecordComponent.hpp:39
std::optional< Dataset > m_dataset
The type and extent of the dataset defined by this component.
Definition: BaseRecordComponent.hpp:44
bool m_datasetDefined
Tracks if there was any write access to the record component.
Definition: BaseRecordComponent.hpp:58
bool m_isConstant
True if this is defined as a constant record component as specified in the openPMD standard.
Definition: BaseRecordComponent.hpp:51
Public definitions of openPMD-api.
Definition: Date.cpp:29
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:51
Definition: Attributable.hpp:125
Functor template to be used in combination with switchType::operator() to set a default value for con...
Definition: BaseRecordComponent.hpp:207