libdap  Updated for version 3.20.6
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 
262  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
263 
264  m_duplicate(rhs);
265 
266  return *this;
267 }
268 
273 {
274  return true;
275 }
276 
278 {
279  ostringstream oss;
280 
281  oss << BaseType::toString();
282 
283  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
284  oss << (*i)->toString();
285  }
286 
287  oss << endl;
288 
289  return oss.str();
290 }
291 
293 {
294  bool linear = true;
295  bool seq_found = false;
296  for (Vars_iter iter = d_vars.begin(); linear && iter != d_vars.end(); iter++) {
297  if ((*iter)->type() == dods_sequence_c) {
298  // A linear sequence cannot have more than one child seq. at any
299  // one level. If we've already found a seq at this level, return
300  // false.
301  if (seq_found) {
302  linear = false;
303  break;
304  }
305  seq_found = true;
306  linear = static_cast<Sequence *>((*iter))->is_linear();
307  }
308  else if ((*iter)->type() == dods_structure_c) {
309  linear = static_cast<Structure*>((*iter))->is_linear();
310  }
311  else {
312  // A linear sequence cannot have Arrays, Lists or Grids.
313  linear = (*iter)->is_simple_type();
314  }
315  }
316 
317  return linear;
318 }
319 
324 BaseTypeRow *
326 {
327  if (row >= d_values.size()) return 0; //nullptr
328  return d_values[row];
329 }
330 
338 {
339  d_values = values;
340 }
341 
345 {
346  return d_values;
347 }
348 
353 {
354  return d_values;
355 }
356 
362 BaseType *
363 Sequence::var_value(size_t row, const string &name)
364 {
365  BaseTypeRow *bt_row_ptr = row_value(row);
366  if (!bt_row_ptr) return 0;
367 
368  BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
369  BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
370  while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
371  ++bt_row_iter;
372 
373  if (bt_row_iter == bt_row_end)
374  return 0;
375  else
376  return *bt_row_iter;
377 }
378 
384 BaseType *
385 Sequence::var_value(size_t row, size_t i)
386 {
387  BaseTypeRow *bt_row_ptr = row_value(row);
388  if (!bt_row_ptr) return 0;
389 
390  if (i >= bt_row_ptr->size()) return 0;
391 
392  return (*bt_row_ptr)[i];
393 }
394 
395 // This version returns -1. Each API-specific subclass should define a more
396 // reasonable version. jhrg 5/24/96
397 
413 int Sequence::length() const
414 {
415  return -1;
416 }
417 
418 // Hmmm. how is this different from length()?
419 int Sequence::number_of_rows() const
420 {
421  return d_values.size();
422 }
423 
428 {
429  d_row_number = -1;
430 }
431 
438 {
440 
441  if (recur)
442  for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i)
443  if ((*i)->type() == dods_sequence_c)
444  reset_row_number(true);
445 }
446 
447 // Notes:
448 // Assume that read() is implemented so that, when reading data for a nested
449 // sequence, only the outer most level is *actually* read.
450 // This is a consequence of our current (12/7/99) implementation of
451 // the JGOFS server (which is the only server to actually use nested
452 // sequences). 12/7/99 jhrg
453 //
454 // Stop assuming this. This logic is being moved into the JGOFS server
455 // itself. 6/1/2001 jhrg
456 
457 // The read() function returns a boolean value, with TRUE
458 // indicating that read() should be called again because there's
459 // more data to read, and FALSE indicating there's no more data
460 // to read. Note that this behavior is necessary to properly
461 // handle variables that contain Sequences. Jose Garcia If an
462 // error exists while reading, the implementers of the surrogate
463 // library SHOULD throw an Error object which will propagate
464 // beyond this point to to the original caller.
465 // Jose Garcia
466 
499 bool Sequence::read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval)
500 {
501  DBG2(cerr << "Entering Sequence::read_row for " << name() << ", row number " << row << ", current row " << d_row_number << endl);
502  if (row < d_row_number) throw InternalErr("Trying to back up inside a sequence!");
503 
504  if (row == d_row_number) {
505  DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
506  return false;
507  }
508 
509  bool eof = false; // Start out assuming EOF is false.
510  while (!eof && d_row_number < row) {
511  if (!read_p()) {
512  // jhrg original version from 10/9/13 : eof = (read() == false);
513  eof = read();
514  }
515 
516  // Advance the row number if ce_eval is false (we're not supposed to
517  // evaluate the selection) or both ce_eval and the selection are
518  // true.
519  if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) d_row_number++;
520 
521  set_read_p(false); // ...so that the next instance will be read
522  }
523 
524  // Once we finish the above loop, set read_p to true so that the caller
525  // knows that data *has* been read. This is how the read() methods of the
526  // elements of the sequence know to not call read() but instead look for
527  // data values inside themselves.
528  set_read_p(true);
529 
530  // Return true if we have valid data, false if we've read to the EOF.
531  DBG2(cerr << "Leaving Sequence::read_row for " << name() << " with eof: " << eof << endl);
532  return !eof; // jhrg 10/10/13 was: eof == 0;
533 }
534 
535 // Private. This is used to process constraints on the rows of a sequence.
536 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
537 // odd-looking logic first checks if d_ending_row_number is the sentinel
538 // value of -1. If so, the sequence was not constrained by row number and
539 // this method should never return true (which indicates that we're at the
540 // end of a row-number constraint). If d_ending_row_number is not -1, then is
541 // \e i at the end point? 6/1/2001 jhrg
542 inline bool Sequence::is_end_of_rows(int i)
543 {
544  return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
545 }
546 
607 bool Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval)
608 {
609  // Special case leaf sequences!
610  bool status = false;
611 
612  if (is_leaf_sequence())
613  status = serialize_leaf(dds, eval, m, ce_eval);
614  else
615  status = serialize_parent_part_one(dds, eval, m);
616 
617  return status;
618 }
619 
620 // We know this is not a leaf Sequence. That means that this Sequence holds
621 // another Sequence as one of its fields _and_ that child Sequence triggers
622 // the actual transmission of values.
623 
624 bool Sequence::serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
625 {
626  DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
627 
628  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
629 
630  // read_row returns true if valid data was read, false if the EOF was
631  // found. 6/1/2001 jhrg
632  // Since this is a parent sequence, read the row ignoring the CE (all of
633  // the CE clauses will be evaluated by the leaf sequence).
634  bool status = read_row(i, dds, eval, false);
635  DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
636 
637  while (status && !is_end_of_rows(i)) {
638  i += d_row_stride;
639 
640  // DBG(cerr << "Writing Start of Instance marker" << endl);
641  // write_start_of_instance(sink);
642 
643  // In this loop serialize will signal an error with an exception.
644  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
645  // Only call serialize for child Sequences; the leaf sequence
646  // will trigger the transmission of values for its parents (this
647  // sequence and maybe others) once it gets some valid data to
648  // send.
649  // Note that if the leaf sequence has no variables in the current
650  // projection, its serialize() method will never be called and that's
651  // the method that triggers actually sending values. Thus the leaf
652  // sequence must be the lowest level sequence with values whose send_p
653  // property is true.
654  if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) (*iter)->serialize(eval, dds, m);
655  }
656 
657  set_read_p(false); // ...so this will read the next instance
658 
659  status = read_row(i, dds, eval, false);
660  DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
661  }
662  // Reset current row number for next nested sequence element.
663  d_row_number = -1;
664 
665  // Always write the EOS marker? 12/23/04 jhrg
666  // Yes. According to DAP2, a completely empty response is signaled by
667  // a return value of only the EOS marker for the outermost sequence.
668  if (d_top_most || d_wrote_soi) {
669  DBG(cerr << "Writing End of Sequence marker" << endl);
670  write_end_of_sequence(m);
671  d_wrote_soi = false;
672  }
673 
674  return true; // Signal errors with exceptions.
675 }
676 
677 // If we are here then we know that this is 'parent sequence' and that the
678 // leaf sequence has found valid data to send. We also know that
679 // serialize_parent_part_one has been called so data are in the instance's
680 // fields. This is where we send data. Whereas ..._part_one() contains a
681 // loop to iterate over all of rows in a parent sequence, this does not. This
682 // method assumes that the serialize_leaf() will call it each time it needs
683 // to be called.
684 //
685 // NB: This code only works if the child sequences appear after all other
686 // variables.
687 void Sequence::serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
688 {
689  DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
690 
691  BaseType *btp = get_parent();
692  if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
693 
694  if (d_unsent_data) {
695  DBG(cerr << "Writing Start of Instance marker" << endl);
696  d_wrote_soi = true;
697  write_start_of_instance(m);
698 
699  // In this loop serialize will signal an error with an exception.
700  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
701  // Send all the non-sequence variables
702  DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
703  << (*iter)->name() << endl);
704  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
705  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
706  (*iter)->serialize(eval, dds, m, false);
707  }
708  }
709 
710  d_unsent_data = false; // read should set this.
711  }
712 }
713 
714 // This code is only run by a leaf sequence. Note that a one level sequence
715 // is also a leaf sequence.
716 bool Sequence::serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
717 {
718  DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
719  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
720 
721  // read_row returns true if valid data was read, false if the EOF was
722  // found. 6/1/2001 jhrg
723  bool status = read_row(i, dds, eval, ce_eval);
724  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
725 
726  // Once the first valid (satisfies the CE) row of the leaf sequence has
727  // been read, we know we're going to send data. Send the current instance
728  // of the parent/ancestor sequences now, if there are any. We only need
729  // to do this once, hence it's not inside the while loop, but we only
730  // send the parent seq data _if_ there's data in the leaf to send, that's
731  // why we wait until after the first call to read_row() here in the leaf
732  // sequence.
733  //
734  // NB: It's important to only call serialize_parent_part_two() for a
735  // Sequence that really is the parent of a leaf sequence.
736  if (status && !is_end_of_rows(i)) {
737  BaseType *btp = get_parent();
738  if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
739  }
740 
741  d_wrote_soi = false;
742  while (status && !is_end_of_rows(i)) {
743  i += d_row_stride;
744 
745  DBG(cerr << "Writing Start of Instance marker" << endl);
746  d_wrote_soi = true;
747  write_start_of_instance(m);
748 
749  // In this loop serialize will signal an error with an exception.
750  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
751  DBG(cerr << "Sequence::serialize_leaf(), serializing "
752  << (*iter)->name() << endl);
753  if ((*iter)->send_p()) {
754  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
755  (*iter)->serialize(eval, dds, m, false);
756  }
757  }
758 
759  set_read_p(false); // ...so this will read the next instance
760 
761  status = read_row(i, dds, eval, ce_eval);
762  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
763  }
764 
765  // Only write the EOS marker if there's a matching Start Of Instance
766  // Marker in the stream.
767  if (d_wrote_soi || d_top_most) {
768  DBG(cerr << "Writing End of Sequence marker" << endl);
769  write_end_of_sequence(m);
770  }
771 
772  return true; // Signal errors with exceptions.
773 }
774 
798 {
799  DBG(cerr << "Sequence::intern_data - for " << name() << endl); DBG2(cerr << " intern_data, values: " << &d_values << endl);
800 
801  // Why use a stack instead of return values? We need the stack because
802  // Sequences nested three of more levels deep will loose the middle
803  // instances when the intern_data_parent_part_two() code is run.
804  sequence_values_stack_t sequence_values_stack;
805 
806  sequence_values_stack.push(&d_values);
807 
808  intern_data_private(eval, dds, sequence_values_stack);
809 }
810 
811 void Sequence::intern_data_private(ConstraintEvaluator &eval, DDS &dds, sequence_values_stack_t &sequence_values_stack)
812 {
813  DBG(cerr << "Entering intern_data_private for " << name() << endl);
814 
815  if (is_leaf_sequence())
816  intern_data_for_leaf(dds, eval, sequence_values_stack);
817  else
818  intern_data_parent_part_one(dds, eval, sequence_values_stack);
819 }
820 
821 void Sequence::intern_data_parent_part_one(DDS & dds, ConstraintEvaluator & eval,
822  sequence_values_stack_t & sequence_values_stack)
823 {
824  DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
825 
826  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
827 
828  // read_row returns true if valid data was read, false if the EOF was
829  // found. 6/1/2001 jhrg
830  // Since this is a parent sequence, read the row ignoring the CE (all of
831  // the CE clauses will be evaluated by the leaf sequence).
832  bool status = read_row(i, dds, eval, false);
833 
834  // Grab the current size of the value stack. We do this because it is
835  // possible that no nested sequences for this row happened to be
836  // selected because of a constraint evaluation or the last row is not
837  // selected because of a constraint evaluation. In either case, no
838  // nested sequence d_values are pushed onto the stack, so there is
839  // nothing to pop at the end of this function. pcw 07/14/08
840  SequenceValues::size_type orig_stack_size = sequence_values_stack.size();
841 
842  while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
843  i += get_row_stride();
844  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
845  if ((*iter)->send_p()) {
846  switch ((*iter)->type()) {
847  case dods_sequence_c:
848  static_cast<Sequence&>(**iter).intern_data_private(eval, dds, sequence_values_stack);
849  break;
850 
851  default:
852  (*iter)->intern_data(eval, dds);
853  break;
854  }
855  }
856  }
857 
858  set_read_p(false); // ...so this will read the next instance
859 
860  status = read_row(i, dds, eval, false);
861  }
862 
863  // Reset current row number for next nested sequence element.
865 
866  // if the size of the stack is larger than the original size (retrieved
867  // above) then pop the top set of d_values from the stack. If it's the
868  // same, then no nested sequences, or possibly the last nested sequence,
869  // were pushed onto the stack, so there is nothing to pop.
870  if (sequence_values_stack.size() > orig_stack_size) {
871  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
872  << ") off stack; size: " << sequence_values_stack.size() << endl);
873  sequence_values_stack.pop();
874  }
875 
876  DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
877 }
878 
879 void Sequence::intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval,
880  sequence_values_stack_t &sequence_values_stack)
881 {
882  DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
883 
884  BaseType *btp = get_parent();
885  if (btp && btp->type() == dods_sequence_c) {
886  static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
887  }
888 
889  DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl);
890  SequenceValues *values = sequence_values_stack.top();
891  DBG2(cerr << " using values = " << (void *)values << endl);
892 
893  if (get_unsent_data()) {
894  BaseTypeRow *row_data = new BaseTypeRow;
895 
896  // In this loop transfer_data will signal an error with an exception.
897  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
898 
899  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
900  row_data->push_back((*iter)->ptr_duplicate());
901  }
902  else if ((*iter)->send_p()) { //Sequence; must be the last variable
903  Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
904  if (!tmp) {
905  delete row_data;
906  throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
907  }
908  row_data->push_back(tmp);
909  DBG2(cerr << " pushing d_values of " << tmp->name()
910  << " (" << &(tmp->d_values)
911  << ") on stack; size: " << sequence_values_stack.size()
912  << endl);
913  // This pushes the d_values field of the newly created leaf
914  // Sequence onto the stack. The code then returns to intern
915  // _data_for_leaf() where this value will be used.
916  sequence_values_stack.push(&(tmp->d_values));
917  }
918  }
919 
920  DBG2(cerr << " pushing values for " << name()
921  << " to " << values << endl);
922  values->push_back(row_data);
923  set_unsent_data(false);
924  }
925 
926  DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
927 }
928 
929 void Sequence::intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
930 {
931  DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
932 
933  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
934 
935  DBG2(cerr << " reading row " << i << endl);
936  bool status = read_row(i, dds, eval, true);
937  DBG2(cerr << " status: " << status << endl); DBG2(cerr << " ending row number: " << get_ending_row_number() << endl);
938 
939  if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
940  BaseType *btp = get_parent();
941  if (btp && btp->type() == dods_sequence_c) {
942  // This call will read the values for the parent sequences and
943  // then allocate a new instance for the leaf and push that onto
944  // the stack.
945  static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
946  }
947 
948  // intern_data_parent_part_two pushes the d_values field of the leaf
949  // onto the stack, so this operation grabs that value and then loads
950  // data into it.
951  SequenceValues *values = sequence_values_stack.top();
952  DBG2(cerr << " using values = " << values << endl);
953 
954  while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
955  i += get_row_stride();
956 
957  // Copy data from the object's fields to this new BaeTypeRow instance
958  BaseTypeRow *row_data = new BaseTypeRow;
959  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
960  if ((*iter)->send_p()) {
961  row_data->push_back((*iter)->ptr_duplicate());
962  }
963  }
964 
965  DBG2(cerr << " pushing values for " << name()
966  << " to " << values << endl);
967  // Save the row_data to values().
968  values->push_back(row_data);
969 
970  set_read_p(false); // ...so this will read the next instance
971  // Read the ith row into this object's fields
972  status = read_row(i, dds, eval, true);
973  }
974 
975  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
976  << ") off stack; size: " << sequence_values_stack.size() << endl);
977  sequence_values_stack.pop();
978  }
979 
980  DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
981 }
982 
1003 bool Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
1004 {
1005 #if 0
1006  // Nathan's tip - this is something that should never happen
1007  DataDDS *dd = dynamic_cast<DataDDS *>(dds);
1008  if (!dd) throw InternalErr("Expected argument 'dds' to be a DataDDS!");
1009 
1010  DBG2(cerr << "Reading from server/protocol version: "
1011  << dd->get_protocol_major() << "." << dd->get_protocol_minor()
1012  << endl);
1013 
1014  // Check for old servers.
1015  if (dd->get_protocol_major() < 2) {
1016  throw Error(
1017  string("The protocl version (") + dd->get_protocol()
1018  + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
1019  }
1020 #endif
1021  while (true) {
1022  // Grab the sequence stream's marker.
1023  unsigned char marker = read_marker(um);
1024  if (is_end_of_sequence(marker))
1025  break; // EXIT the while loop here!!!
1026  else if (is_start_of_instance(marker)) {
1027  d_row_number++;
1028  DBG2(cerr << "Reading row " << d_row_number << " of "
1029  << name() << endl);
1030  BaseTypeRow *bt_row_ptr = new BaseTypeRow;
1031  // Read the instance's values, building up the row
1032  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1033  BaseType *bt_ptr = (*iter)->ptr_duplicate();
1034  bt_ptr->deserialize(um, dds, reuse);
1035  DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
1036  << bt_ptr << ") = "); DBG2(bt_ptr->print_val(stderr, ""));
1037  bt_row_ptr->push_back(bt_ptr);
1038  }
1039  // Append this row to those accumulated.
1040  d_values.push_back(bt_row_ptr);
1041  }
1042  else
1043  throw Error("I could not read the expected Sequence data stream marker!");
1044  };
1045 
1046  return false;
1047 }
1048 
1049 // Return the current row number.
1050 
1063 {
1064  return d_starting_row_number;
1065 }
1066 
1078 {
1079  return d_row_stride;
1080 }
1081 
1094 {
1095  return d_ending_row_number;
1096 }
1097 
1106 void Sequence::set_row_number_constraint(int start, int stop, int stride)
1107 {
1108  if (stop < start) throw Error(malformed_expr, "Starting row number must precede the ending row number.");
1109 
1110  d_starting_row_number = start;
1111  d_row_stride = stride;
1112  d_ending_row_number = stop;
1113 }
1114 
1115 void Sequence::print_one_row(FILE *out, int row, string space, bool print_row_num)
1116 {
1117  ostringstream oss;
1118  print_one_row(oss, row, space, print_row_num);
1119  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1120 }
1121 
1122 void Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num)
1123 {
1124  if (print_row_num) out << "\n" << space << row << ": ";
1125 
1126  out << "{ ";
1127 
1128  int elements = element_count();
1129  int j = 0;
1130  BaseType *bt_ptr = 0;
1131 
1132  // This version of print_one_row() works for both data read with
1133  // deserialize(), where each variable is assumed to have valid data, and
1134  // intern_data(), where some/many variables do not. Because of that, it's
1135  // not correct to assume that all of the elements will be printed, which
1136  // is what the old code did.
1137  // Print the first value
1138  while (j < elements && !bt_ptr) {
1139  bt_ptr = var_value(row, j++);
1140  if (bt_ptr) { // data
1141  if (bt_ptr->type() == dods_sequence_c)
1142  static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1143  else
1144  bt_ptr->print_val(out, space, false);
1145  }
1146  }
1147 
1148  // Print the remaining values
1149  while (j < elements) {
1150  bt_ptr = var_value(row, j++);
1151  if (bt_ptr) { // data
1152  out << ", ";
1153  if (bt_ptr->type() == dods_sequence_c)
1154  static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1155  else
1156  bt_ptr->print_val(out, space, false);
1157  }
1158  }
1159 
1160  out << " }";
1161 }
1162 
1163 void Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, bool print_row_numbers)
1164 {
1165  ostringstream oss;
1166  print_val_by_rows(oss, space, print_decl_p, print_row_numbers);
1167  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1168 }
1169 
1170 void Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers)
1171 {
1172  if (print_decl_p) {
1173  print_decl(out, space, false);
1174  out << " = ";
1175  }
1176 
1177  out << "{ ";
1178 
1179  int rows = number_of_rows() - 1;
1180  int i;
1181  for (i = 0; i < rows; ++i) {
1182  print_one_row(out, i, space, print_row_numbers);
1183  out << ", ";
1184  }
1185  print_one_row(out, i, space, print_row_numbers);
1186 
1187  out << " }";
1188 
1189  if (print_decl_p) out << ";\n";
1190 }
1191 
1192 void Sequence::print_val(FILE *out, string space, bool print_decl_p)
1193 {
1194  print_val_by_rows(out, space, print_decl_p, false);
1195 }
1196 
1197 void Sequence::print_val(ostream &out, string space, bool print_decl_p)
1198 {
1199  print_val_by_rows(out, space, print_decl_p, false);
1200 }
1201 
1202 void Sequence::set_leaf_p(bool state)
1203 {
1204  d_leaf_sequence = state;
1205 }
1206 
1207 bool Sequence::is_leaf_sequence()
1208 {
1209  return d_leaf_sequence;
1210 }
1211 
1237 {
1238  bool has_child_sequence = false;
1239 
1240  if (lvl == 1) d_top_most = true;
1241 
1242  DBG2(cerr << "Processing sequence " << name() << endl);
1243 
1244  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1245  // About the test for send_p(): Only descend into a sequence if it has
1246  // fields that might be sent. Thus if, in a two-level sequence, nothing
1247  // in the lower level is to be sent, the upper level is marked as the
1248  // leaf sequence. This ensures that values _will_ be sent (see the comment
1249  // in serialize_leaf() and serialize_parent_part_one()).
1250  if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
1251  if (has_child_sequence)
1252  throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
1253 
1254  has_child_sequence = true;
1255  static_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
1256  }
1257  else if ((*iter)->type() == dods_structure_c) {
1258  static_cast<Structure&>(**iter).set_leaf_sequence(lvl);
1259  }
1260  }
1261 
1262  if (!has_child_sequence)
1263  set_leaf_p(true);
1264  else
1265  set_leaf_p(false);
1266 
1267  DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
1268 }
1269 
1278 void Sequence::dump(ostream &strm) const
1279 {
1280  strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl;
1281  DapIndent::Indent();
1282  Constructor::dump(strm);
1283  strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number << endl;
1284  strm << DapIndent::LMarg << "bracket notation information:" << endl;
1285  DapIndent::Indent();
1286  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
1287  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
1288  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
1289  DapIndent::UnIndent();
1290 
1291  strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl;
1292  strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl;
1293  strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence << endl;
1294  strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most << endl;
1295  DapIndent::UnIndent();
1296 }
1297 
1298 } // namespace libdap
1299 
virtual void clear_local_data()
Definition: Sequence.cc:247
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
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:54
bool get_unsent_data() const
Get the unsent data property.
Definition: Sequence.h:271
void set_unsent_data(bool usd)
Set the unsent data property.
Definition: Sequence.h:277
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: BaseType.cc:943
virtual bool read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval=true)
Definition: Sequence.cc:499
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Deserialize (read from the network) the entire Sequence.
Definition: Sequence.cc:1003
virtual bool is_dap2_only_type()
Definition: Sequence.cc:272
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Definition: Sequence.cc:607
STL namespace.
virtual void add_var_nocopy(BaseType *bt, Part part=nil)
Definition: Constructor.cc:432
virtual BaseTypeRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: Sequence.cc:325
vector< BaseTypeRow * > SequenceValues
Definition: D4Sequence.h:53
virtual void set_row_number_constraint(int start, int stop, int stride=1)
Definition: Sequence.cc:1106
Holds a structure (aggregate) type.
Definition: Structure.h:83
virtual string toString()
Definition: BaseType.cc:184
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Constructor.cc:194
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
Definition: Structure.cc:331
top level DAP object to house generic methods
Definition: AISConnect.cc:30
A class for software fault reporting.
Definition: InternalErr.h:64
virtual bool is_linear()
Check to see whether this variable can be printed simply.
Definition: Sequence.cc:292
virtual void transform_to_dap4(D4Group *root, Constructor *dest)
DAP2 to DAP4 transform.
Definition: Constructor.cc:141
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: BaseType.cc:1090
Sequence(const string &n)
The Sequence constructor.
Definition: Sequence.cc:161
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 set_leaf_sequence(int lvl=1)
Mark the Sequence which holds the leaf elements.
Definition: Sequence.cc:1236
Holds a sequence.
Definition: Sequence.h:162
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:913
virtual string toString()
Definition: Sequence.cc:277
virtual BaseType * ptr_duplicate()=0
int get_starting_row_number()
Get the starting row number.
Definition: Sequence.cc:1062
Evaluate a constraint expression.
virtual SequenceValues & value_ref()
Definition: Sequence.cc:352
virtual SequenceValues value()
Definition: Sequence.cc:344
void reset_row_number()
Rest the row number counter.
Definition: Sequence.cc:427
virtual int length() const
Definition: Sequence.cc:413
virtual BaseType * get_parent() const
Definition: BaseType.cc:751
The basic data type for the DODS DAP types.
Definition: BaseType.h:117
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:50
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:363
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
Vars_iter var_begin()
Definition: Constructor.cc:356
Vars_iter var_end()
Definition: Constructor.cc:364
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: Sequence.cc:1197
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 ...
virtual void intern_data()
Read data into this variable.
Definition: Constructor.cc:556
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Sequence.cc:1278
virtual void transform_to_dap4(D4Group *root, Constructor *container)
Definition: Sequence.cc:212
A class for error processing.
Definition: Error.h:92
virtual int get_ending_row_number()
Get the ending row number.
Definition: Sequence.cc:1093
virtual BaseType * ptr_duplicate()
Definition: Sequence.cc:192
Holds a DAP2 DDS.
Definition: DataDDS.h:77
virtual int get_row_stride()
Get the row stride.
Definition: Sequence.cc:1077
virtual void set_value(SequenceValues &values)
Definition: Sequence.cc:337
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:358
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Constructor.cc:218
vector< BaseType * > BaseTypeRow
Definition: D4Sequence.h:50