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