libdap  Updated for version 3.19.1
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 
47 #undef CLEAR_LOCAL_DATA
48 
49 using namespace std;
50 
51 namespace libdap {
52 
53 #if 0
54 // Keep this stuff around in case we decide to switch back to sentinels
55 
56 static const unsigned char end_of_sequence = 0xA5;// binary pattern 1010 0101
57 static const unsigned char start_of_instance = 0x5A;// binary pattern 0101 1010
58 
59 static void
60 write_end_of_sequence(Marshaller &m)
61 {
62  m.put_opaque( (char *)&end_of_sequence, 1 );
63 }
64 
65 static void
66 write_start_of_instance(Marshaller &m)
67 {
68  m.put_opaque( (char *)&start_of_instance, 1 );
69 }
70 
71 static unsigned char
72 read_marker(UnMarshaller &um)
73 {
74  unsigned char marker;
75  um.get_opaque( (char *)&marker, 1 );
76 
77  return marker;
78 }
79 
80 static bool
81 is_start_of_instance(unsigned char marker)
82 {
83  return (marker == start_of_instance);
84 }
85 
86 static bool
87 is_end_of_sequence(unsigned char marker)
88 {
89  return (marker == end_of_sequence);
90 }
91 #endif
92 
93 // Private member functions
94 
95 // A reminder of these type defs
96 //
97 // typedef vector<BaseType *> D4SeqRow;
98 // typedef vector<D4SeqRow *> D4SeqValues;
99 // D4SeqValues d_values;
100 
101 void D4Sequence::m_duplicate(const D4Sequence &s)
102 {
103  d_length = s.d_length;
104 #if INDEX_SUBSETTING
105  d_starting_row_number = s.d_starting_row_number;
106  d_ending_row_number = s.d_ending_row_number;
107  d_row_stride = s.d_row_stride;
108 #endif
109  // Deep copy for the values
110  for (D4SeqValues::const_iterator i = s.d_values.begin(), e = s.d_values.end(); i != e; ++i) {
111  D4SeqRow &row = **i;
112  D4SeqRow *dest = new D4SeqRow;
113  for (D4SeqRow::const_iterator j = row.begin(), e = row.end(); j != e; ++j) {
114  // *j is a BaseType*
115  dest->push_back((*j)->ptr_duplicate());
116  }
117 
118  d_values.push_back(dest);
119  }
120 
121  d_copy_clauses = s.d_copy_clauses;
122  d_clauses = (s.d_clauses != 0) ? new D4FilterClauseList(*s.d_clauses) : 0; // deep copy if != 0
123 }
124 
125 // Public member functions
126 
135 D4Sequence::D4Sequence(const string &n) :
136  Constructor(n, dods_sequence_c, true /* is dap4 */), d_clauses(0), d_copy_clauses(true), d_length(0)
137 {
138 }
139 
150 D4Sequence::D4Sequence(const string &n, const string &d) :
151  Constructor(n, d, dods_sequence_c, true /* is dap4 */), d_clauses(0), d_copy_clauses(true), d_length(0)
152 {
153 }
154 
157 {
158  m_duplicate(rhs);
159 }
160 
161 BaseType *
163 {
164  return new D4Sequence(*this);
165 }
166 
167 static inline void delete_bt(BaseType *bt_ptr)
168 {
169  delete bt_ptr;
170 }
171 
172 static inline void delete_rows(D4SeqRow *bt_row_ptr)
173 {
174  for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
175 
176  delete bt_row_ptr;
177 }
178 
179 D4Sequence::~D4Sequence()
180 {
182  delete d_clauses;
183 }
184 
186 {
187  if (!d_values.empty()) {
188  for_each(d_values.begin(), d_values.end(), delete_rows);
189  d_values.resize(0);
190  }
191 
192  set_read_p(false);
193 }
194 
195 D4Sequence &
196 D4Sequence::operator=(const D4Sequence &rhs)
197 {
198  if (this == &rhs) return *this;
199 
200  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
201 
202  m_duplicate(rhs);
203 
204  return *this;
205 }
206 
231 {
232  bool eof = false;
233  bool done = false;
234 
235  do {
236  eof = read();
237  if (eof) { // bail if EOF
238  continue;
239  }
240  // if we are supposed to filter and the clauses eval to true, we're done
241  else if (filter && d_clauses && d_clauses->value()) {
242  d_length++;
243  done = true;
244  }
245  // else if we're not supposed to filter or there are no clauses, we're done
246  else if (!filter || !d_clauses) {
247  d_length++;
248  done = true;
249  }
250 
251  // Set up the next call to get another row's worth of data
252  set_read_p(false);
253 
254  } while (!eof && !done);
255 
256  return !eof;
257 }
258 
260 {
261  read_sequence_values(true);
262 
263 #if 0
264  // Read the data values, then serialize.
265  while (read_next_instance(true /*filter*/)) {
266  D4SeqRow *row = new D4SeqRow;
267  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) {
268  if ((*i)->send_p()) {
269  // store the variable's value.
270  row->push_back((*i)->ptr_duplicate());
271  // the copy should have read_p true to prevent the serialize() call
272  // below in the nested for loops from triggering a second call to
273  // read().
274  row->back()->set_read_p(true);
275  }
276  }
277  d_values.push_back(row);
278  }
279 
280  set_length(d_values.size());
281 #endif
282 }
283 
306 {
307  DBG(cerr << __PRETTY_FUNCTION__ << " BEGIN" << endl);
308 
309  if (read_p()) return;
310 
311  // Read the data values, then serialize. NB: read_next_instance sets d_length
312  // evaluates the filter expression
313  while (read_next_instance(filter)) {
314  DBG(cerr << "read_sequence_values() - Adding row" << endl);
315  D4SeqRow* row = new D4SeqRow;
316  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) {
317  if ((*i)->send_p()) {
318  DBG(cerr << ":serialize() - reading data for " << (*i)->type_name() << " " << (*i)->name() << endl);
319  if ((*i)->type() == dods_sequence_c) {
320  DBG(cerr << "Reading child sequence values for " << (*i)->name() << endl);
321  D4Sequence *d4s = static_cast<D4Sequence*>(*i);
322  d4s->read_sequence_values(filter);
323  d4s->d_copy_clauses = false;
324  row->push_back(d4s->ptr_duplicate());
325  d4s->d_copy_clauses = true; // Must be sure to not break the object in general
326  row->back()->set_read_p(true);
327  }
328  else {
329  // store the variable's value.
330  row->push_back((*i)->ptr_duplicate());
331  // the copy should have read_p true to prevent the serialize() call
332  // below in the nested for loops from triggering a second call to
333  // read().
334  row->back()->set_read_p(true);
335  }
336  }
337  }
338 
339  // When specializing this, use set_value()
340  d_values.push_back(row);
341  DBG(cerr << " read_sequence_values() - Row completed" << endl);
342  }
343 
344  set_length(d_values.size());
345 
346  DBGN(cerr << __PRETTY_FUNCTION__ << " END added " << d_values.size() << endl);
347 }
348 
368 void D4Sequence::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter)
369 {
370  DBGN(cerr << __PRETTY_FUNCTION__ << " BEGIN" << endl);
371 
372  // Read the data values, then serialize. NB: read_next_instance sets d_length
373  // evaluates the filter expression
374  read_sequence_values(filter);
375 
376  // write D4Sequecne::length(); don't include the length in the checksum
377  m.put_count(d_length);
378 
379  // By this point the d_values object holds all and only the values to be sent;
380  // use the serialize methods to send them (but no need to test send_p).
381  for (D4SeqValues::iterator i = d_values.begin(), e = d_values.end(); i != e; ++i) {
382  for (D4SeqRow::iterator j = (*i)->begin(), f = (*i)->end(); j != f; ++j) {
383  (*j)->serialize(m, dmr, /*eval,*/false);
384  }
385  }
386 
387  DBGN(cerr << __PRETTY_FUNCTION__ << " END" << endl);
388 }
389 
391 {
392  int64_t um_count = um.get_count();
393 
394  set_length(um_count);
395 
396  for (int64_t i = 0; i < d_length; ++i) {
397  D4SeqRow *row = new D4SeqRow;
398  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; ++i) {
399  (*i)->deserialize(um, dmr);
400  row->push_back((*i)->ptr_duplicate());
401  }
402  d_values.push_back(row);
403  }
404 }
405 
417 {
418  if (!d_clauses) d_clauses = new D4FilterClauseList();
419  return *d_clauses;
420 }
421 
422 
423 #if INDEX_SUBSETTING
424 
432 virtual void set_row_number_constraint(int start, int stop, int stride)
433 {
434  if (stop < start)
435  throw Error(malformed_expr, "Starting row number must precede the ending row number.");
436 
437  d_starting_row_number = start;
438  d_row_stride = stride;
439  d_ending_row_number = stop;
440 }
441 #endif
442 
447 D4SeqRow *
449 {
450  if (row >= d_values.size()) return 0;
451  return d_values[row];
452 }
453 
454 static bool base_type_name_eq(BaseType *btp, const string name)
455 {
456  return btp->name() == name;
457 }
458 
464 BaseType *
465 D4Sequence::var_value(size_t row_num, const string &name)
466 {
467  D4SeqRow *row = row_value(row_num);
468  if (!row) return 0;
469 
470  D4SeqRow::iterator elem = find_if(row->begin(), row->end(), bind2nd(ptr_fun(base_type_name_eq), name));
471  return (elem != row->end()) ? *elem : 0;
472 }
473 
479 BaseType *
480 D4Sequence::var_value(size_t row_num, size_t i)
481 {
482  D4SeqRow *row = row_value(row_num);
483  if (!row) return 0;
484 
485  if (i >= row->size()) return 0;
486 
487  return (*row)[i];
488 }
489 
490 void D4Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num)
491 {
492  if (print_row_num) out << "\n" << space << row << ": ";
493 
494  out << "{ ";
495 
496  int elements = element_count();
497  int j = 0;
498  BaseType *bt_ptr = 0;
499 
500  // This version of print_one_row() works for both data read with
501  // deserialize(), where each variable is assumed to have valid data, and
502  // intern_data(), where some/many variables do not. Because of that, it's
503  // not correct to assume that all of the elements will be printed, which
504  // is what the old code did.
505 
506  // Print the first value
507  while (j < elements && !bt_ptr) {
508  bt_ptr = var_value(row, j++);
509  if (bt_ptr) { // data
510  if (bt_ptr->type() == dods_sequence_c) static_cast<D4Sequence*>(bt_ptr)->print_val_by_rows(out,
511  space + " ", false, print_row_num);
512  else
513  bt_ptr->print_val(out, space, false);
514  }
515  }
516 
517  // Print the remaining values
518  while (j < elements) {
519  bt_ptr = var_value(row, j++);
520  if (bt_ptr) { // data
521  out << ", ";
522  if (bt_ptr->type() == dods_sequence_c) static_cast<D4Sequence*>(bt_ptr)->print_val_by_rows(out,
523  space + " ", false, print_row_num);
524  else
525  bt_ptr->print_val(out, space, false);
526  }
527  }
528 
529  out << " }";
530 }
531 
532 void D4Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers)
533 {
534  if (print_decl_p) {
535  print_decl(out, space, false);
536  out << " = ";
537  }
538 
539  out << "{ ";
540 
541  if (length() != 0) {
542  int rows = length() - 1; // -1 because the last row is treated specially
543  for (int i = 0; i < rows; ++i) {
544  print_one_row(out, i, space, print_row_numbers);
545  out << ", ";
546  }
547  print_one_row(out, rows, space, print_row_numbers);
548  }
549 
550  out << " }";
551 
552  if (print_decl_p) out << ";\n";
553 }
554 
555 void D4Sequence::print_val(ostream &out, string space, bool print_decl_p)
556 {
557  DBG(cerr << name() << " isa " << type_name() << endl);
558 
559  print_val_by_rows(out, space, print_decl_p, false);
560 }
561 
570 void D4Sequence::dump(ostream &strm) const
571 {
572  strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl;
573  DapIndent::Indent();
574  Constructor::dump(strm);
575  strm << DapIndent::LMarg << "# rows deserialized: " << d_length << endl;
576  strm << DapIndent::LMarg << "bracket notation information:" << endl;
577 
578  DapIndent::Indent();
579 #if INDEX_SUBSETTING
580  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
581  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
582  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
583 #endif
584  DapIndent::UnIndent();
585 
586  DapIndent::UnIndent();
587 }
588 
589 } // namespace libdap
590 
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:471
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:311
virtual BaseType * ptr_duplicate()
Definition: D4Sequence.cc:162
bool value(DMR &dmr)
Evaluate the list of clauses.
void read_sequence_values(bool filter)
Read a Sequence&#39;s value into memory.
Definition: D4Sequence.cc:305
virtual void put_count(int64_t count)
D4Sequence(const string &n)
The Sequence constructor.
Definition: D4Sequence.cc:135
virtual bool read_next_instance(bool filter)
Read the next instance of the sequence While the rest of the variables&#39; read() methods are assumed to...
Definition: D4Sequence.cc:230
Read data from the stream made by D4StreamMarshaller.
STL namespace.
virtual void clear_local_data()
Definition: D4Sequence.cc:185
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:465
D4FilterClauseList & clauses()
Access the filter clauses for this D4Sequence.
Definition: D4Sequence.cc:416
vector< BaseType * > D4SeqRow
Definition: D4Sequence.h:39
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Constructor.cc:194
List of DAP4 Filter Clauses.
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: BaseType.cc:1081
Marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using DAP4&#39;s receiv...
virtual void dump(ostream &strm) const
dumps information about this object
Definition: D4Sequence.cc:570
virtual Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:356
virtual void set_length(int count)
Definition: D4Sequence.h:199
Holds a sequence.
Definition: D4Sequence.h:133
virtual bool read()
simple implementation of read that iterates through vars and calls read on them
Definition: Constructor.cc:476
virtual void intern_data()
Read data into this variable.
Definition: D4Sequence.cc:259
virtual int length() const
The number of elements in a Sequence object.
Definition: D4Sequence.h:193
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:913
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: D4Sequence.cc:555
virtual bool deserialize(UnMarshaller &, DDS *, bool)
Receive data from the net.
Definition: D4Sequence.h:209
The basic data type for the DODS DAP types.
Definition: BaseType.h:117
virtual void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Print an ASCII representation of the variable structure.
Definition: Constructor.cc:626
virtual string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:370
virtual D4SeqRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: D4Sequence.cc:448
A class for error processing.
Definition: Error.h:90
virtual bool serialize(ConstraintEvaluator &, DDS &, Marshaller &, bool)
Move data to the net, then remove them from the object.
Definition: D4Sequence.h:206
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Constructor.cc:218