libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
D4Sequence.cc
Go to the documentation of this file.
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2013 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22//
23// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
25#include "config.h"
26
27#include <algorithm>
28#include <sstream>
29#include <string>
30
31#include "D4Sequence.h"
32
33#include "D4StreamMarshaller.h"
35
36#include "D4FilterClause.h" // also contains D4FilterClauseList
37#include "D4RValue.h"
38
39#include "DapIndent.h"
40#include "Error.h"
41#include "InternalErr.h"
42#include "debug.h"
43#include "escaping.h"
44#include "util.h"
45
46#undef CLEAR_LOCAL_DATA
47
48using namespace std;
49
50namespace libdap {
51
52// Private member functions
53
54// A reminder of these type defs
55//
56// typedef vector<BaseType *> D4SeqRow;
57// typedef vector<D4SeqRow *> D4SeqValues;
58// D4SeqValues d_values;
59
62#if INDEX_SUBSETTING
63 d_starting_row_number = s.d_starting_row_number;
64 d_ending_row_number = s.d_ending_row_number;
65 d_row_stride = s.d_row_stride;
66#endif
67 // Deep copy for the values
68 for (const auto &row :
69 s.d_values) { // D4SeqValues::const_iterator i = s.d_values.begin(), e = s.d_values.end(); i != e; ++i) {
70 // D4SeqRow &row = **i;
71 auto dest = make_unique<D4SeqRow>();
72 for (const auto &basetype : *row) { // D4SeqRow::const_iterator j = row.begin(), e = row.end(); j != e; ++j) {
73 // *j is a BaseType*
74 dest->push_back(basetype->ptr_duplicate());
75 }
76
77 d_values.push_back(dest.release());
78 }
79
80 d_copy_clauses = s.d_copy_clauses;
81 d_clauses = (s.d_clauses != nullptr) ? new D4FilterClauseList(*s.d_clauses) : nullptr; // deep copy if != 0
82}
83
84// Public member functions
85
94D4Sequence::D4Sequence(const string &n)
95 : Constructor(n, dods_sequence_c, true /* is dap4 */), d_clauses(0), d_copy_clauses(true), d_length(0) {}
96
107D4Sequence::D4Sequence(const string &n, const string &d)
108 : Constructor(n, d, dods_sequence_c, true /* is dap4 */), d_clauses(0), d_copy_clauses(true), d_length(0) {}
109
112
114
115static inline void delete_bt(BaseType *bt_ptr) { delete bt_ptr; }
116
117static inline void delete_rows(D4SeqRow *bt_row_ptr) {
118 for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
119
120 delete bt_row_ptr;
121}
122
125 delete d_clauses;
126}
127
129 if (!d_values.empty()) {
130 for_each(d_values.begin(), d_values.end(), delete_rows);
131 d_values.resize(0);
132 }
133
134 set_read_p(false);
135}
136
138 if (this == &rhs)
139 return *this;
141 m_duplicate(rhs);
142 return *this;
143}
144
167 bool eof = false;
168 bool done = false;
169
170 do {
171 eof = read();
172 if (eof) { // bail if EOF
173 continue;
174 }
175 // if we are supposed to filter and the clauses eval to true, we're done
176 else if (filter && d_clauses && d_clauses->value()) {
177 d_length++;
178 done = true;
179 }
180 // else if we're not supposed to filter or there are no clauses, we're done
181 else if (!filter || !d_clauses) {
182 d_length++;
183 done = true;
184 }
185
186 // Set up the next call to get another row's worth of data
187 set_read_p(false);
188
189 } while (!eof && !done);
190
191 return !eof;
192}
193
195
218 DBG(cerr << __PRETTY_FUNCTION__ << " BEGIN" << endl);
219
220 if (read_p())
221 return;
222
223 // Read the data values, then serialize. NB: read_next_instance sets d_length
224 // evaluates the filter expression
225 while (read_next_instance(filter)) {
226 DBG(cerr << "read_sequence_values() - Adding row" << endl);
227 auto row = make_unique<D4SeqRow>();
228 for (auto &var : d_vars) { // Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) {
229 if (var->send_p()) {
230 DBG(cerr << ":serialize() - reading data for " << (*i)->type_name() << " " << (*i)->name() << endl);
231 if (var->type() == dods_sequence_c) {
232 DBG(cerr << "Reading child sequence values for " << (*i)->name() << endl);
233 const auto d4s = static_cast<D4Sequence *>(var);
234 d4s->read_sequence_values(filter);
235 d4s->d_copy_clauses = false;
236 row->push_back(d4s->ptr_duplicate());
237 d4s->d_copy_clauses = true; // Must be sure to not break the object in general
238 row->back()->set_read_p(true);
239 } else {
240 // store the variable's value.
241 row->push_back(var->ptr_duplicate());
242 // the copy should have read_p true to prevent the serialize() call
243 // below in the nested for loops from triggering a second call to
244 // read().
245 row->back()->set_read_p(true);
246 }
247 }
248 }
249
250 // When specializing this, use set_value()
251 d_values.push_back(row.release());
252 DBG(cerr << " read_sequence_values() - Row completed" << endl);
253 }
254
255 set_length(d_values.size());
256
257 DBGN(cerr << __PRETTY_FUNCTION__ << " END added " << d_values.size() << endl);
258}
259
279void D4Sequence::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter) {
280 DBGN(cerr << __PRETTY_FUNCTION__ << " BEGIN" << endl);
281
282 // Read the data values, then serialize. NB: read_next_instance sets d_length
283 // evaluates the filter expression
284 read_sequence_values(filter);
285
286 // write D4Sequence::length(); don't include the length in the checksum
288
289 // By this point the d_values object holds all and only the values to be sent;
290 // use the serialize methods to send them (but no need to test send_p).
291 for (auto const &row : d_values) {
292 for (auto &var : *row) {
293 var->serialize(m, dmr, /*eval,*/ filter);
294 }
295 }
296
297 DBGN(cerr << __PRETTY_FUNCTION__ << " END" << endl);
298}
299
301 const int64_t um_count = um.get_count();
302
303 set_length(um_count);
304
305 for (int64_t i = 0; i < d_length; ++i) {
306 auto row = make_unique<D4SeqRow>();
307 for (const auto &var : d_vars) {
308 var->deserialize(um, dmr);
309 row->push_back(var->ptr_duplicate());
310 }
311 d_values.push_back(row.release());
312 }
313}
314
326 if (!d_clauses)
327 d_clauses = new D4FilterClauseList();
328 return *d_clauses;
329}
330
331#if INDEX_SUBSETTING
340virtual void set_row_number_constraint(int start, int stop, int stride) {
341 if (stop < start)
342 throw Error(malformed_expr, "Starting row number must precede the ending row number.");
343
344 d_starting_row_number = start;
345 d_row_stride = stride;
346 d_ending_row_number = stop;
347}
348#endif
349
355 if (row >= d_values.size())
356 return nullptr;
357 return d_values[row];
358}
359
365BaseType *D4Sequence::var_value(size_t row_num, const string &name) {
366 D4SeqRow *row = row_value(row_num);
367 if (!row)
368 return nullptr;
369
370 auto elem = find_if(row->begin(), row->end(), [name](const BaseType *btp) { return btp->name() == name; });
371
372 return (elem != row->end()) ? *elem : nullptr;
373}
374
380BaseType *D4Sequence::var_value(size_t row_num, size_t i) {
381 const D4SeqRow *row = row_value(row_num);
382 if (!row)
383 return nullptr;
384
385 if (i >= row->size())
386 return nullptr;
387
388 return (*row)[i];
389}
390
391void D4Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num) {
392 if (print_row_num)
393 out << "\n" << space << row << ": ";
394
395 out << "{ ";
396
397 const int elements = element_count();
398 int j = 0;
399 BaseType *bt_ptr = 0;
400
401 // This version of print_one_row() works for both data read with
402 // deserialize(), where each variable is assumed to have valid data, and
403 // intern_data(), where some/many variables do not. Because of that, it's
404 // not correct to assume that all the elements will be printed, which
405 // is what the old code did.
406
407 // Print the first value
408 while (j < elements && !bt_ptr) {
409 bt_ptr = var_value(row, j++);
410 if (bt_ptr) { // data
411 if (bt_ptr->type() == dods_sequence_c)
412 static_cast<D4Sequence *>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
413 else
414 bt_ptr->print_val(out, space, false);
415 }
416 }
417
418 // Print the remaining values
419 while (j < elements) {
420 bt_ptr = var_value(row, j++);
421 if (bt_ptr) { // data
422 out << ", ";
423 if (bt_ptr->type() == dods_sequence_c)
424 static_cast<D4Sequence *>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
425 else
426 bt_ptr->print_val(out, space, false);
427 }
428 }
429
430 out << " }";
431}
432
433void D4Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers) {
434 if (print_decl_p) {
435 print_decl(out, space, false);
436 out << " = ";
437 }
438
439 out << "{ ";
440
441 if (length() != 0) {
442 int rows = length() - 1; // -1 because the last row is treated specially
443 for (int i = 0; i < rows; ++i) {
444 print_one_row(out, i, space, print_row_numbers);
445 out << ", ";
446 }
447 print_one_row(out, rows, space, print_row_numbers);
448 }
449
450 out << " }";
451
452 if (print_decl_p)
453 out << ";\n";
454}
455
456void D4Sequence::print_val(ostream &out, string space, bool print_decl_p) {
457 DBG(cerr << name() << " isa " << type_name() << endl);
458
459 print_val_by_rows(out, space, print_decl_p, false);
460}
461
470void D4Sequence::dump(ostream &strm) const {
471 strm << DapIndent::LMarg << "Sequence::dump - (" << (void *)this << ")" << endl;
473 Constructor::dump(strm);
474 strm << DapIndent::LMarg << "# rows deserialized: " << d_length << endl;
475 strm << DapIndent::LMarg << "bracket notation information:" << endl;
476
478#if INDEX_SUBSETTING
479 strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
480 strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
481 strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
482#endif
484
486}
487
488} // namespace libdap
#define malformed_expr
(400)
Definition Error.h:66
The basic data type for the DODS DAP types.
Definition BaseType.h:118
virtual string type_name() const
Returns the type of the class instance as a string.
Definition BaseType.cc:335
virtual string name() const
Returns the name of the class instance.
Definition BaseType.cc:296
virtual bool read_p()
Has this variable been read?
Definition BaseType.cc:410
virtual Type type() const
Returns the type of the class instance.
Definition BaseType.cc:329
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition BaseType.cc:949
int element_count(bool leaves=false) override
Count the members of constructor types.
BaseType * var(const string &name, bool exact_match=true, btp_stack *s=nullptr) override
btp_stack no longer needed; use back pointers (BaseType::get_parent())
void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false) override
Print an ASCII representation of the variable structure.
void set_read_p(bool state) override
Set the 'read_p' property for the Constructor and its members.
std::vector< BaseType * > d_vars
Definition Constructor.h:47
bool read() override
Read the elements of Constructor marked for transmission.
Constructor & operator=(const Constructor &rhs)
Definition Constructor.h:70
Constructor(const string &name, const Type &type, bool is_dap4=false)
Definition Constructor.h:52
void dump(ostream &strm) const override
dumps information about this object
List of DAP4 Filter Clauses.
virtual D4SeqRow * row_value(size_t row)
Get a whole row from the sequence.
virtual bool read_next_instance(bool filter)
Read the next instance of the sequence While the rest of the variables' read() methods are assumed to...
BaseType * ptr_duplicate() override
D4Sequence(const string &n)
The Sequence constructor.
Definition D4Sequence.cc:94
int length() const override
The number of elements in a Sequence object.
Definition D4Sequence.h:189
virtual void print_one_row(ostream &out, int row, string space, bool print_row_num=false)
D4FilterClauseList & clauses()
Access the filter clauses for this D4Sequence.
virtual void print_val_by_rows(ostream &out, string space="", bool print_decl_p=true, bool print_row_numbers=true)
D4SeqValues d_values
Definition D4Sequence.h:149
void set_length(int64_t count) override
Definition D4Sequence.h:195
bool serialize(ConstraintEvaluator &, DDS &, Marshaller &, bool) override
Move data to the net, then remove them from the object.
Definition D4Sequence.h:203
void m_duplicate(const D4Sequence &s)
Definition D4Sequence.cc:60
bool deserialize(UnMarshaller &, DDS *, bool) override
Receive data from the net.
Definition D4Sequence.h:206
void dump(ostream &strm) const override
dumps information about this object
void print_val(ostream &out, string space="", bool print_decl_p=true) override
Prints the value of the variable.
void intern_data() override
Read data into this variable.
void read_sequence_values(bool filter)
Read a Sequence's value into memory.
virtual BaseType * var_value(size_t row, const string &name)
Get the BaseType pointer to the named variable of a given row.
D4Sequence & operator=(const D4Sequence &rhs)
void clear_local_data() override
virtual ~D4Sequence()
Marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using DAP4's receiv...
virtual void put_count(int64_t count)
Read data from the stream made by D4StreamMarshaller.
static ostream & LMarg(ostream &strm)
Definition DapIndent.cc:61
static void Indent()
Definition DapIndent.cc:44
static void UnIndent()
Definition DapIndent.cc:46
A class for error processing.
Definition Error.h:92
#define DBGN(x)
Definition debug.h:59
#define DBG(x)
Definition debug.h:58
top level DAP object to house generic methods
Definition AISConnect.cc:30
@ dods_sequence_c
Definition Type.h:108
vector< BaseType * > D4SeqRow
Definition D4Sequence.h:42