libdballe  9.14
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 <cstring>
7 #include <dballe/core/cursor.h>
8 #include <dballe/core/data.h>
9 #include <dballe/core/enq.h>
10 #include <dballe/core/query.h>
11 #include <dballe/values.h>
12 #include <functional>
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 
27  wreport::Varcode next();
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,
63  int& sec) const = 0;
64 };
65 
66 namespace {
67 
68 inline Level cursor_get_level(const CursorStation& c) { return Level(); }
69 inline Level cursor_get_level(const CursorStationData& c) { return Level(); }
70 inline Level cursor_get_level(const CursorData& c) { return c.get_level(); }
71 inline Level cursor_get_level(const CursorSummary& c) { return c.get_level(); }
72 inline Trange cursor_get_trange(const CursorStation& c) { return Trange(); }
73 inline Trange cursor_get_trange(const CursorStationData& c) { return Trange(); }
74 inline Trange cursor_get_trange(const CursorData& c) { return c.get_trange(); }
75 inline Trange cursor_get_trange(const CursorSummary& c)
76 {
77  return c.get_trange();
78 }
79 inline Datetime cursor_get_datetime(const CursorStation& c)
80 {
81  return Datetime();
82 }
83 inline Datetime cursor_get_datetime(const CursorSummary& c)
84 {
85  return Datetime();
86 }
87 inline Datetime cursor_get_datetime(const CursorStationData& c)
88 {
89  return Datetime();
90 }
91 inline Datetime cursor_get_datetime(const CursorData& c)
92 {
93  return c.get_datetime();
94 }
95 
96 } // namespace
97 
98 template <typename Cursor> struct CursorOperation : public Operation
99 {
100  std::shared_ptr<Cursor> cursor;
101 
102  ~CursorOperation()
103  {
104  if (cursor)
105  cursor->discard();
106  }
107 
108  int enqi(const char* param) const override
109  {
110  if (!cursor)
112  "enqi called before running a query");
113 
114  impl::Enqi enq(param, strlen(param));
115  cursor->enq(enq);
116  if (enq.missing)
117  return API::missing_int;
118  return enq.res;
119  }
120  double enqd(const char* param) const override
121  {
122  if (!cursor)
124  "enqd called before running a query");
125  impl::Enqd enq(param, strlen(param));
126  cursor->enq(enq);
127  if (enq.missing)
128  return API::missing_double;
129  return enq.res;
130  }
131  bool enqc(const char* param, char* res, unsigned res_len) const override
132  {
133  if (!cursor)
135  "enqc called before running a query");
136  Enqc enq(param, strlen(param), res, res_len);
137  cursor->enq(enq);
138  return !enq.missing;
139  }
140  void enqlevel(int& ltype1, int& l1, int& ltype2, int& l2) const override
141  {
142  Level lev = cursor_get_level(*cursor);
143  ltype1 = lev.ltype1 != MISSING_INT ? lev.ltype1 : API::missing_int;
144  l1 = lev.l1 != MISSING_INT ? lev.l1 : API::missing_int;
145  ltype2 = lev.ltype2 != MISSING_INT ? lev.ltype2 : API::missing_int;
146  l2 = lev.l2 != MISSING_INT ? lev.l2 : API::missing_int;
147  }
148  void enqtimerange(int& ptype, int& p1, int& p2) const override
149  {
150  Trange tr = cursor_get_trange(*cursor);
151  ptype = tr.pind != MISSING_INT ? tr.pind : API::missing_int;
152  p1 = tr.p1 != MISSING_INT ? tr.p1 : API::missing_int;
153  p2 = tr.p2 != MISSING_INT ? tr.p2 : API::missing_int;
154  }
155  void enqdate(int& year, int& month, int& day, int& hour, int& min,
156  int& sec) const override
157  {
158  Datetime dt = cursor_get_datetime(*cursor);
159  year = dt.year != 0xffff ? dt.year : API::missing_int;
160  month = dt.month != 0xff ? dt.month : API::missing_int;
161  day = dt.day != 0xff ? dt.day : API::missing_int;
162  hour = dt.hour != 0xff ? dt.hour : API::missing_int;
163  min = dt.minute != 0xff ? dt.minute : API::missing_int;
164  sec = dt.second != 0xff ? dt.second : API::missing_int;
165  }
166 };
167 
173 {
174 public:
175  enum Permissions {
176  PERM_ANA_RO = (1 << 0),
177  PERM_ANA_WRITE = (1 << 1),
178  PERM_DATA_RO = (1 << 2),
179  PERM_DATA_ADD = (1 << 3),
180  PERM_DATA_WRITE = (1 << 4),
181  PERM_ATTR_RO = (1 << 5),
182  PERM_ATTR_WRITE = (1 << 6)
183  };
184 
188  static unsigned compute_permissions(const char* anaflag,
189  const char* dataflag,
190  const char* attrflag);
191 
192  unsigned perms = 0;
193 
194  core::Query input_query;
195  /*
196  * Fortran code wants to do something like set("var", …); unset("varlist").
197  *
198  * If both var and varlist edit input_query.varcodes, the unset of varlist
199  * will also unset the previous set of var, with unexpected results.
200  *
201  * To work around this, var and varlist are stored in the following
202  * members, and merged into input_query when validate_input_query() is
203  * called.
204  */
205  wreport::Varcode input_query_var = 0;
206  std::set<wreport::Varcode> input_query_varlist;
207 
208  core::Data input_data;
210  std::vector<wreport::Varcode> selected_attr_codes;
211  bool station_context = false;
212  Values qcinput;
213  Attributes qcoutput;
214 
215 protected:
216  Operation* operation = nullptr;
217 
218  // Last string returned by one of the spiega* functions, held here so
219  // that we can deallocate it when needed.
220  std::string cached_spiega;
221 
222  bool _seti(const char* key, unsigned len, int val);
223  bool _setd(const char* key, unsigned len, double val);
224  bool _setc(const char* key, unsigned len, const char* val);
225  bool _unset(const char* key, unsigned len);
226  void validate_input_query();
227 
228 public:
232  virtual ~CommonAPIImplementation();
233  CommonAPIImplementation& operator=(const CommonAPIImplementation&) = delete;
234  CommonAPIImplementation& operator=(CommonAPIImplementation&&) = delete;
235 
236  template <typename Operation>
237  auto reset_operation(Operation* op) -> decltype(op->run())
238  {
239  delete operation;
240  operation = op;
241  qcoutput.invalidate();
242  return op->run();
243  }
244 
245  void reset_operation()
246  {
247  delete operation;
248  operation = nullptr;
249  qcoutput.invalidate();
250  }
251 
252  int enqi(const char* param) override;
253  signed char enqb(const char* param) override;
254  float enqr(const char* param) override;
255  double enqd(const char* param) override;
256  bool enqc(const char* param, char* res, unsigned res_len) override;
257  void seti(const char* param, int value) override;
258  void setb(const char* param, signed char value) override;
259  void setr(const char* param, float value) override;
260  void setd(const char* param, double value) override;
261  void setc(const char* param, const char* value) override;
262  void set_station_context() override;
263  void enqlevel(int& ltype1, int& l1, int& ltype2, int& l2) override;
264  void setlevel(int ltype1, int l1, int ltype2, int l2) override;
265  void enqtimerange(int& ptype, int& p1, int& p2) override;
266  void settimerange(int ptype, int p1, int p2) override;
267  void enqdate(int& year, int& month, int& day, int& hour, int& min,
268  int& sec) override;
269  void setdate(int year, int month, int day, int hour, int min,
270  int sec) override;
271  void setdatemin(int year, int month, int day, int hour, int min,
272  int sec) override;
273  void setdatemax(int year, int month, int day, int hour, int min,
274  int sec) override;
275  void unset(const char* param) override;
276  void unsetall() override;
277  void unsetb() override;
278  const char* describe_level(int ltype1, int l1, int ltype2, int l2) override;
279  const char* describe_timerange(int ptype, int p1, int p2) override;
280  const char* describe_var(const char* varcode, const char* value) override;
281  void next_station() override;
282  wreport::Varcode next_data() override;
283  int query_attributes() override;
284  const char* next_attribute() override;
285  void insert_attributes() override;
286  void remove_attributes() override;
287  void commit() override;
288 
289  const Operation* test_get_operation() const { return operation; }
290 
291  const core::Query& test_get_input_query() const { return input_query; }
292  const core::Data& test_get_input_data() const { return input_data; }
293  const Values& test_get_qcinput() const { return qcinput; }
294 
295  friend class Operation;
296 };
297 
298 } // namespace fortran
299 } // namespace dballe
300 #endif
std::vector< wreport::Varcode > selected_attr_codes
Selected attribute varcodes (*varlist)
Definition: commonapi.h:210
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:172
int p1
Time range P1 indicator.
Definition: types.h:693
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:98
Information on how a value has been sampled or computed with regards to time.
Definition: types.h:688
int pind
Time range type indicator.
Definition: types.h:691
Standard dballe::Query implementation.
Definition: core/query.h:35
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
Definition: core/enq.h:176
void has_new_values()
Mark that there is a new set of values in values.
Cursor iterating over station data values.
Definition: cursor.h:67
Date and time.
Definition: types.h:163
Cursor iterating over stations.
Definition: cursor.h:57
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:695
Collection of Value objects, indexed by wreport::Varcode.
Definition: values.h:215
Definition: core/enq.h:226