TECA
The Toolkit for Extreme Climate Analysis
teca_variant_array.h
Go to the documentation of this file.
1 #ifndef teca_variant_array_h
2 #define teca_variant_array_h
3 
4 /// @file
5 
6 #include <vector>
7 #include <string>
8 #include <sstream>
9 #include <exception>
10 #include <typeinfo>
11 #include <iterator>
12 #include <algorithm>
13 #include <type_traits>
14 #include <typeinfo>
15 #include <utility>
16 
17 #include "teca_common.h"
18 #include "teca_binary_stream.h"
19 #include "teca_bad_cast.h"
20 #include "teca_shared_object.h"
21 
22 TECA_SHARED_OBJECT_FORWARD_DECL(teca_variant_array)
23 TECA_SHARED_OBJECT_TEMPLATE_FORWARD_DECL(teca_variant_array_impl)
24 
25 #ifndef SWIG
27 using p_teca_string_array = std::shared_ptr<teca_variant_array_impl<std::string>>;
28 using const_p_teca_string_array = std::shared_ptr<const teca_variant_array_impl<std::string>>;
29 
31 using p_teca_float_array = std::shared_ptr<teca_variant_array_impl<float>>;
32 using const_p_teca_float_array = std::shared_ptr<const teca_variant_array_impl<float>>;
33 
35 using p_teca_double_array = std::shared_ptr<teca_variant_array_impl<double>>;
36 using const_p_teca_double_array = std::shared_ptr<const teca_variant_array_impl<double>>;
37 
39 using p_teca_char_array = std::shared_ptr<teca_variant_array_impl<char>>;
40 using const_p_teca_char_array = std::shared_ptr<const teca_variant_array_impl<char>>;
41 
43 using p_teca_unsigned_char_array = std::shared_ptr<teca_variant_array_impl<unsigned char>>;
44 using const_p_teca_unsigned_char_array = std::shared_ptr<const teca_variant_array_impl<unsigned char>>;
45 
47 using p_teca_short_array = std::shared_ptr<teca_variant_array_impl<short>>;
48 using const_p_teca_short_array = std::shared_ptr<const teca_variant_array_impl<short>>;
49 
51 using p_teca_unsigned_short_array = std::shared_ptr<teca_variant_array_impl<unsigned short>>;
52 using const_p_teca_unsigned_short_array = std::shared_ptr<const teca_variant_array_impl<unsigned short>>;
53 
55 using p_teca_int_array = std::shared_ptr<teca_variant_array_impl<int>>;
56 using const_p_teca_int_array = std::shared_ptr<const teca_variant_array_impl<int>>;
57 
59 using p_teca_unsigned_int_array = std::shared_ptr<teca_variant_array_impl<unsigned int>>;
60 using const_p_teca_unsigned_int_array = std::shared_ptr<const teca_variant_array_impl<unsigned int>>;
61 
63 using p_teca_long_array = std::shared_ptr<teca_variant_array_impl<long>>;
64 using const_p_teca_long_array = std::shared_ptr<const teca_variant_array_impl<long>>;
65 
67 using p_teca_unsigned_long_array = std::shared_ptr<teca_variant_array_impl<unsigned long>>;
68 using const_p_teca_unsigned_long_array = std::shared_ptr<const teca_variant_array_impl<unsigned long>>;
69 
71 using p_teca_long_long_array = std::shared_ptr<teca_variant_array_impl<long long>>;
72 using const_p_teca_long_long_array = std::shared_ptr<const teca_variant_array_impl<long long>>;
73 
75 using p_teca_unsigned_long_long_array = std::shared_ptr<teca_variant_array_impl<unsigned long long>>;
76 using const_p_teca_unsigned_long_long_array = std::shared_ptr<const teca_variant_array_impl<unsigned long long>>;
77 
79 using p_teca_size_t_array = std::shared_ptr<teca_variant_array_impl<size_t>>;
80 using const_p_teca_size_t_array = std::shared_ptr<const teca_variant_array_impl<size_t>>;
81 #endif
82 
83 /** this is a convenience macro to be used to declare a static
84  * New method that will be used to construct new objects in
85  * shared_ptr's. This manages the details of interoperability
86  * with std C++11 shared pointer
87  */
88 #define TECA_VARIANT_ARRAY_STATIC_NEW(T, t) \
89  \
90 /** Allocate a T<t> */ \
91 static std::shared_ptr<T<t>> New() \
92 { \
93  return std::shared_ptr<T<t>>(new T<t>); \
94 } \
95  \
96 /** Allocate a T<t> of size n */ \
97 static std::shared_ptr<T<t>> New(size_t n) \
98 { \
99  return std::shared_ptr<T<t>>(new T<t>(n)); \
100 } \
101  \
102 /** Allocate a T<t> of size n initialized with v */ \
103 static std::shared_ptr<T<t>> New(size_t n, const t &v) \
104 { \
105  return std::shared_ptr<T<t>>(new T<t>(n, v)); \
106 } \
107  \
108 /** Allocate a T<t> initialized with n values from vals */ \
109 static std::shared_ptr<T<t>> New(const t *vals, size_t n) \
110 { \
111  return std::shared_ptr<T<t>>(new T<t>(vals, n)); \
112 } \
113  \
114 using teca_variant_array::shared_from_this; \
115  \
116 std::shared_ptr<T> shared_from_this() \
117 { \
118  return std::static_pointer_cast<T>(shared_from_this()); \
119 } \
120  \
121 std::shared_ptr<T const> shared_from_this() const \
122 { \
123  return std::static_pointer_cast<T const>(shared_from_this()); \
124 }
125 
126 
127 
128 
129 
130 
131 
132 
133 /// @cond
134 /// A tag for dispatching operations on POD data
135 template <typename T>
136 struct pod_dispatch :
137  std::integral_constant<bool,
138  std::is_arithmetic<T>::value>
139 {};
140 
141 /// A tag for disp[atching operations on classes
142 template <typename T>
143 struct object_dispatch :
144  std::integral_constant<bool,
145  !std::is_arithmetic<T>::value>
146 {};
147 /// @endcond
148 
149 /** Executes the code in body if p is a tt<nt>
150  * @param tt derived container
151  * @param nt contained type
152  * @param p base class pointer
153  * @param body the code to execute if the type matches
154  *
155  * The following aliases are provided to know the type within the code to execute.
156  *
157  * using TT = tt<nt>;
158  * using NT = nt;
159  *
160  */
161 #define TEMPLATE_DISPATCH_CASE(tt, nt, p, body) \
162  if (dynamic_cast<tt<nt>*>(p)) \
163  { \
164  using TT = tt<nt>; \
165  using NT = nt; \
166  body \
167  }
168 
169 /** Executes the code in body if p is a tt<nt> an idnetifier disambiguates type
170  * aliases when nested
171  *
172  * @param tt derived container
173  * @param nt contained type
174  * @param p base class pointer
175  * @param i identifier
176  * @param body the code to execute if the type matches
177  *
178  * The following aliases are provided to know the type within the code to execute.
179  *
180  * using TT##i = tt<nt>;
181  * using NT##i = nt;
182  *
183  */
184 #define NESTED_TEMPLATE_DISPATCH_CASE(tt, nt, p, i, body) \
185  if (dynamic_cast<tt<nt>*>(p)) \
186  { \
187  using TT##i = tt<nt>; \
188  using NT##i = nt; \
189  body \
190  }
191 
192 /// Executes the code in body if p is a t<nt> where nt is a floating point type
193 #define TEMPLATE_DISPATCH_FP(t, p, body) \
194  TEMPLATE_DISPATCH_CASE(t, float, p, body) \
195  else TEMPLATE_DISPATCH_CASE(t, double, p, body)
196 
197 /// Executes the code in body if p is a t<nt> where nt is a signed inetegral type
198 #define TEMPLATE_DISPATCH_SI(t, p, body) \
199  TEMPLATE_DISPATCH_CASE(t, long long, p, body) \
200  else TEMPLATE_DISPATCH_CASE(t, long, p, body) \
201  else TEMPLATE_DISPATCH_CASE(t, int, p, body) \
202  else TEMPLATE_DISPATCH_CASE(t, short int, p, body) \
203  else TEMPLATE_DISPATCH_CASE(t, char, p, body)
204 
205 /// Executes the code in body if p is a t<nt> where nt is either a signed integral or floating point type
206 #define TEMPLATE_DISPATCH_FP_SI(t, p, body) \
207  TEMPLATE_DISPATCH_CASE(t, float, p, body) \
208  else TEMPLATE_DISPATCH_CASE(t, double, p, body) \
209  else TEMPLATE_DISPATCH_SI(t, p, body)
210 
211 /// Executes the code in body if p is a t<nt> where nt is an integral type
212 #define TEMPLATE_DISPATCH_I(t, p, body) \
213  TEMPLATE_DISPATCH_CASE(t, long long, p, body) \
214  else TEMPLATE_DISPATCH_CASE(t, unsigned long long, p, body) \
215  else TEMPLATE_DISPATCH_CASE(t, long, p, body) \
216  else TEMPLATE_DISPATCH_CASE(t, int, p, body) \
217  else TEMPLATE_DISPATCH_CASE(t, unsigned int, p, body) \
218  else TEMPLATE_DISPATCH_CASE(t, unsigned long, p, body) \
219  else TEMPLATE_DISPATCH_CASE(t, short int, p, body) \
220  else TEMPLATE_DISPATCH_CASE(t, short unsigned int, p, body) \
221  else TEMPLATE_DISPATCH_CASE(t, char, p, body) \
222  else TEMPLATE_DISPATCH_CASE(t, unsigned char, p, body)
223 
224 /** A macro for accessing the typed contents of a teca_variant_array
225  * @param t container type
226  * @param p pointer to an instance to match on
227  * @param body code to execute on match
228  *
229  * See #TEMPLATE_DISPATCH_CASE for details.
230  */
231 #define TEMPLATE_DISPATCH(t, p, body) \
232  TEMPLATE_DISPATCH_FP(t, p, body) \
233  else TEMPLATE_DISPATCH_I(t, p, body)
234 
235 /** A macro for accessing the floating point typed contents of a teca_variant_array
236  * @param t container type
237  * @param p pointer to an instance to match on
238  * @param i an indentifier to use with type aliases
239  * @param body code to execute on match
240  *
241  * See #NESTED_TEMPLATE_DISPATCH_CASE for details.
242  */
243 #define NESTED_TEMPLATE_DISPATCH_FP(t, p, i, body) \
244  NESTED_TEMPLATE_DISPATCH_CASE(t, float, p, i, body) \
245  else NESTED_TEMPLATE_DISPATCH_CASE(t, double, p, i, body)
246 
247 /** A macro for accessing the inetgral typed contents of a teca_variant_array
248  * @param t container type
249  * @param p pointer to an instance to match on
250  * @param i an indentifier to use with type aliases
251  * @param body code to execute on match
252  *
253  * See #NESTED_TEMPLATE_DISPATCH_CASE for details.
254  */
255 #define NESTED_TEMPLATE_DISPATCH_I(t, p, i, body) \
256  NESTED_TEMPLATE_DISPATCH_CASE(t, long long, p, i, body) \
257  else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned long long, p, i, body) \
258  else NESTED_TEMPLATE_DISPATCH_CASE(t, long, p, i, body) \
259  else NESTED_TEMPLATE_DISPATCH_CASE(t, int, p, i, body) \
260  else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned int, p, i, body) \
261  else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned long, p, i, body) \
262  else NESTED_TEMPLATE_DISPATCH_CASE(t, short int, p, i, body) \
263  else NESTED_TEMPLATE_DISPATCH_CASE(t, short unsigned int, p, i, body) \
264  else NESTED_TEMPLATE_DISPATCH_CASE(t, char, p, i, body) \
265  else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned char, p, i, body)
266 
267 /** \def NESTED_TEMPLATE_DISPATCH(t, p, i, body)
268  * A macro for accessing the typed contents of a teca_variant_array
269  * @param t container type
270  * @param p pointer to an instance to match on
271  * @param i an indentifier to use with type aliases
272  * @param body code to execute on match
273  *
274  * See #NESTED_TEMPLATE_DISPATCH_CASE for details.
275  */
276 #define NESTED_TEMPLATE_DISPATCH(t, p, i, body) \
277  NESTED_TEMPLATE_DISPATCH_FP(t, p, i, body) \
278  else NESTED_TEMPLATE_DISPATCH_I(t, p, i, body)
279 
280 
281 
282 /// A type agnostic container for array based data.
283 /** See #TEMPLATE_DISPATCH and #NESTED_TEMPLATE_DISPATCH for details on how to
284  * apply type specific code to an instance of teca_variant_array.
285  */
286 class teca_variant_array : public std::enable_shared_from_this<teca_variant_array>
287 {
288 public:
289  // construct
290  teca_variant_array() noexcept = default;
291  virtual ~teca_variant_array() noexcept = default;
292 
293  // copy/move construct. can't copy/move construct from a base
294  // pointer. these require a downcast.
295  teca_variant_array(const teca_variant_array &other) = delete;
296  teca_variant_array(teca_variant_array &&other) = delete;
297 
298  // copy assign
299  teca_variant_array &operator=(const teca_variant_array &other)
300  { this->copy(other); return *this; }
301 
302  // move assign
303  teca_variant_array &operator=(teca_variant_array &&other)
304  { this->swap(other); return *this; }
305 
306  // virtual constructor. return a newly allocated
307  // empty object of the same type.
308  virtual p_teca_variant_array new_instance() const = 0;
309  virtual p_teca_variant_array new_instance(size_t n) const = 0;
310 
311  // virtual copy construct. return a newly allocated object,
312  // initialized copy from this. caller must delete.
313  virtual p_teca_variant_array new_copy() const = 0;
314  virtual p_teca_variant_array new_copy(size_t start, size_t end) const = 0;
315 
316  // return true if values are equal
317  bool operator==(const teca_variant_array &other) const
318  { return this->equal(other); }
319 
320  // return the name of the class in a human readable form
321  virtual std::string get_class_name() const = 0;
322 
323  // initialize contents with the native type initializer
324  virtual void initialize() = 0;
325 
326  // get methods. could throw std::bad_cast if the
327  // internal type is not castable to the return type.
328  template<typename T>
329  void get(unsigned long i, T &val) const
330  { this->get_dispatch<T>(i, val); }
331 
332  template<typename T>
333  void get(std::vector<T> &vals) const
334  { this->get_dispatch<T>(vals); }
335 
336  template<typename T>
337  void get(size_t start, size_t end, T *vals) const
338  { this->get_dispatch<T>(start, end, vals); }
339 
340  // set methods. could throw std::bad_cast if the
341  // passed in type is not castable to the internal type.
342  template<typename T>
343  void set(const std::vector<T> &vals)
344  { this->set_dispatch<T>(vals); }
345 
346  template<typename T>
347  void set(unsigned long i, const T &val)
348  { this->set_dispatch<T>(i, val); }
349 
350  template<typename T>
351  void set(size_t start, size_t end, const T *vals)
352  { this->set_dispatch<T>(start, end, vals); }
353 
354  // append methods. could throw std::bad_cast if the
355  // passed in type is not castable to the internal type.
356  template<typename T>
357  void append(const T &val)
358  { this->append_dispatch(val); }
359 
360  template<typename T>
361  void append(const std::vector<T> &vals)
362  { this->append_dispatch(vals); }
363 
364  // get the number of elements in the array
365  virtual unsigned long size() const noexcept = 0;
366 
367  // resize. allocates new storage and copies in existing values
368  virtual void resize(unsigned long i) = 0;
369 
370  // reserve. reserves the requested amount of space with out
371  // constructing elements
372  virtual void reserve(unsigned long i) = 0;
373 
374  // free all the internal data
375  virtual void clear() noexcept = 0;
376 
377  // copy the contents from the other array.
378  // an exception is thrown when no conversion
379  // between the two types exists. This method
380  // is not virtual so that string can be handled
381  // as a special case in the base class.
382  void copy(const teca_variant_array &other);
383  void copy(const const_p_teca_variant_array &other)
384  { this->copy(*other.get()); }
385 
386  void append(const teca_variant_array &other);
387  void append(const const_p_teca_variant_array &other)
388  { this->append(*other.get()); }
389 
390  // swap the contents of this and the other object.
391  // an exception is thrown when no conversion
392  // between the two types exists.
393  virtual void swap(teca_variant_array &other) = 0;
394  void swap(const p_teca_variant_array &other)
395  { this->swap(*other.get()); }
396 
397  // compare the two objects for equality
398  virtual bool equal(const teca_variant_array &other) const = 0;
399  bool equal(const const_p_teca_variant_array &other) const
400  { return this->equal(*other.get()); }
401 
402  // serrialize to/from stream
403  virtual int to_stream(teca_binary_stream &s) const = 0;
404  virtual int from_stream(teca_binary_stream &s) = 0;
405 
406  virtual int to_stream(std::ostream &s) const = 0;
407  virtual int from_stream(std::ostream &s) = 0;
408 
409  // used for serialization
410  virtual unsigned int type_code() const noexcept = 0;
411 
412 private:
413  // dispatch methods, each set/get above has a pair
414  // one for POD and one for the rest. this allows us to
415  // seamlessly handle casting and conversion between POD
416  // types
417  template<typename T>
418  void append_dispatch(const std::vector<T> &vals,
419  typename std::enable_if<pod_dispatch<T>::value, T>::type* = 0);
420 
421  template<typename T>
422  void append_dispatch(const std::vector<T> &vals,
423  typename std::enable_if<object_dispatch<T>::value, T>::type* = 0);
424 
425  template<typename T>
426  void append_dispatch(const T &val,
427  typename std::enable_if<pod_dispatch<T>::value, T>::type* = 0);
428 
429  template<typename T>
430  void append_dispatch(const T &val,
431  typename std::enable_if<object_dispatch<T>::value, T>::type* = 0);
432  template<typename T>
433 
434  void set_dispatch(const std::vector<T> &vals,
435  typename std::enable_if<pod_dispatch<T>::value, T>::type* = 0);
436 
437  template<typename T>
438  void set_dispatch(const std::vector<T> &vals,
439  typename std::enable_if<object_dispatch<T>::value, T>::type* = 0);
440 
441  template<typename T>
442  void set_dispatch(unsigned long i, const T &val,
443  typename std::enable_if<pod_dispatch<T>::value, T>::type* = 0);
444 
445  template<typename T>
446  void set_dispatch(unsigned long i, const T &val,
447  typename std::enable_if<object_dispatch<T>::value, T>::type* = 0);
448 
449  template<typename T>
450  void set_dispatch(size_t start, size_t end, const T *vals,
451  typename std::enable_if<pod_dispatch<T>::value, T>::type* = 0);
452 
453  template<typename T>
454  void set_dispatch(size_t start, size_t end, const T *vals,
455  typename std::enable_if<object_dispatch<T>::value, T>::type* = 0);
456 
457  template<typename T>
458  void get_dispatch(std::vector<T> &vals,
459  typename std::enable_if<pod_dispatch<T>::value, T>::type* = 0) const;
460 
461  template<typename T>
462  void get_dispatch(std::vector<T> &vals,
463  typename std::enable_if<object_dispatch<T>::value, T>::type* = 0) const;
464 
465  template<typename T>
466  void get_dispatch(unsigned long i, T &val,
467  typename std::enable_if<pod_dispatch<T>::value, T>::type* = 0) const;
468 
469  template<typename T>
470  void get_dispatch(unsigned long i, T &val,
471  typename std::enable_if<object_dispatch<T>::value, T>::type* = 0) const;
472 
473  template<typename T>
474  void get_dispatch(size_t start, size_t end, T *vals,
475  typename std::enable_if<pod_dispatch<T>::value, T>::type* = 0) const;
476 
477  template<typename T>
478  void get_dispatch(size_t start, size_t end, T *vals,
479  typename std::enable_if<object_dispatch<T>::value, T>::type* = 0) const;
480 };
481 
482 
483 /// @cond
484 // tag for contiguous arrays, and objects that have
485 // overrides in teca_binary_stream
486 template<typename T>
487 struct pack_array
488  : std::integral_constant<bool,
489  std::is_arithmetic<T>::value ||
490  std::is_same<T, std::string>::value>
491 {};
492 
493 // tag for arrays of pointers of other objects
494 template<typename T>
495 struct pack_object_ptr
496  : std::integral_constant<bool,
497  (std::is_pointer<T>::value ||
498  std::is_same<T, p_teca_variant_array>::value) &&
499  !pack_array<T>::value>
500 {};
501 
502 // tag for arrays of other objects
503 template<typename T>
504 struct pack_object
505  : std::integral_constant<bool,
506  !pack_array<T>::value &&
507  !std::is_pointer<T>::value &&
508  !pack_object_ptr<T>::value>
509 {};
510 /// @endcond
511 
512 
513 /** @brief
514  * The concrete implementation of our type agnostic container for contiguous
515  * arrays.
516  */
517 template<typename T>
519 {
520 public:
521  /** @name Array constructors
522  * Constructs a new instance containing the templated type.
523  */
524  ///@{
526 
527  /// Returns a new instance initialized with a copy of this one.
528  p_teca_variant_array new_copy() const override;
529 
530  /// Returns a new instance initialized with a copy of a subset of this one.
531  p_teca_variant_array new_copy(size_t start, size_t end) const override;
532 
533  /// Returns a new instance of the same type.
534  p_teca_variant_array new_instance() const override;
535 
536  /// Returns a new instance of the same type sized to hold n elements.
537  p_teca_variant_array new_instance(size_t n) const override;
538  ///@}
539 
540  virtual ~teca_variant_array_impl() noexcept;
541 
542  /// Returns the name of the class in a human readable form
543  std::string get_class_name() const override;
544 
545  /// Initialize all elements with T()
546  void initialize() override;
547 
548  /// Copy from the other array
549  const teca_variant_array_impl<T> &
550  operator=(const teca_variant_array_impl<T> &other);
551 
552  /// Copy from the other array
553  template<typename U>
554  const teca_variant_array_impl<T> &
555  operator=(const teca_variant_array_impl<U> &other);
556 
557  /// Move the contents of the other array
559 
560  /// Move the contents of the other array
561  const teca_variant_array_impl<T> &
562  operator=(teca_variant_array_impl<T> &&other);
563 
564  /// Get the ith value
565  T &get(unsigned long i)
566  { return m_data[i]; }
567 
568  /// Get the ith value
569  const T &get(unsigned long i) const
570  { return m_data[i]; }
571 
572  /// Get the ith value
573  template<typename U>
574  void get(unsigned long i, U &val) const;
575 
576  // get a range of values described by [start end]
577  // inclusive
578  template<typename U>
579  void get(size_t start, size_t end, U *vals) const;
580 
581  /// Copy the data out into the passed in vector
582  template<typename U>
583  void get(std::vector<U> &val) const;
584 
585  /// Get a pointer to the data
586  T *get(){ return &m_data[0]; }
587  const T *get() const { return &m_data[0]; }
588 
589  /// Set the ith value
590  template<typename U>
591  void set(unsigned long i, const U &val);
592 
593  /// Set a range of values described by [start end] inclusive
594  template<typename U>
595  void set(size_t start, size_t end, const U *vals);
596 
597  /// Copy data, replacing contents with the passed in vector
598  template<typename U>
599  void set(const std::vector<U> &val);
600 
601  /// Insert from the passed in vector at the back
602  template<typename U>
603  void append(const std::vector<U> &val);
604 
605  // insert a single value at the back
606  template<typename U>
607  void append(const U &val);
608 
609  /// Get the current size of the data
610  virtual unsigned long size() const noexcept override;
611 
612  /// Resize the data
613  virtual void resize(unsigned long n) override;
614  void resize(unsigned long n, const T &val);
615 
616  /// Reserve space
617  virtual void reserve(unsigned long n) override;
618 
619  /// Clear the data
620  virtual void clear() noexcept override;
621 
622  /** copy. This method is not virtual so that string can be handled as a
623  * special case in the base class.
624  */
625  void copy(const teca_variant_array &other);
626 
627  /** append. This method is not virtual so that
628  * string can be handled as a special case in the base class.
629  */
630  void append(const teca_variant_array &other);
631 
632  /// virtual swap
633  void swap(teca_variant_array &other) override;
634 
635  /// virtual equivalence test
636  bool equal(const teca_variant_array &other) const override;
637 
638  /// Serialize to the stream
639  int to_stream(teca_binary_stream &s) const override
640  {
641  this->to_binary<T>(s);
642  return 0;
643  }
644 
645  /// Deserialize from the stream
647  {
648  this->from_binary<T>(s);
649  return 0;
650  }
651 
652  /// Serialize to the stream
653  int to_stream(std::ostream &s) const override
654  {
655  this->to_ascii<T>(s);
656  return 0;
657  }
658 
659  /// Deserialize from the stream
660  int from_stream(std::ostream &s) override
661  {
662  this->from_ascii<T>(s);
663  return 0;
664  }
665 
666 protected:
667  // construct
668  teca_variant_array_impl() noexcept {}
669 
670  // construct with preallocated size
671  teca_variant_array_impl(unsigned long n)
672  : m_data(n) {}
673 
674  // construct with preallocated size and initialized
675  // to a specific value
676  teca_variant_array_impl(unsigned long n, const T &v)
677  : m_data(n, v) {}
678 
679  // construct from a c-array of length n
680  teca_variant_array_impl(const T *vals, unsigned long n)
681  : teca_variant_array(), m_data(vals, vals+n) {}
682 
683  // copy construct from an instance of different type
684  template<typename U>
686  : teca_variant_array(), m_data(other.m_data) {}
687 
688  // copy construct from an instance of same type
690  : teca_variant_array(), m_data(other.m_data) {}
691 
692 private:
693  // tag dispatch c style array, and types that have overrides in
694  // binary stream
695  template <typename U = T>
696  void to_binary(teca_binary_stream &s,
697  typename std::enable_if<pack_array<U>::value, U>::type* = 0)
698  const;
699 
700  template <typename U = T>
701  void from_binary(teca_binary_stream &s,
702  typename std::enable_if<pack_array<U>::value, U>::type* = 0);
703 
704  // tag dispatch array of other objects
705  template <typename U = T>
706  void to_binary(teca_binary_stream &s,
707  typename std::enable_if<pack_object<U>::value, U>::type* = 0)
708  const;
709 
710  template <typename U = T>
711  void from_binary(teca_binary_stream &s,
712  typename std::enable_if<pack_object<U>::value, U>::type* = 0);
713 
714  // tag dispatch array of pointer to other objects
715  template <typename U = T>
716  void to_binary(teca_binary_stream &s,
717  typename std::enable_if<pack_object_ptr<U>::value, U>::type* = 0)
718  const;
719 
720  template <typename U = T>
721  void from_binary(teca_binary_stream &s,
722  typename std::enable_if<pack_object_ptr<U>::value, U>::type* = 0);
723 
724  // ostream
725  template <typename U = T>
726  void to_ascii(std::ostream &s,
727  typename std::enable_if<pack_array<U>::value, U>::type* = 0)
728  const;
729 
730  template <typename U = T>
731  void from_ascii(std::ostream &s,
732  typename std::enable_if<pack_array<U>::value, U>::type* = 0);
733 
734  // tag dispatch array of other objects
735  template <typename U = T>
736  void to_ascii(std::ostream &s,
737  typename std::enable_if<pack_object<U>::value, U>::type* = 0)
738  const;
739 
740  template <typename U = T>
741  void from_ascii(std::ostream &s,
742  typename std::enable_if<pack_object<U>::value, U>::type* = 0);
743 
744  // tag dispatch array of pointer to other objects
745  template <typename U = T>
746  void to_ascii(std::ostream &s,
747  typename std::enable_if<pack_object_ptr<U>::value, U>::type* = 0)
748  const;
749 
750  template <typename U = T>
751  void from_ascii(std::ostream &s,
752  typename std::enable_if<pack_object_ptr<U>::value, U>::type* = 0);
753 
754  // for serialization
755  unsigned int type_code() const noexcept override;
756 private:
757  std::vector<T> m_data;
758 
759  friend class teca_variant_array;
760  template<typename U> friend class teca_variant_array_impl;
761 };
762 
763 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
764 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
765 
766 // --------------------------------------------------------------------------
767 template<typename T>
768 void teca_variant_array::get_dispatch(std::vector<T> &vals,
769  typename std::enable_if<pod_dispatch<T>::value, T>::type*) const
770 {
772  TT *this_t = static_cast<TT*>(this);
773  this_t->get(vals);
774  return;
775  )
776  throw std::bad_cast();
777 }
778 
779 // --------------------------------------------------------------------------
780 template<typename T>
781 void teca_variant_array::get_dispatch(std::vector<T> &vals,
782  typename std::enable_if<object_dispatch<T>::value, T>::type*) const
783 {
785  TT *this_t = static_cast<TT*>(this);
786  this_t->get(vals);
787  return;
788  )
789  throw std::bad_cast();
790 }
791 
792 // --------------------------------------------------------------------------
793 template<typename T>
794 void teca_variant_array::get_dispatch(unsigned long i, T &val,
795  typename std::enable_if<pod_dispatch<T>::value, T>::type*) const
796 {
798  TT *this_t = static_cast<TT*>(this);
799  this_t->get(i, val);
800  return;
801  )
802  throw std::bad_cast();
803 }
804 
805 // --------------------------------------------------------------------------
806 template<typename T>
807 void teca_variant_array::get_dispatch(unsigned long i, T &val,
808  typename std::enable_if<object_dispatch<T>::value, T>::type*) const
809 {
811  TT *this_t = static_cast<TT*>(this);
812  this_t->get(i, val);
813  return;
814  )
815  throw std::bad_cast();
816 }
817 
818 // --------------------------------------------------------------------------
819 template<typename T>
820 void teca_variant_array::get_dispatch(size_t start, size_t end, T *vals,
821  typename std::enable_if<pod_dispatch<T>::value, T>::type*) const
822 {
824  TT *this_t = static_cast<TT*>(this);
825  this_t->get(start, end, vals);
826  return;
827  )
828  throw std::bad_cast();
829 }
830 
831 // --------------------------------------------------------------------------
832 template<typename T>
833 void teca_variant_array::get_dispatch(size_t start, size_t end, T *vals,
834  typename std::enable_if<object_dispatch<T>::value, T>::type*) const
835 {
837  TT *this_t = static_cast<TT*>(this);
838  this_t->get(start, end, vals);
839  return;
840  )
841  throw std::bad_cast();
842 }
843 
844 // --------------------------------------------------------------------------
845 template<typename T>
846 void teca_variant_array::set_dispatch(const std::vector<T> &vals,
847  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
848 {
850  TT *this_t = static_cast<TT*>(this);
851  this_t->set(vals);
852  return;
853  )
854  throw std::bad_cast();
855 }
856 
857 // --------------------------------------------------------------------------
858 template<typename T>
859 void teca_variant_array::set_dispatch(const std::vector<T> &vals,
860  typename std::enable_if<object_dispatch<T>::value, T>::type*)
861 {
863  TT *this_t = static_cast<TT*>(this);
864  this_t->set(vals);
865  return;
866  )
867  throw std::bad_cast();
868 }
869 
870 // --------------------------------------------------------------------------
871 template<typename T>
872 void teca_variant_array::set_dispatch(unsigned long i, const T &val,
873  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
874 {
876  TT *this_t = static_cast<TT*>(this);
877  this_t->set(i, val);
878  return;
879  )
880  throw std::bad_cast();
881 }
882 
883 // --------------------------------------------------------------------------
884 template<typename T>
885 void teca_variant_array::set_dispatch(unsigned long i, const T &val,
886  typename std::enable_if<object_dispatch<T>::value, T>::type*)
887 {
889  TT *this_t = static_cast<TT*>(this);
890  this_t->set(i, val);
891  return;
892  )
893  throw std::bad_cast();
894 }
895 
896 // --------------------------------------------------------------------------
897 template<typename T>
898 void teca_variant_array::set_dispatch(size_t start, size_t end, const T *vals,
899  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
900 {
902  TT *this_t = static_cast<TT*>(this);
903  this_t->set(start, end, vals);
904  return;
905  )
906  throw std::bad_cast();
907 }
908 
909 // --------------------------------------------------------------------------
910 template<typename T>
911 void teca_variant_array::set_dispatch(size_t start, size_t end, const T *vals,
912  typename std::enable_if<object_dispatch<T>::value, T>::type*)
913 {
915  TT *this_t = static_cast<TT*>(this);
916  this_t->set(start, end, vals);
917  return;
918  )
919  throw std::bad_cast();
920 }
921 
922 // --------------------------------------------------------------------------
923 template<typename T>
924 void teca_variant_array::append_dispatch(const std::vector<T> &vals,
925  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
926 {
928  TT *this_t = static_cast<TT*>(this);
929  this_t->append(vals);
930  return;
931  )
932  throw std::bad_cast();
933 }
934 
935 // --------------------------------------------------------------------------
936 template<typename T>
937 void teca_variant_array::append_dispatch(const std::vector<T> &vals,
938  typename std::enable_if<object_dispatch<T>::value, T>::type*)
939 {
941  TT *this_t = static_cast<TT*>(this);
942  this_t->append(vals);
943  return;
944  )
945  throw std::bad_cast();
946 }
947 
948 // --------------------------------------------------------------------------
949 template<typename T>
950 void teca_variant_array::append_dispatch(const T &val,
951  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
952 {
954  TT *this_t = static_cast<TT*>(this);
955  this_t->append(val);
956  return;
957  )
958  throw std::bad_cast();
959 }
960 
961 // --------------------------------------------------------------------------
962 template<typename T>
963 void teca_variant_array::append_dispatch(const T &val,
964  typename std::enable_if<object_dispatch<T>::value, T>::type*)
965 {
967  TT *this_t = static_cast<TT*>(this);
968  this_t->append(val);
969  return;
970  )
971  throw std::bad_cast();
972 }
973 
974 
975 
976 
977 
978 // --------------------------------------------------------------------------
979 template<typename T>
981 {
982  this->clear();
983 }
984 
985 // --------------------------------------------------------------------------
986 template<typename T>
988 {
990 }
991 
992 // --------------------------------------------------------------------------
993 template<typename T>
995  size_t start, size_t end) const
996 {
998  this->get(start, end, c->get());
999  return c;
1000 }
1001 
1002 // --------------------------------------------------------------------------
1003 template<typename T>
1005 {
1007 }
1008 
1009 // --------------------------------------------------------------------------
1010 template<typename T>
1012 {
1014 }
1015 
1016 // --------------------------------------------------------------------------
1017 template<typename T>
1020 {
1021  m_data.assign(other.m_data.begin(), other.m_data.end());
1022  return *this;
1023 }
1024 
1025 // copy assignment from different type
1026 // --------------------------------------------------------------------------
1027 template<typename T>
1028 template<typename U>
1031 {
1032  m_data.assign(other.m_data.begin(), other.m_data.end());
1033  return *this;
1034 }
1035 
1036 // --------------------------------------------------------------------------
1037 template<typename T>
1040  : m_data(std::move(other.m_data))
1041 {}
1042 
1043 // --------------------------------------------------------------------------
1044 template<typename T>
1047 {
1048  m_data = std::move(other.m_data);
1049  return *this;
1050 }
1051 
1052 // --------------------------------------------------------------------------
1053 template<typename T>
1055 {
1056  const char *element_name = typeid(T).name();
1057  size_t element_size = sizeof(T);
1058  std::ostringstream oss;
1059  oss << "teca_variant_array_impl<" << element_name
1060  << element_size << ">";
1061  return oss.str();
1062 }
1063 
1064 // --------------------------------------------------------------------------
1065 template<typename T>
1067 {
1068  m_data.assign(m_data.size(), T());
1069 }
1070 
1071 // --------------------------------------------------------------------------
1072 template<typename T>
1073 template<typename U>
1074 void teca_variant_array_impl<T>::get(unsigned long i, U &val) const
1075 {
1076  val = m_data[i];
1077 }
1078 
1079 // --------------------------------------------------------------------------
1080 template<typename T>
1081 template<typename U>
1082 void teca_variant_array_impl<T>::get(size_t start, size_t end, U *vals) const
1083 {
1084  for (size_t i = start, ii = 0; i <= end; ++i, ++ii)
1085  vals[ii] = m_data[i];
1086 }
1087 
1088 // --------------------------------------------------------------------------
1089 template<typename T>
1090 template<typename U>
1091 void teca_variant_array_impl<T>::get(std::vector<U> &val) const
1092 {
1093  val.assign(m_data.begin(), m_data.end());
1094 }
1095 
1096 // --------------------------------------------------------------------------
1097 template<typename T>
1098 template<typename U>
1099 void teca_variant_array_impl<T>::set(unsigned long i, const U &val)
1100 {
1101  m_data[i] = val;
1102 }
1103 
1104 // --------------------------------------------------------------------------
1105 template<typename T>
1106 template<typename U>
1107 void teca_variant_array_impl<T>::set(size_t start, size_t end, const U *vals)
1108 {
1109  for (size_t i = start, ii = 0; i <= end; ++i, ++ii)
1110  m_data[i] = vals[ii];
1111 }
1112 
1113 // --------------------------------------------------------------------------
1114 template<typename T>
1115 template<typename U>
1116 void teca_variant_array_impl<T>::set(const std::vector<U> &val)
1117 {
1118  size_t n = val.size();
1119  m_data.resize(n);
1120  for (size_t i = 0; i < n; ++i)
1121  m_data[i] = static_cast<T>(val[i]);
1122 }
1123 
1124 // --------------------------------------------------------------------------
1125 template<typename T>
1126 template<typename U>
1127 void teca_variant_array_impl<T>::append(const std::vector<U> &val)
1128 {
1129  std::copy(val.begin(), val.end(), std::back_inserter(m_data));
1130 }
1131 
1132 // --------------------------------------------------------------------------
1133 template<typename T>
1134 template<typename U>
1135 void teca_variant_array_impl<T>::append(const U &val)
1136 {
1137  m_data.push_back(val);
1138 }
1139 
1140 // --------------------------------------------------------------------------
1141 template<typename T>
1142 unsigned long teca_variant_array_impl<T>::size() const noexcept
1143 { return m_data.size(); }
1144 
1145 // --------------------------------------------------------------------------
1146 template<typename T>
1148 {
1149  m_data.resize(n);
1150 }
1151 
1152 // --------------------------------------------------------------------------
1153 template<typename T>
1154 void teca_variant_array_impl<T>::resize(unsigned long n, const T &val)
1155 {
1156  m_data.resize(n, val);
1157 }
1158 
1159 // --------------------------------------------------------------------------
1160 template<typename T>
1162 {
1163  m_data.reserve(n);
1164 }
1165 
1166 // --------------------------------------------------------------------------
1167 template<typename T>
1169 {
1170  m_data.clear();
1171 }
1172 
1173 // --------------------------------------------------------------------------
1174 template<typename T>
1176 {
1178  TT *other_t = static_cast<TT*>(&other);
1179  *this = *other_t;
1180  return;
1181  )
1182  throw teca_bad_cast(safe_class_name(&other), safe_class_name(this));
1183 }
1184 
1185 // --------------------------------------------------------------------------
1186 template<typename T>
1188 {
1190  TT *other_t = static_cast<TT*>(&other);
1191  std::copy(
1192  other_t->m_data.begin(),
1193  other_t->m_data.end(),
1194  std::back_inserter(this->m_data));
1195  return;
1196  )
1197  throw teca_bad_cast(safe_class_name(&other), safe_class_name(this));
1198 }
1199 
1200 // --------------------------------------------------------------------------
1201 template<typename T>
1203 {
1204  using TT = teca_variant_array_impl<T>;
1205  TT *other_t = dynamic_cast<TT*>(&other);
1206  if (other_t)
1207  {
1208  this->m_data.swap(other_t->m_data);
1209  return;
1210  }
1211  throw teca_bad_cast(safe_class_name(&other), safe_class_name(this));
1212 }
1213 
1214 // --------------------------------------------------------------------------
1215 template<typename T>
1217 {
1218  using TT = teca_variant_array_impl<T>;
1219  const TT *other_t = dynamic_cast<const TT*>(&other);
1220  if (other_t)
1221  {
1222  return this->m_data == other_t->m_data;
1223  }
1224  throw teca_bad_cast(safe_class_name(&other), safe_class_name(this));
1225  return false;
1226 }
1227 
1228 // --------------------------------------------------------------------------
1229 template<typename T>
1230  template <typename U>
1232  teca_binary_stream &s,
1233  typename std::enable_if<pack_array<U>::value, U>::type*) const
1234 {
1235  s.pack(this->m_data);
1236 }
1237 
1238 // --------------------------------------------------------------------------
1239 template<typename T>
1240  template <typename U>
1242  teca_binary_stream &s,
1243  typename std::enable_if<pack_array<U>::value, U>::type*)
1244 {
1245  s.unpack(this->m_data);
1246 }
1247 
1248 // --------------------------------------------------------------------------
1249 template<typename T>
1250  template <typename U>
1252  teca_binary_stream &s,
1253  typename std::enable_if<pack_object<U>::value, U>::type*) const
1254 {
1255  unsigned long long n = this->size();
1256  s.pack(n);
1257  for (unsigned long long i=0; i<n; ++i)
1258  this->m_data[i].to_stream(s);
1259 }
1260 
1261 // --------------------------------------------------------------------------
1262 template<typename T>
1263  template <typename U>
1265  teca_binary_stream &s,
1266  typename std::enable_if<pack_object<U>::value, U>::type*)
1267 {
1268  unsigned long long n;
1269  s.unpack(n);
1270  this->resize(n);
1271  for (unsigned long long i=0; i<n; ++i)
1272  this->m_data[i].from_stream(s);
1273 }
1274 
1275 // --------------------------------------------------------------------------
1276 template<typename T>
1277  template <typename U>
1279  teca_binary_stream &s,
1280  typename std::enable_if<pack_object_ptr<U>::value, U>::type*) const
1281 {
1282  unsigned long long n = this->size();
1283  s.pack(n);
1284  for (unsigned long long i=0; i<n; ++i)
1285  this->m_data[i]->to_stream(s);
1286 }
1287 
1288 // --------------------------------------------------------------------------
1289 template<typename T>
1290  template <typename U>
1292  teca_binary_stream &s,
1293  typename std::enable_if<pack_object_ptr<U>::value, U>::type*)
1294 {
1295  unsigned long long n;
1296  s.unpack(n);
1297  this->resize(n);
1298  for (unsigned long long i=0; i<n; ++i)
1299  this->m_data[i]->from_stream(s);
1300 }
1301 
1302 #define STR_DELIM(_a, _b) \
1303  (std::is_same<T, std::string>::value ? _a : _b)
1304 
1305 // --------------------------------------------------------------------------
1306 template<typename T>
1307  template <typename U>
1309  std::ostream &s,
1310  typename std::enable_if<pack_array<U>::value, U>::type*) const
1311 {
1312  size_t n = this->m_data.size();
1313  if (n)
1314  {
1315  s << STR_DELIM("\"", "")
1316  << this->m_data[0] << STR_DELIM("\"", "");
1317  for (size_t i = 1; i < n; ++i)
1318  {
1319  s << STR_DELIM(", \"", ", ")
1320  << this->m_data[i] << STR_DELIM("\"", "");
1321  }
1322  }
1323 }
1324 
1325 // --------------------------------------------------------------------------
1326 template<typename T>
1327  template <typename U>
1329  std::ostream &,
1330  typename std::enable_if<pack_array<U>::value, U>::type*)
1331 {
1332  // TODO
1333 }
1334 
1335 // --------------------------------------------------------------------------
1336 template<typename T>
1337  template <typename U>
1339  std::ostream &s,
1340  typename std::enable_if<pack_object<U>::value, U>::type*) const
1341 {
1342  size_t n = this->m_data.size();
1343  if (n)
1344  {
1345  s << "{";
1346  this->m_data[0].to_stream(s);
1347  s << "}";
1348  for (size_t i = 1; i < n; ++i)
1349  {
1350  s << ", {";
1351  this->m_data[i].to_stream(s);
1352  s << "}";
1353  }
1354  }
1355 }
1356 
1357 // --------------------------------------------------------------------------
1358 template<typename T>
1359  template <typename U>
1361  std::ostream &,
1362  typename std::enable_if<pack_object<U>::value, U>::type*)
1363 {
1364  // TODO
1365 }
1366 
1367 // --------------------------------------------------------------------------
1368 template<typename T>
1369  template <typename U>
1371  std::ostream &s,
1372  typename std::enable_if<pack_object_ptr<U>::value, U>::type*) const
1373 {
1374  size_t n = this->m_data.size();
1375  if (n)
1376  {
1377  s << "{";
1378  this->m_data[0]->to_stream(s);
1379  s << "}";
1380  for (size_t i = 1; i < n; ++i)
1381  {
1382  s << ", {";
1383  this->m_data[i]->to_stream(s);
1384  s << "}";
1385  }
1386  }
1387 }
1388 
1389 // --------------------------------------------------------------------------
1390 template<typename T>
1391  template <typename U>
1393  std::ostream &,
1394  typename std::enable_if<pack_object_ptr<U>::value, U>::type*)
1395 {
1396  // TODO
1397 }
1398 
1399 /// @cond
1400 template <typename T>
1401 struct teca_variant_array_code {};
1402 
1403 template <unsigned int I>
1404 struct teca_variant_array_new {};
1405 
1406 template <unsigned int I>
1407 struct teca_variant_array_type {};
1408 
1409 #define TECA_VARIANT_ARRAY_TT_SPEC(T, v) \
1410 template <> \
1411 struct teca_variant_array_code<T> \
1412 { \
1413  static constexpr unsigned int get() \
1414  { return v; } \
1415 }; \
1416 template <> \
1417 struct teca_variant_array_new<v> \
1418 { \
1419  static p_teca_variant_array_impl<T> New() \
1420  { return teca_variant_array_impl<T>::New(); } \
1421 }; \
1422 template <> \
1423 struct teca_variant_array_type<v> \
1424 { \
1425  using type = T; \
1426  \
1427  static constexpr const char *name() \
1428  { return #T; } \
1429 };
1430 
1431 #define TECA_VARIANT_ARRAY_FACTORY_NEW(_v) \
1432  case _v: \
1433  return teca_variant_array_new<_v>::New();
1434 
1435 #include "teca_metadata.h"
1436 class teca_metadata;
1437 
1438 TECA_VARIANT_ARRAY_TT_SPEC(char, 1)
1439 TECA_VARIANT_ARRAY_TT_SPEC(unsigned char, 2)
1440 TECA_VARIANT_ARRAY_TT_SPEC(int, 3)
1441 TECA_VARIANT_ARRAY_TT_SPEC(unsigned int, 4)
1442 TECA_VARIANT_ARRAY_TT_SPEC(short int, 5)
1443 TECA_VARIANT_ARRAY_TT_SPEC(short unsigned int, 6)
1444 TECA_VARIANT_ARRAY_TT_SPEC(long, 7)
1445 TECA_VARIANT_ARRAY_TT_SPEC(unsigned long, 8)
1446 TECA_VARIANT_ARRAY_TT_SPEC(long long, 9)
1447 TECA_VARIANT_ARRAY_TT_SPEC(unsigned long long, 10)
1448 TECA_VARIANT_ARRAY_TT_SPEC(float, 11)
1449 TECA_VARIANT_ARRAY_TT_SPEC(double, 12)
1450 TECA_VARIANT_ARRAY_TT_SPEC(std::string, 13)
1451 TECA_VARIANT_ARRAY_TT_SPEC(teca_metadata, 14)
1452 TECA_VARIANT_ARRAY_TT_SPEC(p_teca_variant_array, 15)
1453 /// @endcond
1454 
1455 /// Creates an instance of teca_variant_array_impl<T> where T is determined from the type code.
1457 {
1458  static p_teca_variant_array New(unsigned int type_code)
1459  {
1460  switch (type_code)
1461  {
1462  TECA_VARIANT_ARRAY_FACTORY_NEW(1)
1463  TECA_VARIANT_ARRAY_FACTORY_NEW(2)
1464  TECA_VARIANT_ARRAY_FACTORY_NEW(3)
1465  TECA_VARIANT_ARRAY_FACTORY_NEW(4)
1466  TECA_VARIANT_ARRAY_FACTORY_NEW(5)
1467  TECA_VARIANT_ARRAY_FACTORY_NEW(6)
1468  TECA_VARIANT_ARRAY_FACTORY_NEW(7)
1469  TECA_VARIANT_ARRAY_FACTORY_NEW(8)
1470  TECA_VARIANT_ARRAY_FACTORY_NEW(9)
1471  TECA_VARIANT_ARRAY_FACTORY_NEW(10)
1472  TECA_VARIANT_ARRAY_FACTORY_NEW(11)
1473  TECA_VARIANT_ARRAY_FACTORY_NEW(12)
1474  TECA_VARIANT_ARRAY_FACTORY_NEW(13)
1475  TECA_VARIANT_ARRAY_FACTORY_NEW(14)
1476  TECA_VARIANT_ARRAY_FACTORY_NEW(15)
1477  default:
1478  TECA_ERROR(
1479  << "Failed to create from "
1480  << type_code)
1481  }
1482  return nullptr;
1483  }
1484 };
1485 
1486 /// @cond
1487 #define CODE_DISPATCH_CASE(_v, _c, _code) \
1488  if (_v == _c) \
1489  { \
1490  using NT = teca_variant_array_type<_c>::type; \
1491  using TT = teca_variant_array_impl<NT>; \
1492  _code \
1493  }
1494 
1495 #define CODE_DISPATCH_I(_v, _code) \
1496  CODE_DISPATCH_CASE(_v, 1, _code) \
1497  else CODE_DISPATCH_CASE(_v, 2, _code) \
1498  else CODE_DISPATCH_CASE(_v, 3, _code) \
1499  else CODE_DISPATCH_CASE(_v, 4, _code) \
1500  else CODE_DISPATCH_CASE(_v, 5, _code) \
1501  else CODE_DISPATCH_CASE(_v, 6, _code) \
1502  else CODE_DISPATCH_CASE(_v, 7, _code) \
1503  else CODE_DISPATCH_CASE(_v, 8, _code) \
1504  else CODE_DISPATCH_CASE(_v, 9, _code) \
1505  else CODE_DISPATCH_CASE(_v, 10, _code)
1506 
1507 #define CODE_DISPATCH_FP(_v, _code) \
1508  CODE_DISPATCH_CASE(_v, 11, _code) \
1509  else CODE_DISPATCH_CASE(_v, 12, _code)
1510 
1511 #define CODE_DISPATCH_CLASS(_v, _code) \
1512  CODE_DISPATCH_CASE(_v, 13, _code) \
1513  else CODE_DISPATCH_CASE(_v, 14, _code) \
1514  else CODE_DISPATCH_CASE(_v, 15, _code)
1515 
1516 #define CODE_DISPATCH(_v, _code) \
1517  CODE_DISPATCH_I(_v, _code) \
1518  else CODE_DISPATCH_FP(_v, _code)
1519 
1520 /// @endcond
1521 
1522 // --------------------------------------------------------------------------
1523 template<typename T>
1524 unsigned int teca_variant_array_impl<T>::type_code() const noexcept
1525 {
1526  return teca_variant_array_code<T>::get();
1527 }
1528 
1529 // **************************************************************************
1530 template <typename num_t>
1531 num_t min(const const_p_teca_variant_array_impl<num_t> &a)
1532 {
1533  num_t mn = std::numeric_limits<num_t>::max();
1535  a.get(),
1536  const NT *pa = std::dynamic_pointer_cast<TT>(a)->get();
1537  size_t n = a->size();
1538  for (size_t i = 0; i < n; ++i)
1539  mn = mn > pa[i] ? pa[i] : mn;
1540  )
1541  return mn;
1542 }
1543 
1544 // **************************************************************************
1545 template <typename num_t>
1546 num_t min(const p_teca_variant_array_impl<num_t> &a)
1547 {
1549 }
1550 
1551 // **************************************************************************
1552 template <typename num_t>
1553 num_t max(const const_p_teca_variant_array_impl<num_t> &a)
1554 {
1555  num_t mx = std::numeric_limits<num_t>::lowest();
1557  a.get(),
1558  const NT *pa = std::dynamic_pointer_cast<TT>(a)->get();
1559  size_t n = a->size();
1560  for (size_t i = 0; i < n; ++i)
1561  mx = mx < pa[i] ? pa[i] : mx;
1562  )
1563  return mx;
1564 }
1565 
1566 // **************************************************************************
1567 template <typename num_t>
1568 num_t max(const p_teca_variant_array_impl<num_t> &a)
1569 {
1571 }
1572 
1573 #endif
teca_variant_array_impl::from_stream
int from_stream(std::ostream &s) override
Deserialize from the stream.
Definition: teca_variant_array.h:660
teca_variant_array_impl::get
T * get()
Get a pointer to the data.
Definition: teca_variant_array.h:586
teca_variant_array_impl::new_instance
p_teca_variant_array new_instance() const override
Returns a new instance of the same type.
Definition: teca_variant_array.h:1004
teca_variant_array_impl::clear
virtual void clear() noexcept override
Clear the data.
Definition: teca_variant_array.h:1168
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_variant_array_impl::new_copy
p_teca_variant_array new_copy() const override
Returns a new instance initialized with a copy of this one.
Definition: teca_variant_array.h:987
teca_variant_array_impl::from_stream
int from_stream(teca_binary_stream &s) override
Deserialize from the stream.
Definition: teca_variant_array.h:646
teca_variant_array
A type agnostic container for array based data.
Definition: teca_variant_array.h:286
teca_variant_array_impl
The concrete implementation of our type agnostic container for contiguous arrays.
Definition: teca_variant_array.h:23
teca_variant_array_impl::reserve
virtual void reserve(unsigned long n) override
Reserve space.
Definition: teca_variant_array.h:1161
teca_variant_array_impl::initialize
void initialize() override
Initialize all elements with T()
Definition: teca_variant_array.h:1066
teca_variant_array_impl::copy
void copy(const teca_variant_array &other)
Definition: teca_variant_array.h:1175
teca_variant_array_impl::append
void append(const std::vector< U > &val)
Insert from the passed in vector at the back.
Definition: teca_variant_array.h:1127
TECA_VARIANT_ARRAY_STATIC_NEW
#define TECA_VARIANT_ARRAY_STATIC_NEW(T, t)
Definition: teca_variant_array.h:88
teca_variant_array_impl::swap
void swap(teca_variant_array &other) override
virtual swap
Definition: teca_variant_array.h:1202
teca_variant_array_impl::size
virtual unsigned long size() const noexcept override
Get the current size of the data.
Definition: teca_variant_array.h:1142
teca_variant_array_impl::get
T & get(unsigned long i)
Get the ith value.
Definition: teca_variant_array.h:565
teca_common.h
teca_bad_cast
An exception that maybe thrown when a conversion between two data types fails.
Definition: teca_bad_cast.h:11
const_p_teca_variant_array
std::shared_ptr< const teca_variant_array > const_p_teca_variant_array
Definition: teca_variant_array.h:22
TEMPLATE_DISPATCH
#define TEMPLATE_DISPATCH(t, p, body)
Definition: teca_variant_array.h:231
const_p_teca_variant_array_impl
std::shared_ptr< const teca_variant_array_impl< T > > const_p_teca_variant_array_impl
Definition: teca_variant_array.h:23
teca_variant_array_impl::New
static std::shared_ptr< teca_variant_array_impl< T > > New()
Definition: teca_variant_array.h:525
teca_variant_array_impl::to_stream
int to_stream(teca_binary_stream &s) const override
Serialize to the stream.
Definition: teca_variant_array.h:639
teca_variant_array_impl::get_class_name
std::string get_class_name() const override
Returns the name of the class in a human readable form.
Definition: teca_variant_array.h:1054
TEMPLATE_DISPATCH_CASE
#define TEMPLATE_DISPATCH_CASE(tt, nt, p, body)
Definition: teca_variant_array.h:161
p_teca_variant_array_impl
std::shared_ptr< teca_variant_array_impl< T > > p_teca_variant_array_impl
Definition: teca_variant_array.h:23
teca_shared_object.h
teca_variant_array_impl::resize
virtual void resize(unsigned long n) override
Resize the data.
Definition: teca_variant_array.h:1147
teca_variant_array_impl::operator=
const teca_variant_array_impl< T > & operator=(const teca_variant_array_impl< T > &other)
Copy from the other array.
Definition: teca_variant_array.h:1019
p_teca_variant_array
std::shared_ptr< teca_variant_array > p_teca_variant_array
Definition: teca_variant_array.h:22
teca_variant_array_impl::get
const T & get(unsigned long i) const
Get the ith value.
Definition: teca_variant_array.h:569
teca_variant_array_impl::equal
bool equal(const teca_variant_array &other) const override
virtual equivalence test
Definition: teca_variant_array.h:1216
teca_variant_array_factory
Creates an instance of teca_variant_array_impl<T> where T is determined from the type code.
Definition: teca_variant_array.h:1456
teca_variant_array_impl::to_stream
int to_stream(std::ostream &s) const override
Serialize to the stream.
Definition: teca_variant_array.h:653
TECA_ERROR
#define TECA_ERROR(_msg)
Constructs an error message and sends it to the stderr stream.
Definition: teca_common.h:138
teca_variant_array_impl::set
void set(unsigned long i, const U &val)
Set the ith value.
Definition: teca_variant_array.h:1099
teca_py_array::copy
bool copy(teca_variant_array *varr, PyObject *obj)
Copy values from the object into variant array.
Definition: teca_py_array.h:270