openPMD-api
Attribute.hpp
1 /* Copyright 2017-2020 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/auxiliary/Variant.hpp"
24 #include "openPMD/Datatype.hpp"
25 
26 #include <algorithm>
27 #include <array>
28 #include <cstdint>
29 #include <iterator>
30 #include <stdexcept>
31 #include <string>
32 #include <type_traits>
33 #include <utility>
34 #include <vector>
35 
36 
37 namespace openPMD
38 {
39 //TODO This might have to be a Writable
40 //Reasoning - Flushes are expected to be done often.
41 //Attributes should not be written unless dirty.
42 //At the moment the dirty check is done at Attributable level,
43 //resulting in all of an Attributables Attributes being written to disk even if only one changes
49 class Attribute :
50  public auxiliary::Variant< Datatype,
51  char, unsigned char, // signed char,
52  short, int, long, long long,
53  unsigned short, unsigned int, unsigned long, unsigned long long,
54  float, double, long double,
55  std::string,
56  std::vector< char >,
57  std::vector< short >,
58  std::vector< int >,
59  std::vector< long >,
60  std::vector< long long >,
61  std::vector< unsigned char >,
62  std::vector< unsigned short >,
63  std::vector< unsigned int >,
64  std::vector< unsigned long >,
65  std::vector< unsigned long long >,
66  std::vector< float >,
67  std::vector< double >,
68  std::vector< long double >,
69  std::vector< std::string >,
70  std::array< double, 7 >,
71  bool >
72 {
73 public:
74  Attribute(resource r) : Variant(std::move(r))
75  { }
76 
86  template< typename U >
87  U get() const;
88 };
89 
90 template< typename T, typename U, bool isConvertible = std::is_convertible<T, U>::value >
91 struct DoConvert;
92 
93 template< typename T, typename U >
94 struct DoConvert<T, U, false>
95 {
96  template< typename PV >
97  U operator()( PV )
98  {
99  throw std::runtime_error("getCast: no cast possible.");
100  }
101 };
102 
103 template< typename T, typename U >
104 struct DoConvert<T, U, true>
105 {
106  template< typename PV >
107  U operator()( PV pv )
108  {
109  return static_cast< U >( *pv );
110  }
111 };
112 
113 template< typename T, typename U >
114 struct DoConvert<std::vector< T >, std::vector< U >, false>
115 {
116  static constexpr bool convertible = std::is_convertible<T, U>::value;
117 
118  template< typename PV, typename UU = U >
119  auto operator()( PV pv )
120  -> typename std::enable_if< convertible, std::vector< UU > >::type
121  {
122  std::vector< U > u;
123  u.reserve( pv->size() );
124  std::copy( pv->begin(), pv->end(), std::back_inserter(u) );
125  return u;
126  }
127 
128  template< typename PV, typename UU = U >
129  auto operator()( PV )
130  -> typename std::enable_if< !convertible, std::vector< UU > >::type
131  {
132  throw std::runtime_error("getCast: no vector cast possible.");
133  }
134 };
135 
142 template< typename U >
143 inline U
144 getCast( Attribute const & a )
145 {
146  auto v = a.getResource();
147 
148  if(auto pvalue_c = variantSrc::get_if< char >( &v ) )
149  return DoConvert<char, U>{}(pvalue_c);
150  else if(auto pvalue_uc = variantSrc::get_if< unsigned char >( &v ) )
151  return DoConvert<unsigned char, U>{}(pvalue_uc);
152  else if(auto pvalue_s = variantSrc::get_if< short >( &v ) )
153  return DoConvert<short, U>{}(pvalue_s);
154  else if(auto pvalue_i = variantSrc::get_if< int >( &v ) )
155  return DoConvert<int, U>{}(pvalue_i);
156  else if(auto pvalue_l = variantSrc::get_if< long >( &v ) )
157  return DoConvert<long, U>{}(pvalue_l);
158  else if(auto pvalue_ll = variantSrc::get_if< long long >( &v ) )
159  return DoConvert<long long, U>{}(pvalue_ll);
160  else if(auto pvalue_us = variantSrc::get_if< unsigned short >( &v ) )
161  return DoConvert<unsigned short, U>{}(pvalue_us);
162  else if(auto pvalue_ui = variantSrc::get_if< unsigned int >( &v ) )
163  return DoConvert<unsigned int, U>{}(pvalue_ui);
164  else if(auto pvalue_ul = variantSrc::get_if< unsigned long >( &v ) )
165  return DoConvert<unsigned long, U>{}(pvalue_ul);
166  else if(auto pvalue_ull = variantSrc::get_if< unsigned long long >( &v ) )
167  return DoConvert<unsigned long long, U>{}(pvalue_ull);
168  else if(auto pvalue_f = variantSrc::get_if< float >( &v ) )
169  return DoConvert<float, U>{}(pvalue_f);
170  else if(auto pvalue_d = variantSrc::get_if< double >( &v ) )
171  return DoConvert<double, U>{}(pvalue_d);
172  else if(auto pvalue_ld = variantSrc::get_if< long double >( &v ) )
173  return DoConvert<long double, U>{}(pvalue_ld);
174  else if(auto pvalue_str = variantSrc::get_if< std::string >( &v ) )
175  return DoConvert<std::string, U>{}(pvalue_str);
176  // vector
177  else if(auto pvalue_vc = variantSrc::get_if< std::vector< char > >( &v ) )
178  return DoConvert<std::vector< char >, U>{}(pvalue_vc);
179  else if(auto pvalue_vuc = variantSrc::get_if< std::vector< unsigned char > >( &v ) )
180  return DoConvert<std::vector< unsigned char >, U>{}(pvalue_vuc);
181  else if(auto pvalue_vs = variantSrc::get_if< std::vector< short > >( &v ) )
182  return DoConvert<std::vector< short >, U>{}(pvalue_vs);
183  else if(auto pvalue_vi = variantSrc::get_if< std::vector< int > >( &v ) )
184  return DoConvert<std::vector< int >, U>{}(pvalue_vi);
185  else if(auto pvalue_vl = variantSrc::get_if< std::vector< long > >( &v ) )
186  return DoConvert<std::vector< long >, U>{}(pvalue_vl);
187  else if(auto pvalue_vll = variantSrc::get_if< std::vector< long long > >( &v ) )
188  return DoConvert<std::vector< long long >, U>{}(pvalue_vll);
189  else if(auto pvalue_vus = variantSrc::get_if< std::vector< unsigned short > >( &v ) )
190  return DoConvert<std::vector< unsigned short >, U>{}(pvalue_vus);
191  else if(auto pvalue_vui = variantSrc::get_if< std::vector< unsigned int > >( &v ) )
192  return DoConvert<std::vector< unsigned int >, U>{}(pvalue_vui);
193  else if(auto pvalue_vul = variantSrc::get_if< std::vector< unsigned long > >( &v ) )
194  return DoConvert<std::vector< unsigned long >, U>{}(pvalue_vul);
195  else if(auto pvalue_vull = variantSrc::get_if< std::vector< unsigned long long > >( &v ) )
196  return DoConvert<std::vector< unsigned long long >, U>{}(pvalue_vull);
197  else if(auto pvalue_vf = variantSrc::get_if< std::vector< float > >( &v ) )
198  return DoConvert<std::vector< float >, U>{}(pvalue_vf);
199  else if(auto pvalue_vd = variantSrc::get_if< std::vector< double > >( &v ) )
200  return DoConvert<std::vector< double >, U>{}(pvalue_vd);
201  else if(auto pvalue_vld = variantSrc::get_if< std::vector< long double > >( &v ) )
202  return DoConvert<std::vector< long double >, U>{}(pvalue_vld);
203  else if(auto pvalue_vstr = variantSrc::get_if< std::vector< std::string > >( &v ) )
204  return DoConvert<std::vector< std::string >, U>{}(pvalue_vstr);
205  // extra
206  else if(auto pvalue_vad = variantSrc::get_if< std::array< double, 7 > >( &v ) )
207  return DoConvert<std::array< double, 7 >, U>{}(pvalue_vad);
208  else if(auto pvalue_b = variantSrc::get_if< bool >( &v ) )
209  return DoConvert<bool, U>{}(pvalue_b);
210  else
211  throw std::runtime_error("getCast: unknown Datatype.");
212 }
213 
214 template< typename U >
215 U Attribute::get() const
216 {
217  return getCast< U >( Variant::getResource() );
218 }
219 
220 } // namespace openPMD
U get() const
Retrieve a stored specific Attribute and cast if convertible.
Definition: Attribute.hpp:215
Definition: Attribute.hpp:91
STL namespace.
Generic object to store a set of datatypes in without losing type safety.
Definition: Variant.hpp:44
U getCast(Attribute const &a)
Retrieve a stored specific Attribute and cast if convertible.
Definition: Attribute.hpp:144
Varidic datatype supporting at least all formats for attributes specified in the openPMD standard...
Definition: Attribute.hpp:49
Public definitions of openPMD-api.
Definition: Date.cpp:28
resource getResource() const
Retrieve the stored generic object.
Definition: Variant.hpp:78