libdballe  9.11
commonapi.h
1 #ifndef DBALLE_FORTRAN_COMMONAPI_H
2 #define DBALLE_FORTRAN_COMMONAPI_H
3 
4 #include "api.h"
5 #include "enq.h"
6 #include <dballe/core/cursor.h>
7 #include <dballe/core/enq.h>
8 #include <dballe/values.h>
9 #include <dballe/core/query.h>
10 #include <dballe/core/data.h>
11 #include <functional>
12 #include <cstring>
13 
14 namespace dballe {
15 namespace fortran {
16 
20 struct Attributes
21 {
22  Values values;
23  Values::const_iterator current;
24  bool valid = false;
25 
28 
30  void invalidate();
31 
38  void has_new_values();
39 };
40 
44 class Operation
45 {
46 public:
47  virtual ~Operation();
48  virtual void set_varcode(wreport::Varcode varcode);
49  virtual void query_attributes(Attributes& dest) = 0;
50  virtual void insert_attributes(Values& qcinput) = 0;
51  virtual void remove_attributes() = 0;
52  virtual bool next_station();
53  virtual wreport::Varcode next_data();
54 
55  virtual int enqi(const char* param) const = 0;
56  virtual signed char enqb(const char* param) const;
57  virtual float enqr(const char* param) const;
58  virtual double enqd(const char* param) const = 0;
59  virtual bool enqc(const char* param, char* res, unsigned res_len) const = 0;
60  virtual void enqlevel(int& ltype1, int& l1, int& ltype2, int& l2) const = 0;
61  virtual void enqtimerange(int& ptype, int& p1, int& p2) const = 0;
62  virtual void enqdate(int& year, int& month, int& day, int& hour, int& min, int& sec) const = 0;
63 };
64 
65 namespace {
66 
67 inline Level cursor_get_level(const CursorStation& c) { return Level(); }
68 inline Level cursor_get_level(const CursorStationData& c) { return Level(); }
69 inline Level cursor_get_level(const CursorData& c) { return c.get_level(); }
70 inline Level cursor_get_level(const CursorSummary& c) { return c.get_level(); }
71 inline Trange cursor_get_trange(const CursorStation& c) { return Trange(); }
72 inline Trange cursor_get_trange(const CursorStationData& c) { return Trange(); }
73 inline Trange cursor_get_trange(const CursorData& c) { return c.get_trange(); }
74 inline Trange cursor_get_trange(const CursorSummary& c) { return c.get_trange(); }
75 inline Datetime cursor_get_datetime(const CursorStation& c) { return Datetime(); }
76 inline Datetime cursor_get_datetime(const CursorSummary& c) { return Datetime(); }
77 inline Datetime cursor_get_datetime(const CursorStationData& c) { return Datetime(); }
78 inline Datetime cursor_get_datetime(const CursorData& c) { return c.get_datetime(); }
79 
80 }
81 
82 template<typename Cursor>
83 struct CursorOperation : public Operation
84 {
85  std::shared_ptr<Cursor> cursor;
86 
88  {
89  if (cursor) cursor->discard();
90  }
91 
92  int enqi(const char* param) const override
93  {
94  if (!cursor)
95  throw wreport::error_consistency("enqi called before running a query");
96 
97  impl::Enqi enq(param, strlen(param));
98  cursor->enq(enq);
99  if (enq.missing)
100  return API::missing_int;
101  return enq.res;
102  }
103  double enqd(const char* param) const override
104  {
105  if (!cursor)
106  throw wreport::error_consistency("enqd called before running a query");
107  impl::Enqd enq(param, strlen(param));
108  cursor->enq(enq);
109  if (enq.missing)
110  return API::missing_double;
111  return enq.res;
112  }
113  bool enqc(const char* param, char* res, unsigned res_len) const override
114  {
115  if (!cursor)
116  throw wreport::error_consistency("enqc called before running a query");
117  Enqc enq(param, strlen(param), res, res_len);
118  cursor->enq(enq);
119  return !enq.missing;
120  }
121  void enqlevel(int& ltype1, int& l1, int& ltype2, int& l2) const override
122  {
123  Level lev = cursor_get_level(*cursor);
124  ltype1 = lev.ltype1 != MISSING_INT ? lev.ltype1 : API::missing_int;
125  l1 = lev.l1 != MISSING_INT ? lev.l1 : API::missing_int;
126  ltype2 = lev.ltype2 != MISSING_INT ? lev.ltype2 : API::missing_int;
127  l2 = lev.l2 != MISSING_INT ? lev.l2 : API::missing_int;
128  }
129  void enqtimerange(int& ptype, int& p1, int& p2) const override
130  {
131  Trange tr = cursor_get_trange(*cursor);
132  ptype = tr.pind != MISSING_INT ? tr.pind : API::missing_int;
133  p1 = tr.p1 != MISSING_INT ? tr.p1 : API::missing_int;
134  p2 = tr.p2 != MISSING_INT ? tr.p2 : API::missing_int;
135  }
136  void enqdate(int& year, int& month, int& day, int& hour, int& min, int& sec) const override
137  {
138  Datetime dt = cursor_get_datetime(*cursor);
139  year = dt.year != 0xffff ? dt.year : API::missing_int;
140  month = dt.month != 0xff ? dt.month : API::missing_int;
141  day = dt.day != 0xff ? dt.day : API::missing_int;
142  hour = dt.hour != 0xff ? dt.hour : API::missing_int;
143  min = dt.minute != 0xff ? dt.minute : API::missing_int;
144  sec = dt.second != 0xff ? dt.second : API::missing_int;
145  }
146 };
147 
153 {
154 public:
155  enum Permissions {
156  PERM_ANA_RO = (1 << 0),
157  PERM_ANA_WRITE = (1 << 1),
158  PERM_DATA_RO = (1 << 2),
159  PERM_DATA_ADD = (1 << 3),
160  PERM_DATA_WRITE = (1 << 4),
161  PERM_ATTR_RO = (1 << 5),
162  PERM_ATTR_WRITE = (1 << 6)
163  };
164 
168  static unsigned compute_permissions(const char* anaflag, const char* dataflag, const char* attrflag);
169 
170  unsigned perms = 0;
171 
172  core::Query input_query;
173  /*
174  * Fortran code wants to do something like set("var", …); unset("varlist").
175  *
176  * If both var and varlist edit input_query.varcodes, the unset of varlist
177  * will also unset the previous set of var, with unexpected results.
178  *
179  * To work around this, var and varlist are stored in the following
180  * members, and merged into input_query when validate_input_query() is
181  * called.
182  */
183  wreport::Varcode input_query_var = 0;
184  std::set<wreport::Varcode> input_query_varlist;
185 
186  core::Data input_data;
188  std::vector<wreport::Varcode> selected_attr_codes;
189  bool station_context = false;
190  Values qcinput;
191  Attributes qcoutput;
192 
193 protected:
194  Operation* operation = nullptr;
195 
196  // Last string returned by one of the spiega* functions, held here so
197  // that we can deallocate it when needed.
198  std::string cached_spiega;
199 
200  bool _seti(const char* key, unsigned len, int val);
201  bool _setd(const char* key, unsigned len, double val);
202  bool _setc(const char* key, unsigned len, const char* val);
203  bool _unset(const char* key, unsigned len);
204  void validate_input_query();
205 
206 public:
210  virtual ~CommonAPIImplementation();
211  CommonAPIImplementation& operator=(const CommonAPIImplementation&) = delete;
212  CommonAPIImplementation& operator=(CommonAPIImplementation&&) = delete;
213 
214  template<typename Operation>
215  auto reset_operation(Operation* op) -> decltype(op->run())
216  {
217  delete operation;
218  operation = op;
219  qcoutput.invalidate();
220  return op->run();
221  }
222 
223  void reset_operation()
224  {
225  delete operation;
226  operation = nullptr;
227  qcoutput.invalidate();
228  }
229 
230  int enqi(const char* param) override;
231  signed char enqb(const char* param) override;
232  float enqr(const char* param) override;
233  double enqd(const char* param) override;
234  bool enqc(const char* param, char* res, unsigned res_len) override;
235  void seti(const char* param, int value) override;
236  void setb(const char* param, signed char value) override;
237  void setr(const char* param, float value) override;
238  void setd(const char* param, double value) override;
239  void setc(const char* param, const char* value) override;
240  void set_station_context() override;
241  void enqlevel(int& ltype1, int& l1, int& ltype2, int& l2) override;
242  void setlevel(int ltype1, int l1, int ltype2, int l2) override;
243  void enqtimerange(int& ptype, int& p1, int& p2) override;
244  void settimerange(int ptype, int p1, int p2) override;
245  void enqdate(int& year, int& month, int& day, int& hour, int& min, int& sec) override;
246  void setdate(int year, int month, int day, int hour, int min, int sec) override;
247  void setdatemin(int year, int month, int day, int hour, int min, int sec) override;
248  void setdatemax(int year, int month, int day, int hour, int min, int sec) override;
249  void unset(const char* param) override;
250  void unsetall() override;
251  void unsetb() override;
252  const char* describe_level(int ltype1, int l1, int ltype2, int l2) override;
253  const char* describe_timerange(int ptype, int p1, int p2) override;
254  const char* describe_var(const char* varcode, const char* value) override;
255  void next_station() override;
256  wreport::Varcode next_data() override;
257  int query_attributes() override;
258  const char* next_attribute() override;
259  void insert_attributes() override;
260  void remove_attributes() override;
261  void commit() override;
262 
263  const Operation* test_get_operation() const { return operation; }
264 
265  const core::Query& test_get_input_query() const { return input_query; }
266  const core::Data& test_get_input_data() const { return input_data; }
267  const Values& test_get_qcinput() const { return qcinput; }
268 
269  friend class Operation;
270 };
271 
272 }
273 }
274 #endif
std::vector< wreport::Varcode > selected_attr_codes
Selected attribute varcodes (*varlist)
Definition: commonapi.h:188
int ltype1
Type of the level or the first layer.
Definition: types.h:627
wreport::Varcode next()
Return the next attribute in the result set.
int ltype2
Type of the the second layer.
Definition: types.h:631
void invalidate()
Mark the result set as invalid.
Storage for currently queried attributes.
Definition: commonapi.h:20
Common implementation of the set* and enq* machinery using input and output records.
Definition: commonapi.h:152
int p1
Time range P1 indicator.
Definition: types.h:691
static unsigned compute_permissions(const char *anaflag, const char *dataflag, const char *attrflag)
Set the permission bits, parsing the flags and doing consistency checks.
Definition: commonapi.h:83
Information on how a value has been sampled or computed with regards to time.
Definition: types.h:686
int pind
Time range type indicator.
Definition: types.h:689
Standard dballe::Query implementation.
Definition: core/query.h:34
Operation-specific behaviour for the API.
Definition: commonapi.h:44
Definition: cmdline.h:18
C++ implementation for the Fortran API.
Definition: api.h:15
Vertical level or layer.
Definition: types.h:624
Definition: fortran/enq.h:10
int l2
L2 value of the second layer.
Definition: types.h:633
uint16_t Varcode
Definition: core/enq.h:156
void has_new_values()
Mark that there is a new set of values in values.
Cursor iterating over station data values.
Definition: cursor.h:66
Date and time.
Definition: types.h:164
Cursor iterating over stations.
Definition: cursor.h:56
Holds data for database I/O.
Definition: core/data.h:17
Structures used as input to database insert functions.
int l1
L1 value of the level or the first layer.
Definition: types.h:629
int p2
Time range P2 indicator.
Definition: types.h:693
Collection of Value objects, indexed by wreport::Varcode.
Definition: values.h:176
Definition: core/enq.h:206