TECA
The Toolkit for Extreme Climate Analysis
teca_dataset.h
1 #ifndef teca_dataset_h
2 #define teca_dataset_h
3 
4 #include "teca_common.h"
5 #include "teca_shared_object.h"
6 #include "teca_variant_array.h"
7 
8 #include <vector>
9 #include <iosfwd>
10 
11 class teca_binary_stream;
12 class teca_metadata;
13 
14 TECA_SHARED_OBJECT_FORWARD_DECL(teca_dataset)
15 
16 // this is a convenience macro to be used to
17 // declare New and enable seamless operation
18 // with std C++11 shared pointer
19 #define TECA_DATASET_STATIC_NEW(T) \
20  \
21 static p_##T New() \
22 { \
23  return p_##T(new T); \
24 } \
25  \
26 std::shared_ptr<T> shared_from_this() \
27 { \
28  return std::static_pointer_cast<T>( \
29  teca_dataset::shared_from_this()); \
30 } \
31  \
32 std::shared_ptr<T const> shared_from_this() const \
33 { \
34  return std::static_pointer_cast<T const>( \
35  teca_dataset::shared_from_this()); \
36 }
37 
38 // convenience macro implementing new_instance method
39 #define TECA_DATASET_NEW_INSTANCE() \
40 virtual p_teca_dataset new_instance() const override\
41 { \
42  return this->New(); \
43 }
44 
45 // convenience macro implementing new_copy method
46 #define TECA_DATASET_NEW_COPY() \
47 virtual p_teca_dataset new_copy() const override \
48 { \
49  p_teca_dataset o = this->new_instance(); \
50  o->copy(this->shared_from_this()); \
51  return o; \
52 } \
53  \
54 virtual p_teca_dataset new_shallow_copy() override \
55 { \
56  p_teca_dataset o = this->new_instance(); \
57  o->shallow_copy(this->shared_from_this()); \
58  return o; \
59 }
60 
61 // convenience macro for adding properties to dataset
62 // objects
63 #define TECA_DATASET_PROPERTY(T, name) \
64  \
65 void set_##name(const T &val) \
66 { \
67  this->name = val; \
68 } \
69  \
70 const T &get_##name() const \
71 { \
72  return this->name; \
73 } \
74  \
75 T &get_##name() \
76 { \
77  return this->name; \
78 }
79 
80 // convenience set get methods for dataset metadata
81 #define TECA_DATASET_METADATA(key, T, len) \
82 TECA_DATASET_METADATA_V(T, key, len) \
83 TECA_DATASET_METADATA_A(T, key, len) \
84 TECA_DATASET_METADATA_ ## len (T, key)
85 
86 
87 #define TECA_DATASET_METADATA_1(T, key) \
88 void set_##key(const T & val_1) \
89 { \
90  this->get_metadata().set<T>(#key, val_1); \
91 } \
92  \
93 int get_##key(T &val_1) const \
94 { \
95  return this->get_metadata().get<T>( \
96  #key, val_1); \
97 }
98 
99 #define TECA_DATASET_METADATA_2(T, key) \
100 void set_##key(const T & val_1, const T & val_2) \
101 { \
102  this->get_metadata().set<T>( \
103  #key, {val_1, val_2}); \
104 } \
105  \
106 int get_##key(T &val_1, T &val_2) const \
107 { \
108  std::vector<T> vals; \
109  if (this->get_metadata().get<T>(#key, vals)) \
110  return -1; \
111  val_1 = vals[0]; \
112  val_2 = vals[1]; \
113  return 0; \
114 }
115 
116 #define TECA_DATASET_METADATA_3(T, key) \
117 void set_##key(const T & val_1, const T & val_2, \
118  const T & val_3) \
119 { \
120  this->get_metadata().set<T>(#key, \
121  {val_1, val_2, val_3}); \
122 } \
123  \
124 int get_##key(T &val_1, T &val_2, T &val_3) const \
125 { \
126  std::vector<T> vals; \
127  if (this->get_metadata().get<T>(#key, vals)) \
128  return -1; \
129  val_1 = vals[0]; \
130  val_2 = vals[1]; \
131  val_3 = vals[2]; \
132  return 0; \
133 }
134 
135 #define TECA_DATASET_METADATA_4(T, key) \
136 void set_##key(const T & val_1, const T & val_2, \
137  const T & val_3, const T & val_4) \
138 { \
139  this->get_metadata().set<T>(#key, \
140  {val_1, val_2, val_3, val_4}); \
141 }
142 
143 #define TECA_DATASET_METADATA_6(T, key) \
144 void set_##key(const T & val_1, const T & val_2, \
145  const T & val_3, const T & val_4, \
146  const T & val_5, const T & val_6) \
147 { \
148  this->get_metadata().set<T>(#key, \
149  {val_1, val_2, val_3, \
150  val_4, val_5, val_6}); \
151 }
152 
153 #define TECA_DATASET_METADATA_8(T, key) \
154 void set_##key(const T & val_1, const T & val_2, \
155  const T & val_3, const T & val_4, \
156  const T & val_5, const T & val_6, \
157  const T & val_7, const T & val_8) \
158 { \
159  this->get_metadata().set<T>(#key, \
160  {val_1, val_2, val_3, val_4, val_5, \
161  val_6, val_7, val_8}); \
162 }
163 
164 #define TECA_DATASET_METADATA_V(T, key, len) \
165 void set_##key(const std::vector<T> &vals) \
166 { \
167  if (vals.size() != len) \
168  { \
169  TECA_ERROR(#key " requires " #len " values") \
170  } \
171  this->get_metadata().set<T>(#key, vals); \
172 } \
173  \
174 int get_##key(std::vector<T> &vals) const \
175 { \
176  return this->get_metadata().get<T>(#key, vals); \
177 } \
178  \
179 void set_##key(const p_teca_variant_array &vals) \
180 { \
181  if (vals->size() != len) \
182  { \
183  TECA_ERROR(#key " requires " #len " values") \
184  } \
185  this->get_metadata().set(#key, vals); \
186 } \
187  \
188 int get_##key(p_teca_variant_array vals) const \
189 { \
190  return this->get_metadata().get(#key, vals); \
191 } \
192  \
193 void set_##key(const std::initializer_list<T> &l) \
194 { \
195  std::vector<T> vals(l); \
196  if (vals.size() != len) \
197  { \
198  TECA_ERROR(#key " requires " #len " values") \
199  } \
200  this->get_metadata().set<T>(#key, vals); \
201 } \
202 
203 #define TECA_DATASET_METADATA_A(T, key, len) \
204 void set_##key(const T *vals) \
205 { \
206  this->get_metadata().set<T>(#key, vals, len); \
207 } \
208  \
209 int get_##key(T *vals) const \
210 { \
211  return this->get_metadata().get<T>( \
212  #key, vals, len); \
213 }
214 
215 /// Interface for TECA datasets.
216 class teca_dataset : public std::enable_shared_from_this<teca_dataset>
217 {
218 public:
219  virtual ~teca_dataset();
220 
221  // the name of the key that holds the index identifying this dataset
222  // this should be set by the algorithm that creates the dataset.
223  TECA_DATASET_METADATA(index_request_key, std::string, 1)
224 
225  // a dataset metadata that uses the value of index_request_key to
226  // store the index that identifies this dataset. this should be set
227  // by the algorithm that creates the dataset.
228  virtual int get_request_index(long &val) const;
229  virtual int set_request_index(const std::string &key, long val);
230  virtual int set_request_index(long val);
231 
232  // covert to boolean. true if the dataset is not empty.
233  // otherwise false.
234  explicit operator bool() const noexcept
235  { return !this->empty(); }
236 
237  // return true if the dataset is empty.
238  virtual bool empty() const noexcept
239  { return true; }
240 
241  // virtual constructor. return a new dataset of the same type.
242  virtual p_teca_dataset new_instance() const = 0;
243 
244  // virtual copy constructor. return a shallow/deep copy of this
245  // dataset in a new instance.
246  virtual p_teca_dataset new_copy() const = 0;
247  virtual p_teca_dataset new_shallow_copy() = 0;
248 
249  // return a string identifier uniquely naming the dataset type
250  virtual std::string get_class_name() const = 0;
251 
252  // return an integer identifier uniquely naming the dataset type
253  virtual int get_type_code() const = 0;
254 
255  // copy data and metadata. shallow copy uses reference
256  // counting, while copy duplicates the data.
257  virtual void copy(const const_p_teca_dataset &other);
258  virtual void shallow_copy(const p_teca_dataset &other);
259 
260  // copy metadata. always a deep copy.
261  virtual void copy_metadata(const const_p_teca_dataset &other);
262 
263  // swap internals of the two objects
264  virtual void swap(const p_teca_dataset &other);
265 
266  // access metadata
267  virtual teca_metadata &get_metadata() noexcept;
268  virtual const teca_metadata &get_metadata() const noexcept;
269  virtual void set_metadata(const teca_metadata &md);
270 
271  // serialize the dataset to/from the given stream
272  // for I/O or communication
273  virtual int to_stream(teca_binary_stream &) const;
274  virtual int from_stream(teca_binary_stream &);
275 
276  // stream to/from human readable representation
277  virtual int to_stream(std::ostream &) const;
278  virtual int from_stream(std::istream &);
279 
280 protected:
281  teca_dataset();
282 
283  teca_dataset(const teca_dataset &) = delete;
284  teca_dataset(const teca_dataset &&) = delete;
285 
286  void operator=(const p_teca_dataset &other) = delete;
287  void operator=(p_teca_dataset &&other) = delete;
288 
289  teca_metadata *metadata;
290 };
291 
292 #endif
teca_variant_array.h
teca_binary_stream
Serialize objects into a binary stream.
Definition: teca_binary_stream.h:15
teca_metadata
A generic container for meta data in the form of name=value pairs.
Definition: teca_metadata.h:18
teca_dataset
Interface for TECA datasets.
Definition: teca_dataset.h:216
teca_common.h
teca_shared_object.h