TECA
teca_table.h
1 #ifndef teca_table_h
2 #define teca_table_h
3 
4 #include "teca_dataset.h"
5 #include "teca_variant_array.h"
6 #include "teca_array_collection.h"
7 #include "teca_shared_object.h"
8 
9 #include <map>
10 #include <vector>
11 #include <string>
12 
13 TECA_SHARED_OBJECT_FORWARD_DECL(teca_table)
14 
15 
19 class teca_table : public teca_dataset
20 {
21 public:
22  TECA_DATASET_STATIC_NEW(teca_table)
23  TECA_DATASET_NEW_INSTANCE()
24  TECA_DATASET_NEW_COPY()
25 
26  virtual ~teca_table() = default;
27 
28  // set/get metadata
29  TECA_DATASET_METADATA(calendar, std::string, 1)
30  TECA_DATASET_METADATA(time_units, std::string, 1)
31 
32  // remove all column definitions and data
33  void clear();
34 
35  // define the table columns. requires name,type pairs
36  // for ex. define("c1",int(),"c2",float()) creates a
37  // table with 2 columns the first storing int's the
38  // second storing float's.
39  template<typename nT, typename cT, typename... oT>
40  void declare_columns(nT &&col_name, cT col_type, oT &&...args);
41 
42  // add a column definition to the table.
43  template<typename nT, typename cT>
44  void declare_column(nT &&col_name, cT col_type);
45 
46  // get the number of rows/columns
47  unsigned int get_number_of_columns() const noexcept;
48  unsigned long get_number_of_rows() const noexcept;
49 
50  // get a specific column. return a nullptr if
51  // the column doesn't exist.
52  p_teca_variant_array get_column(unsigned int i);
53  p_teca_variant_array get_column(const std::string &col_name);
54 
55  const_p_teca_variant_array get_column(unsigned int i) const;
56  const_p_teca_variant_array get_column(const std::string &col_name) const;
57 
58  // test for the existance of a specific column
59  bool has_column(const std::string &col_name) const
60  { return m_impl->columns->has(col_name); }
61 
62  // get the name of the column, see also get_number_of_columns
63  std::string get_column_name(unsigned int i) const
64  { return m_impl->columns->get_name(i); }
65 
66  // add a column
67  int append_column(p_teca_variant_array array)
68  { return m_impl->columns->append(array); }
69 
70  int append_column(const std::string &name, p_teca_variant_array array)
71  { return m_impl->columns->append(name, array); }
72 
73  // remove a column
74  int remove_column(unsigned int i)
75  { return m_impl->columns->remove(i); }
76 
77  int remove_column(const std::string &name)
78  { return m_impl->columns->remove(name); }
79 
80  // get container holding columns
81  p_teca_array_collection get_columns()
82  { return m_impl->columns; }
83 
84  const_p_teca_array_collection get_columns() const
85  { return m_impl->columns; }
86 
87  // default initialize n rows of data
88  void resize(unsigned long n);
89 
90  // reserve memory for future rows
91  void reserve(unsigned long n);
92 
93  // append the collection of data in succession to
94  // each column. see also operator<< for sequential
95  // stream insertion like append.
96  template<typename cT, typename... oT>
97  void append(cT &&val, oT &&... args);
98 
99  // return a unique string identifier
100  std::string get_class_name() const override
101  { return "teca_table"; }
102 
103  // return an integer identifier uniquely naming the dataset type
104  int get_type_code() const override;
105 
106  // covert to bool. true if the dataset is not empty.
107  // otherwise false.
108  explicit operator bool() const noexcept
109  { return !this->empty(); }
110 
111  // return true if the dataset is empty.
112  bool empty() const noexcept override;
113 
114  // serialize the dataset to/from the given stream
115  // for I/O or communication
116  int to_stream(teca_binary_stream &) const override;
117  int from_stream(teca_binary_stream &) override;
118 
119  // stream to/from human readable representation
120  int to_stream(std::ostream &) const override;
121  int from_stream(std::istream &) override;
122 
123  // copy data and metadata. shallow copy uses reference
124  // counting, while copy duplicates the data.
125  void copy(const const_p_teca_dataset &other) override;
126 
127  // deep copy a subset of row values.
128  void copy(const const_p_teca_table &other,
129  unsigned long first_row, unsigned long last_row);
130 
131  void shallow_copy(const p_teca_dataset &other) override;
132 
133  // copy the column layout and types
134  void copy_structure(const const_p_teca_table &other);
135 
136  // swap internals of the two objects
137  void swap(p_teca_dataset &other) override;
138 
139  // append rows from the passed in table which must have identical
140  // columns.
141  void concatenate_rows(const const_p_teca_table &other);
142 
143  // append columns from the passed in table which must have same
144  // number of rows. if deep flag is true a full copy of the data
145  // is made, else a shallow copy is made.
146  void concatenate_cols(const const_p_teca_table &other, bool deep=false);
147 
148 protected:
149  teca_table();
150 
151  teca_table(const teca_table &other) = delete;
152  teca_table(teca_table &&other) = delete;
153  teca_table &operator=(const teca_table &other) = delete;
154 
155  void declare_columns(){}
156  void append(){}
157 
158 private:
159  struct impl_t
160  {
161  impl_t();
162  //
163  p_teca_array_collection columns;
164  unsigned int active_column;
165  };
166  std::shared_ptr<impl_t> m_impl;
167 };
168 
169 
170 
171 
172 
173 // --------------------------------------------------------------------------
174 inline
175 p_teca_variant_array teca_table::get_column(unsigned int i)
176 {
177  return m_impl->columns->get(i);
178 }
179 
180 // --------------------------------------------------------------------------
181 inline
182 const_p_teca_variant_array teca_table::get_column(unsigned int i) const
183 {
184  return m_impl->columns->get(i);
185 }
186 
187 // --------------------------------------------------------------------------
188 template<typename nT, typename cT, typename... oT>
189 void teca_table::declare_columns(nT &&col_name, cT col_type, oT &&... args)
190 {
191  m_impl->columns->declare(std::forward<nT>(col_name), col_type);
192  this->declare_columns(args...);
193 }
194 
195 // --------------------------------------------------------------------------
196 template<typename nT, typename cT>
197 void teca_table::declare_column(nT &&col_name, cT col_type)
198 {
199  m_impl->columns->declare(std::forward<nT>(col_name), col_type);
200 }
201 
202 // --------------------------------------------------------------------------
203 template<typename cT, typename... oT>
204 void teca_table::append(cT &&val, oT &&... args)
205 {
206  unsigned int col = m_impl->active_column++%this->get_number_of_columns();
207  m_impl->columns->get(col)->append(std::forward<cT>(val));
208  this->append(args...);
209 }
210 
211 template<typename T>
212 p_teca_table &operator<<(p_teca_table &t, T &&v)
213 {
214  t->append(std::forward<T>(v));
215  return t;
216 }
217 
218 #endif
teca_binary_stream
Definition: teca_binary_stream.h:16
teca_dataset
Definition: teca_dataset.h:14
teca_table
Definition: teca_table.h:20