libdap  Updated for version 3.20.10
libdap4 is an implementation of OPeNDAP's DAP protocol.
Sequence.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) 2002,2003 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 // (c) COPYRIGHT URI/MIT 1994-1999
26 // Please read the full copyright statement in the file COPYRIGHT_URI.
27 //
28 // Authors:
29 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
30 
31 // Implementation for the class Structure
32 //
33 // jhrg 9/14/94
34 
35 #include "config.h"
36 
37 //#define DODS_DEBUG
38 //#define DODS_DEBUG2
39 
40 #include <algorithm>
41 #include <string>
42 #include <sstream>
43 
44 #include "Byte.h"
45 #include "Int16.h"
46 #include "UInt16.h"
47 #include "Int32.h"
48 #include "UInt32.h"
49 #include "Float32.h"
50 #include "Float64.h"
51 #include "Str.h"
52 #include "Url.h"
53 #include "Array.h"
54 #include "Structure.h"
55 #include "Sequence.h"
56 #include "Grid.h"
57 
58 #include "Marshaller.h"
59 #include "UnMarshaller.h"
60 
61 #include "debug.h"
62 #include "Error.h"
63 #include "InternalErr.h"
64 #include "Sequence.h"
65 #include "DDS.h"
66 #include "DataDDS.h"
67 #include "util.h"
68 #include "InternalErr.h"
69 #include "escaping.h"
70 
71 #include "D4Attributes.h"
72 #include "D4Sequence.h"
73 #include "D4Group.h"
74 #include "Constructor.h"
75 #include "DMR.h"
76 #include "DapIndent.h"
77 
78 #undef CLEAR_LOCAL_DATA
79 
80 using namespace std;
81 
82 namespace libdap {
83 
84 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
85 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
86 
87 // Private member functions
88 
89 void Sequence::m_duplicate(const Sequence &s)
90 {
91  DBG(cerr << "In Sequence::m_duplicate" << endl);
92 
93  d_row_number = s.d_row_number;
94  d_starting_row_number = s.d_starting_row_number;
95  d_ending_row_number = s.d_ending_row_number;
96  d_row_stride = s.d_row_stride;
97  d_leaf_sequence = s.d_leaf_sequence;
98  d_unsent_data = s.d_unsent_data;
99  d_wrote_soi = s.d_wrote_soi;
100  d_top_most = s.d_top_most;
101 
102  Sequence &cs = const_cast<Sequence &>(s);
103 
104  // Copy the BaseType objects used to hold values.
105  for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin(); rows_iter != cs.d_values.end(); rows_iter++) {
106  // Get the current BaseType Row
107  BaseTypeRow *src_bt_row_ptr = *rows_iter;
108  // Create a new row.
109  BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow;
110  // Copy the BaseType objects from a row to new BaseType objects.
111  // Push new BaseType objects onto new row.
112  for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin(); bt_row_iter != src_bt_row_ptr->end();
113  bt_row_iter++) {
114  BaseType *src_bt_ptr = *bt_row_iter;
115  BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate();
116  dest_bt_row_ptr->push_back(dest_bt_ptr);
117  }
118  // Push new row onto d_values.
119  d_values.push_back(dest_bt_row_ptr);
120  }
121 }
122 
123 static void write_end_of_sequence(Marshaller &m)
124 {
125  m.put_opaque((char *) &end_of_sequence, 1);
126 }
127 
128 static void write_start_of_instance(Marshaller &m)
129 {
130  m.put_opaque((char *) &start_of_instance, 1);
131 }
132 
133 static unsigned char read_marker(UnMarshaller &um)
134 {
135  unsigned char marker;
136  um.get_opaque((char *) &marker, 1);
137 
138  return marker;
139 }
140 
141 static bool is_start_of_instance(unsigned char marker)
142 {
143  return (marker == start_of_instance);
144 }
145 
146 static bool is_end_of_sequence(unsigned char marker)
147 {
148  return (marker == end_of_sequence);
149 }
150 
151 // Public member functions
152 
161 Sequence::Sequence(const string &n) :
162  Constructor(n, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(
163  -1), d_unsent_data(false), d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
164 {
165 }
166 
177 Sequence::Sequence(const string &n, const string &d) :
178  Constructor(n, d, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1),
179  d_row_stride(1), d_ending_row_number(-1), d_unsent_data(false),
180  d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
181 {
182 }
183 
186  Constructor(rhs)
187 {
188  m_duplicate(rhs);
189 }
190 
191 BaseType *
193 {
194  return new Sequence(*this);
195 }
196 
211 void
213 {
214  D4Sequence *dest;
215  // If it's already a DAP4 object then we can just return it!
216  if(is_dap4()){
217  dest = static_cast<D4Sequence*>(ptr_duplicate());
218  dest->set_length(-1);
219  container->add_var_nocopy(dest);
220  return;
221  }
222  dest = new D4Sequence(name());
223  Constructor::transform_to_dap4(root, dest);
224  dest->set_length(-1);
225  container->add_var_nocopy(dest);
226 }
227 
228 static inline void delete_bt(BaseType *bt_ptr)
229 {
230  delete bt_ptr;
231  bt_ptr = 0;
232 }
233 
234 static inline void delete_rows(BaseTypeRow *bt_row_ptr)
235 {
236  for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
237 
238  delete bt_row_ptr;
239  bt_row_ptr = 0;
240 }
241 
242 Sequence::~Sequence()
243 {
245 }
246 
248 {
249  if (!d_values.empty()) {
250  for_each(d_values.begin(), d_values.end(), delete_rows);
251  d_values.resize(0);
252  }
253 
254  set_read_p(false);
255 }
256 
257 Sequence &
258 Sequence::operator=(const Sequence &rhs)
259 {
260  if (this == &rhs) return *this;
261  Constructor::operator=(rhs);
262  m_duplicate(rhs);
263  return *this;
264 }
265 
270 {
271  return true;
272 }
273 
275 {
276  ostringstream oss;
277 
278  oss << BaseType::toString();
279 
280  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
281  oss << (*i)->toString();
282  }
283 
284  oss << endl;
285 
286  return oss.str();
287 }
288 
290 {
291  bool linear = true;
292  bool seq_found = false;
293  for (Vars_iter iter = d_vars.begin(); linear && iter != d_vars.end(); iter++) {
294  if ((*iter)->type() == dods_sequence_c) {
295  // A linear sequence cannot have more than one child seq. at any
296  // one level. If we've already found a seq at this level, return
297  // false.
298  if (seq_found) {
299  linear = false;
300  break;
301  }
302  seq_found = true;
303  linear = static_cast<Sequence *>((*iter))->is_linear();
304  }
305  else if ((*iter)->type() == dods_structure_c) {
306  linear = static_cast<Structure*>((*iter))->is_linear();
307  }
308  else {
309  // A linear sequence cannot have Arrays, Lists or Grids.
310  linear = (*iter)->is_simple_type();
311  }
312  }
313 
314  return linear;
315 }
316 
321 BaseTypeRow *
323 {
324  if (row >= d_values.size()) return 0; //nullptr
325  return d_values[row];
326 }
327 
335 {
336  d_values = values;
337 }
338 
342 {
343  return d_values;
344 }
345 
350 {
351  return d_values;
352 }
353 
359 BaseType *
360 Sequence::var_value(size_t row, const string &name)
361 {
362  BaseTypeRow *bt_row_ptr = row_value(row);
363  if (!bt_row_ptr) return 0;
364 
365  BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
366  BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
367  while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
368  ++bt_row_iter;
369 
370  if (bt_row_iter == bt_row_end)
371  return 0;
372  else
373  return *bt_row_iter;
374 }
375 
381 BaseType *
382 Sequence::var_value(size_t row, size_t i)
383 {
384  BaseTypeRow *bt_row_ptr = row_value(row);
385  if (!bt_row_ptr) return 0;
386 
387  if (i >= bt_row_ptr->size()) return 0;
388 
389  return (*bt_row_ptr)[i];
390 }
391 
392 // This version returns -1. Each API-specific subclass should define a more
393 // reasonable version. jhrg 5/24/96
394 
410 int Sequence::length() const
411 {
412  return -1;
413 }
414 
415 // Hmmm. how is this different from length()?
416 int Sequence::number_of_rows() const
417 {
418  return d_values.size();
419 }
420 
425 {
426  d_row_number = -1;
427 }
428 
435 {
437 
438  if (recur)
439  for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i)
440  if ((*i)->type() == dods_sequence_c)
441  reset_row_number(true);
442 }
443 
444 // Notes:
445 // Assume that read() is implemented so that, when reading data for a nested
446 // sequence, only the outer most level is *actually* read.
447 // This is a consequence of our current (12/7/99) implementation of
448 // the JGOFS server (which is the only server to actually use nested
449 // sequences). 12/7/99 jhrg
450 //
451 // Stop assuming this. This logic is being moved into the JGOFS server
452 // itself. 6/1/2001 jhrg
453 
454 // The read() function returns a boolean value, with TRUE
455 // indicating that read() should be called again because there's
456 // more data to read, and FALSE indicating there's no more data
457 // to read. Note that this behavior is necessary to properly
458 // handle variables that contain Sequences. Jose Garcia If an
459 // error exists while reading, the implementers of the surrogate
460 // library SHOULD throw an Error object which will propagate
461 // beyond this point to to the original caller.
462 // Jose Garcia
463 
496 bool Sequence::read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval)
497 {
498  DBG2(cerr << "Entering Sequence::read_row for " << name() << ", row number " << row << ", current row " << d_row_number << endl);
499  if (row < d_row_number) throw InternalErr("Trying to back up inside a sequence!");
500 
501  if (row == d_row_number) {
502  DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
503  return false;
504  }
505 
506  bool eof = false; // Start out assuming EOF is false.
507  while (!eof && d_row_number < row) {
508  if (!read_p()) {
509  // jhrg original version from 10/9/13 : eof = (read() == false);
510  eof = read();
511  }
512 
513  // Advance the row number if ce_eval is false (we're not supposed to
514  // evaluate the selection) or both ce_eval and the selection are
515  // true.
516  if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) d_row_number++;
517 
518  set_read_p(false); // ...so that the next instance will be read
519  }
520 
521  // Once we finish the above loop, set read_p to true so that the caller
522  // knows that data *has* been read. This is how the read() methods of the
523  // elements of the sequence know to not call read() but instead look for
524  // data values inside themselves.
525  set_read_p(true);
526 
527  // Return true if we have valid data, false if we've read to the EOF.
528  DBG2(cerr << "Leaving Sequence::read_row for " << name() << " with eof: " << eof << endl);
529  return !eof; // jhrg 10/10/13 was: eof == 0;
530 }
531 
532 // Private. This is used to process constraints on the rows of a sequence.
533 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
534 // odd-looking logic first checks if d_ending_row_number is the sentinel
535 // value of -1. If so, the sequence was not constrained by row number and
536 // this method should never return true (which indicates that we're at the
537 // end of a row-number constraint). If d_ending_row_number is not -1, then is
538 // \e i at the end point? 6/1/2001 jhrg
539 inline bool Sequence::is_end_of_rows(int i)
540 {
541  return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
542 }
543 
604 bool Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval)
605 {
606  // Special case leaf sequences!
607  bool status = false;
608 
609  if (is_leaf_sequence())
610  status = serialize_leaf(dds, eval, m, ce_eval);
611  else
612  status = serialize_parent_part_one(dds, eval, m);
613 
614  return status;
615 }
616 
617 // We know this is not a leaf Sequence. That means that this Sequence holds
618 // another Sequence as one of its fields _and_ that child Sequence triggers
619 // the actual transmission of values.
620 
621 bool Sequence::serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
622 {
623  DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
624 
625  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
626 
627  // read_row returns true if valid data was read, false if the EOF was
628  // found. 6/1/2001 jhrg
629  // Since this is a parent sequence, read the row ignoring the CE (all of
630  // the CE clauses will be evaluated by the leaf sequence).
631  bool status = read_row(i, dds, eval, false);
632  DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
633 
634  while (status && !is_end_of_rows(i)) {
635  i += d_row_stride;
636 
637  // DBG(cerr << "Writing Start of Instance marker" << endl);
638  // write_start_of_instance(sink);
639 
640  // In this loop serialize will signal an error with an exception.
641  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
642  // Only call serialize for child Sequences; the leaf sequence
643  // will trigger the transmission of values for its parents (this
644  // sequence and maybe others) once it gets some valid data to
645  // send.
646  // Note that if the leaf sequence has no variables in the current
647  // projection, its serialize() method will never be called and that's
648  // the method that triggers actually sending values. Thus the leaf
649  // sequence must be the lowest level sequence with values whose send_p
650  // property is true.
651  if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) (*iter)->serialize(eval, dds, m);
652  }
653 
654  set_read_p(false); // ...so this will read the next instance
655 
656  status = read_row(i, dds, eval, false);
657  DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
658  }
659  // Reset current row number for next nested sequence element.
660  d_row_number = -1;
661 
662  // Always write the EOS marker? 12/23/04 jhrg
663  // Yes. According to DAP2, a completely empty response is signaled by
664  // a return value of only the EOS marker for the outermost sequence.
665  if (d_top_most || d_wrote_soi) {
666  DBG(cerr << "Writing End of Sequence marker" << endl);
667  write_end_of_sequence(m);
668  d_wrote_soi = false;
669  }
670 
671  return true; // Signal errors with exceptions.
672 }
673 
674 // If we are here then we know that this is 'parent sequence' and that the
675 // leaf sequence has found valid data to send. We also know that
676 // serialize_parent_part_one has been called so data are in the instance's
677 // fields. This is where we send data. Whereas ..._part_one() contains a
678 // loop to iterate over all of rows in a parent sequence, this does not. This
679 // method assumes that the serialize_leaf() will call it each time it needs
680 // to be called.
681 //
682 // NB: This code only works if the child sequences appear after all other
683 // variables.
684 void Sequence::serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
685 {
686  DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
687 
688  BaseType *btp = get_parent();
689  if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
690 
691  if (d_unsent_data) {
692  DBG(cerr << "Writing Start of Instance marker" << endl);
693  d_wrote_soi = true;
694  write_start_of_instance(m);
695 
696  // In this loop serialize will signal an error with an exception.
697  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
698  // Send all the non-sequence variables
699  DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
700  << (*iter)->name() << endl);
701  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
702  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
703  (*iter)->serialize(eval, dds, m, false);
704  }
705  }
706 
707  d_unsent_data = false; // read should set this.
708  }
709 }
710 
711 // This code is only run by a leaf sequence. Note that a one level sequence
712 // is also a leaf sequence.
713 bool Sequence::serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
714 {
715  DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
716  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
717 
718  // read_row returns true if valid data was read, false if the EOF was
719  // found. 6/1/2001 jhrg
720  bool status = read_row(i, dds, eval, ce_eval);
721  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
722 
723  // Once the first valid (satisfies the CE) row of the leaf sequence has
724  // been read, we know we're going to send data. Send the current instance
725  // of the parent/ancestor sequences now, if there are any. We only need
726  // to do this once, hence it's not inside the while loop, but we only
727  // send the parent seq data _if_ there's data in the leaf to send, that's
728  // why we wait until after the first call to read_row() here in the leaf
729  // sequence.
730  //
731  // NB: It's important to only call serialize_parent_part_two() for a
732  // Sequence that really is the parent of a leaf sequence.
733  if (status && !is_end_of_rows(i)) {
734  BaseType *btp = get_parent();
735  if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
736  }
737 
738  d_wrote_soi = false;
739  while (status && !is_end_of_rows(i)) {
740  i += d_row_stride;
741 
742  DBG(cerr << "Writing Start of Instance marker" << endl);
743  d_wrote_soi = true;
744  write_start_of_instance(m);
745 
746  // In this loop serialize will signal an error with an exception.
747  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
748  DBG(cerr << "Sequence::serialize_leaf(), serializing "
749  << (*iter)->name() << endl);
750  if ((*iter)->send_p()) {
751  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
752  (*iter)->serialize(eval, dds, m, false);
753  }
754  }
755 
756  set_read_p(false); // ...so this will read the next instance
757 
758  status = read_row(i, dds, eval, ce_eval);
759  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
760  }
761 
762  // Only write the EOS marker if there's a matching Start Of Instance
763  // Marker in the stream.
764  if (d_wrote_soi || d_top_most) {
765  DBG(cerr << "Writing End of Sequence marker" << endl);
766  write_end_of_sequence(m);
767  }
768 
769  return true; // Signal errors with exceptions.
770 }
771 
795 {
796  DBG(cerr << "Sequence::intern_data - for " << name() << endl); DBG2(cerr << " intern_data, values: " << &d_values << endl);
797 
798  // Why use a stack instead of return values? We need the stack because
799  // Sequences nested three of more levels deep will loose the middle
800  // instances when the intern_data_parent_part_two() code is run.
801  sequence_values_stack_t sequence_values_stack;
802 
803  sequence_values_stack.push(&d_values);
804 
805  intern_data_private(eval, dds, sequence_values_stack);
806 }
807 
808 void Sequence::intern_data_private(ConstraintEvaluator &eval, DDS &dds, sequence_values_stack_t &sequence_values_stack)
809 {
810  DBG(cerr << "Entering intern_data_private for " << name() << endl);
811 
812  if (is_leaf_sequence())
813  intern_data_for_leaf(dds, eval, sequence_values_stack);
814  else
815  intern_data_parent_part_one(dds, eval, sequence_values_stack);
816 }
817 
818 void Sequence::intern_data_parent_part_one(DDS & dds, ConstraintEvaluator & eval,
819  sequence_values_stack_t & sequence_values_stack)
820 {
821  DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
822 
823  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
824 
825  // read_row returns true if valid data was read, false if the EOF was
826  // found. 6/1/2001 jhrg
827  // Since this is a parent sequence, read the row ignoring the CE (all of
828  // the CE clauses will be evaluated by the leaf sequence).
829  bool status = read_row(i, dds, eval, false);
830 
831  // Grab the current size of the value stack. We do this because it is
832  // possible that no nested sequences for this row happened to be
833  // selected because of a constraint evaluation or the last row is not
834  // selected because of a constraint evaluation. In either case, no
835  // nested sequence d_values are pushed onto the stack, so there is
836  // nothing to pop at the end of this function. pcw 07/14/08
837  SequenceValues::size_type orig_stack_size = sequence_values_stack.size();
838 
839  while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
840  i += get_row_stride();
841  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
842  if ((*iter)->send_p()) {
843  switch ((*iter)->type()) {
844  case dods_sequence_c:
845  static_cast<Sequence&>(**iter).intern_data_private(eval, dds, sequence_values_stack);
846  break;
847 
848  default:
849  (*iter)->intern_data(eval, dds);
850  break;
851  }
852  }
853  }
854 
855  set_read_p(false); // ...so this will read the next instance
856 
857  status = read_row(i, dds, eval, false);
858  }
859 
860  // Reset current row number for next nested sequence element.
862 
863  // if the size of the stack is larger than the original size (retrieved
864  // above) then pop the top set of d_values from the stack. If it's the
865  // same, then no nested sequences, or possibly the last nested sequence,
866  // were pushed onto the stack, so there is nothing to pop.
867  if (sequence_values_stack.size() > orig_stack_size) {
868  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
869  << ") off stack; size: " << sequence_values_stack.size() << endl);
870  sequence_values_stack.pop();
871  }
872 
873  DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
874 }
875 
876 void Sequence::intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval,
877  sequence_values_stack_t &sequence_values_stack)
878 {
879  DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
880 
881  BaseType *btp = get_parent();
882  if (btp && btp->type() == dods_sequence_c) {
883  static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
884  }
885 
886  DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl);
887  SequenceValues *values = sequence_values_stack.top();
888  DBG2(cerr << " using values = " << (void *)values << endl);
889 
890  if (get_unsent_data()) {
891  BaseTypeRow *row_data = new BaseTypeRow;
892 
893  // In this loop transfer_data will signal an error with an exception.
894  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
895 
896  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
897  row_data->push_back((*iter)->ptr_duplicate());
898  }
899  else if ((*iter)->send_p()) { //Sequence; must be the last variable
900  Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
901  if (!tmp) {
902  delete row_data;
903  throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
904  }
905  row_data->push_back(tmp);
906  DBG2(cerr << " pushing d_values of " << tmp->name()
907  << " (" << &(tmp->d_values)
908  << ") on stack; size: " << sequence_values_stack.size()
909  << endl);
910  // This pushes the d_values field of the newly created leaf
911  // Sequence onto the stack. The code then returns to intern
912  // _data_for_leaf() where this value will be used.
913  sequence_values_stack.push(&(tmp->d_values));
914  }
915  }
916 
917  DBG2(cerr << " pushing values for " << name()
918  << " to " << values << endl);
919  values->push_back(row_data);
920  set_unsent_data(false);
921  }
922 
923  DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
924 }
925 
926 void Sequence::intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
927 {
928  DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
929 
930  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
931 
932  DBG2(cerr << " reading row " << i << endl);
933  bool status = read_row(i, dds, eval, true);
934  DBG2(cerr << " status: " << status << endl); DBG2(cerr << " ending row number: " << get_ending_row_number() << endl);
935 
936  if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
937  BaseType *btp = get_parent();
938  if (btp && btp->type() == dods_sequence_c) {
939  // This call will read the values for the parent sequences and
940  // then allocate a new instance for the leaf and push that onto
941  // the stack.
942  static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
943  }
944 
945  // intern_data_parent_part_two pushes the d_values field of the leaf
946  // onto the stack, so this operation grabs that value and then loads
947  // data into it.
948  SequenceValues *values = sequence_values_stack.top();
949  DBG2(cerr << " using values = " << values << endl);
950 
951  while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
952  i += get_row_stride();
953 
954  // Copy data from the object's fields to this new BaeTypeRow instance
955  BaseTypeRow *row_data = new BaseTypeRow;
956  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
957  if ((*iter)->send_p()) {
958  row_data->push_back((*iter)->ptr_duplicate());
959  }
960  }
961 
962  DBG2(cerr << " pushing values for " << name()
963  << " to " << values << endl);
964  // Save the row_data to values().
965  values->push_back(row_data);
966 
967  set_read_p(false); // ...so this will read the next instance
968  // Read the ith row into this object's fields
969  status = read_row(i, dds, eval, true);
970  }
971 
972  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
973  << ") off stack; size: " << sequence_values_stack.size() << endl);
974  sequence_values_stack.pop();
975  }
976 
977  DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
978 }
979 
1000 bool Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
1001 {
1002 #if 0
1003  // Nathan's tip - this is something that should never happen
1004  DataDDS *dd = dynamic_cast<DataDDS *>(dds);
1005  if (!dd) throw InternalErr("Expected argument 'dds' to be a DataDDS!");
1006 
1007  DBG2(cerr << "Reading from server/protocol version: "
1008  << dd->get_protocol_major() << "." << dd->get_protocol_minor()
1009  << endl);
1010 
1011  // Check for old servers.
1012  if (dd->get_protocol_major() < 2) {
1013  throw Error(
1014  string("The protocl version (") + dd->get_protocol()
1015  + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
1016  }
1017 #endif
1018  while (true) {
1019  // Grab the sequence stream's marker.
1020  unsigned char marker = read_marker(um);
1021  if (is_end_of_sequence(marker))
1022  break; // EXIT the while loop here!!!
1023  else if (is_start_of_instance(marker)) {
1024  d_row_number++;
1025  DBG2(cerr << "Reading row " << d_row_number << " of "
1026  << name() << endl);
1027  BaseTypeRow *bt_row_ptr = new BaseTypeRow;
1028  // Read the instance's values, building up the row
1029  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1030  BaseType *bt_ptr = (*iter)->ptr_duplicate();
1031  bt_ptr->deserialize(um, dds, reuse);
1032  DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
1033  << bt_ptr << ") = "); DBG2(bt_ptr->print_val(stderr, ""));
1034  bt_row_ptr->push_back(bt_ptr);
1035  }
1036  // Append this row to those accumulated.
1037  d_values.push_back(bt_row_ptr);
1038  }
1039  else
1040  throw Error("I could not read the expected Sequence data stream marker!");
1041  };
1042 
1043  return false;
1044 }
1045 
1046 // Return the current row number.
1047 
1060 {
1061  return d_starting_row_number;
1062 }
1063 
1075 {
1076  return d_row_stride;
1077 }
1078 
1091 {
1092  return d_ending_row_number;
1093 }
1094 
1103 void Sequence::set_row_number_constraint(int start, int stop, int stride)
1104 {
1105  if (stop < start) throw Error(malformed_expr, "Starting row number must precede the ending row number.");
1106 
1107  d_starting_row_number = start;
1108  d_row_stride = stride;
1109  d_ending_row_number = stop;
1110 }
1111 
1112 void Sequence::print_one_row(FILE *out, int row, string space, bool print_row_num)
1113 {
1114  ostringstream oss;
1115  print_one_row(oss, row, space, print_row_num);
1116  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1117 }
1118 
1119 void Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num)
1120 {
1121  if (print_row_num) out << "\n" << space << row << ": ";
1122 
1123  out << "{ ";
1124 
1125  int elements = element_count();
1126  int j = 0;
1127  BaseType *bt_ptr = 0;
1128 
1129  // This version of print_one_row() works for both data read with
1130  // deserialize(), where each variable is assumed to have valid data, and
1131  // intern_data(), where some/many variables do not. Because of that, it's
1132  // not correct to assume that all of the elements will be printed, which
1133  // is what the old code did.
1134  // Print the first value
1135  while (j < elements && !bt_ptr) {
1136  bt_ptr = var_value(row, j++);
1137  if (bt_ptr) { // data
1138  if (bt_ptr->type() == dods_sequence_c)
1139  static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1140  else
1141  bt_ptr->print_val(out, space, false);
1142  }
1143  }
1144 
1145  // Print the remaining values
1146  while (j < elements) {
1147  bt_ptr = var_value(row, j++);
1148  if (bt_ptr) { // data
1149  out << ", ";
1150  if (bt_ptr->type() == dods_sequence_c)
1151  static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1152  else
1153  bt_ptr->print_val(out, space, false);
1154  }
1155  }
1156 
1157  out << " }";
1158 }
1159 
1160 void Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, bool print_row_numbers)
1161 {
1162  ostringstream oss;
1163  print_val_by_rows(oss, space, print_decl_p, print_row_numbers);
1164  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1165 }
1166 
1167 void Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers)
1168 {
1169  if (print_decl_p) {
1170  print_decl(out, space, false);
1171  out << " = ";
1172  }
1173 
1174  out << "{ ";
1175 
1176  int rows = number_of_rows() - 1;
1177  int i;
1178  for (i = 0; i < rows; ++i) {
1179  print_one_row(out, i, space, print_row_numbers);
1180  out << ", ";
1181  }
1182  print_one_row(out, i, space, print_row_numbers);
1183 
1184  out << " }";
1185 
1186  if (print_decl_p) out << ";\n";
1187 }
1188 
1189 void Sequence::print_val(FILE *out, string space, bool print_decl_p)
1190 {
1191  print_val_by_rows(out, space, print_decl_p, false);
1192 }
1193 
1194 void Sequence::print_val(ostream &out, string space, bool print_decl_p)
1195 {
1196  print_val_by_rows(out, space, print_decl_p, false);
1197 }
1198 
1199 void Sequence::set_leaf_p(bool state)
1200 {
1201  d_leaf_sequence = state;
1202 }
1203 
1204 bool Sequence::is_leaf_sequence()
1205 {
1206  return d_leaf_sequence;
1207 }
1208 
1234 {
1235  bool has_child_sequence = false;
1236 
1237  if (lvl == 1) d_top_most = true;
1238 
1239  DBG2(cerr << "Processing sequence " << name() << endl);
1240 
1241  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1242  // About the test for send_p(): Only descend into a sequence if it has
1243  // fields that might be sent. Thus if, in a two-level sequence, nothing
1244  // in the lower level is to be sent, the upper level is marked as the
1245  // leaf sequence. This ensures that values _will_ be sent (see the comment
1246  // in serialize_leaf() and serialize_parent_part_one()).
1247  if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
1248  if (has_child_sequence)
1249  throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
1250 
1251  has_child_sequence = true;
1252  static_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
1253  }
1254  else if ((*iter)->type() == dods_structure_c) {
1255  static_cast<Structure&>(**iter).set_leaf_sequence(lvl);
1256  }
1257  }
1258 
1259  if (!has_child_sequence)
1260  set_leaf_p(true);
1261  else
1262  set_leaf_p(false);
1263 
1264  DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
1265 }
1266 
1275 void Sequence::dump(ostream &strm) const
1276 {
1277  strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl;
1278  DapIndent::Indent();
1279  Constructor::dump(strm);
1280  strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number << endl;
1281  strm << DapIndent::LMarg << "bracket notation information:" << endl;
1282  DapIndent::Indent();
1283  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
1284  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
1285  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
1286  DapIndent::UnIndent();
1287 
1288  strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl;
1289  strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl;
1290  strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence << endl;
1291  strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most << endl;
1292  DapIndent::UnIndent();
1293 }
1294 
1295 } // namespace libdap
1296 
The basic data type for the DODS DAP types.
Definition: BaseType.h:118
virtual BaseType * ptr_duplicate()=0
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: BaseType.cc:939
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:316
virtual BaseType * get_parent() const
Definition: BaseType.cc:747
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:476
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:354
virtual string toString()
Definition: BaseType.cc:180
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition: BaseType.cc:126
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: BaseType.cc:1086
Evaluate a constraint expression.
bool eval_selection(DDS &dds, const std::string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator and is called ...
int element_count(bool leaves=false) override
Count the members of constructor types.
Definition: Constructor.cc:115
void transform_to_dap4(D4Group *root, Constructor *dest) override
DAP2 to DAP4 transform.
Definition: Constructor.cc:84
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 intern_data() override
Read data into this variable.
Definition: Constructor.cc:468
void set_read_p(bool state) override
Set the 'read_p' property for the Constructor and its members.
Definition: Constructor.cc:150
Vars_iter var_end()
Definition: Constructor.cc:280
bool read() override
Read the elements of Constructor marked for transmission.
Definition: Constructor.cc:393
void add_var_nocopy(BaseType *bt, Part part=nil) override
Definition: Constructor.cc:345
Vars_iter var_begin()
Definition: Constructor.cc:272
void dump(ostream &strm) const override
dumps information about this object
Definition: Constructor.cc:767
Holds a sequence.
Definition: D4Sequence.h:134
virtual void set_length(int count)
Definition: D4Sequence.h:199
Holds a DAP2 DDS.
Definition: DataDDS.h:78
A class for error processing.
Definition: Error.h:94
A class for software fault reporting.
Definition: InternalErr.h:65
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:50
Holds a sequence.
Definition: Sequence.h:163
virtual void transform_to_dap4(D4Group *root, Constructor *container)
Definition: Sequence.cc:212
virtual SequenceValues value()
Definition: Sequence.cc:341
virtual string toString()
Definition: Sequence.cc:274
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Sequence.cc:1275
virtual bool read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval=true)
Definition: Sequence.cc:496
virtual void set_leaf_sequence(int lvl=1)
Mark the Sequence which holds the leaf elements.
Definition: Sequence.cc:1233
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: Sequence.cc:1194
Sequence(const string &n)
The Sequence constructor.
Definition: Sequence.cc:161
virtual SequenceValues & value_ref()
Definition: Sequence.cc:349
virtual void set_value(SequenceValues &values)
Definition: Sequence.cc:334
virtual BaseType * ptr_duplicate()
Definition: Sequence.cc:192
virtual bool is_linear()
Check to see whether this variable can be printed simply.
Definition: Sequence.cc:289
virtual BaseType * var_value(size_t row, const string &name)
Get the BaseType pointer to the named variable of a given row.
Definition: Sequence.cc:360
virtual void clear_local_data()
Definition: Sequence.cc:247
virtual bool is_dap2_only_type()
Definition: Sequence.cc:269
bool get_unsent_data() const
Get the unsent data property.
Definition: Sequence.h:271
int get_starting_row_number()
Get the starting row number.
Definition: Sequence.cc:1059
void reset_row_number()
Rest the row number counter.
Definition: Sequence.cc:424
void set_unsent_data(bool usd)
Set the unsent data property.
Definition: Sequence.h:277
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Definition: Sequence.cc:604
virtual int length() const
Definition: Sequence.cc:410
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Deserialize (read from the network) the entire Sequence.
Definition: Sequence.cc:1000
virtual int get_row_stride()
Get the row stride.
Definition: Sequence.cc:1074
virtual int get_ending_row_number()
Get the ending row number.
Definition: Sequence.cc:1090
virtual BaseTypeRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: Sequence.cc:322
virtual void set_row_number_constraint(int start, int stop, int stride=1)
Definition: Sequence.cc:1103
Holds a structure (aggregate) type.
Definition: Structure.h:84
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
Definition: Structure.cc:309
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:55
top level DAP object to house generic methods
Definition: AlarmHandler.h:36
vector< BaseType * > BaseTypeRow
Definition: D4Sequence.h:50
vector< BaseTypeRow * > SequenceValues
Definition: D4Sequence.h:53