libdap  Updated for version 3.20.10
libdap4 is an implementation of OPeNDAP's DAP protocol.
D4Sequence.cc
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 //#define DODS_DEBUG
28 
29 #include <algorithm>
30 #include <string>
31 #include <sstream>
32 
33 #include "D4Sequence.h"
34 
35 #include "D4StreamMarshaller.h"
36 #include "D4StreamUnMarshaller.h"
37 
38 #include "D4RValue.h"
39 #include "D4FilterClause.h" // also contains D4FilterClauseList
40 
41 #include "debug.h"
42 #include "Error.h"
43 #include "InternalErr.h"
44 #include "util.h"
45 #include "escaping.h"
46 #include "DapIndent.h"
47 
48 #undef CLEAR_LOCAL_DATA
49 
50 using namespace std;
51 
52 namespace libdap {
53 
54 // Private member functions
55 
56 // A reminder of these type defs
57 //
58 // typedef vector<BaseType *> D4SeqRow;
59 // typedef vector<D4SeqRow *> D4SeqValues;
60 // D4SeqValues d_values;
61 
62 void D4Sequence::m_duplicate(const D4Sequence &s)
63 {
64  d_length = s.d_length;
65 #if INDEX_SUBSETTING
66  d_starting_row_number = s.d_starting_row_number;
67  d_ending_row_number = s.d_ending_row_number;
68  d_row_stride = s.d_row_stride;
69 #endif
70  // Deep copy for the values
71  for (D4SeqValues::const_iterator i = s.d_values.begin(), e = s.d_values.end(); i != e; ++i) {
72  D4SeqRow &row = **i;
73  D4SeqRow *dest = new D4SeqRow;
74  for (D4SeqRow::const_iterator j = row.begin(), e = row.end(); j != e; ++j) {
75  // *j is a BaseType*
76  dest->push_back((*j)->ptr_duplicate());
77  }
78 
79  d_values.push_back(dest);
80  }
81 
82  d_copy_clauses = s.d_copy_clauses;
83  d_clauses = (s.d_clauses != 0) ? new D4FilterClauseList(*s.d_clauses) : 0; // deep copy if != 0
84 }
85 
86 // Public member functions
87 
96 D4Sequence::D4Sequence(const string &n) :
97  Constructor(n, dods_sequence_c, true /* is dap4 */), d_clauses(0), d_copy_clauses(true), d_length(0)
98 {
99 }
100 
111 D4Sequence::D4Sequence(const string &n, const string &d) :
112  Constructor(n, d, dods_sequence_c, true /* is dap4 */), d_clauses(0), d_copy_clauses(true), d_length(0)
113 {
114 }
115 
118 {
119  m_duplicate(rhs);
120 }
121 
122 BaseType *
124 {
125  return new D4Sequence(*this);
126 }
127 
128 static inline void delete_bt(BaseType *bt_ptr)
129 {
130  delete bt_ptr;
131 }
132 
133 static inline void delete_rows(D4SeqRow *bt_row_ptr)
134 {
135  for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
136 
137  delete bt_row_ptr;
138 }
139 
140 D4Sequence::~D4Sequence()
141 {
143  delete d_clauses;
144 }
145 
147 {
148  if (!d_values.empty()) {
149  for_each(d_values.begin(), d_values.end(), delete_rows);
150  d_values.resize(0);
151  }
152 
153  set_read_p(false);
154 }
155 
156 D4Sequence &
157 D4Sequence::operator=(const D4Sequence &rhs)
158 {
159  if (this == &rhs) return *this;
160  Constructor::operator=(rhs);
161  m_duplicate(rhs);
162  return *this;
163 }
164 
189 {
190  bool eof = false;
191  bool done = false;
192 
193  do {
194  eof = read();
195  if (eof) { // bail if EOF
196  continue;
197  }
198  // if we are supposed to filter and the clauses eval to true, we're done
199  else if (filter && d_clauses && d_clauses->value()) {
200  d_length++;
201  done = true;
202  }
203  // else if we're not supposed to filter or there are no clauses, we're done
204  else if (!filter || !d_clauses) {
205  d_length++;
206  done = true;
207  }
208 
209  // Set up the next call to get another row's worth of data
210  set_read_p(false);
211 
212  } while (!eof && !done);
213 
214  return !eof;
215 }
216 
218 {
219  read_sequence_values(true);
220 }
221 
244 {
245  DBG(cerr << __PRETTY_FUNCTION__ << " BEGIN" << endl);
246 
247  if (read_p()) return;
248 
249  // Read the data values, then serialize. NB: read_next_instance sets d_length
250  // evaluates the filter expression
251  while (read_next_instance(filter)) {
252  DBG(cerr << "read_sequence_values() - Adding row" << endl);
253  D4SeqRow* row = new D4SeqRow;
254  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) {
255  if ((*i)->send_p()) {
256  DBG(cerr << ":serialize() - reading data for " << (*i)->type_name() << " " << (*i)->name() << endl);
257  if ((*i)->type() == dods_sequence_c) {
258  DBG(cerr << "Reading child sequence values for " << (*i)->name() << endl);
259  D4Sequence *d4s = static_cast<D4Sequence*>(*i);
260  d4s->read_sequence_values(filter);
261  d4s->d_copy_clauses = false;
262  row->push_back(d4s->ptr_duplicate());
263  d4s->d_copy_clauses = true; // Must be sure to not break the object in general
264  row->back()->set_read_p(true);
265  }
266  else {
267  // store the variable's value.
268  row->push_back((*i)->ptr_duplicate());
269  // the copy should have read_p true to prevent the serialize() call
270  // below in the nested for loops from triggering a second call to
271  // read().
272  row->back()->set_read_p(true);
273  }
274  }
275  }
276 
277  // When specializing this, use set_value()
278  d_values.push_back(row);
279  DBG(cerr << " read_sequence_values() - Row completed" << endl);
280  }
281 
282  set_length(d_values.size());
283 
284  DBGN(cerr << __PRETTY_FUNCTION__ << " END added " << d_values.size() << endl);
285 }
286 
306 void D4Sequence::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter)
307 {
308  DBGN(cerr << __PRETTY_FUNCTION__ << " BEGIN" << endl);
309 
310  // Read the data values, then serialize. NB: read_next_instance sets d_length
311  // evaluates the filter expression
312  read_sequence_values(filter);
313 
314  // write D4Sequecne::length(); don't include the length in the checksum
315  m.put_count(d_length);
316 
317  // By this point the d_values object holds all and only the values to be sent;
318  // use the serialize methods to send them (but no need to test send_p).
319  for (D4SeqValues::iterator i = d_values.begin(), e = d_values.end(); i != e; ++i) {
320  for (D4SeqRow::iterator j = (*i)->begin(), f = (*i)->end(); j != f; ++j) {
321  (*j)->serialize(m, dmr, /*eval,*/false);
322  }
323  }
324 
325  DBGN(cerr << __PRETTY_FUNCTION__ << " END" << endl);
326 }
327 
329 {
330  int64_t um_count = um.get_count();
331 
332  set_length(um_count);
333 
334  for (int64_t i = 0; i < d_length; ++i) {
335  D4SeqRow *row = new D4SeqRow;
336  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; ++i) {
337  (*i)->deserialize(um, dmr);
338  row->push_back((*i)->ptr_duplicate());
339  }
340  d_values.push_back(row);
341  }
342 }
343 
355 {
356  if (!d_clauses) d_clauses = new D4FilterClauseList();
357  return *d_clauses;
358 }
359 
360 
361 #if INDEX_SUBSETTING
370 virtual void set_row_number_constraint(int start, int stop, int stride)
371 {
372  if (stop < start)
373  throw Error(malformed_expr, "Starting row number must precede the ending row number.");
374 
375  d_starting_row_number = start;
376  d_row_stride = stride;
377  d_ending_row_number = stop;
378 }
379 #endif
380 
385 D4SeqRow *
387 {
388  if (row >= d_values.size()) return 0;
389  return d_values[row];
390 }
391 
397 BaseType *
398 D4Sequence::var_value(size_t row_num, const string &name)
399 {
400  D4SeqRow *row = row_value(row_num);
401  if (!row) return nullptr;
402 
403  auto elem = find_if(row->begin(), row->end(),
404  [name](const BaseType *btp) { return btp->name() == name; });
405 
406  return (elem != row->end()) ? *elem : nullptr;
407 }
408 
414 BaseType *
415 D4Sequence::var_value(size_t row_num, size_t i)
416 {
417  D4SeqRow *row = row_value(row_num);
418  if (!row) return 0;
419 
420  if (i >= row->size()) return 0;
421 
422  return (*row)[i];
423 }
424 
425 void D4Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num)
426 {
427  if (print_row_num) out << "\n" << space << row << ": ";
428 
429  out << "{ ";
430 
431  int elements = element_count();
432  int j = 0;
433  BaseType *bt_ptr = 0;
434 
435  // This version of print_one_row() works for both data read with
436  // deserialize(), where each variable is assumed to have valid data, and
437  // intern_data(), where some/many variables do not. Because of that, it's
438  // not correct to assume that all of the elements will be printed, which
439  // is what the old code did.
440 
441  // Print the first value
442  while (j < elements && !bt_ptr) {
443  bt_ptr = var_value(row, j++);
444  if (bt_ptr) { // data
445  if (bt_ptr->type() == dods_sequence_c) static_cast<D4Sequence*>(bt_ptr)->print_val_by_rows(out,
446  space + " ", false, print_row_num);
447  else
448  bt_ptr->print_val(out, space, false);
449  }
450  }
451 
452  // Print the remaining values
453  while (j < elements) {
454  bt_ptr = var_value(row, j++);
455  if (bt_ptr) { // data
456  out << ", ";
457  if (bt_ptr->type() == dods_sequence_c) static_cast<D4Sequence*>(bt_ptr)->print_val_by_rows(out,
458  space + " ", false, print_row_num);
459  else
460  bt_ptr->print_val(out, space, false);
461  }
462  }
463 
464  out << " }";
465 }
466 
467 void D4Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers)
468 {
469  if (print_decl_p) {
470  print_decl(out, space, false);
471  out << " = ";
472  }
473 
474  out << "{ ";
475 
476  if (length() != 0) {
477  int rows = length() - 1; // -1 because the last row is treated specially
478  for (int i = 0; i < rows; ++i) {
479  print_one_row(out, i, space, print_row_numbers);
480  out << ", ";
481  }
482  print_one_row(out, rows, space, print_row_numbers);
483  }
484 
485  out << " }";
486 
487  if (print_decl_p) out << ";\n";
488 }
489 
490 void D4Sequence::print_val(ostream &out, string space, bool print_decl_p)
491 {
492  DBG(cerr << name() << " isa " << type_name() << endl);
493 
494  print_val_by_rows(out, space, print_decl_p, false);
495 }
496 
505 void D4Sequence::dump(ostream &strm) const
506 {
507  strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl;
508  DapIndent::Indent();
509  Constructor::dump(strm);
510  strm << DapIndent::LMarg << "# rows deserialized: " << d_length << endl;
511  strm << DapIndent::LMarg << "bracket notation information:" << endl;
512 
513  DapIndent::Indent();
514 #if INDEX_SUBSETTING
515  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
516  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
517  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
518 #endif
519  DapIndent::UnIndent();
520 
521  DapIndent::UnIndent();
522 }
523 
524 } // namespace libdap
525 
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:375
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:316
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:476
virtual Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:361
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: BaseType.cc:1086
int element_count(bool leaves=false) override
Count the members of constructor types.
Definition: Constructor.cc:115
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.
Definition: Constructor.cc:529
void set_read_p(bool state) override
Set the 'read_p' property for the Constructor and its members.
Definition: Constructor.cc:150
bool read() override
Read the elements of Constructor marked for transmission.
Definition: Constructor.cc:393
void dump(ostream &strm) const override
dumps information about this object
Definition: Constructor.cc:767
List of DAP4 Filter Clauses.
bool value(DMR &dmr)
Evaluate the list of clauses.
Holds a sequence.
Definition: D4Sequence.h:134
virtual D4SeqRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: D4Sequence.cc:386
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...
Definition: D4Sequence.cc:188
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: D4Sequence.cc:490
D4Sequence(const string &n)
The Sequence constructor.
Definition: D4Sequence.cc:96
virtual bool serialize(ConstraintEvaluator &, DDS &, Marshaller &, bool)
Move data to the net, then remove them from the object.
Definition: D4Sequence.h:206
D4FilterClauseList & clauses()
Access the filter clauses for this D4Sequence.
Definition: D4Sequence.cc:354
virtual void intern_data()
Read data into this variable.
Definition: D4Sequence.cc:217
virtual BaseType * ptr_duplicate()
Definition: D4Sequence.cc:123
virtual bool deserialize(UnMarshaller &, DDS *, bool)
Receive data from the net.
Definition: D4Sequence.h:209
void read_sequence_values(bool filter)
Read a Sequence's value into memory.
Definition: D4Sequence.cc:243
virtual void set_length(int count)
Definition: D4Sequence.h:199
virtual BaseType * var_value(size_t row, const string &name)
Get the BaseType pointer to the named variable of a given row.
Definition: D4Sequence.cc:398
virtual void dump(ostream &strm) const
dumps information about this object
Definition: D4Sequence.cc:505
virtual void clear_local_data()
Definition: D4Sequence.cc:146
virtual int length() const
The number of elements in a Sequence object.
Definition: D4Sequence.h:193
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.
A class for error processing.
Definition: Error.h:94
top level DAP object to house generic methods
Definition: AlarmHandler.h:36
vector< BaseType * > D4SeqRow
Definition: D4Sequence.h:39