libdap  Updated for version 3.17.2
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 //#define DODS_DEBUG
36 //#define DODS_DEBUG2
37 
38 #include "config.h"
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 BaseType *
212 {
213  D4Sequence *dest = new D4Sequence(name());
214 
215  Constructor::transform_to_dap4(root, dest);
216 
217  dest->set_length(-1);
218  dest->set_parent(container);
219 
220  return dest;
221 }
222 
223 static inline void delete_bt(BaseType *bt_ptr)
224 {
225  delete bt_ptr;
226  bt_ptr = 0;
227 }
228 
229 static inline void delete_rows(BaseTypeRow *bt_row_ptr)
230 {
231  for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
232 
233  delete bt_row_ptr;
234  bt_row_ptr = 0;
235 }
236 
237 Sequence::~Sequence()
238 {
240 }
241 
243 {
244  if (!d_values.empty()) {
245  for_each(d_values.begin(), d_values.end(), delete_rows);
246  d_values.resize(0);
247  }
248 
249  set_read_p(false);
250 }
251 
252 Sequence &
253 Sequence::operator=(const Sequence &rhs)
254 {
255  if (this == &rhs) return *this;
256 
257  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
258 
259  m_duplicate(rhs);
260 
261  return *this;
262 }
263 
268 {
269  return true;
270 }
271 
273 {
274  ostringstream oss;
275 
276  oss << BaseType::toString();
277 
278  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
279  oss << (*i)->toString();
280  }
281 
282  oss << endl;
283 
284  return oss.str();
285 }
286 
288 {
289  bool linear = true;
290  bool seq_found = false;
291  for (Vars_iter iter = d_vars.begin(); linear && iter != d_vars.end(); iter++) {
292  if ((*iter)->type() == dods_sequence_c) {
293  // A linear sequence cannot have more than one child seq. at any
294  // one level. If we've already found a seq at this level, return
295  // false.
296  if (seq_found) {
297  linear = false;
298  break;
299  }
300  seq_found = true;
301  linear = static_cast<Sequence *>((*iter))->is_linear();
302  }
303  else if ((*iter)->type() == dods_structure_c) {
304  linear = static_cast<Structure*>((*iter))->is_linear();
305  }
306  else {
307  // A linear sequence cannot have Arrays, Lists or Grids.
308  linear = (*iter)->is_simple_type();
309  }
310  }
311 
312  return linear;
313 }
314 
319 BaseTypeRow *
321 {
322  if (row >= d_values.size()) return 0;
323  return d_values[row];
324 }
325 
333 {
334  d_values = values;
335 }
336 
340 {
341  return d_values;
342 }
343 
348 {
349  return d_values;
350 }
351 
357 BaseType *
358 Sequence::var_value(size_t row, const string &name)
359 {
360  BaseTypeRow *bt_row_ptr = row_value(row);
361  if (!bt_row_ptr) return 0;
362 
363  BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
364  BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
365  while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
366  ++bt_row_iter;
367 
368  if (bt_row_iter == bt_row_end)
369  return 0;
370  else
371  return *bt_row_iter;
372 }
373 
379 BaseType *
380 Sequence::var_value(size_t row, size_t i)
381 {
382  BaseTypeRow *bt_row_ptr = row_value(row);
383  if (!bt_row_ptr) return 0;
384 
385  if (i >= bt_row_ptr->size()) return 0;
386 
387  return (*bt_row_ptr)[i];
388 }
389 
390 // This version returns -1. Each API-specific subclass should define a more
391 // reasonable version. jhrg 5/24/96
392 
408 int Sequence::length() const
409 {
410  return -1;
411 }
412 
413 // Hmmm. how is this different from length()?
414 int Sequence::number_of_rows() const
415 {
416  return d_values.size();
417 }
418 
423 {
424  d_row_number = -1;
425 }
426 
427 #if 0
428 // written but not used - this was written so that values loaded from
429 // Arrays into a new ('synthesized') sequence by the 'tablar() server
430 // function would be properly used during the evaluation of a selection
431 // expression. But I forgot that tabular() uses a specialized version of
432 // Sequence: TabularSequence and that has it's own version of serialize().
433 // To get the returnAs="ascii" to filter values, I also need to specialize
434 // the intern_data() method of Sequence. jhrg 3/9/15
435 
450 void Sequence::load_prototypes_with_values(int row_number)
451 {
452  vector<BaseType*> *row = d_values.at(row_number);
453 
454  // For each of the prototype variables in the Sequence, load it
455  // with a values from the BaseType* vector. The order should match.
456  // Test the type, but assume if that matches, the value is correct
457  // for the variable.
458  int pos = 0;
459  for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i) {
460  if ((*i)->type() != row->at(pos)->var()->type())
461  throw InternalErr(__FILE__, __LINE__, "Expected types to match when loading values for selection expression evaluation.");
462 
463  // Ugly...
464  switch ((*i)->type()) {
465  case dods_byte_c:
466  static_cast<Byte*>(*i)->set_value(static_cast<Byte*>(row->at(pos++))->value());
467  break;
468  case dods_int16_c:
469  static_cast<Int16*>(*i)->set_value(static_cast<Int16*>(row->at(pos++))->value());
470  break;
471  case dods_int32_c:
472  static_cast<Int32*>(*i)->set_value(static_cast<Int32*>(row->at(pos++))->value());
473  break;
474  case dods_uint16_c:
475  static_cast<UInt16*>(*i)->set_value(static_cast<UInt16*>(row->at(pos++))->value());
476  break;
477  case dods_uint32_c:
478  static_cast<UInt32*>(*i)->set_value(static_cast<UInt32*>(row->at(pos++))->value());
479  break;
480  case dods_float32_c:
481  static_cast<Float32*>(*i)->set_value(static_cast<Float32*>(row->at(pos++))->value());
482  break;
483  case dods_float64_c:
484  static_cast<Float64*>(*i)->set_value(static_cast<Float64*>(row->at(pos++))->value());
485  break;
486  case dods_str_c:
487  static_cast<Str*>(*i)->set_value(static_cast<Str*>(row->at(pos++))->value());
488  break;
489  case dods_url_c:
490  static_cast<Url*>(*i)->set_value(static_cast<Url*>(row->at(pos++))->value());
491  break;
492  default:
493  throw InternalErr(__FILE__, __LINE__, "Expected a scalar type when loading values for selection expression evaluation.");
494  }
495  }
496 }
497 
498 #endif
499 
500 // Notes:
501 // Assume that read() is implemented so that, when reading data for a nested
502 // sequence, only the outer most level is *actually* read.
503 // This is a consequence of our current (12/7/99) implementation of
504 // the JGOFS server (which is the only server to actually use nested
505 // sequences). 12/7/99 jhrg
506 //
507 // Stop assuming this. This logic is being moved into the JGOFS server
508 // itself. 6/1/2001 jhrg
509 
510 // The read() function returns a boolean value, with TRUE
511 // indicating that read() should be called again because there's
512 // more data to read, and FALSE indicating there's no more data
513 // to read. Note that this behavior is necessary to properly
514 // handle variables that contain Sequences. Jose Garcia If an
515 // error exists while reading, the implementers of the surrogate
516 // library SHOULD throw an Error object which will propagate
517 // beyond this point to to the original caller.
518 // Jose Garcia
519 
552 bool Sequence::read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval)
553 {
554  DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
555  if (row < d_row_number) throw InternalErr("Trying to back up inside a sequence!");
556 
557  DBG2(cerr << "read_row: row number " << row << ", current row " << d_row_number << endl);
558  if (row == d_row_number) {
559  DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
560  return false;
561  }
562 #if USE_LOCAL_TIMEOUT_SCHEME
563  dds.timeout_on();
564 #endif
565  bool eof = false; // Start out assuming EOF is false.
566  while (!eof && d_row_number < row) {
567  if (!read_p()) {
568  // jhrg original version from 10/9/13 : eof = (read() == false);
569  eof = read();
570  }
571 #if 0
572  // A change (3/9/15): I've made the is_synthesized property
573  // work so that the prototype variables in the Sequence are loaded
574  // with the scalar values for the ith row so that the eval_selection()
575  // method will function correctly.
576 
577  // See note above
578 
579  if (d_is_synthesized) {
580  load_prototypes_with_values(d_row_number);
581  }
582 #endif
583  // Advance the row number if ce_eval is false (we're not supposed to
584  // evaluate the selection) or both ce_eval and the selection are
585  // true.
586  if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) d_row_number++;
587 
588  set_read_p(false); // ...so that the next instance will be read
589  }
590 
591  // Once we finish the above loop, set read_p to true so that the caller
592  // knows that data *has* been read. This is how the read() methods of the
593  // elements of the sequence know to not call read() but instead look for
594  // data values inside themselves.
595  set_read_p(true);
596 #if USE_LOCAL_TIMEOUT_SCHEME
597  dds.timeout_off();
598 #endif
599  // Return true if we have valid data, false if we've read to the EOF.
600  DBG2(cerr << "Leaving Sequence::read_row for " << name() << " with eof: " << eof << endl);
601  return !eof; // jhrg 10/10/13 was: eof == 0;
602 }
603 
604 // Private. This is used to process constraints on the rows of a sequence.
605 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
606 // odd-looking logic first checks if d_ending_row_number is the sentinel
607 // value of -1. If so, the sequence was not constrained by row number and
608 // this method should never return true (which indicates that we're at the
609 // end of a row-number constraint). If d_ending_row_number is not -1, then is
610 // \e i at the end point? 6/1/2001 jhrg
611 inline bool Sequence::is_end_of_rows(int i)
612 {
613  return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
614 }
615 
676 bool Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval)
677 {
678  DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
679 
680  // Special case leaf sequences!
681  bool status = false;
682 
683  if (is_leaf_sequence())
684  status = serialize_leaf(dds, eval, m, ce_eval);
685  else
686  status = serialize_parent_part_one(dds, eval, m);
687 
688 #ifdef CLEAR_LOCAL_DATA
690 #endif
691 
692  return status;
693 }
694 
695 // We know this is not a leaf Sequence. That means that this Sequence holds
696 // another Sequence as one of its fields _and_ that child Sequence triggers
697 // the actual transmission of values.
698 
699 bool Sequence::serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
700 {
701  DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
702 
703  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
704 
705  // read_row returns true if valid data was read, false if the EOF was
706  // found. 6/1/2001 jhrg
707  // Since this is a parent sequence, read the row ignoring the CE (all of
708  // the CE clauses will be evaluated by the leaf sequence).
709  bool status = read_row(i, dds, eval, false);
710  DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
711 
712  while (status && !is_end_of_rows(i)) {
713  i += d_row_stride;
714 
715  // DBG(cerr << "Writing Start of Instance marker" << endl);
716  // write_start_of_instance(sink);
717 
718  // In this loop serialize will signal an error with an exception.
719  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
720  // Only call serialize for child Sequences; the leaf sequence
721  // will trigger the transmission of values for its parents (this
722  // sequence and maybe others) once it gets some valid data to
723  // send.
724  // Note that if the leaf sequence has no variables in the current
725  // projection, its serialize() method will never be called and that's
726  // the method that triggers actually sending values. Thus the leaf
727  // sequence must be the lowest level sequence with values whose send_p
728  // property is true.
729  if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) (*iter)->serialize(eval, dds, m);
730  }
731 
732  set_read_p(false); // ...so this will read the next instance
733 
734  status = read_row(i, dds, eval, false);
735  DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
736  }
737  // Reset current row number for next nested sequence element.
738  d_row_number = -1;
739 
740  // Always write the EOS marker? 12/23/04 jhrg
741  // Yes. According to DAP2, a completely empty response is signaled by
742  // a return value of only the EOS marker for the outermost sequence.
743  if (d_top_most || d_wrote_soi) {
744  DBG(cerr << "Writing End of Sequence marker" << endl);
745  write_end_of_sequence(m);
746  d_wrote_soi = false;
747  }
748 
749  return true; // Signal errors with exceptions.
750 }
751 
752 // If we are here then we know that this is 'parent sequence' and that the
753 // leaf sequence has found valid data to send. We also know that
754 // serialize_parent_part_one has been called so data are in the instance's
755 // fields. This is where we send data. Whereas ..._part_one() contains a
756 // loop to iterate over all of rows in a parent sequence, this does not. This
757 // method assumes that the serialize_leaf() will call it each time it needs
758 // to be called.
759 //
760 // NB: This code only works if the child sequences appear after all other
761 // variables.
762 void Sequence::serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
763 {
764  DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
765 
766  BaseType *btp = get_parent();
767  if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
768 
769  if (d_unsent_data) {
770  DBG(cerr << "Writing Start of Instance marker" << endl);
771  d_wrote_soi = true;
772  write_start_of_instance(m);
773 
774  // In this loop serialize will signal an error with an exception.
775  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
776  // Send all the non-sequence variables
777  DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
778  << (*iter)->name() << endl);
779  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
780  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
781  (*iter)->serialize(eval, dds, m, false);
782  }
783  }
784 
785  d_unsent_data = false; // read should set this.
786  }
787 }
788 
789 // This code is only run by a leaf sequence. Note that a one level sequence
790 // is also a leaf sequence.
791 bool Sequence::serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
792 {
793  DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
794  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
795 
796  // read_row returns true if valid data was read, false if the EOF was
797  // found. 6/1/2001 jhrg
798  bool status = read_row(i, dds, eval, ce_eval);
799  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
800 
801  // Once the first valid (satisfies the CE) row of the leaf sequence has
802  // been read, we know we're going to send data. Send the current instance
803  // of the parent/ancestor sequences now, if there are any. We only need
804  // to do this once, hence it's not inside the while loop, but we only
805  // send the parent seq data _if_ there's data in the leaf to send, that's
806  // why we wait until after the first call to read_row() here in the leaf
807  // sequence.
808  //
809  // NB: It's important to only call serialize_parent_part_two() for a
810  // Sequence that really is the parent of a leaf sequence.
811  if (status && !is_end_of_rows(i)) {
812  BaseType *btp = get_parent();
813  if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
814  }
815 
816  d_wrote_soi = false;
817  while (status && !is_end_of_rows(i)) {
818  i += d_row_stride;
819 
820  DBG(cerr << "Writing Start of Instance marker" << endl);
821  d_wrote_soi = true;
822  write_start_of_instance(m);
823 
824  // In this loop serialize will signal an error with an exception.
825  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
826  DBG(cerr << "Sequence::serialize_leaf(), serializing "
827  << (*iter)->name() << endl);
828  if ((*iter)->send_p()) {
829  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
830  (*iter)->serialize(eval, dds, m, false);
831  }
832  }
833 
834  set_read_p(false); // ...so this will read the next instance
835 
836  status = read_row(i, dds, eval, ce_eval);
837  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
838  }
839 
840  // Only write the EOS marker if there's a matching Start Of Instance
841  // Marker in the stream.
842  if (d_wrote_soi || d_top_most) {
843  DBG(cerr << "Writing End of Sequence marker" << endl);
844  write_end_of_sequence(m);
845  }
846 
847  return true; // Signal errors with exceptions.
848 }
849 
873 {
874  DBG(cerr << "Sequence::intern_data - for " << name() << endl); DBG2(cerr << " intern_data, values: " << &d_values << endl);
875 
876  // Why use a stack instead of return values? We need the stack because
877  // Sequences nested three of more levels deep will loose the middle
878  // instances when the intern_data_parent_part_two() code is run.
879  sequence_values_stack_t sequence_values_stack;
880 
881  DBG2(cerr << " pushing d_values of " << name() << " (" << &d_values
882  << ") on stack; size: " << sequence_values_stack.size() << endl);
883  sequence_values_stack.push(&d_values);
884 
885  intern_data_private(eval, dds, sequence_values_stack);
886 }
887 
888 void Sequence::intern_data_private(ConstraintEvaluator &eval, DDS &dds, sequence_values_stack_t &sequence_values_stack)
889 {
890  DBG(cerr << "Entering intern_data_private for " << name() << endl);
891 
892  if (is_leaf_sequence())
893  intern_data_for_leaf(dds, eval, sequence_values_stack);
894  else
895  intern_data_parent_part_one(dds, eval, sequence_values_stack);
896 }
897 
898 void Sequence::intern_data_parent_part_one(DDS & dds, ConstraintEvaluator & eval,
899  sequence_values_stack_t & sequence_values_stack)
900 {
901  DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
902 
903  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
904 
905  // read_row returns true if valid data was read, false if the EOF was
906  // found. 6/1/2001 jhrg
907  // Since this is a parent sequence, read the row ignoring the CE (all of
908  // the CE clauses will be evaluated by the leaf sequence).
909  bool status = read_row(i, dds, eval, false);
910 
911  // Grab the current size of the value stack. We do this because it is
912  // possible that no nested sequences for this row happened to be
913  // selected because of a constraint evaluation or the last row is not
914  // selected because of a constraint evaluation. In either case, no
915  // nested sequence d_values are pushed onto the stack, so there is
916  // nothing to pop at the end of this function. pcw 07/14/08
917  SequenceValues::size_type orig_stack_size = sequence_values_stack.size();
918 
919  while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
920  i += get_row_stride();
921  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
922  if ((*iter)->send_p()) {
923  switch ((*iter)->type()) {
924  case dods_sequence_c:
925  static_cast<Sequence&>(**iter).intern_data_private(eval, dds, sequence_values_stack);
926  break;
927 
928  default:
929  (*iter)->intern_data(eval, dds);
930  break;
931  }
932  }
933  }
934 
935  set_read_p(false); // ...so this will read the next instance
936 
937  status = read_row(i, dds, eval, false);
938  }
939 
940  // Reset current row number for next nested sequence element.
942 
943  // if the size of the stack is larger than the original size (retrieved
944  // above) then pop the top set of d_values from the stack. If it's the
945  // same, then no nested sequences, or possible the last nested sequence,
946  // were pushed onto the stack, so there is nothing to pop.
947  if (sequence_values_stack.size() > orig_stack_size) {
948  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
949  << ") off stack; size: " << sequence_values_stack.size() << endl);
950  sequence_values_stack.pop();
951  } DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
952 }
953 
954 void Sequence::intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval,
955  sequence_values_stack_t &sequence_values_stack)
956 {
957  DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
958 
959  BaseType *btp = get_parent();
960  if (btp && btp->type() == dods_sequence_c) {
961  static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
962  }
963 
964  DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl);
965  SequenceValues *values = sequence_values_stack.top();
966  DBG2(cerr << " using values = " << (void *)values << endl);
967 
968  if (get_unsent_data()) {
969  BaseTypeRow *row_data = new BaseTypeRow;
970 
971  // In this loop transfer_data will signal an error with an exception.
972  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
973 
974  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
975  row_data->push_back((*iter)->ptr_duplicate());
976  }
977  else if ((*iter)->send_p()) { //Sequence; must be the last variable
978  Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
979  if (!tmp) {
980  delete row_data;
981  throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
982  }
983  row_data->push_back(tmp);
984  DBG2(cerr << " pushing d_values of " << tmp->name()
985  << " (" << &(tmp->d_values)
986  << ") on stack; size: " << sequence_values_stack.size()
987  << endl);
988  // This pushes the d_values field of the newly created leaf
989  // Sequence onto the stack. The code then returns to intern
990  // _data_for_leaf() where this value will be used.
991  sequence_values_stack.push(&(tmp->d_values));
992  }
993  }
994 
995  DBG2(cerr << " pushing values for " << name()
996  << " to " << values << endl);
997  values->push_back(row_data);
998  set_unsent_data(false);
999  } DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
1000 }
1001 
1002 void Sequence::intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
1003 {
1004  DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
1005 
1006  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
1007 
1008  DBG2(cerr << " reading row " << i << endl);
1009  bool status = read_row(i, dds, eval, true);
1010  DBG2(cerr << " status: " << status << endl); DBG2(cerr << " ending row number: " << get_ending_row_number() << endl);
1011 
1012  if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
1013  BaseType *btp = get_parent();
1014  if (btp && btp->type() == dods_sequence_c) {
1015  // This call will read the values for the parent sequences and
1016  // then allocate a new instance for the leaf and push that onto
1017  // the stack.
1018  static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
1019  }
1020 
1021  // intern_data_parent_part_two pushes the d_values field of the leaf
1022  // onto the stack, so this operation grabs that value and then loads
1023  // data into it.
1024  SequenceValues *values = sequence_values_stack.top();
1025  DBG2(cerr << " using values = " << values << endl);
1026 
1027  while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
1028  i += get_row_stride();
1029 
1030  // Copy data from the object's fields to this new BaeTypeRow instance
1031  BaseTypeRow *row_data = new BaseTypeRow;
1032  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1033  if ((*iter)->send_p()) {
1034  row_data->push_back((*iter)->ptr_duplicate());
1035  }
1036  }
1037 
1038  DBG2(cerr << " pushing values for " << name()
1039  << " to " << values << endl);
1040  // Save the row_data to values().
1041  values->push_back(row_data);
1042 
1043  set_read_p(false); // ...so this will read the next instance
1044  // Read the ith row into this object's fields
1045  status = read_row(i, dds, eval, true);
1046  }
1047 
1048  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
1049  << ") off stack; size: " << sequence_values_stack.size() << endl);
1050  sequence_values_stack.pop();
1051  } DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
1052 }
1053 
1074 bool Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
1075 {
1076  DataDDS *dd = dynamic_cast<DataDDS *>(dds);
1077  if (!dd) throw InternalErr("Expected argument 'dds' to be a DataDDS!");
1078 
1079  DBG2(cerr << "Reading from server/protocol version: "
1080  << dd->get_protocol_major() << "." << dd->get_protocol_minor()
1081  << endl);
1082 
1083  // Check for old servers.
1084  if (dd->get_protocol_major() < 2) {
1085  throw Error(
1086  string("The protocl version (") + dd->get_protocol()
1087  + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
1088  }
1089 
1090  while (true) {
1091  // Grab the sequence stream's marker.
1092  unsigned char marker = read_marker(um);
1093  if (is_end_of_sequence(marker))
1094  break; // EXIT the while loop here!!!
1095  else if (is_start_of_instance(marker)) {
1096  d_row_number++;
1097  DBG2(cerr << "Reading row " << d_row_number << " of "
1098  << name() << endl);
1099  BaseTypeRow *bt_row_ptr = new BaseTypeRow;
1100  // Read the instance's values, building up the row
1101  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1102  BaseType *bt_ptr = (*iter)->ptr_duplicate();
1103  bt_ptr->deserialize(um, dds, reuse);
1104  DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
1105  << bt_ptr << ") = "); DBG2(bt_ptr->print_val(stderr, ""));
1106  bt_row_ptr->push_back(bt_ptr);
1107  }
1108  // Append this row to those accumulated.
1109  d_values.push_back(bt_row_ptr);
1110  }
1111  else
1112  throw Error("I could not read the expected Sequence data stream marker!");
1113  };
1114 
1115  return false;
1116 }
1117 
1118 // Return the current row number.
1119 
1132 {
1133  return d_starting_row_number;
1134 }
1135 
1147 {
1148  return d_row_stride;
1149 }
1150 
1163 {
1164  return d_ending_row_number;
1165 }
1166 
1175 void Sequence::set_row_number_constraint(int start, int stop, int stride)
1176 {
1177  if (stop < start) throw Error(malformed_expr, "Starting row number must precede the ending row number.");
1178 
1179  d_starting_row_number = start;
1180  d_row_stride = stride;
1181  d_ending_row_number = stop;
1182 }
1183 
1184 void Sequence::print_one_row(FILE *out, int row, string space, bool print_row_num)
1185 {
1186  ostringstream oss;
1187  print_one_row(oss, row, space, print_row_num);
1188  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1189 }
1190 
1191 void Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num)
1192 {
1193  if (print_row_num) out << "\n" << space << row << ": ";
1194 
1195  out << "{ ";
1196 
1197  int elements = element_count();
1198  int j = 0;
1199  BaseType *bt_ptr = 0;
1200 
1201  // This version of print_one_row() works for both data read with
1202  // deserialize(), where each variable is assumed to have valid data, and
1203  // intern_data(), where some/many variables do not. Because of that, it's
1204  // not correct to assume that all of the elements will be printed, which
1205  // is what the old code did.
1206  // Print the first value
1207  while (j < elements && !bt_ptr) {
1208  bt_ptr = var_value(row, j++);
1209  if (bt_ptr) { // data
1210  if (bt_ptr->type() == dods_sequence_c)
1211  static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1212  else
1213  bt_ptr->print_val(out, space, false);
1214  }
1215  }
1216 
1217  // Print the remaining values
1218  while (j < elements) {
1219  bt_ptr = var_value(row, j++);
1220  if (bt_ptr) { // data
1221  out << ", ";
1222  if (bt_ptr->type() == dods_sequence_c)
1223  static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1224  else
1225  bt_ptr->print_val(out, space, false);
1226  }
1227  }
1228 
1229  out << " }";
1230 }
1231 
1232 void Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, bool print_row_numbers)
1233 {
1234  ostringstream oss;
1235  print_val_by_rows(oss, space, print_decl_p, print_row_numbers);
1236  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1237 }
1238 
1239 void Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers)
1240 {
1241  if (print_decl_p) {
1242  print_decl(out, space, false);
1243  out << " = ";
1244  }
1245 
1246  out << "{ ";
1247 
1248  int rows = number_of_rows() - 1;
1249  int i;
1250  for (i = 0; i < rows; ++i) {
1251  print_one_row(out, i, space, print_row_numbers);
1252  out << ", ";
1253  }
1254  print_one_row(out, i, space, print_row_numbers);
1255 
1256  out << " }";
1257 
1258  if (print_decl_p) out << ";\n";
1259 }
1260 
1261 void Sequence::print_val(FILE *out, string space, bool print_decl_p)
1262 {
1263  print_val_by_rows(out, space, print_decl_p, false);
1264 }
1265 
1266 void Sequence::print_val(ostream &out, string space, bool print_decl_p)
1267 {
1268  print_val_by_rows(out, space, print_decl_p, false);
1269 }
1270 
1271 void Sequence::set_leaf_p(bool state)
1272 {
1273  d_leaf_sequence = state;
1274 }
1275 
1276 bool Sequence::is_leaf_sequence()
1277 {
1278  return d_leaf_sequence;
1279 }
1280 
1306 {
1307  bool has_child_sequence = false;
1308 
1309  if (lvl == 1) d_top_most = true;
1310 
1311  DBG2(cerr << "Processing sequence " << name() << endl);
1312 
1313  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1314  // About the test for send_p(): Only descend into a sequence if it has
1315  // fields that might be sent. Thus if, in a two-level sequence, nothing
1316  // in the lower level is to be sent, the upper level is marked as the
1317  // leaf sequence. This ensures that values _will_ be sent (see the comment
1318  // in serialize_leaf() and serialize_parent_part_one()).
1319  if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
1320  if (has_child_sequence)
1321  throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
1322 
1323  has_child_sequence = true;
1324  static_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
1325  }
1326  else if ((*iter)->type() == dods_structure_c) {
1327  static_cast<Structure&>(**iter).set_leaf_sequence(lvl);
1328  }
1329  }
1330 
1331  if (!has_child_sequence)
1332  set_leaf_p(true);
1333  else
1334  set_leaf_p(false);
1335 
1336  DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
1337 }
1338 
1347 void Sequence::dump(ostream &strm) const
1348 {
1349  strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl;
1350  DapIndent::Indent();
1351  Constructor::dump(strm);
1352  strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number << endl;
1353  strm << DapIndent::LMarg << "bracket notation information:" << endl;
1354  DapIndent::Indent();
1355  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
1356  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
1357  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
1358  DapIndent::UnIndent();
1359 
1360  strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl;
1361  strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl;
1362  strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence << endl;
1363  strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most << endl;
1364  DapIndent::UnIndent();
1365 }
1366 
1367 } // namespace libdap
1368 
virtual void clear_local_data()
Definition: Sequence.cc:242
Holds an Internet address (URL).
Definition: Url.h:63
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:425
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:54
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Sequence.cc:1347
void set_unsent_data(bool usd)
Set the unsent data property.
Definition: Sequence.h:279
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: BaseType.cc:864
virtual bool read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval=true)
Definition: Sequence.cc:552
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Deserialize (read from the network) the entire Sequence.
Definition: Sequence.cc:1074
virtual bool is_dap2_only_type()
Definition: Sequence.cc:267
Holds an unsigned 16-bit integer.
Definition: UInt16.h:57
vector< BaseTypeRow * > SequenceValues
Definition: Sequence.h:64
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Definition: Sequence.cc:676
STL namespace.
BaseType * transform_to_dap4(D4Group *root, Constructor *dest)
DAP2 to DAP4 transform.
Definition: Constructor.cc:137
virtual BaseTypeRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: Sequence.cc:320
virtual void set_row_number_constraint(int start, int stop, int stride=1)
Definition: Sequence.cc:1175
Holds a structure (aggregate) type.
Definition: Structure.h:83
virtual Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:310
virtual string toString()
Definition: BaseType.cc:183
Holds a 32-bit floating point value.
Definition: Float32.h:61
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Constructor.cc:169
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:654
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
Definition: Structure.cc:252
A class for software fault reporting.
Definition: InternalErr.h:64
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:303
virtual bool is_linear()
Check to see whether this variable can be printed simply.
Definition: Sequence.cc:287
Holds character string data.
Definition: Str.h:62
virtual int length() const
Definition: Sequence.cc:408
bool get_unsent_data()
Get the unsent data property.
Definition: Sequence.h:273
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: BaseType.cc:1011
Holds a 16-bit signed integer value.
Definition: Int16.h:59
Sequence(const string &n)
The Sequence constructor.
Definition: Sequence.cc:160
virtual BaseType * get_parent() const
Definition: BaseType.cc:672
virtual void set_length(int count)
Definition: D4Sequence.h:176
Holds a sequence.
Definition: D4Sequence.h:124
virtual bool read()
simple implementation of read that iterates through vars and calls read on them
Definition: Constructor.cc:451
virtual void set_leaf_sequence(int lvl=1)
Mark the Sequence which holds the leaf elements.
Definition: Sequence.cc:1305
virtual bool set_value(const dods_byte value)
Definition: Byte.cc:230
Holds a sequence.
Definition: Sequence.h:162
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:824
virtual bool set_value(const string &value)
Definition: Str.cc:253
vector< BaseType * > BaseTypeRow
Definition: Sequence.h:57
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:265
virtual string toString()
Definition: Sequence.cc:272
virtual BaseType * ptr_duplicate()=0
int get_starting_row_number()
Get the starting row number.
Definition: Sequence.cc:1131
Evaluate a constraint expression.
virtual SequenceValues & value_ref()
Definition: Sequence.cc:347
virtual SequenceValues value()
Definition: Sequence.cc:339
void reset_row_number()
Rest the row number counter.
Definition: Sequence.cc:422
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:358
virtual void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Print an ASCII representation of the variable structure.
Definition: Constructor.cc:601
Vars_iter var_begin()
Definition: Constructor.cc:331
Holds a 64-bit (double precision) floating point value.
Definition: Float64.h:60
Holds a single byte.
Definition: Byte.h:60
Vars_iter var_end()
Definition: Constructor.cc:339
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: Sequence.cc:1266
bool eval_selection(DDS &dds, const std::string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator ans is called ...
virtual void intern_data()
Read data into this variable.
Definition: Constructor.cc:531
A class for error processing.
Definition: Error.h:90
virtual BaseType * transform_to_dap4(D4Group *root, Constructor *container)
Definition: Sequence.cc:211
virtual int get_ending_row_number()
Get the ending row number.
Definition: Sequence.cc:1162
Holds a 32-bit unsigned integer.
Definition: UInt32.h:59
virtual BaseType * ptr_duplicate()
Definition: Sequence.cc:191
Holds a DAP2 DDS.
Definition: DataDDS.h:77
virtual int get_row_stride()
Get the row stride.
Definition: Sequence.cc:1146
virtual void set_value(SequenceValues &values)
Definition: Sequence.cc:332
Holds a 32-bit signed integer.
Definition: Int32.h:65
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Constructor.cc:193