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