libdap++  Updated for version 3.14.0
Sequence.cc
Go to the documentation of this file.
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 using namespace std;
78 
79 namespace libdap {
80 
81 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
82 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
83 
84 // Private member functions
85 
86 void Sequence::m_duplicate(const Sequence &s)
87 {
88  DBG(cerr << "In Sequence::m_duplicate" << endl);
89 
90  d_row_number = s.d_row_number;
91  d_starting_row_number = s.d_starting_row_number;
92  d_ending_row_number = s.d_ending_row_number;
93  d_row_stride = s.d_row_stride;
94  d_leaf_sequence = s.d_leaf_sequence;
95  d_unsent_data = s.d_unsent_data;
96  d_wrote_soi = s.d_wrote_soi;
97  d_top_most = s.d_top_most;
98 
99  Sequence &cs = const_cast<Sequence &>(s);
100 
101  // Copy the BaseType objects used to hold values.
102  for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin(); rows_iter != cs.d_values.end(); rows_iter++) {
103  // Get the current BaseType Row
104  BaseTypeRow *src_bt_row_ptr = *rows_iter;
105  // Create a new row.
106  BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow;
107  // Copy the BaseType objects from a row to new BaseType objects.
108  // Push new BaseType objects onto new row.
109  for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin(); bt_row_iter != src_bt_row_ptr->end();
110  bt_row_iter++) {
111  BaseType *src_bt_ptr = *bt_row_iter;
112  BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate();
113  dest_bt_row_ptr->push_back(dest_bt_ptr);
114  }
115  // Push new row onto d_values.
116  d_values.push_back(dest_bt_row_ptr);
117  }
118 }
119 
120 static void write_end_of_sequence(Marshaller &m)
121 {
122  m.put_opaque((char *) &end_of_sequence, 1);
123 }
124 
125 static void write_start_of_instance(Marshaller &m)
126 {
127  m.put_opaque((char *) &start_of_instance, 1);
128 }
129 
130 static unsigned char read_marker(UnMarshaller &um)
131 {
132  unsigned char marker;
133  um.get_opaque((char *) &marker, 1);
134 
135  return marker;
136 }
137 
138 static bool is_start_of_instance(unsigned char marker)
139 {
140  return (marker == start_of_instance);
141 }
142 
143 static bool is_end_of_sequence(unsigned char marker)
144 {
145  return (marker == end_of_sequence);
146 }
147 
148 // Public member functions
149 
158 Sequence::Sequence(const string &n) :
159  Constructor(n, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(
160  -1), d_unsent_data(false), d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
161 {
162 }
163 
174 Sequence::Sequence(const string &n, const string &d) :
175  Constructor(n, d, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(
176  -1), d_unsent_data(false), d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
177 {
178 }
179 
182  Constructor(rhs)
183 {
184  m_duplicate(rhs);
185 }
186 
187 BaseType *
189 {
190  return new Sequence(*this);
191 }
192 
207 BaseType *
209 {
210  D4Sequence *dest = new D4Sequence(name());
211 
212  Constructor::transform_to_dap4(root, dest);
213 
214  dest->set_length(-1);
215  dest->set_parent(container);
216 
217  return dest;
218 }
219 
220 static inline void delete_bt(BaseType *bt_ptr)
221 {
222  delete bt_ptr;
223  bt_ptr = 0;
224 }
225 
226 static inline void delete_rows(BaseTypeRow *bt_row_ptr)
227 {
228  for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
229 
230  delete bt_row_ptr;
231  bt_row_ptr = 0;
232 }
233 
235 {
236  for_each(d_values.begin(), d_values.end(), delete_rows);
237 }
238 
239 Sequence &
241 {
242  if (this == &rhs) return *this;
243 
244  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
245 
246  m_duplicate(rhs);
247 
248  return *this;
249 }
250 
255 {
256  return true;
257 }
258 
260 {
261  ostringstream oss;
262 
263  oss << BaseType::toString();
264 
265  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
266  oss << (*i)->toString();
267  }
268 
269  oss << endl;
270 
271  return oss.str();
272 }
273 
275 {
276  bool linear = true;
277  bool seq_found = false;
278  for (Vars_iter iter = d_vars.begin(); linear && iter != d_vars.end(); iter++) {
279  if ((*iter)->type() == dods_sequence_c) {
280  // A linear sequence cannot have more than one child seq. at any
281  // one level. If we've already found a seq at this level, return
282  // false.
283  if (seq_found) {
284  linear = false;
285  break;
286  }
287  seq_found = true;
288  linear = static_cast<Sequence *>((*iter))->is_linear();
289  }
290  else if ((*iter)->type() == dods_structure_c) {
291  linear = static_cast<Structure*>((*iter))->is_linear();
292  }
293  else {
294  // A linear sequence cannot have Arrays, Lists or Grids.
295  linear = (*iter)->is_simple_type();
296  }
297  }
298 
299  return linear;
300 }
301 
306 BaseTypeRow *
308 {
309  if (row >= d_values.size()) return 0;
310  return d_values[row];
311 }
312 
320 {
321  d_values = values;
322 }
323 
327 {
328  return d_values;
329 }
330 
335 {
336  return d_values;
337 }
338 
344 BaseType *
345 Sequence::var_value(size_t row, const string &name)
346 {
347  BaseTypeRow *bt_row_ptr = row_value(row);
348  if (!bt_row_ptr) return 0;
349 
350  BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
351  BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
352  while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
353  ++bt_row_iter;
354 
355  if (bt_row_iter == bt_row_end)
356  return 0;
357  else
358  return *bt_row_iter;
359 }
360 
366 BaseType *
367 Sequence::var_value(size_t row, size_t i)
368 {
369  BaseTypeRow *bt_row_ptr = row_value(row);
370  if (!bt_row_ptr) return 0;
371 
372  if (i >= bt_row_ptr->size()) return 0;
373 
374  return (*bt_row_ptr)[i];
375 }
376 
377 // This version returns -1. Each API-specific subclass should define a more
378 // reasonable version. jhrg 5/24/96
379 
395 int Sequence::length() const
396 {
397  return -1;
398 }
399 
400 // Hmmm. how is this different from length()?
402 {
403  return d_values.size();
404 }
405 
410 {
411  d_row_number = -1;
412 }
413 
414 #if 0
415 // written but not used - this was written so that values loaded from
416 // Arrays into a new ('synthesized') sequence by the 'tablar() server
417 // function would be properly used during the evaluation of a selection
418 // expression. But I forgot that tabular() uses a specialized version of
419 // Sequence: TabularSequence and that has it's own version of serialize().
420 // To get the returnAs="ascii" to filter values, I also need to specialize
421 // the intern_data() method of Sequence. jhrg 3/9/15
422 
437 void Sequence::load_prototypes_with_values(int row_number)
438 {
439  vector<BaseType*> *row = d_values.at(row_number);
440 
441  // For each of the prototype variables in the Sequence, load it
442  // with a values from the BaseType* vector. The order should match.
443  // Test the type, but assume if that matches, the value is correct
444  // for the variable.
445  int pos = 0;
446  for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i) {
447  if ((*i)->type() != row->at(pos)->var()->type())
448  throw InternalErr(__FILE__, __LINE__, "Expected types to match when loading values for selection expression evaluation.");
449 
450  // Ugly...
451  switch ((*i)->type()) {
452  case dods_byte_c:
453  static_cast<Byte*>(*i)->set_value(static_cast<Byte*>(row->at(pos++))->value());
454  break;
455  case dods_int16_c:
456  static_cast<Int16*>(*i)->set_value(static_cast<Int16*>(row->at(pos++))->value());
457  break;
458  case dods_int32_c:
459  static_cast<Int32*>(*i)->set_value(static_cast<Int32*>(row->at(pos++))->value());
460  break;
461  case dods_uint16_c:
462  static_cast<UInt16*>(*i)->set_value(static_cast<UInt16*>(row->at(pos++))->value());
463  break;
464  case dods_uint32_c:
465  static_cast<UInt32*>(*i)->set_value(static_cast<UInt32*>(row->at(pos++))->value());
466  break;
467  case dods_float32_c:
468  static_cast<Float32*>(*i)->set_value(static_cast<Float32*>(row->at(pos++))->value());
469  break;
470  case dods_float64_c:
471  static_cast<Float64*>(*i)->set_value(static_cast<Float64*>(row->at(pos++))->value());
472  break;
473  case dods_str_c:
474  static_cast<Str*>(*i)->set_value(static_cast<Str*>(row->at(pos++))->value());
475  break;
476  case dods_url_c:
477  static_cast<Url*>(*i)->set_value(static_cast<Url*>(row->at(pos++))->value());
478  break;
479  default:
480  throw InternalErr(__FILE__, __LINE__, "Expected a scalar type when loading values for selection expression evaluation.");
481  }
482  }
483 }
484 
485 #endif
486 
487 // Notes:
488 // Assume that read() is implemented so that, when reading data for a nested
489 // sequence, only the outer most level is *actually* read.
490 // This is a consequence of our current (12/7/99) implementation of
491 // the JGOFS server (which is the only server to actually use nested
492 // sequences). 12/7/99 jhrg
493 //
494 // Stop assuming this. This logic is being moved into the JGOFS server
495 // itself. 6/1/2001 jhrg
496 
497 // The read() function returns a boolean value, with TRUE
498 // indicating that read() should be called again because there's
499 // more data to read, and FALSE indicating there's no more data
500 // to read. Note that this behavior is necessary to properly
501 // handle variables that contain Sequences. Jose Garcia If an
502 // error exists while reading, the implementers of the surrogate
503 // library SHOULD throw an Error object which will propagate
504 // beyond this point to to the original caller.
505 // Jose Garcia
506 
539 bool Sequence::read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval)
540 {
541  DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
542  if (row < d_row_number) throw InternalErr("Trying to back up inside a sequence!");
543 
544  DBG2(cerr << "read_row: row number " << row << ", current row " << d_row_number << endl);
545  if (row == d_row_number) {
546  DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
547  return false;
548  }
549 
550  dds.timeout_on();
551 
552  bool eof = false; // Start out assuming EOF is false.
553  while (!eof && d_row_number < row) {
554  if (!read_p()) {
555  // jhrg original version from 10/9/13 : eof = (read() == false);
556  eof = read();
557  }
558 #if 0
559  // A change (3/9/15): I've made the is_synthesized property
560  // work so that the prototype variables in the Sequence are loaded
561  // with the scalar values for the ith row so that the eval_selection()
562  // method will function correctly.
563 
564  // See note above
565 
566  if (d_is_synthesized) {
567  load_prototypes_with_values(d_row_number);
568  }
569 #endif
570  // Advance the row number if ce_eval is false (we're not supposed to
571  // evaluate the selection) or both ce_eval and the selection are
572  // true.
573  if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) d_row_number++;
574 
575  set_read_p(false); // ...so that the next instance will be read
576  }
577 
578  // Once we finish the above loop, set read_p to true so that the caller
579  // knows that data *has* been read. This is how the read() methods of the
580  // elements of the sequence know to not call read() but instead look for
581  // data values inside themselves.
582  set_read_p(true);
583 
584  dds.timeout_off();
585 
586  // Return true if we have valid data, false if we've read to the EOF.
587  DBG2(cerr << "Leaving Sequence::read_row for " << name() << " with eof: " << eof << endl);
588  return !eof; // jhrg 10/10/13 was: eof == 0;
589 }
590 
591 // Private. This is used to process constraints on the rows of a sequence.
592 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
593 // odd-looking logic first checks if d_ending_row_number is the sentinel
594 // value of -1. If so, the sequence was not constrained by row number and
595 // this method should never return true (which indicates that we're at the
596 // end of a row-number constraint). If d_ending_row_number is not -1, then is
597 // \e i at the end point? 6/1/2001 jhrg
598 inline bool Sequence::is_end_of_rows(int i)
599 {
600  return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
601 }
602 
663 bool Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval)
664 {
665  DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
666 
667  // Special case leaf sequences!
668  if (is_leaf_sequence())
669  return serialize_leaf(dds, eval, m, ce_eval);
670  else
671  return serialize_parent_part_one(dds, eval, m);
672 }
673 
674 // We know this is not a leaf Sequence. That means that this Sequence holds
675 // another Sequence as one of its fields _and_ that child Sequence triggers
676 // the actual transmission of values.
677 
679 {
680  DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
681 
682  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
683 
684  // read_row returns true if valid data was read, false if the EOF was
685  // found. 6/1/2001 jhrg
686  // Since this is a parent sequence, read the row ignoring the CE (all of
687  // the CE clauses will be evaluated by the leaf sequence).
688  bool status = read_row(i, dds, eval, false);
689  DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
690 
691  while (status && !is_end_of_rows(i)) {
692  i += d_row_stride;
693 
694  // DBG(cerr << "Writing Start of Instance marker" << endl);
695  // write_start_of_instance(sink);
696 
697  // In this loop serialize will signal an error with an exception.
698  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
699  // Only call serialize for child Sequences; the leaf sequence
700  // will trigger the transmission of values for its parents (this
701  // sequence and maybe others) once it gets some valid data to
702  // send.
703  // Note that if the leaf sequence has no variables in the current
704  // projection, its serialize() method will never be called and that's
705  // the method that triggers actually sending values. Thus the leaf
706  // sequence must be the lowest level sequence with values whose send_p
707  // property is true.
708  if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) (*iter)->serialize(eval, dds, m);
709  }
710 
711  set_read_p(false); // ...so this will read the next instance
712 
713  status = read_row(i, dds, eval, false);
714  DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
715  }
716  // Reset current row number for next nested sequence element.
717  d_row_number = -1;
718 
719  // Always write the EOS marker? 12/23/04 jhrg
720  // Yes. According to DAP2, a completely empty response is signaled by
721  // a return value of only the EOS marker for the outermost sequence.
722  if (d_top_most || d_wrote_soi) {
723  DBG(cerr << "Writing End of Sequence marker" << endl);
724  write_end_of_sequence(m);
725  d_wrote_soi = false;
726  }
727 
728  return true; // Signal errors with exceptions.
729 }
730 
731 // If we are here then we know that this is 'parent sequence' and that the
732 // leaf sequence has found valid data to send. We also know that
733 // serialize_parent_part_one has been called so data are in the instance's
734 // fields. This is where we send data. Whereas ..._part_one() contains a
735 // loop to iterate over all of rows in a parent sequence, this does not. This
736 // method assumes that the serialize_leaf() will call it each time it needs
737 // to be called.
738 //
739 // NB: This code only works if the child sequences appear after all other
740 // variables.
742 {
743  DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
744 
745  BaseType *btp = get_parent();
746  if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
747 
748  if (d_unsent_data) {
749  DBG(cerr << "Writing Start of Instance marker" << endl);
750  d_wrote_soi = true;
751  write_start_of_instance(m);
752 
753  // In this loop serialize will signal an error with an exception.
754  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
755  // Send all the non-sequence variables
756  DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
757  << (*iter)->name() << endl);
758  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
759  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
760  (*iter)->serialize(eval, dds, m, false);
761  }
762  }
763 
764  d_unsent_data = false; // read should set this.
765  }
766 }
767 
768 // This code is only run by a leaf sequence. Note that a one level sequence
769 // is also a leaf sequence.
770 bool Sequence::serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
771 {
772  DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
773  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
774 
775  // read_row returns true if valid data was read, false if the EOF was
776  // found. 6/1/2001 jhrg
777  bool status = read_row(i, dds, eval, ce_eval);
778  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
779 
780  // Once the first valid (satisfies the CE) row of the leaf sequence has
781  // been read, we know we're going to send data. Send the current instance
782  // of the parent/ancestor sequences now, if there are any. We only need
783  // to do this once, hence it's not inside the while loop, but we only
784  // send the parent seq data _if_ there's data in the leaf to send, that's
785  // why we wait until after the first call to read_row() here in the leaf
786  // sequence.
787  //
788  // NB: It's important to only call serialize_parent_part_two() for a
789  // Sequence that really is the parent of a leaf sequence.
790  if (status && !is_end_of_rows(i)) {
791  BaseType *btp = get_parent();
792  if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
793  }
794 
795  d_wrote_soi = false;
796  while (status && !is_end_of_rows(i)) {
797  i += d_row_stride;
798 
799  DBG(cerr << "Writing Start of Instance marker" << endl);
800  d_wrote_soi = true;
801  write_start_of_instance(m);
802 
803  // In this loop serialize will signal an error with an exception.
804  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
805  DBG(cerr << "Sequence::serialize_leaf(), serializing "
806  << (*iter)->name() << endl);
807  if ((*iter)->send_p()) {
808  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
809  (*iter)->serialize(eval, dds, m, false);
810  }
811  }
812 
813  set_read_p(false); // ...so this will read the next instance
814 
815  status = read_row(i, dds, eval, ce_eval);
816  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
817  }
818 
819  // Only write the EOS marker if there's a matching Start Of Instance
820  // Marker in the stream.
821  if (d_wrote_soi || d_top_most) {
822  DBG(cerr << "Writing End of Sequence marker" << endl);
823  write_end_of_sequence(m);
824  }
825 
826  return true; // Signal errors with exceptions.
827 }
828 
852 {
853  DBG(cerr << "Sequence::intern_data - for " << name() << endl); DBG2(cerr << " intern_data, values: " << &d_values << endl);
854 
855  // Why use a stack instead of return values? We need the stack because
856  // Sequences nested three of more levels deep will loose the middle
857  // instances when the intern_data_parent_part_two() code is run.
858  sequence_values_stack_t sequence_values_stack;
859 
860  DBG2(cerr << " pushing d_values of " << name() << " (" << &d_values
861  << ") on stack; size: " << sequence_values_stack.size() << endl);
862  sequence_values_stack.push(&d_values);
863 
864  intern_data_private(eval, dds, sequence_values_stack);
865 }
866 
868 {
869  DBG(cerr << "Entering intern_data_private for " << name() << endl);
870 
871  if (is_leaf_sequence())
872  intern_data_for_leaf(dds, eval, sequence_values_stack);
873  else
874  intern_data_parent_part_one(dds, eval, sequence_values_stack);
875 }
876 
878  sequence_values_stack_t & sequence_values_stack)
879 {
880  DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
881 
882  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
883 
884  // read_row returns true if valid data was read, false if the EOF was
885  // found. 6/1/2001 jhrg
886  // Since this is a parent sequence, read the row ignoring the CE (all of
887  // the CE clauses will be evaluated by the leaf sequence).
888  bool status = read_row(i, dds, eval, false);
889 
890  // Grab the current size of the value stack. We do this because it is
891  // possible that no nested sequences for this row happened to be
892  // selected because of a constraint evaluation or the last row is not
893  // selected because of a constraint evaluation. In either case, no
894  // nested sequence d_values are pushed onto the stack, so there is
895  // nothing to pop at the end of this function. pcw 07/14/08
896  SequenceValues::size_type orig_stack_size = sequence_values_stack.size();
897 
898  while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
899  i += get_row_stride();
900  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
901  if ((*iter)->send_p()) {
902  switch ((*iter)->type()) {
903  case dods_sequence_c:
904  static_cast<Sequence&>(**iter).intern_data_private(eval, dds, sequence_values_stack);
905  break;
906 
907  default:
908  (*iter)->intern_data(eval, dds);
909  break;
910  }
911  }
912  }
913 
914  set_read_p(false); // ...so this will read the next instance
915 
916  status = read_row(i, dds, eval, false);
917  }
918 
919  // Reset current row number for next nested sequence element.
921 
922  // if the size of the stack is larger than the original size (retrieved
923  // above) then pop the top set of d_values from the stack. If it's the
924  // same, then no nested sequences, or possible the last nested sequence,
925  // were pushed onto the stack, so there is nothing to pop.
926  if (sequence_values_stack.size() > orig_stack_size) {
927  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
928  << ") off stack; size: " << sequence_values_stack.size() << endl);
929  sequence_values_stack.pop();
930  } DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
931 }
932 
934  sequence_values_stack_t &sequence_values_stack)
935 {
936  DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
937 
938  BaseType *btp = get_parent();
939  if (btp && btp->type() == dods_sequence_c) {
940  static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
941  }
942 
943  DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl);
944  SequenceValues *values = sequence_values_stack.top();
945  DBG2(cerr << " using values = " << (void *)values << endl);
946 
947  if (get_unsent_data()) {
948  BaseTypeRow *row_data = new BaseTypeRow;
949 
950  // In this loop transfer_data will signal an error with an exception.
951  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
952 
953  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
954  row_data->push_back((*iter)->ptr_duplicate());
955  }
956  else if ((*iter)->send_p()) { //Sequence; must be the last variable
957  Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
958  if (!tmp) {
959  delete row_data;
960  throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
961  }
962  row_data->push_back(tmp);
963  DBG2(cerr << " pushing d_values of " << tmp->name()
964  << " (" << &(tmp->d_values)
965  << ") on stack; size: " << sequence_values_stack.size()
966  << endl);
967  // This pushes the d_values field of the newly created leaf
968  // Sequence onto the stack. The code then returns to intern
969  // _data_for_leaf() where this value will be used.
970  sequence_values_stack.push(&(tmp->d_values));
971  }
972  }
973 
974  DBG2(cerr << " pushing values for " << name()
975  << " to " << values << endl);
976  values->push_back(row_data);
977  set_unsent_data(false);
978  } DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
979 }
980 
982 {
983  DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
984 
985  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
986 
987  DBG2(cerr << " reading row " << i << endl);
988  bool status = read_row(i, dds, eval, true);
989  DBG2(cerr << " status: " << status << endl); DBG2(cerr << " ending row number: " << get_ending_row_number() << endl);
990 
991  if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
992  BaseType *btp = get_parent();
993  if (btp && btp->type() == dods_sequence_c) {
994  // This call will read the values for the parent sequences and
995  // then allocate a new instance for the leaf and push that onto
996  // the stack.
997  static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
998  }
999 
1000  // intern_data_parent_part_two pushes the d_values field of the leaf
1001  // onto the stack, so this operation grabs that value and then loads
1002  // data into it.
1003  SequenceValues *values = sequence_values_stack.top();
1004  DBG2(cerr << " using values = " << values << endl);
1005 
1006  while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
1007  i += get_row_stride();
1008 
1009  // Copy data from the object's fields to this new BaeTypeRow instance
1010  BaseTypeRow *row_data = new BaseTypeRow;
1011  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1012  if ((*iter)->send_p()) {
1013  row_data->push_back((*iter)->ptr_duplicate());
1014  }
1015  }
1016 
1017  DBG2(cerr << " pushing values for " << name()
1018  << " to " << values << endl);
1019  // Save the row_data to values().
1020  values->push_back(row_data);
1021 
1022  set_read_p(false); // ...so this will read the next instance
1023  // Read the ith row into this object's fields
1024  status = read_row(i, dds, eval, true);
1025  }
1026 
1027  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
1028  << ") off stack; size: " << sequence_values_stack.size() << endl);
1029  sequence_values_stack.pop();
1030  } DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
1031 }
1032 
1053 bool Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
1054 {
1055  DataDDS *dd = dynamic_cast<DataDDS *>(dds);
1056  if (!dd) throw InternalErr("Expected argument 'dds' to be a DataDDS!");
1057 
1058  DBG2(cerr << "Reading from server/protocol version: "
1059  << dd->get_protocol_major() << "." << dd->get_protocol_minor()
1060  << endl);
1061 
1062  // Check for old servers.
1063  if (dd->get_protocol_major() < 2) {
1064  throw Error(
1065  string("The protocl version (") + dd->get_protocol()
1066  + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
1067  }
1068 
1069  while (true) {
1070  // Grab the sequence stream's marker.
1071  unsigned char marker = read_marker(um);
1072  if (is_end_of_sequence(marker))
1073  break; // EXIT the while loop here!!!
1074  else if (is_start_of_instance(marker)) {
1075  d_row_number++;
1076  DBG2(cerr << "Reading row " << d_row_number << " of "
1077  << name() << endl);
1078  BaseTypeRow *bt_row_ptr = new BaseTypeRow;
1079  // Read the instance's values, building up the row
1080  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1081  BaseType *bt_ptr = (*iter)->ptr_duplicate();
1082  bt_ptr->deserialize(um, dds, reuse);
1083  DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
1084  << bt_ptr << ") = "); DBG2(bt_ptr->print_val(stderr, ""));
1085  bt_row_ptr->push_back(bt_ptr);
1086  }
1087  // Append this row to those accumulated.
1088  d_values.push_back(bt_row_ptr);
1089  }
1090  else
1091  throw Error("I could not read the expected Sequence data stream marker!");
1092  };
1093 
1094  return false;
1095 }
1096 
1097 // Return the current row number.
1098 
1111 {
1112  return d_starting_row_number;
1113 }
1114 
1126 {
1127  return d_row_stride;
1128 }
1129 
1142 {
1143  return d_ending_row_number;
1144 }
1145 
1154 void Sequence::set_row_number_constraint(int start, int stop, int stride)
1155 {
1156  if (stop < start) throw Error(malformed_expr, "Starting row number must precede the ending row number.");
1157 
1158  d_starting_row_number = start;
1159  d_row_stride = stride;
1160  d_ending_row_number = stop;
1161 }
1162 
1163 void Sequence::print_one_row(FILE *out, int row, string space, bool print_row_num)
1164 {
1165  ostringstream oss;
1166  print_one_row(oss, row, space, print_row_num);
1167  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1168 }
1169 
1170 void Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num)
1171 {
1172  if (print_row_num) out << "\n" << space << row << ": ";
1173 
1174  out << "{ ";
1175 
1176  int elements = element_count();
1177  int j = 0;
1178  BaseType *bt_ptr = 0;
1179 
1180  // This version of print_one_row() works for both data read with
1181  // deserialize(), where each variable is assumed to have valid data, and
1182  // intern_data(), where some/many variables do not. Because of that, it's
1183  // not correct to assume that all of the elements will be printed, which
1184  // is what the old code did.
1185  // Print the first value
1186  while (j < elements && !bt_ptr) {
1187  bt_ptr = var_value(row, j++);
1188  if (bt_ptr) { // data
1189  if (bt_ptr->type() == dods_sequence_c)
1190  static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1191  else
1192  bt_ptr->print_val(out, space, false);
1193  }
1194  }
1195 
1196  // Print the remaining values
1197  while (j < elements) {
1198  bt_ptr = var_value(row, j++);
1199  if (bt_ptr) { // data
1200  out << ", ";
1201  if (bt_ptr->type() == dods_sequence_c)
1202  static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1203  else
1204  bt_ptr->print_val(out, space, false);
1205  }
1206  }
1207 
1208  out << " }";
1209 }
1210 
1211 void Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, bool print_row_numbers)
1212 {
1213  ostringstream oss;
1214  print_val_by_rows(oss, space, print_decl_p, print_row_numbers);
1215  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1216 }
1217 
1218 void Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers)
1219 {
1220  if (print_decl_p) {
1221  print_decl(out, space, false);
1222  out << " = ";
1223  }
1224 
1225  out << "{ ";
1226 
1227  int rows = number_of_rows() - 1;
1228  int i;
1229  for (i = 0; i < rows; ++i) {
1230  print_one_row(out, i, space, print_row_numbers);
1231  out << ", ";
1232  }
1233  print_one_row(out, i, space, print_row_numbers);
1234 
1235  out << " }";
1236 
1237  if (print_decl_p) out << ";\n";
1238 }
1239 
1240 void Sequence::print_val(FILE *out, string space, bool print_decl_p)
1241 {
1242  print_val_by_rows(out, space, print_decl_p, false);
1243 }
1244 
1245 void Sequence::print_val(ostream &out, string space, bool print_decl_p)
1246 {
1247  print_val_by_rows(out, space, print_decl_p, false);
1248 }
1249 
1250 void Sequence::set_leaf_p(bool state)
1251 {
1252  d_leaf_sequence = state;
1253 }
1254 
1256 {
1257  return d_leaf_sequence;
1258 }
1259 
1285 {
1286  bool has_child_sequence = false;
1287 
1288  if (lvl == 1) d_top_most = true;
1289 
1290  DBG2(cerr << "Processing sequence " << name() << endl);
1291 
1292  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1293  // About the test for send_p(): Only descend into a sequence if it has
1294  // fields that might be sent. Thus if, in a two-level sequence, nothing
1295  // in the lower level is to be sent, the upper level is marked as the
1296  // leaf sequence. This ensures that values _will_ be sent (see the comment
1297  // in serialize_leaf() and serialize_parent_part_one()).
1298  if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
1299  if (has_child_sequence)
1300  throw Error(
1301  "This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
1302 
1303  has_child_sequence = true;
1304  static_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
1305  }
1306  else if ((*iter)->type() == dods_structure_c) {
1307  static_cast<Structure&>(**iter).set_leaf_sequence(lvl);
1308  }
1309  }
1310 
1311  if (!has_child_sequence)
1312  set_leaf_p(true);
1313  else
1314  set_leaf_p(false);
1315 
1316  DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
1317 }
1318 
1327 void Sequence::dump(ostream &strm) const
1328 {
1329  strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl;
1331  Constructor::dump(strm);
1332  strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number << endl;
1333  strm << DapIndent::LMarg << "bracket notation information:" << endl;
1335  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
1336  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
1337  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
1339 
1340  strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl;
1341  strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl;
1342  strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence << endl;
1343  strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most << endl;
1345 }
1346 
1347 } // namespace libdap
1348 
Holds an Internet address (URL).
Definition: Url.h:63
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:421
virtual void intern_data(ConstraintEvaluator &eval, DDS &dds)
Definition: Sequence.cc:851
static void UnIndent()
Definition: DapIndent.cc:51
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:1327
void set_unsent_data(bool usd)
Set the unsent data property.
Definition: Sequence.h:273
virtual bool set_value(dods_float64 val)
Definition: Float64.cc:224
#define malformed_expr
Definition: Error.h:64
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: BaseType.cc:845
std::vector< BaseType * > d_vars
Definition: Constructor.h:49
virtual bool read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval=true)
Definition: Sequence.cc:539
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Deserialize (read from the network) the entire Sequence.
Definition: Sequence.cc:1053
std::vector< BaseType * >::iterator Vars_iter
Definition: Constructor.h:62
virtual bool is_dap2_only_type()
Definition: Sequence.cc:254
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:663
int get_protocol_minor() const
Definition: DataDDS.h:137
virtual bool serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
Definition: Sequence.cc:770
BaseType * transform_to_dap4(D4Group *root, Constructor *dest)
DAP2 to DAP4 transform.
Definition: Constructor.cc:137
virtual void put_opaque(char *val, unsigned int len)=0
virtual BaseTypeRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: Sequence.cc:307
virtual ~Sequence()
Definition: Sequence.cc:234
void timeout_off()
Definition: DDS.cc:894
virtual void set_row_number_constraint(int start, int stop, int stride=1)
Definition: Sequence.cc:1154
Holds a structure (aggregate) type.
Definition: Structure.h:83
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:306
virtual string toString()
Definition: BaseType.cc:184
Holds a 32-bit floating point value.
Definition: Float32.h:61
#define DBG2(x)
Definition: debug.h:73
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Constructor.cc:169
virtual void print_val_by_rows(ostream &out, string space="", bool print_decl_p=true, bool print_row_numbers=true)
Definition: Sequence.cc:1218
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:639
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 void intern_data_private(ConstraintEvaluator &eval, DDS &dds, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:867
string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:299
virtual bool set_value(dods_uint32 val)
Definition: UInt32.cc:217
virtual bool is_linear()
Check to see whether this variable can be printed simply.
Definition: Sequence.cc:274
virtual void intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:981
Holds character string data.
Definition: Str.h:62
virtual int length() const
Definition: Sequence.cc:395
#define DBG(x)
Definition: debug.h:58
bool get_unsent_data()
Get the unsent data property.
Definition: Sequence.h:267
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: BaseType.cc:992
Holds a 16-bit signed integer value.
Definition: Int16.h:59
static void Indent()
Definition: DapIndent.cc:45
Sequence(const string &n)
The Sequence constructor.
Definition: Sequence.cc:158
virtual BaseType * get_parent() const
Definition: BaseType.cc:657
virtual void set_length(int count)
Definition: D4Sequence.h:174
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:1284
Sequence & operator=(const Sequence &rhs)
Definition: Sequence.cc:240
virtual bool set_value(dods_int16 val)
Definition: Int16.cc:215
virtual bool set_value(const dods_byte value)
Definition: Byte.cc:229
Holds a sequence.
Definition: Sequence.h:162
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:823
virtual bool set_value(const string &value)
Definition: Str.cc:253
vector< BaseType * > BaseTypeRow
Definition: Sequence.h:57
virtual void serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
Definition: Sequence.cc:741
virtual bool set_value(dods_float32 f)
Definition: Float32.cc:213
virtual bool is_leaf_sequence()
Definition: Sequence.cc:1255
string name() const
Returns the name of the class instance.
Definition: BaseType.cc:261
virtual string toString()
Definition: Sequence.cc:259
virtual BaseType * ptr_duplicate()=0
void timeout_on()
Definition: DDS.cc:886
int get_starting_row_number()
Get the starting row number.
Definition: Sequence.cc:1110
virtual int number_of_rows() const
Definition: Sequence.cc:401
Evaluate a constraint expression.
virtual SequenceValues & value_ref()
Definition: Sequence.cc:334
bool d_is_synthesized
Definition: BaseType.h:144
virtual SequenceValues value()
Definition: Sequence.cc:326
void reset_row_number()
Rest the row number counter.
Definition: Sequence.cc:409
virtual void intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:933
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:80
virtual bool set_value(dods_int32 i)
Definition: Int32.cc:225
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:53
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:345
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:600
virtual void print_one_row(ostream &out, int row, string space, bool print_row_num=false)
Definition: Sequence.cc:1170
Vars_iter var_begin()
Definition: Constructor.cc:331
Holds a 64-bit (double precision) floating point value.
Definition: Float64.h:60
virtual void intern_data_parent_part_one(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:877
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:1245
string get_protocol() const
Definition: DataDDS.h:129
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 bool set_value(dods_uint16 val)
Definition: UInt16.cc:215
virtual bool serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
Definition: Sequence.cc:678
virtual void set_leaf_p(bool state)
Definition: Sequence.cc:1250
stack< SequenceValues * > sequence_values_stack_t
Definition: Sequence.h:203
void m_duplicate(const Sequence &s)
Definition: Sequence.cc:86
A class for error processing.
Definition: Error.h:90
virtual BaseType * transform_to_dap4(D4Group *root, Constructor *container)
Definition: Sequence.cc:208
virtual int get_ending_row_number()
Get the ending row number.
Definition: Sequence.cc:1141
Holds a 32-bit unsigned integer.
Definition: UInt32.h:59
virtual BaseType * ptr_duplicate()
Definition: Sequence.cc:188
Holds a DAP2 DDS.
Definition: DataDDS.h:77
virtual int get_row_stride()
Get the row stride.
Definition: Sequence.cc:1125
int get_protocol_major() const
Definition: DataDDS.h:133
virtual void set_value(SequenceValues &values)
Definition: Sequence.cc:319
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