libdap++  Updated for version 3.8.2
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 
36 #include "config.h"
37 
38 #include <algorithm>
39 #include <string>
40 #include <sstream>
41 
42 //#define DODS_DEBUG
43 //#define DODS_DEBUG2
44 
45 #include "Byte.h"
46 #include "Int16.h"
47 #include "UInt16.h"
48 #include "Int32.h"
49 #include "UInt32.h"
50 #include "Float32.h"
51 #include "Float64.h"
52 #include "Str.h"
53 #include "Url.h"
54 #include "Array.h"
55 #include "Structure.h"
56 #include "Sequence.h"
57 #include "Grid.h"
58 
59 #include "debug.h"
60 #include "Error.h"
61 #include "InternalErr.h"
62 #include "Sequence.h"
63 #include "DDS.h"
64 #include "DataDDS.h"
65 #include "util.h"
66 #include "InternalErr.h"
67 #include "escaping.h"
68 
69 using namespace std;
70 
71 namespace libdap {
72 
73 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
74 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
75 
76 // Private member functions
77 
78 void
79 Sequence::_duplicate(const Sequence &s)
80 {
81  d_row_number = s.d_row_number;
82  d_starting_row_number = s.d_starting_row_number;
83  d_ending_row_number = s.d_ending_row_number;
84  d_row_stride = s.d_row_stride;
85  d_leaf_sequence = s.d_leaf_sequence;
86  d_unsent_data = s.d_unsent_data;
87  d_wrote_soi = s.d_wrote_soi;
88  d_top_most = s.d_top_most;
89 
90  Sequence &cs = const_cast<Sequence &>(s);
91 
92  // Copy the template BaseType objects.
93  for (Vars_iter i = cs.var_begin(); i != cs.var_end(); i++) {
94  add_var((*i)) ;
95  }
96 
97  // Copy the BaseType objects used to hold values.
98  for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin();
99  rows_iter != cs.d_values.end();
100  rows_iter++) {
101  // Get the current BaseType Row
102  BaseTypeRow *src_bt_row_ptr = *rows_iter;
103  // Create a new row.
104  BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow;
105  // Copy the BaseType objects from a row to new BaseType objects.
106  // Push new BaseType objects onto new row.
107  for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin();
108  bt_row_iter != src_bt_row_ptr->end();
109  bt_row_iter++) {
110  BaseType *src_bt_ptr = *bt_row_iter;
111  BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate();
112  dest_bt_row_ptr->push_back(dest_bt_ptr);
113  }
114  // Push new row onto d_values.
115  d_values.push_back(dest_bt_row_ptr);
116  }
117 }
118 
119 static void
120 write_end_of_sequence(Marshaller &m)
121 {
122  m.put_opaque( (char *)&end_of_sequence, 1 ) ;
123 }
124 
125 static void
126 write_start_of_instance(Marshaller &m)
127 {
128  m.put_opaque( (char *)&start_of_instance, 1 ) ;
129 }
130 
131 static unsigned char
132 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
141 is_start_of_instance(unsigned char marker)
142 {
143  return (marker == start_of_instance);
144 }
145 
146 static bool
147 is_end_of_sequence(unsigned char marker)
148 {
149  return (marker == end_of_sequence);
150 }
151 
152 // Public member functions
153 
162 Sequence::Sequence(const string &n) : Constructor(n, dods_sequence_c),
163  d_row_number(-1), d_starting_row_number(-1),
164  d_row_stride(1), d_ending_row_number(-1),
165  d_unsent_data(false), d_wrote_soi(false),
166  d_leaf_sequence(false), d_top_most(false)
167 {}
168 
179 Sequence::Sequence(const string &n, const string &d)
180  : Constructor(n, d, dods_sequence_c),
181  d_row_number(-1), d_starting_row_number(-1),
182  d_row_stride(1), d_ending_row_number(-1),
183  d_unsent_data(false), d_wrote_soi(false),
184  d_leaf_sequence(false), d_top_most(false)
185 {}
186 
189 {
190  _duplicate(rhs);
191 }
192 
193 BaseType *
195 {
196  return new Sequence(*this);
197 }
198 
199 static inline void
200 delete_bt(BaseType *bt_ptr)
201 {
202  DBG2(cerr << "In delete_bt: " << bt_ptr << endl);
203  delete bt_ptr; bt_ptr = 0;
204 }
205 
206 static inline void
207 delete_rows(BaseTypeRow *bt_row_ptr)
208 {
209  DBG2(cerr << "In delete_rows: " << bt_row_ptr << endl);
210 
211  for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
212 
213  delete bt_row_ptr; bt_row_ptr = 0;
214 }
215 
217 {
218  DBG2(cerr << "Entering Sequence::~Sequence" << endl);
219  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
220  BaseType *btp = *i ;
221  delete btp ; btp = 0;
222  }
223 
224  for_each(d_values.begin(), d_values.end(), delete_rows);
225  DBG2(cerr << "exiting Sequence::~Sequence" << endl);
226 }
227 
228 Sequence &
230 {
231  if (this == &rhs)
232  return *this;
233 
234  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
235 
236  _duplicate(rhs);
237 
238  return *this;
239 }
240 
241 string
243 {
244  ostringstream oss;
245 
246  oss << BaseType::toString();
247 
248  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
249  oss << (*i)->toString();
250  }
251 
252  oss << endl;
253 
254  return oss.str();
255 }
256 
257 int
259 {
260  if (!leaves)
261  return _vars.size();
262  else {
263  int i = 0;
264  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
265  i += (*iter)->element_count(true);
266  }
267  return i;
268  }
269 }
270 
271 bool
273 {
274  bool linear = true;
275  bool seq_found = false;
276  for (Vars_iter iter = _vars.begin(); linear && iter != _vars.end(); iter++) {
277  if ((*iter)->type() == dods_sequence_c) {
278  // A linear sequence cannot have more than one child seq. at any
279  // one level. If we've already found a seq at this level, return
280  // false.
281  if (seq_found) {
282  linear = false;
283  break;
284  }
285  seq_found = true;
286  linear = dynamic_cast<Sequence *>((*iter))->is_linear();
287  }
288  else if ((*iter)->type() == dods_structure_c) {
289  linear = dynamic_cast<Structure*>((*iter))->is_linear();
290  }
291  else {
292  // A linear sequence cannot have Arrays, Lists or Grids.
293  linear = (*iter)->is_simple_type();
294  }
295  }
296 
297  return linear;
298 }
299 
300 void
302 {
303  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
304  (*i)->set_send_p(state);
305  }
306 
307  BaseType::set_send_p(state);
308 }
309 
310 void
312 {
313  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
314  (*i)->set_read_p(state);
315  }
316 
317  BaseType::set_read_p(state);
318 }
319 
320 void
322 {
323  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
324  (*i)->set_in_selection(state);
325  }
326 
328 }
329 
339 void
341 {
342  if (!bt)
343  throw InternalErr(__FILE__, __LINE__,
344  "Cannot add variable: NULL pointer");
345  // Jose Garcia
346  // We append a copy of bt so the owner of bt is free to deallocate
347 
348  BaseType *bt_copy = bt->ptr_duplicate();
349  bt_copy->set_parent(this);
350  _vars.push_back(bt_copy);
351 }
352 
364 void
366 {
367  if (!bt)
368  throw InternalErr(__FILE__, __LINE__,
369  "Cannot add variable: NULL pointer");
370  bt->set_parent(this);
371  _vars.push_back(bt);
372 }
373 
374 // Deprecated
375 BaseType *
376 Sequence::var(const string &n, btp_stack &s)
377 {
378  string name = www2id(n);
379 
380  BaseType *btp = m_exact_match(name, &s);
381  if (btp)
382  return btp;
383 
384  return m_leaf_match(name, &s);
385 }
386 
387 BaseType *
388 Sequence::var(const string &name, bool exact_match, btp_stack *s)
389 {
390  string n = www2id(name);
391 
392  if (exact_match)
393  return m_exact_match(n, s);
394  else
395  return m_leaf_match(n, s);
396 }
397 
398 BaseType *
399 Sequence::m_leaf_match(const string &name, btp_stack *s)
400 {
401  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
402  if ((*i)->name() == name) {
403  if (s)
404  s->push(static_cast<BaseType *>(this));
405  return *i;
406  }
407  if ((*i)->is_constructor_type()) {
408  BaseType *btp = (*i)->var(name, false, s);
409  if (btp) {
410  if (s)
411  s->push(static_cast<BaseType *>(this));
412  return btp;
413  }
414  }
415  }
416 
417  return 0;
418 }
419 
420 BaseType *
421 Sequence::m_exact_match(const string &name, btp_stack *s)
422 {
423  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
424  if ((*i)->name() == name) {
425  if (s)
426  s->push(static_cast<BaseType *>(this));
427  return *i;
428  }
429  }
430 
431  string::size_type dot_pos = name.find("."); // zero-based index of `.'
432  if (dot_pos != string::npos) {
433  string aggregate = name.substr(0, dot_pos);
434  string field = name.substr(dot_pos + 1);
435 
436  BaseType *agg_ptr = var(aggregate);
437  if (agg_ptr) {
438  if (s)
439  s->push(static_cast<BaseType *>(this));
440  return agg_ptr->var(field, true, s); // recurse
441  }
442  else
443  return 0; // qualified names must be *fully* qualified
444  }
445 
446  return 0;
447 }
448 
453 BaseTypeRow *
455 {
456  if (row >= d_values.size())
457  return 0;
458  return d_values[row];
459 }
460 
467 void
469 {
470  d_values = values;
471 }
472 
477 {
478  return d_values;
479 }
480 
486 BaseType *
487 Sequence::var_value(size_t row, const string &name)
488 {
489  BaseTypeRow *bt_row_ptr = row_value(row);
490  if (!bt_row_ptr)
491  return 0;
492 
493  BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
494  BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
495  while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
496  ++bt_row_iter;
497 
498  if (bt_row_iter == bt_row_end)
499  return 0;
500  else
501  return *bt_row_iter;
502 }
503 
509 BaseType *
510 Sequence::var_value(size_t row, size_t i)
511 {
512  BaseTypeRow *bt_row_ptr = row_value(row);
513  if (!bt_row_ptr)
514  return 0;
515 
516  if (i >= bt_row_ptr->size())
517  return 0;
518 
519  return (*bt_row_ptr)[i];
520 }
521 
522 unsigned int
524 {
525  unsigned int sz = 0;
526 
527  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
528  sz += (*i)->width();
529  }
530 
531  return sz;
532 }
533 
541 unsigned int
542 Sequence::width(bool constrained)
543 {
544  unsigned int sz = 0;
545 
546  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
547  if (constrained) {
548  if ((*i)->send_p())
549  sz += (*i)->width(constrained);
550  }
551  else {
552  sz += (*i)->width(constrained);
553  }
554  }
555 
556  return sz;
557 }
558 
559 // This version returns -1. Each API-specific subclass should define a more
560 // reasonable version. jhrg 5/24/96
561 
577 int
579 {
580  return -1;
581 }
582 
583 
584 int
586 {
587  return d_values.size();
588 }
589 
593 void
595 {
596  d_row_number = -1;
597 }
598 
599 // Notes:
600 // Assume that read() is implemented so that, when reading data for a nested
601 // sequence, only the outer most level is *actually* read.
602 // This is a consequence of our current (12/7/99) implementation of
603 // the JGOFS server (which is the only server to actually use nested
604 // sequences). 12/7/99 jhrg
605 //
606 // Stop assuming this. This logic is being moved into the JGOFS server
607 // itself. 6/1/2001 jhrg
608 
609 // The read() function returns a boolean value, with TRUE
610 // indicating that read() should be called again because there's
611 // more data to read, and FALSE indicating there's no more data
612 // to read. Note that this behavior is necessary to properly
613 // handle variables that contain Sequences. Jose Garcia If an
614 // error exists while reading, the implementers of the surrogate
615 // library SHOULD throw an Error object which will propagate
616 // beyond this point to to the original caller.
617 // Jose Garcia
618 
651 bool
652 Sequence::read_row(int row, DDS &dds,
653  ConstraintEvaluator &eval, bool ce_eval)
654 {
655  DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
656  if (row < d_row_number)
657  throw InternalErr("Trying to back up inside a sequence!");
658 
659  DBG2(cerr << "read_row: row number " << row
660  << ", current row " << d_row_number << endl);
661  if (row == d_row_number)
662  {
663  DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
664  return true;
665  }
666 
667  dds.timeout_on();
668 
669  int eof = 0; // Start out assuming EOF is false.
670  while (!eof && d_row_number < row) {
671  if (!read_p()) {
672  eof = (read() == false);
673  }
674 
675  // Advance the row number if ce_eval is false (we're not supposed to
676  // evaluate the selection) or both ce_eval and the selection are
677  // true.
678  if (!eof && (!ce_eval || eval.eval_selection(dds, dataset())))
679  d_row_number++;
680 
681  set_read_p(false); // ...so that the next instance will be read
682  }
683 
684  // Once we finish the above loop, set read_p to true so that the caller
685  // knows that data *has* been read. This is how the read() methods of the
686  // elements of the sequence know to not call read() but instead look for
687  // data values inside themselves.
688  set_read_p(true);
689 
690  dds.timeout_off();
691 
692  // Return true if we have valid data, false if we've read to the EOF.
693  DBG2(cerr << "Leaving Sequence::read_row for " << name()
694  << " with " << (eof == 0) << endl);
695  return eof == 0;
696 }
697 
698 // Private. This is used to process constraints on the rows of a sequence.
699 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
700 // odd-looking logic first checks if d_ending_row_number is the sentinel
701 // value of -1. If so, the sequence was not constrained by row number and
702 // this method should never return true (which indicates that we're at the
703 // end of a row-number constraint). If d_ending_row_number is not -1, then is
704 // \e i at the end point? 6/1/2001 jhrg
705 inline bool
706 Sequence::is_end_of_rows(int i)
707 {
708  return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
709 }
710 
771 bool
773  Marshaller &m, bool ce_eval)
774 {
775  DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
776 
777  // Special case leaf sequences!
778  if (is_leaf_sequence())
779  return serialize_leaf(dds, eval, m, ce_eval);
780  else
781  return serialize_parent_part_one(dds, eval, m);
782 }
783 
784 // We know this is not a leaf Sequence. That means that this Sequence holds
785 // another Sequence as one of its fields _and_ that child Sequence triggers
786 // the actual transmission of values.
787 
788 bool
791 {
792  DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
793 
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  // Since this is a parent sequence, read the row ignoring the CE (all of
799  // the CE clauses will be evaluated by the leaf sequence).
800  bool status = read_row(i, dds, eval, false);
801  DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
802 
803  while (status && !is_end_of_rows(i)) {
804  i += d_row_stride;
805 
806  // DBG(cerr << "Writing Start of Instance marker" << endl);
807  // write_start_of_instance(sink);
808 
809  // In this loop serialize will signal an error with an exception.
810  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
811  // Only call serialize for child Sequences; the leaf sequence
812  // will trigger the transmission of values for its parents (this
813  // sequence and maybe others) once it gets soem valid data to
814  // send.
815  // Note that if the leaf sequence has no variables in the current
816  // projection, its serialize() method will never be called and that's
817  // the method that triggers actually sending values. Thus the leaf
818  // sequence must be the lowest level sequence with values whose send_p
819  // property is true.
820  if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c)
821  (*iter)->serialize(eval, dds, m);
822  }
823 
824  set_read_p(false); // ...so this will read the next instance
825 
826  status = read_row(i, dds, eval, false);
827  DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
828  }
829  // Reset current row number for next nested sequence element.
830  d_row_number = -1;
831 
832  // Always write the EOS marker? 12/23/04 jhrg
833  // Yes. According to DAP2, a completely empty response is signalled by
834  // a return value of only the EOS marker for the outermost sequence.
835  if (d_top_most || d_wrote_soi) {
836  DBG(cerr << "Writing End of Sequence marker" << endl);
837  write_end_of_sequence(m);
838  d_wrote_soi = false;
839  }
840 
841  return true; // Signal errors with exceptions.
842 }
843 
844 // If we are here then we know that this is 'parent sequence' and that the
845 // leaf seq has found valid data to send. We also know that
846 // serialize_parent_part_one has been called so data are in the instance's
847 // fields. This is wheree we send data. Whereas ..._part_one() contains a
848 // loop to iterate over all of rows in a parent sequence, this does not. This
849 // method assumes that the serialize_leaf() will call it each time it needs
850 // to be called.
851 //
852 // NB: This code only works if the child sequences appear after all other
853 // variables.
854 void
857 {
858  DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
859 
860  BaseType *btp = get_parent();
861  if (btp && btp->type() == dods_sequence_c)
862  dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
863 
864  if (d_unsent_data) {
865  DBG(cerr << "Writing Start of Instance marker" << endl);
866  d_wrote_soi = true;
867  write_start_of_instance(m);
868 
869  // In this loop serialize will signal an error with an exception.
870  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
871  // Send all the non-sequence variables
872  DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
873  << (*iter)->name() << endl);
874  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
875  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
876  (*iter)->serialize(eval, dds, m, false);
877  }
878  }
879 
880  d_unsent_data = false; // read should set this.
881  }
882 }
883 
884 // This code is only run by a leaf sequence. Note that a one level sequence
885 // is also a leaf sequence.
886 bool
888  ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
889 {
890  DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
891  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
892 
893  // read_row returns true if valid data was read, false if the EOF was
894  // found. 6/1/2001 jhrg
895  bool status = read_row(i, dds, eval, ce_eval);
896  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
897 
898  // Once the first valid (satisfies the CE) row of the leaf sequence has
899  // been read, we know we're going to send data. Send the current instance
900  // of the parent/ancestor sequences now, if there are any. We only need
901  // to do this once, hence it's not inside the while loop, but we only
902  // send the parent seq data _if_ there's data in the leaf to send, that's
903  // why we wait until after the first call to read_row() here in the leaf
904  // sequence.
905  //
906  // NB: It's important to only call serialize_parent_part_two() for a
907  // Sequence that really is the parent of a leaf sequence. The fancy cast
908  // will throw and exception if btp is not a Sequence, but doesn't test
909  // that it's a parent sequence as we've defined them here.
910  if (status && !is_end_of_rows(i)) {
911  BaseType *btp = get_parent();
912  if (btp && btp->type() == dods_sequence_c)
913  dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds,
914  eval, m);
915  }
916 
917  d_wrote_soi = false;
918  while (status && !is_end_of_rows(i)) {
919  i += d_row_stride;
920 
921  DBG(cerr << "Writing Start of Instance marker" << endl);
922  d_wrote_soi = true;
923  write_start_of_instance(m);
924 
925  // In this loop serialize will signal an error with an exception.
926  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
927  DBG(cerr << "Sequence::serialize_leaf(), serializing "
928  << (*iter)->name() << endl);
929  if ((*iter)->send_p()) {
930  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
931  (*iter)->serialize(eval, dds, m, false);
932  }
933  }
934 
935  set_read_p(false); // ...so this will read the next instance
936 
937  status = read_row(i, dds, eval, ce_eval);
938  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
939  }
940 
941  // Only write the EOS marker if there's a matching Start Of Instnace
942  // Marker in the stream.
943  if (d_wrote_soi || d_top_most) {
944  DBG(cerr << "Writing End of Sequence marker" << endl);
945  write_end_of_sequence(m);
946  }
947 
948  return true; // Signal errors with exceptions.
949 }
950 
973 void
975 {
976  DBG(cerr << "Sequence::intern_data - for " << name() << endl);
977  DBG2(cerr << " intern_data, values: " << &d_values << endl);
978 
979  // Why use a stack instead of return values? We need the stack because
980  // Sequences neted three of more levels deep will loose the middle
981  // instances when the intern_data_parent_part_two() code is run.
982  sequence_values_stack_t sequence_values_stack;
983 
984  DBG2(cerr << " pushing d_values of " << name() << " (" << &d_values
985  << ") on stack; size: " << sequence_values_stack.size() << endl);
986  sequence_values_stack.push(&d_values);
987 
988  intern_data_private(eval, dds, sequence_values_stack);
989 }
990 
991 void
993  DDS &dds,
994  sequence_values_stack_t &sequence_values_stack)
995 {
996  DBG(cerr << "Entering intern_data_private for " << name() << endl);
997 
998  if (is_leaf_sequence())
999  intern_data_for_leaf(dds, eval, sequence_values_stack);
1000  else
1001  intern_data_parent_part_one(dds, eval, sequence_values_stack);
1002 }
1003 
1004 void
1006  ConstraintEvaluator & eval,
1008  sequence_values_stack)
1009 {
1010  DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
1011 
1012  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
1013 
1014  // read_row returns true if valid data was read, false if the EOF was
1015  // found. 6/1/2001 jhrg
1016  // Since this is a parent sequence, read the row ignoring the CE (all of
1017  // the CE clauses will be evaluated by the leaf sequence).
1018  bool status = read_row(i, dds, eval, false);
1019 
1020  // Grab the current size of the value stack. We do this because it is
1021  // possible that no nested sequences for this row happened to be
1022  // selected because of a constract evaluation or the last row is not
1023  // selected because of a constraint evaluation. In either case, no
1024  // nested sequence d_values are pused onto the stack, so there is
1025  // nothing to pop at the end of this function. pcw 07/14/08
1026  SequenceValues::size_type orig_stack_size = sequence_values_stack.size() ;
1027 
1028  while (status
1029  && (get_ending_row_number() == -1
1030  || i <= get_ending_row_number()))
1031  {
1032  i += get_row_stride();
1033  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1034  if ((*iter)->send_p()) {
1035  switch ((*iter)->type()) {
1036  case dods_sequence_c:
1037  dynamic_cast<Sequence&>(**iter).intern_data_private(
1038  eval, dds, sequence_values_stack);
1039  break;
1040 
1041  default:
1042  (*iter)->intern_data(eval, dds);
1043  break;
1044  }
1045  }
1046  }
1047 
1048  set_read_p(false); // ...so this will read the next instance
1049 
1050  status = read_row(i, dds, eval, false);
1051  }
1052 
1053  // Reset current row number for next nested sequence element.
1054  reset_row_number();
1055 
1056  // if the size of the stack is larger than the original size (retrieved
1057  // above) then pop the top set of d_values from the stack. If it's the
1058  // same, then no nested sequences, or possible the last nested sequence,
1059  // were pushed onto the stack, so there is nothing to pop.
1060  if( sequence_values_stack.size() > orig_stack_size )
1061  {
1062  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
1063  << ") off stack; size: " << sequence_values_stack.size() << endl);
1064  sequence_values_stack.pop();
1065  }
1066  DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
1067 }
1068 
1069 void
1071  ConstraintEvaluator &eval,
1072  sequence_values_stack_t &sequence_values_stack)
1073 {
1074  DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
1075 
1076  BaseType *btp = get_parent();
1077  if (btp && btp->type() == dods_sequence_c) {
1078  dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(
1079  dds, eval, sequence_values_stack);
1080  }
1081 
1082  DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl);
1083  SequenceValues *values = sequence_values_stack.top();
1084  DBG2(cerr << " using values = " << (void *)values << endl);
1085 
1086  if (get_unsent_data()) {
1087  BaseTypeRow *row_data = new BaseTypeRow;
1088 
1089  // In this loop transfer_data will signal an error with an exception.
1090  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1091 
1092  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
1093  row_data->push_back((*iter)->ptr_duplicate());
1094  }
1095  else if ((*iter)->send_p()) { //Sequence; must be the last variable
1096  Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
1097  if (!tmp) {
1098  delete row_data;
1099  throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
1100  }
1101  row_data->push_back(tmp);
1102  DBG2(cerr << " pushing d_values of " << tmp->name()
1103  << " (" << &(tmp->d_values)
1104  << ") on stack; size: " << sequence_values_stack.size()
1105  << endl);
1106  // This pushes the d_values field of the newly created leaf
1107  // Sequence onto the stack. The code then returns to intern
1108  // _data_for_leaf() where this value will be used.
1109  sequence_values_stack.push(&(tmp->d_values));
1110  }
1111  }
1112 
1113  DBG2(cerr << " pushing values for " << name()
1114  << " to " << values << endl);
1115  values->push_back(row_data);
1116  set_unsent_data(false);
1117  }
1118  DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
1119 }
1120 
1121 void
1123  ConstraintEvaluator &eval,
1124  sequence_values_stack_t &sequence_values_stack)
1125 {
1126  DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
1127 
1128  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
1129 
1130  DBG2(cerr << " reading row " << i << endl);
1131  bool status = read_row(i, dds, eval, true);
1132  DBG2(cerr << " status: " << status << endl);
1133  DBG2(cerr << " ending row number: " << get_ending_row_number() << endl);
1134 
1135  if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
1136  BaseType *btp = get_parent();
1137  if (btp && btp->type() == dods_sequence_c) {
1138  // This call will read the values for the parent sequences and
1139  // then allocate a new instance for the leaf and push that onto
1140  // the stack.
1141  dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(
1142  dds, eval, sequence_values_stack);
1143  }
1144 
1145  // intern_data_parent_part_two pushes the d_values field of the leaf
1146  // onto the stack, so this operation grabs that value and then loads
1147  // data into it.
1148  SequenceValues *values = sequence_values_stack.top();
1149  DBG2(cerr << " using values = " << values << endl);
1150 
1151  while (status && (get_ending_row_number() == -1
1152  || i <= get_ending_row_number())) {
1153  i += get_row_stride();
1154 
1155  // Copy data from the object's fields to this new BaeTypeRow instance
1156  BaseTypeRow *row_data = new BaseTypeRow;
1157  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1158  if ((*iter)->send_p()) {
1159  row_data->push_back((*iter)->ptr_duplicate());
1160  }
1161  }
1162 
1163  DBG2(cerr << " pushing values for " << name()
1164  << " to " << values << endl);
1165  // Save the row_data to values().
1166  values->push_back(row_data);
1167 
1168  set_read_p(false); // ...so this will read the next instance
1169  // Read the ith row into this object's fields
1170  status = read_row(i, dds, eval, true);
1171  }
1172 
1173  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
1174  << ") off stack; size: " << sequence_values_stack.size() << endl);
1175  sequence_values_stack.pop();
1176  }
1177  DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
1178 }
1179 
1200 bool
1202 {
1203  DataDDS *dd = dynamic_cast<DataDDS *>(dds);
1204  if (!dd)
1205  throw InternalErr("Expected argument 'dds' to be a DataDDS!");
1206 
1207  DBG2(cerr << "Reading from server/protocol version: "
1208  << dd->get_protocol_major() << "." << dd->get_protocol_minor()
1209  << endl);
1210 
1211  // Check for old servers.
1212  if (dd->get_protocol_major() < 2) {
1213  throw Error(string("The protocl version (") + dd->get_protocol()
1214  + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
1215  }
1216 
1217  while (true) {
1218  // Grab the sequence stream's marker.
1219  unsigned char marker = read_marker(um);
1220  if (is_end_of_sequence(marker))
1221  break; // EXIT the while loop here!!!
1222  else if (is_start_of_instance(marker)) {
1223  d_row_number++;
1224  DBG2(cerr << "Reading row " << d_row_number << " of "
1225  << name() << endl);
1226  BaseTypeRow *bt_row_ptr = new BaseTypeRow;
1227  // Read the instance's values, building up the row
1228  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
1229  BaseType *bt_ptr = (*iter)->ptr_duplicate();
1230  bt_ptr->deserialize(um, dds, reuse);
1231  DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
1232  << bt_ptr << ") = ");
1233  DBG2(bt_ptr->print_val(stderr, ""));
1234  bt_row_ptr->push_back(bt_ptr);
1235  }
1236  // Append this row to those accumulated.
1237  d_values.push_back(bt_row_ptr);
1238  }
1239  else
1240  throw Error("I could not read the expected Sequence data stream marker!");
1241  };
1242 
1243  return false;
1244 }
1245 
1246 // Return the current row number.
1247 
1259 int
1261 {
1262  return d_starting_row_number;
1263 }
1264 
1275 int
1277 {
1278  return d_row_stride;
1279 }
1280 
1292 int
1294 {
1295  return d_ending_row_number;
1296 }
1297 
1306 void
1307 Sequence::set_row_number_constraint(int start, int stop, int stride)
1308 {
1309  if (stop < start)
1310  throw Error(malformed_expr, "Starting row number must precede the ending row number.");
1311 
1312  d_starting_row_number = start;
1313  d_row_stride = stride;
1314  d_ending_row_number = stop;
1315 }
1316 
1319 unsigned int
1320 Sequence::val2buf(void *, bool)
1321 {
1322  throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation.");
1323  return sizeof(Sequence);
1324 }
1325 
1330 unsigned int
1332 {
1333  throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()");
1334  return sizeof(Sequence);
1335 }
1336 
1337 #if FILE_METHODS
1338 void
1339 Sequence::print_one_row(FILE *out, int row, string space,
1340  bool print_row_num)
1341 {
1342  if (print_row_num)
1343  fprintf(out, "\n%s%d: ", space.c_str(), row) ;
1344 
1345  fprintf(out, "{ ") ;
1346 
1347  int elements = element_count() - 1;
1348  int j;
1349  BaseType *bt_ptr;
1350  // Print first N-1 elements of the row.
1351  for (j = 0; j < elements; ++j) {
1352  bt_ptr = var_value(row, j);
1353  if (bt_ptr) { // data
1354  if (bt_ptr->type() == dods_sequence_c)
1355  dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
1356  (out, space + " ", false, print_row_num);
1357  else
1358  bt_ptr->print_val(out, space, false);
1359  fprintf(out, ", ") ;
1360  }
1361  }
1362 
1363  // Print Nth element; end with a `}.'
1364  bt_ptr = var_value(row, j);
1365  if (bt_ptr) { // data
1366  if (bt_ptr->type() == dods_sequence_c)
1367  dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
1368  (out, space + " ", false, print_row_num);
1369  else
1370  bt_ptr->print_val(out, space, false);
1371  }
1372 
1373  fprintf(out, " }") ;
1374 }
1375 #endif
1376 
1377 void
1378 Sequence::print_one_row(ostream &out, int row, string space,
1379  bool print_row_num)
1380 {
1381  if (print_row_num)
1382  out << "\n" << space << row << ": " ;
1383 
1384  out << "{ " ;
1385 
1386  int elements = element_count();
1387  int j = 0;
1388  BaseType *bt_ptr = 0;
1389 
1390  // This version of print_one_row() works for both data read with
1391  // deserialize(), where each variable is assumed to have valid data, and
1392  // intern_data(), where some/many variables do not. Because of that, it's
1393  // not correct to assume that all of the elements will be printed, which
1394  // is what the old code did.
1395  // Print the first value
1396  while (j < elements && !bt_ptr) {
1397  bt_ptr = var_value(row, j++);
1398  if (bt_ptr) { // data
1399  if (bt_ptr->type() == dods_sequence_c)
1400  dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
1401  (out, space + " ", false, print_row_num);
1402  else
1403  bt_ptr->print_val(out, space, false);
1404  }
1405  }
1406 
1407  // Print the remaining values
1408  while (j < elements) {
1409  bt_ptr = var_value(row, j++);
1410  if (bt_ptr) { // data
1411  out << ", ";
1412  if (bt_ptr->type() == dods_sequence_c)
1413  dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
1414  (out, space + " ", false, print_row_num);
1415  else
1416  bt_ptr->print_val(out, space, false);
1417  }
1418  }
1419 
1420  out << " }" ;
1421 }
1422 
1423 #if FILE_METHODS
1424 void
1425 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p,
1426  bool print_row_numbers)
1427 {
1428  if (print_decl_p) {
1429  print_decl(out, space, false);
1430  fprintf(out, " = ") ;
1431  }
1432 
1433  fprintf(out, "{ ") ;
1434 
1435  int rows = number_of_rows() - 1;
1436  int i;
1437  for (i = 0; i < rows; ++i) {
1438  print_one_row(out, i, space, print_row_numbers);
1439  fprintf(out, ", ") ;
1440  }
1441  print_one_row(out, i, space, print_row_numbers);
1442 
1443  fprintf(out, " }") ;
1444 
1445  if (print_decl_p)
1446  fprintf(out, ";\n") ;
1447 }
1448 #endif
1449 
1450 void
1451 Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p,
1452  bool print_row_numbers)
1453 {
1454  if (print_decl_p) {
1455  print_decl(out, space, false);
1456  out << " = " ;
1457  }
1458 
1459  out << "{ " ;
1460 
1461  int rows = number_of_rows() - 1;
1462  int i;
1463  for (i = 0; i < rows; ++i) {
1464  print_one_row(out, i, space, print_row_numbers);
1465  out << ", " ;
1466  }
1467  print_one_row(out, i, space, print_row_numbers);
1468 
1469  out << " }" ;
1470 
1471  if (print_decl_p)
1472  out << ";\n" ;
1473 }
1474 
1475 #if FILE_METHODS
1476 void
1477 Sequence::print_val(FILE *out, string space, bool print_decl_p)
1478 {
1479  print_val_by_rows(out, space, print_decl_p, false);
1480 }
1481 #endif
1482 
1483 void
1484 Sequence::print_val(ostream &out, string space, bool print_decl_p)
1485 {
1486  print_val_by_rows(out, space, print_decl_p, false);
1487 }
1488 
1489 
1490 bool
1491 Sequence::check_semantics(string &msg, bool all)
1492 {
1493  if (!BaseType::check_semantics(msg))
1494  return false;
1495 
1496  if (!unique_names(_vars, name(), type_name(), msg))
1497  return false;
1498 
1499  if (all)
1500  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
1501  if (!(*i)->check_semantics(msg, true)) {
1502  return false;
1503  }
1504  }
1505 
1506  return true;
1507 }
1508 
1509 void
1511 {
1512  d_leaf_sequence = state;
1513 }
1514 
1515 bool
1517 {
1518  return d_leaf_sequence;
1519 }
1520 
1545 void
1547 {
1548  bool has_child_sequence = false;
1549 
1550  if (lvl == 1) d_top_most = true;
1551 
1552  DBG2(cerr << "Processing sequence " << name() << endl);
1553 
1554  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
1555  // About the test for send_p(): Only descend into a sequence if it has
1556  // fields that might be sent. Thus if, in a two-level sequence, nothing
1557  // in the lower level is to be sent, the upper level is marked as the
1558  // leaf sequence. This ensures that values _will_ be sent (see the comment
1559  // in serialize_leaf() and serialize_parent_part_one()).
1560  if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
1561  if (has_child_sequence)
1562  throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
1563 
1564  has_child_sequence = true;
1565  dynamic_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
1566  }
1567  else if ((*iter)->type() == dods_structure_c) {
1568  dynamic_cast<Structure&>(**iter).set_leaf_sequence(lvl);
1569  }
1570  }
1571 
1572  if (!has_child_sequence)
1573  set_leaf_p(true);
1574  else
1575  set_leaf_p(false);
1576 
1577  DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
1578 }
1579 
1588 void
1589 Sequence::dump(ostream &strm) const
1590 {
1591  strm << DapIndent::LMarg << "Sequence::dump - ("
1592  << (void *)this << ")" << endl ;
1593  DapIndent::Indent() ;
1594  Constructor::dump(strm) ;
1595  strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number
1596  << endl ;
1597  strm << DapIndent::LMarg << "bracket notation information:" << endl ;
1598  DapIndent::Indent() ;
1599  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number
1600  << endl ;
1601  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ;
1602  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number
1603  << endl ;
1605 
1606  strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ;
1607  strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ;
1608  strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence
1609  << endl ;
1610  strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most
1611  << endl ;
1613 }
1614 
1615 } // namespace libdap
1616