libdap  Updated for version 3.17.2
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 #include <algorithm>
28 #include <string>
29 #include <sstream>
30 
31 //#define DODS_DEBUG
32 //#define DODS_DEBUG2
33 
34 #include "Byte.h"
35 #include "Int16.h"
36 #include "UInt16.h"
37 #include "Int32.h"
38 #include "UInt32.h"
39 #include "Float32.h"
40 #include "Float64.h"
41 #include "Str.h"
42 #include "Url.h"
43 #include "Array.h"
44 #include "Structure.h"
45 #include "D4Sequence.h"
46 
47 #include "D4StreamMarshaller.h"
48 #include "D4StreamUnMarshaller.h"
49 
50 #include "debug.h"
51 #include "Error.h"
52 #include "InternalErr.h"
53 #include "util.h"
54 #include "escaping.h"
55 
56 #undef CLEAR_LOCAL_DATA
57 
58 using namespace std;
59 
60 namespace libdap {
61 
62 #if 0
63 // Keep this stuff around in case we decide to switch back to sentinels
64 
65 static const unsigned char end_of_sequence = 0xA5;// binary pattern 1010 0101
66 static const unsigned char start_of_instance = 0x5A;// binary pattern 0101 1010
67 
68 static void
69 write_end_of_sequence(Marshaller &m)
70 {
71  m.put_opaque( (char *)&end_of_sequence, 1 );
72 }
73 
74 static void
75 write_start_of_instance(Marshaller &m)
76 {
77  m.put_opaque( (char *)&start_of_instance, 1 );
78 }
79 
80 static unsigned char
81 read_marker(UnMarshaller &um)
82 {
83  unsigned char marker;
84  um.get_opaque( (char *)&marker, 1 );
85 
86  return marker;
87 }
88 
89 static bool
90 is_start_of_instance(unsigned char marker)
91 {
92  return (marker == start_of_instance);
93 }
94 
95 static bool
96 is_end_of_sequence(unsigned char marker)
97 {
98  return (marker == end_of_sequence);
99 }
100 #endif
101 
102 // Private member functions
103 
104 // A reminder of these type defs
105 //
106 // typedef vector<BaseType *> D4SeqRow;
107 // typedef vector<D4SeqRow *> D4SeqValues;
108 // D4SeqValues d_values;
109 
110 void D4Sequence::m_duplicate(const D4Sequence &s)
111 {
112  d_length = s.d_length;
113 #if INDEX_SUBSETTING
114  d_starting_row_number = s.d_starting_row_number;
115  d_ending_row_number = s.d_ending_row_number;
116  d_row_stride = s.d_row_stride;
117 #endif
118  // Deep copy for the values
119  for (D4SeqValues::const_iterator i = s.d_values.begin(), e = s.d_values.end(); i != e; ++i) {
120  D4SeqRow &row = **i;
121  D4SeqRow *dest = new D4SeqRow;
122  for (D4SeqRow::const_iterator j = row.begin(), e = row.end(); j != e; ++j) {
123  // *j is a BaseType*
124  dest->push_back((*j)->ptr_duplicate());
125  }
126 
127  d_values.push_back(dest);
128  }
129 }
130 
131 // Public member functions
132 
141 D4Sequence::D4Sequence(const string &n) :
142  Constructor(n, dods_sequence_c, true /* is dap4 */), d_length(0) // , d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(-1)
143 {
144 }
145 
156 D4Sequence::D4Sequence(const string &n, const string &d) :
157  Constructor(n, d, dods_sequence_c, true /* is dap4 */), d_length(0) //, d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(-1)
158 {
159 }
160 
163  Constructor(rhs)
164 {
165  m_duplicate(rhs);
166 }
167 
168 BaseType *
170 {
171  return new D4Sequence(*this);
172 }
173 
174 static inline void delete_bt(BaseType *bt_ptr)
175 {
176  delete bt_ptr;
177 }
178 
179 static inline void delete_rows(D4SeqRow *bt_row_ptr)
180 {
181  for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
182 
183  delete bt_row_ptr;
184 }
185 
186 D4Sequence::~D4Sequence()
187 {
189 }
190 
192 {
193  if (!d_values.empty()) {
194  for_each(d_values.begin(), d_values.end(), delete_rows);
195  d_values.resize(0);
196  }
197 
198  set_read_p(false);
199 }
200 
201 D4Sequence &
202 D4Sequence::operator=(const D4Sequence &rhs)
203 {
204  if (this == &rhs) return *this;
205 
206  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
207 
208  m_duplicate(rhs);
209 
210  return *this;
211 }
212 
236 bool D4Sequence::read_next_instance(/*DMR &dmr, ConstraintEvaluator &eval,*/bool filter)
237 {
238  bool eof = false;
239  bool done = false;
240 
241  do {
242  eof = read();
243  // Advance the row number if ce_eval is false (we're not supposed to
244  // evaluate the selection) or both filter and the selection are
245  // true.
246  // FIXME CE's not supported for DAP4 yet. jhrg 10/11/13
247  filter = false;
248  if (!eof && (!filter /*|| eval.eval_selection(dmr, dataset()*/)) {
249  d_length++;
250  done = true;
251  }
252  } while (!eof && !done);
253 
254  DBG(cerr << "D4Sequence::read_next_instance eof: " << eof << endl);
255  return !eof;
256 }
257 
258 #if 0
259 // Used the version in Constructor, which throws an exception because we should
260 // not compute these for constructor types. In the case of Sequence, it requires
261 // that the values all get read.
269 void
271 {
272  // Read the data values, then serialize.
273  while (read_next_instance(dmr, eval, true)) {
274  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) {
275  if ((*i)->send_p()) {
276  (*i)->compute_checksum(checksum);
277  }
278  }
279  }
280 }
281 #endif
282 
283 void D4Sequence::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
284 {
285  // Read the data values, then serialize.
286  while (read_next_instance(/*dmr, eval,*/true /*filter*/)) {
287  D4SeqRow *row = new D4SeqRow;
288  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) {
289  if ((*i)->send_p()) {
290  // store the variable's value.
291  row->push_back((*i)->ptr_duplicate());
292  // the copy should have read_p true to prevent the serialize() call
293  // below in the nested for loops from triggering a second call to
294  // read().
295  row->back()->set_read_p(true);
296 #if 0
297  // Do not compute the checksum for constructor types; those
298  // types will compute the checksum on the values they contain.
299  // TODO Check on this
300  if (!row->back()->is_constructor_type()) row->back()->compute_checksum(checksum);
301 #endif
302  }
303  }
304  d_values.push_back(row);
305  }
306 }
307 
327 void D4Sequence::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter)
328 {
329  // Read the data values, then serialize. NB: read_next_instance sets d_length.
330  while (read_next_instance(filter)) {
331  D4SeqRow *row = new D4SeqRow;
332  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) {
333  if ((*i)->send_p()) {
334  // store the variable's value.
335  row->push_back((*i)->ptr_duplicate());
336  // the copy should have read_p true to prevent the serialize() call
337  // below in the nested for loops from triggering a second call to
338  // read().
339  row->back()->set_read_p(true);
340  }
341  }
342  d_values.push_back(row);
343  DBG(cerr << "D4Sequence::serialize Added row" << endl);
344  }
345 
346  // write D4Sequecne::length(); don't include the length in the checksum
347  m.put_count(d_length);
348  DBG(cerr << "D4Sequence::serialize count: " << d_length << endl);
349 
350  // By this point the d_values object holds all and only the values to be sent;
351  // use the serialize methods to send them (but no need to test send_p).
352  for (D4SeqValues::iterator i = d_values.begin(), e = d_values.end(); i != e; ++i) {
353  for (D4SeqRow::iterator j = (*i)->begin(), f = (*i)->end(); j != f; ++j) {
354  (*j)->serialize(m, dmr, /*eval,*/false);
355  }
356  }
357 
358 #ifdef CLEAR_LOCAL_DATA
360 #endif
361 
362 }
363 
364 #if 0
365 void D4Sequence::serialize_no_release(D4StreamMarshaller &m, DMR &dmr, bool filter)
366 {
367  // Read the data values, then serialize. NB: read_next_instance sets d_length.
368  while (read_next_instance(filter)) {
369  D4SeqRow *row = new D4SeqRow;
370  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; i++) {
371  if ((*i)->send_p()) {
372  // store the variable's value.
373  row->push_back((*i)->ptr_duplicate());
374  // the copy should have read_p true to prevent the serialize() call
375  // below in the nested for loops from triggering a second call to
376  // read().
377  row->back()->set_read_p(true);
378  }
379  }
380  d_values.push_back(row);
381  DBG(cerr << "D4Sequence::serialize Added row" << endl);
382  }
383 
384  // write D4Sequecne::length(); don't include the length in the checksum
385  m.put_count(d_length);
386  DBG(cerr << "D4Sequence::serialize count: " << d_length << endl);
387 
388  // By this point the d_values object holds all and only the values to be sent;
389  // use the serialize methods to send them (but no need to test send_p).
390  for (D4SeqValues::iterator i = d_values.begin(), e = d_values.end(); i != e; ++i) {
391  for (D4SeqRow::iterator j = (*i)->begin(), f = (*i)->end(); j != f; ++j) {
392  (*j)->serialize(m, dmr, /*eval,*/false);
393  }
394  }
395 }
396 #endif
397 
399 {
400  set_length(um.get_count());
401  DBG(cerr << "D4Sequence::deserialize count: " << d_length << endl);
402 
403  for (int64_t i = 0; i < d_length; ++i) {
404  D4SeqRow *row = new D4SeqRow;
405  for (Vars_iter i = d_vars.begin(), e = d_vars.end(); i != e; ++i) {
406  (*i)->deserialize(um, dmr);
407  row->push_back((*i)->ptr_duplicate());
408  }
409  d_values.push_back(row);
410  }
411 }
412 
413 #if INDEX_SUBSETTING
414 
422 virtual void set_row_number_constraint(int start, int stop, int stride)
423 {
424  if (stop < start)
425  throw Error(malformed_expr, "Starting row number must precede the ending row number.");
426 
427  d_starting_row_number = start;
428  d_row_stride = stride;
429  d_ending_row_number = stop;
430 }
431 #endif
432 
437 D4SeqRow *
439 {
440  if (row >= d_values.size()) return 0;
441  return d_values[row];
442 }
443 
444 static bool base_type_name_eq(BaseType *btp, const string name)
445 {
446  return btp->name() == name;
447 }
448 
454 BaseType *
455 D4Sequence::var_value(size_t row_num, const string &name)
456 {
457  D4SeqRow *row = row_value(row_num);
458  if (!row) return 0;
459 
460  D4SeqRow::iterator elem = find_if(row->begin(), row->end(), bind2nd(ptr_fun(base_type_name_eq), name));
461  return (elem != row->end()) ? *elem : 0;
462 }
463 
469 BaseType *
470 D4Sequence::var_value(size_t row_num, size_t i)
471 {
472  D4SeqRow *row = row_value(row_num);
473  if (!row) return 0;
474 
475  if (i >= row->size()) return 0;
476 
477  return (*row)[i];
478 }
479 
480 void D4Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num)
481 {
482  if (print_row_num) out << "\n" << space << row << ": ";
483 
484  out << "{ ";
485 
486  int elements = element_count();
487  int j = 0;
488  BaseType *bt_ptr = 0;
489 
490  // This version of print_one_row() works for both data read with
491  // deserialize(), where each variable is assumed to have valid data, and
492  // intern_data(), where some/many variables do not. Because of that, it's
493  // not correct to assume that all of the elements will be printed, which
494  // is what the old code did.
495 
496  // Print the first value
497  while (j < elements && !bt_ptr) {
498  bt_ptr = var_value(row, j++);
499  if (bt_ptr) { // data
500  if (bt_ptr->type() == dods_sequence_c) static_cast<D4Sequence*>(bt_ptr)->print_val_by_rows(out,
501  space + " ", false, print_row_num);
502  else
503  bt_ptr->print_val(out, space, false);
504  }
505  }
506 
507  // Print the remaining values
508  while (j < elements) {
509  bt_ptr = var_value(row, j++);
510  if (bt_ptr) { // data
511  out << ", ";
512  if (bt_ptr->type() == dods_sequence_c) static_cast<D4Sequence*>(bt_ptr)->print_val_by_rows(out,
513  space + " ", false, print_row_num);
514  else
515  bt_ptr->print_val(out, space, false);
516  }
517  }
518 
519  out << " }";
520 }
521 
522 void D4Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers)
523 {
524  if (print_decl_p) {
525  print_decl(out, space, false);
526  out << " = ";
527  }
528 
529  out << "{ ";
530 
531  if (length() != 0) {
532  int rows = length() - 1; // -1 because the last row is treated specially
533  for (int i = 0; i < rows; ++i) {
534  print_one_row(out, i, space, print_row_numbers);
535  out << ", ";
536  }
537  print_one_row(out, rows, space, print_row_numbers);
538  }
539 
540  out << " }";
541 
542  if (print_decl_p) out << ";\n";
543 }
544 
545 void D4Sequence::print_val(ostream &out, string space, bool print_decl_p)
546 {
547  print_val_by_rows(out, space, print_decl_p, false);
548 }
549 
558 void D4Sequence::dump(ostream &strm) const
559 {
560  strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl;
561  DapIndent::Indent();
562  Constructor::dump(strm);
563  strm << DapIndent::LMarg << "# rows deserialized: " << d_length << endl;
564  strm << DapIndent::LMarg << "bracket notation information:" << endl;
565 
566  DapIndent::Indent();
567 #if INDEX_SUBSETTING
568  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
569  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
570  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
571 #endif
572  DapIndent::UnIndent();
573 
574  DapIndent::UnIndent();
575 }
576 
577 } // namespace libdap
578 
virtual BaseType * ptr_duplicate()
Definition: D4Sequence.cc:169
virtual void put_count(int64_t count)
D4Sequence(const string &n)
The Sequence constructor.
Definition: D4Sequence.cc:141
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:236
Read data from the stream made by D4StreamMarshaller.
Definition: crc.h:76
virtual void compute_checksum(Crc32 &checksum)
include the data for this variable in the checksum DAP4 includes a checksum with every data response...
Definition: Constructor.cc:525
STL namespace.
virtual void clear_local_data()
Definition: D4Sequence.cc:191
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:455
virtual Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:310
vector< BaseType * > D4SeqRow
Definition: D4Sequence.h:38
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Constructor.cc:169
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: BaseType.cc:1011
Marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using DAP4&#39;s receiv...
virtual void set_length(int count)
Definition: D4Sequence.h:176
virtual void dump(ostream &strm) const
dumps information about this object
Definition: D4Sequence.cc:558
Holds a sequence.
Definition: D4Sequence.h:124
virtual int length() const
The number of elements in a Sequence object.
Definition: D4Sequence.h:170
virtual bool read()
simple implementation of read that iterates through vars and calls read on them
Definition: Constructor.cc:451
virtual void intern_data()
Read data into this variable.
Definition: D4Sequence.cc:283
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:824
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:265
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: D4Sequence.cc:545
Evaluate a constraint expression.
virtual bool deserialize(UnMarshaller &, DDS *, bool)
Receive data from the net.
Definition: D4Sequence.h:186
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:601
virtual D4SeqRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: D4Sequence.cc:438
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:183
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Constructor.cc:193