libdap++  Updated for version 3.13.1
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 
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 "Marshaller.h"
60 #include "UnMarshaller.h"
61 
62 #include "debug.h"
63 #include "Error.h"
64 #include "InternalErr.h"
65 #include "Sequence.h"
66 #include "DDS.h"
67 #include "DataDDS.h"
68 #include "util.h"
69 #include "InternalErr.h"
70 #include "escaping.h"
71 
72 using namespace std;
73 
74 namespace libdap {
75 
76 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
77 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
78 
79 // Private member functions
80 
81 void
82 Sequence::m_duplicate(const Sequence &s)
83 {
84  d_row_number = s.d_row_number;
85  d_starting_row_number = s.d_starting_row_number;
86  d_ending_row_number = s.d_ending_row_number;
87  d_row_stride = s.d_row_stride;
88  d_leaf_sequence = s.d_leaf_sequence;
89  d_unsent_data = s.d_unsent_data;
90  d_wrote_soi = s.d_wrote_soi;
91  d_top_most = s.d_top_most;
92 
93  Sequence &cs = const_cast<Sequence &>(s);
94 
95  // Copy the template BaseType objects.
96  for (Vars_iter i = cs.var_begin(); i != cs.var_end(); i++) {
97  add_var((*i)) ;
98  }
99 
100  // Copy the BaseType objects used to hold values.
101  for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin();
102  rows_iter != cs.d_values.end();
103  rows_iter++) {
104  // Get the current BaseType Row
105  BaseTypeRow *src_bt_row_ptr = *rows_iter;
106  // Create a new row.
107  BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow;
108  // Copy the BaseType objects from a row to new BaseType objects.
109  // Push new BaseType objects onto new row.
110  for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin();
111  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
123 write_end_of_sequence(Marshaller &m)
124 {
125  m.put_opaque( (char *)&end_of_sequence, 1 ) ;
126 }
127 
128 static void
129 write_start_of_instance(Marshaller &m)
130 {
131  m.put_opaque( (char *)&start_of_instance, 1 ) ;
132 }
133 
134 static unsigned char
135 read_marker(UnMarshaller &um)
136 {
137  unsigned char marker;
138  um.get_opaque( (char *)&marker, 1 ) ;
139 
140  return marker;
141 }
142 
143 static bool
144 is_start_of_instance(unsigned char marker)
145 {
146  return (marker == start_of_instance);
147 }
148 
149 static bool
150 is_end_of_sequence(unsigned char marker)
151 {
152  return (marker == end_of_sequence);
153 }
154 
155 // Public member functions
156 
165 Sequence::Sequence(const string &n) : Constructor(n, dods_sequence_c),
166  d_row_number(-1), d_starting_row_number(-1),
167  d_row_stride(1), d_ending_row_number(-1),
168  d_unsent_data(false), d_wrote_soi(false),
169  d_leaf_sequence(false), d_top_most(false)
170 {}
171 
182 Sequence::Sequence(const string &n, const string &d)
183  : Constructor(n, d, dods_sequence_c),
184  d_row_number(-1), d_starting_row_number(-1),
185  d_row_stride(1), d_ending_row_number(-1),
186  d_unsent_data(false), d_wrote_soi(false),
187  d_leaf_sequence(false), d_top_most(false)
188 {}
189 
192 {
193  m_duplicate(rhs);
194 }
195 
196 BaseType *
198 {
199  return new Sequence(*this);
200 }
201 
202 static inline void
203 delete_bt(BaseType *bt_ptr)
204 {
205  DBG2(cerr << "In delete_bt: " << bt_ptr << endl);
206  delete bt_ptr; bt_ptr = 0;
207 }
208 
209 static inline void
210 delete_rows(BaseTypeRow *bt_row_ptr)
211 {
212  DBG2(cerr << "In delete_rows: " << bt_row_ptr << endl);
213 
214  for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
215 
216  delete bt_row_ptr; bt_row_ptr = 0;
217 }
218 
220 {
221  DBG2(cerr << "Entering Sequence::~Sequence" << endl);
222  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
223  BaseType *btp = *i ;
224  delete btp ; btp = 0;
225  }
226 
227  for_each(d_values.begin(), d_values.end(), delete_rows);
228  DBG2(cerr << "exiting Sequence::~Sequence" << endl);
229 }
230 
231 Sequence &
233 {
234  if (this == &rhs)
235  return *this;
236 
237  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
238 
239  m_duplicate(rhs);
240 
241  return *this;
242 }
243 
247 bool
249 {
250  return true;
251 }
252 
253 string
255 {
256  ostringstream oss;
257 
258  oss << BaseType::toString();
259 
260  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
261  oss << (*i)->toString();
262  }
263 
264  oss << endl;
265 
266  return oss.str();
267 }
268 
269 #if 0
270 int
271 Sequence::element_count(bool leaves)
272 {
273  if (!leaves)
274  return d_vars.size();
275  else {
276  int i = 0;
277  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
278  i += (*iter)->element_count(true);
279  }
280  return i;
281  }
282 }
283 #endif
284 
285 bool
287 {
288  bool linear = true;
289  bool seq_found = false;
290  for (Vars_iter iter = d_vars.begin(); linear && iter != d_vars.end(); iter++) {
291  if ((*iter)->type() == dods_sequence_c) {
292  // A linear sequence cannot have more than one child seq. at any
293  // one level. If we've already found a seq at this level, return
294  // false.
295  if (seq_found) {
296  linear = false;
297  break;
298  }
299  seq_found = true;
300  linear = static_cast<Sequence *>((*iter))->is_linear();
301  }
302  else if ((*iter)->type() == dods_structure_c) {
303  linear = static_cast<Structure*>((*iter))->is_linear();
304  }
305  else {
306  // A linear sequence cannot have Arrays, Lists or Grids.
307  linear = (*iter)->is_simple_type();
308  }
309  }
310 
311  return linear;
312 }
313 
314 #if 0
315 void
316 Sequence::set_send_p(bool state)
317 {
318  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
319  (*i)->set_send_p(state);
320  }
321 
322  BaseType::set_send_p(state);
323 }
324 
325 void
326 Sequence::set_read_p(bool state)
327 {
328  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
329  (*i)->set_read_p(state);
330  }
331 
332  BaseType::set_read_p(state);
333 }
334 #endif
335 #if 0
336 void
337 Sequence::set_in_selection(bool state)
338 {
339  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
340  (*i)->set_in_selection(state);
341  }
342 
344 }
345 #endif
346 #if 0
347 
356 void
357 Sequence::add_var(BaseType *bt, Part)
358 {
359  if (!bt)
360  throw InternalErr(__FILE__, __LINE__,
361  "Cannot add variable: NULL pointer");
362  if (bt->is_dap4_only_type())
363  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Sequence.");
364 
365  // Jose Garcia
366  // We append a copy of bt so the owner of bt is free to deallocate
367 
368  BaseType *bt_copy = bt->ptr_duplicate();
369  bt_copy->set_parent(this);
370  d_vars.push_back(bt_copy);
371 }
372 
384 void
385 Sequence::add_var_nocopy(BaseType *bt, Part)
386 {
387  if (!bt)
388  throw InternalErr(__FILE__, __LINE__,
389  "Cannot add variable: NULL pointer");
390  if (bt->is_dap4_only_type())
391  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Sequence.");
392 
393  bt->set_parent(this);
394  d_vars.push_back(bt);
395 }
396 #endif
397 #if 0
398 // Deprecated
399 BaseType *
400 Sequence::var(const string &n, btp_stack &s)
401 {
402  string name = www2id(n);
403 
404  BaseType *btp = m_exact_match(name, &s);
405  if (btp)
406  return btp;
407 
408  return m_leaf_match(name, &s);
409 }
410 
411 BaseType *
412 Sequence::var(const string &name, bool exact_match, btp_stack *s)
413 {
414  string n = www2id(name);
415 
416  if (exact_match)
417  return m_exact_match(n, s);
418  else
419  return m_leaf_match(n, s);
420 }
421 #endif
422 #if 0
423 BaseType *
424 Sequence::m_leaf_match(const string &name, btp_stack *s)
425 {
426  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
427  if ((*i)->name() == name) {
428  if (s)
429  s->push(static_cast<BaseType *>(this));
430  return *i;
431  }
432  if ((*i)->is_constructor_type()) {
433  BaseType *btp = (*i)->var(name, false, s);
434  if (btp) {
435  if (s)
436  s->push(static_cast<BaseType *>(this));
437  return btp;
438  }
439  }
440  }
441 
442  return 0;
443 }
444 
445 BaseType *
446 Sequence::m_exact_match(const string &name, btp_stack *s)
447 {
448  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
449  if ((*i)->name() == name) {
450  if (s)
451  s->push(static_cast<BaseType *>(this));
452  return *i;
453  }
454  }
455 
456  string::size_type dot_pos = name.find("."); // zero-based index of `.'
457  if (dot_pos != string::npos) {
458  string aggregate = name.substr(0, dot_pos);
459  string field = name.substr(dot_pos + 1);
460 
461  BaseType *agg_ptr = var(aggregate);
462  if (agg_ptr) {
463  if (s)
464  s->push(static_cast<BaseType *>(this));
465  return agg_ptr->var(field, true, s); // recurse
466  }
467  else
468  return 0; // qualified names must be *fully* qualified
469  }
470 
471  return 0;
472 }
473 #endif
474 
478 BaseTypeRow *
480 {
481  if (row >= d_values.size())
482  return 0;
483  return d_values[row];
484 }
485 
492 void
494 {
495  d_values = values;
496 }
497 
502 {
503  return d_values;
504 }
505 
511 BaseType *
512 Sequence::var_value(size_t row, const string &name)
513 {
514  BaseTypeRow *bt_row_ptr = row_value(row);
515  if (!bt_row_ptr)
516  return 0;
517 
518  BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
519  BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
520  while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
521  ++bt_row_iter;
522 
523  if (bt_row_iter == bt_row_end)
524  return 0;
525  else
526  return *bt_row_iter;
527 }
528 
534 BaseType *
535 Sequence::var_value(size_t row, size_t i)
536 {
537  BaseTypeRow *bt_row_ptr = row_value(row);
538  if (!bt_row_ptr)
539  return 0;
540 
541  if (i >= bt_row_ptr->size())
542  return 0;
543 
544  return (*bt_row_ptr)[i];
545 }
546 
547 #if 0
548 unsigned int
550 {
551  unsigned int sz = 0;
552 
553  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
554  sz += (*i)->width();
555  }
556 
557  return sz;
558 }
559 
567 unsigned int
568 Sequence::width(bool constrained)
569 {
570  unsigned int sz = 0;
571 
572  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
573  if (constrained) {
574  if ((*i)->send_p())
575  sz += (*i)->width(constrained);
576  }
577  else {
578  sz += (*i)->width(constrained);
579  }
580  }
581 
582  return sz;
583 }
584 #endif
585 
586 // This version returns -1. Each API-specific subclass should define a more
587 // reasonable version. jhrg 5/24/96
588 
604 int
606 {
607  return -1;
608 }
609 
610 
611 int
613 {
614  return d_values.size();
615 }
616 
620 void
622 {
623  d_row_number = -1;
624 }
625 
626 // Notes:
627 // Assume that read() is implemented so that, when reading data for a nested
628 // sequence, only the outer most level is *actually* read.
629 // This is a consequence of our current (12/7/99) implementation of
630 // the JGOFS server (which is the only server to actually use nested
631 // sequences). 12/7/99 jhrg
632 //
633 // Stop assuming this. This logic is being moved into the JGOFS server
634 // itself. 6/1/2001 jhrg
635 
636 // The read() function returns a boolean value, with TRUE
637 // indicating that read() should be called again because there's
638 // more data to read, and FALSE indicating there's no more data
639 // to read. Note that this behavior is necessary to properly
640 // handle variables that contain Sequences. Jose Garcia If an
641 // error exists while reading, the implementers of the surrogate
642 // library SHOULD throw an Error object which will propagate
643 // beyond this point to to the original caller.
644 // Jose Garcia
645 
678 bool Sequence::read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval)
679 {
680  DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
681  if (row < d_row_number) throw InternalErr("Trying to back up inside a sequence!");
682 
683  DBG2(cerr << "read_row: row number " << row << ", current row " << d_row_number << endl);
684  if (row == d_row_number) {
685  DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
686  return false;
687  }
688 
689  dds.timeout_on();
690 
691  bool eof = false; // Start out assuming EOF is false.
692  while (!eof && d_row_number < row) {
693  if (!read_p()) {
694  // jhrg original version from 10/9/13 : eof = (read() == false);
695  eof = read();
696  }
697 
698  // Advance the row number if ce_eval is false (we're not supposed to
699  // evaluate the selection) or both ce_eval and the selection are
700  // true.
701  if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) d_row_number++;
702 
703  set_read_p(false); // ...so that the next instance will be read
704  }
705 
706  // Once we finish the above loop, set read_p to true so that the caller
707  // knows that data *has* been read. This is how the read() methods of the
708  // elements of the sequence know to not call read() but instead look for
709  // data values inside themselves.
710  set_read_p(true);
711 
712  dds.timeout_off();
713 
714  // Return true if we have valid data, false if we've read to the EOF.
715  DBG2(cerr << "Leaving Sequence::read_row for " << name() << " with eof: " << eof << endl);
716  return !eof; // jhrg 10/10/13 was: eof == 0;
717 }
718 
719 // Private. This is used to process constraints on the rows of a sequence.
720 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
721 // odd-looking logic first checks if d_ending_row_number is the sentinel
722 // value of -1. If so, the sequence was not constrained by row number and
723 // this method should never return true (which indicates that we're at the
724 // end of a row-number constraint). If d_ending_row_number is not -1, then is
725 // \e i at the end point? 6/1/2001 jhrg
726 inline bool
727 Sequence::is_end_of_rows(int i)
728 {
729  return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
730 }
731 
792 bool
794  Marshaller &m, bool ce_eval)
795 {
796  DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
797 
798  // Special case leaf sequences!
799  if (is_leaf_sequence())
800  return serialize_leaf(dds, eval, m, ce_eval);
801  else
802  return serialize_parent_part_one(dds, eval, m);
803 }
804 
805 // We know this is not a leaf Sequence. That means that this Sequence holds
806 // another Sequence as one of its fields _and_ that child Sequence triggers
807 // the actual transmission of values.
808 
809 bool
812 {
813  DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
814 
815  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
816 
817  // read_row returns true if valid data was read, false if the EOF was
818  // found. 6/1/2001 jhrg
819  // Since this is a parent sequence, read the row ignoring the CE (all of
820  // the CE clauses will be evaluated by the leaf sequence).
821  bool status = read_row(i, dds, eval, false);
822  DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
823 
824  while (status && !is_end_of_rows(i)) {
825  i += d_row_stride;
826 
827  // DBG(cerr << "Writing Start of Instance marker" << endl);
828  // write_start_of_instance(sink);
829 
830  // In this loop serialize will signal an error with an exception.
831  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
832  // Only call serialize for child Sequences; the leaf sequence
833  // will trigger the transmission of values for its parents (this
834  // sequence and maybe others) once it gets some valid data to
835  // send.
836  // Note that if the leaf sequence has no variables in the current
837  // projection, its serialize() method will never be called and that's
838  // the method that triggers actually sending values. Thus the leaf
839  // sequence must be the lowest level sequence with values whose send_p
840  // property is true.
841  if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c)
842  (*iter)->serialize(eval, dds, m);
843  }
844 
845  set_read_p(false); // ...so this will read the next instance
846 
847  status = read_row(i, dds, eval, false);
848  DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
849  }
850  // Reset current row number for next nested sequence element.
851  d_row_number = -1;
852 
853  // Always write the EOS marker? 12/23/04 jhrg
854  // Yes. According to DAP2, a completely empty response is signaled by
855  // a return value of only the EOS marker for the outermost sequence.
856  if (d_top_most || d_wrote_soi) {
857  DBG(cerr << "Writing End of Sequence marker" << endl);
858  write_end_of_sequence(m);
859  d_wrote_soi = false;
860  }
861 
862  return true; // Signal errors with exceptions.
863 }
864 
865 // If we are here then we know that this is 'parent sequence' and that the
866 // leaf sequence has found valid data to send. We also know that
867 // serialize_parent_part_one has been called so data are in the instance's
868 // fields. This is where we send data. Whereas ..._part_one() contains a
869 // loop to iterate over all of rows in a parent sequence, this does not. This
870 // method assumes that the serialize_leaf() will call it each time it needs
871 // to be called.
872 //
873 // NB: This code only works if the child sequences appear after all other
874 // variables.
875 void
878 {
879  DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
880 
881  BaseType *btp = get_parent();
882  if (btp && btp->type() == dods_sequence_c)
883  static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
884 
885  if (d_unsent_data) {
886  DBG(cerr << "Writing Start of Instance marker" << endl);
887  d_wrote_soi = true;
888  write_start_of_instance(m);
889 
890  // In this loop serialize will signal an error with an exception.
891  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
892  // Send all the non-sequence variables
893  DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
894  << (*iter)->name() << endl);
895  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
896  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
897  (*iter)->serialize(eval, dds, m, false);
898  }
899  }
900 
901  d_unsent_data = false; // read should set this.
902  }
903 }
904 
905 // This code is only run by a leaf sequence. Note that a one level sequence
906 // is also a leaf sequence.
907 bool
909  ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
910 {
911  DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
912  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
913 
914  // read_row returns true if valid data was read, false if the EOF was
915  // found. 6/1/2001 jhrg
916  bool status = read_row(i, dds, eval, ce_eval);
917  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
918 
919  // Once the first valid (satisfies the CE) row of the leaf sequence has
920  // been read, we know we're going to send data. Send the current instance
921  // of the parent/ancestor sequences now, if there are any. We only need
922  // to do this once, hence it's not inside the while loop, but we only
923  // send the parent seq data _if_ there's data in the leaf to send, that's
924  // why we wait until after the first call to read_row() here in the leaf
925  // sequence.
926  //
927  // NB: It's important to only call serialize_parent_part_two() for a
928  // Sequence that really is the parent of a leaf sequence. The fancy cast
929  // will throw and exception if btp is not a Sequence, but doesn't test
930  // that it's a parent sequence as we've defined them here.
931  if (status && !is_end_of_rows(i)) {
932  BaseType *btp = get_parent();
933  if (btp && btp->type() == dods_sequence_c)
934  static_cast<Sequence&>(*btp).serialize_parent_part_two(dds,
935  eval, m);
936  }
937 
938  d_wrote_soi = false;
939  while (status && !is_end_of_rows(i)) {
940  i += d_row_stride;
941 
942  DBG(cerr << "Writing Start of Instance marker" << endl);
943  d_wrote_soi = true;
944  write_start_of_instance(m);
945 
946  // In this loop serialize will signal an error with an exception.
947  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
948  DBG(cerr << "Sequence::serialize_leaf(), serializing "
949  << (*iter)->name() << endl);
950  if ((*iter)->send_p()) {
951  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
952  (*iter)->serialize(eval, dds, m, false);
953  }
954  }
955 
956  set_read_p(false); // ...so this will read the next instance
957 
958  status = read_row(i, dds, eval, ce_eval);
959  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
960  }
961 
962  // Only write the EOS marker if there's a matching Start Of Instance
963  // Marker in the stream.
964  if (d_wrote_soi || d_top_most) {
965  DBG(cerr << "Writing End of Sequence marker" << endl);
966  write_end_of_sequence(m);
967  }
968 
969  return true; // Signal errors with exceptions.
970 }
971 
994 void
996 {
997  DBG(cerr << "Sequence::intern_data - for " << name() << endl);
998  DBG2(cerr << " intern_data, values: " << &d_values << endl);
999 
1000  // Why use a stack instead of return values? We need the stack because
1001  // Sequences nested three of more levels deep will loose the middle
1002  // instances when the intern_data_parent_part_two() code is run.
1003  sequence_values_stack_t sequence_values_stack;
1004 
1005  DBG2(cerr << " pushing d_values of " << name() << " (" << &d_values
1006  << ") on stack; size: " << sequence_values_stack.size() << endl);
1007  sequence_values_stack.push(&d_values);
1008 
1009  intern_data_private(eval, dds, sequence_values_stack);
1010 }
1011 
1012 void
1014  DDS &dds,
1015  sequence_values_stack_t &sequence_values_stack)
1016 {
1017  DBG(cerr << "Entering intern_data_private for " << name() << endl);
1018 
1019  if (is_leaf_sequence())
1020  intern_data_for_leaf(dds, eval, sequence_values_stack);
1021  else
1022  intern_data_parent_part_one(dds, eval, sequence_values_stack);
1023 }
1024 
1025 void
1027  ConstraintEvaluator & eval,
1029  sequence_values_stack)
1030 {
1031  DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
1032 
1033  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
1034 
1035  // read_row returns true if valid data was read, false if the EOF was
1036  // found. 6/1/2001 jhrg
1037  // Since this is a parent sequence, read the row ignoring the CE (all of
1038  // the CE clauses will be evaluated by the leaf sequence).
1039  bool status = read_row(i, dds, eval, false);
1040 
1041  // Grab the current size of the value stack. We do this because it is
1042  // possible that no nested sequences for this row happened to be
1043  // selected because of a constraint evaluation or the last row is not
1044  // selected because of a constraint evaluation. In either case, no
1045  // nested sequence d_values are pushed onto the stack, so there is
1046  // nothing to pop at the end of this function. pcw 07/14/08
1047  SequenceValues::size_type orig_stack_size = sequence_values_stack.size() ;
1048 
1049  while (status
1050  && (get_ending_row_number() == -1
1051  || i <= get_ending_row_number()))
1052  {
1053  i += get_row_stride();
1054  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1055  if ((*iter)->send_p()) {
1056  switch ((*iter)->type()) {
1057  case dods_sequence_c:
1058  static_cast<Sequence&>(**iter).intern_data_private(
1059  eval, dds, sequence_values_stack);
1060  break;
1061 
1062  default:
1063  (*iter)->intern_data(eval, dds);
1064  break;
1065  }
1066  }
1067  }
1068 
1069  set_read_p(false); // ...so this will read the next instance
1070 
1071  status = read_row(i, dds, eval, false);
1072  }
1073 
1074  // Reset current row number for next nested sequence element.
1075  reset_row_number();
1076 
1077  // if the size of the stack is larger than the original size (retrieved
1078  // above) then pop the top set of d_values from the stack. If it's the
1079  // same, then no nested sequences, or possible the last nested sequence,
1080  // were pushed onto the stack, so there is nothing to pop.
1081  if( sequence_values_stack.size() > orig_stack_size )
1082  {
1083  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
1084  << ") off stack; size: " << sequence_values_stack.size() << endl);
1085  sequence_values_stack.pop();
1086  }
1087  DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
1088 }
1089 
1090 void
1092  ConstraintEvaluator &eval,
1093  sequence_values_stack_t &sequence_values_stack)
1094 {
1095  DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
1096 
1097  BaseType *btp = get_parent();
1098  if (btp && btp->type() == dods_sequence_c) {
1099  static_cast<Sequence&>(*btp).intern_data_parent_part_two(
1100  dds, eval, sequence_values_stack);
1101  }
1102 
1103  DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl);
1104  SequenceValues *values = sequence_values_stack.top();
1105  DBG2(cerr << " using values = " << (void *)values << endl);
1106 
1107  if (get_unsent_data()) {
1108  BaseTypeRow *row_data = new BaseTypeRow;
1109 
1110  // In this loop transfer_data will signal an error with an exception.
1111  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1112 
1113  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
1114  row_data->push_back((*iter)->ptr_duplicate());
1115  }
1116  else if ((*iter)->send_p()) { //Sequence; must be the last variable
1117  Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
1118  if (!tmp) {
1119  delete row_data;
1120  throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
1121  }
1122  row_data->push_back(tmp);
1123  DBG2(cerr << " pushing d_values of " << tmp->name()
1124  << " (" << &(tmp->d_values)
1125  << ") on stack; size: " << sequence_values_stack.size()
1126  << endl);
1127  // This pushes the d_values field of the newly created leaf
1128  // Sequence onto the stack. The code then returns to intern
1129  // _data_for_leaf() where this value will be used.
1130  sequence_values_stack.push(&(tmp->d_values));
1131  }
1132  }
1133 
1134  DBG2(cerr << " pushing values for " << name()
1135  << " to " << values << endl);
1136  values->push_back(row_data);
1137  set_unsent_data(false);
1138  }
1139  DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
1140 }
1141 
1142 void
1144  ConstraintEvaluator &eval,
1145  sequence_values_stack_t &sequence_values_stack)
1146 {
1147  DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
1148 
1149  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
1150 
1151  DBG2(cerr << " reading row " << i << endl);
1152  bool status = read_row(i, dds, eval, true);
1153  DBG2(cerr << " status: " << status << endl);
1154  DBG2(cerr << " ending row number: " << get_ending_row_number() << endl);
1155 
1156  if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
1157  BaseType *btp = get_parent();
1158  if (btp && btp->type() == dods_sequence_c) {
1159  // This call will read the values for the parent sequences and
1160  // then allocate a new instance for the leaf and push that onto
1161  // the stack.
1162  static_cast<Sequence&>(*btp).intern_data_parent_part_two(
1163  dds, eval, sequence_values_stack);
1164  }
1165 
1166  // intern_data_parent_part_two pushes the d_values field of the leaf
1167  // onto the stack, so this operation grabs that value and then loads
1168  // data into it.
1169  SequenceValues *values = sequence_values_stack.top();
1170  DBG2(cerr << " using values = " << values << endl);
1171 
1172  while (status && (get_ending_row_number() == -1
1173  || i <= get_ending_row_number())) {
1174  i += get_row_stride();
1175 
1176  // Copy data from the object's fields to this new BaeTypeRow instance
1177  BaseTypeRow *row_data = new BaseTypeRow;
1178  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1179  if ((*iter)->send_p()) {
1180  row_data->push_back((*iter)->ptr_duplicate());
1181  }
1182  }
1183 
1184  DBG2(cerr << " pushing values for " << name()
1185  << " to " << values << endl);
1186  // Save the row_data to values().
1187  values->push_back(row_data);
1188 
1189  set_read_p(false); // ...so this will read the next instance
1190  // Read the ith row into this object's fields
1191  status = read_row(i, dds, eval, true);
1192  }
1193 
1194  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
1195  << ") off stack; size: " << sequence_values_stack.size() << endl);
1196  sequence_values_stack.pop();
1197  }
1198  DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
1199 }
1200 
1221 bool
1223 {
1224  DataDDS *dd = dynamic_cast<DataDDS *>(dds);
1225  if (!dd)
1226  throw InternalErr("Expected argument 'dds' to be a DataDDS!");
1227 
1228  DBG2(cerr << "Reading from server/protocol version: "
1229  << dd->get_protocol_major() << "." << dd->get_protocol_minor()
1230  << endl);
1231 
1232  // Check for old servers.
1233  if (dd->get_protocol_major() < 2) {
1234  throw Error(string("The protocl version (") + dd->get_protocol()
1235  + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
1236  }
1237 
1238  while (true) {
1239  // Grab the sequence stream's marker.
1240  unsigned char marker = read_marker(um);
1241  if (is_end_of_sequence(marker))
1242  break; // EXIT the while loop here!!!
1243  else if (is_start_of_instance(marker)) {
1244  d_row_number++;
1245  DBG2(cerr << "Reading row " << d_row_number << " of "
1246  << name() << endl);
1247  BaseTypeRow *bt_row_ptr = new BaseTypeRow;
1248  // Read the instance's values, building up the row
1249  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1250  BaseType *bt_ptr = (*iter)->ptr_duplicate();
1251  bt_ptr->deserialize(um, dds, reuse);
1252  DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
1253  << bt_ptr << ") = ");
1254  DBG2(bt_ptr->print_val(stderr, ""));
1255  bt_row_ptr->push_back(bt_ptr);
1256  }
1257  // Append this row to those accumulated.
1258  d_values.push_back(bt_row_ptr);
1259  }
1260  else
1261  throw Error("I could not read the expected Sequence data stream marker!");
1262  };
1263 
1264  return false;
1265 }
1266 
1267 // Return the current row number.
1268 
1280 int
1282 {
1283  return d_starting_row_number;
1284 }
1285 
1296 int
1298 {
1299  return d_row_stride;
1300 }
1301 
1313 int
1315 {
1316  return d_ending_row_number;
1317 }
1318 
1327 void
1328 Sequence::set_row_number_constraint(int start, int stop, int stride)
1329 {
1330  if (stop < start)
1331  throw Error(malformed_expr, "Starting row number must precede the ending row number.");
1332 
1333  d_starting_row_number = start;
1334  d_row_stride = stride;
1335  d_ending_row_number = stop;
1336 }
1337 
1338 #if 0
1339 
1341 unsigned int
1342 Sequence::val2buf(void *, bool)
1343 {
1344  throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation.");
1345  return sizeof(Sequence);
1346 }
1347 
1352 unsigned int
1353 Sequence::buf2val(void **)
1354 {
1355  throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()");
1356  return sizeof(Sequence);
1357 }
1358 #endif
1359 
1360 void
1361 Sequence::print_one_row(FILE *out, int row, string space,
1362  bool print_row_num)
1363 {
1364  ostringstream oss;
1365  print_one_row(oss, row, space, print_row_num);
1366  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1367 }
1368 
1369 void
1370 Sequence::print_one_row(ostream &out, int row, string space,
1371  bool print_row_num)
1372 {
1373  if (print_row_num)
1374  out << "\n" << space << row << ": " ;
1375 
1376  out << "{ " ;
1377 
1378  int elements = element_count();
1379  int j = 0;
1380  BaseType *bt_ptr = 0;
1381 
1382  // This version of print_one_row() works for both data read with
1383  // deserialize(), where each variable is assumed to have valid data, and
1384  // intern_data(), where some/many variables do not. Because of that, it's
1385  // not correct to assume that all of the elements will be printed, which
1386  // is what the old code did.
1387  // Print the first value
1388  while (j < elements && !bt_ptr) {
1389  bt_ptr = var_value(row, j++);
1390  if (bt_ptr) { // data
1391  if (bt_ptr->type() == dods_sequence_c)
1392  static_cast<Sequence*>(bt_ptr)->print_val_by_rows
1393  (out, space + " ", false, print_row_num);
1394  else
1395  bt_ptr->print_val(out, space, false);
1396  }
1397  }
1398 
1399  // Print the remaining values
1400  while (j < elements) {
1401  bt_ptr = var_value(row, j++);
1402  if (bt_ptr) { // data
1403  out << ", ";
1404  if (bt_ptr->type() == dods_sequence_c)
1405  static_cast<Sequence*>(bt_ptr)->print_val_by_rows
1406  (out, space + " ", false, print_row_num);
1407  else
1408  bt_ptr->print_val(out, space, false);
1409  }
1410  }
1411 
1412  out << " }" ;
1413 }
1414 
1415 void
1416 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p,
1417  bool print_row_numbers)
1418 {
1419  ostringstream oss;
1420  print_val_by_rows(oss, space, print_decl_p, print_row_numbers);
1421  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1422 }
1423 
1424 void
1425 Sequence::print_val_by_rows(ostream &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  out << " = " ;
1431  }
1432 
1433  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  out << ", " ;
1440  }
1441  print_one_row(out, i, space, print_row_numbers);
1442 
1443  out << " }" ;
1444 
1445  if (print_decl_p)
1446  out << ";\n" ;
1447 }
1448 
1449 void
1450 Sequence::print_val(FILE *out, string space, bool print_decl_p)
1451 {
1452  print_val_by_rows(out, space, print_decl_p, false);
1453 }
1454 
1455 void
1456 Sequence::print_val(ostream &out, string space, bool print_decl_p)
1457 {
1458  print_val_by_rows(out, space, print_decl_p, false);
1459 }
1460 
1461 #if 0
1462 bool
1463 Sequence::check_semantics(string &msg, bool all)
1464 {
1465  if (!BaseType::check_semantics(msg))
1466  return false;
1467 
1468  if (!unique_names(d_vars, name(), type_name(), msg))
1469  return false;
1470 
1471  if (all)
1472  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
1473  if (!(*i)->check_semantics(msg, true)) {
1474  return false;
1475  }
1476  }
1477 
1478  return true;
1479 }
1480 #endif
1481 
1482 void
1484 {
1485  d_leaf_sequence = state;
1486 }
1487 
1488 bool
1490 {
1491  return d_leaf_sequence;
1492 }
1493 
1518 void
1520 {
1521  bool has_child_sequence = false;
1522 
1523  if (lvl == 1) d_top_most = true;
1524 
1525  DBG2(cerr << "Processing sequence " << name() << endl);
1526 
1527  for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1528  // About the test for send_p(): Only descend into a sequence if it has
1529  // fields that might be sent. Thus if, in a two-level sequence, nothing
1530  // in the lower level is to be sent, the upper level is marked as the
1531  // leaf sequence. This ensures that values _will_ be sent (see the comment
1532  // in serialize_leaf() and serialize_parent_part_one()).
1533  if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
1534  if (has_child_sequence)
1535  throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
1536 
1537  has_child_sequence = true;
1538  static_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
1539  }
1540  else if ((*iter)->type() == dods_structure_c) {
1541  static_cast<Structure&>(**iter).set_leaf_sequence(lvl);
1542  }
1543  }
1544 
1545  if (!has_child_sequence)
1546  set_leaf_p(true);
1547  else
1548  set_leaf_p(false);
1549 
1550  DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
1551 }
1552 
1561 void
1562 Sequence::dump(ostream &strm) const
1563 {
1564  strm << DapIndent::LMarg << "Sequence::dump - ("
1565  << (void *)this << ")" << endl ;
1566  DapIndent::Indent() ;
1567  Constructor::dump(strm) ;
1568  strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number
1569  << endl ;
1570  strm << DapIndent::LMarg << "bracket notation information:" << endl ;
1571  DapIndent::Indent() ;
1572  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number
1573  << endl ;
1574  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ;
1575  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number
1576  << endl ;
1578 
1579  strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ;
1580  strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ;
1581  strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence
1582  << endl ;
1583  strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most
1584  << endl ;
1586 }
1587 
1588 } // namespace libdap
1589 
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:579
virtual void intern_data(ConstraintEvaluator &eval, DDS &dds)
Definition: Sequence.cc:995
virtual void set_in_selection(bool state)
Set the in_selection property.
Definition: Constructor.cc:625
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:1562
virtual BaseType * var(const string &name, bool exact_match=true, btp_stack *s=0)
btp_stack no longer needed; use back pointers (BaseType::get_parent())
Definition: Constructor.cc:183
Part
Names the parts of multi-section constructor data types.
Definition: BaseType.h:95
void set_unsent_data(bool usd)
Set the unsent data property.
Definition: Sequence.h:305
#define malformed_expr
Definition: Error.h:64
std::vector< BaseType * > d_vars
Definition: Constructor.h:43
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)=0
Receive data from the net.
virtual bool read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval=true)
Definition: Sequence.cc:678
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Deserialize (read from the network) the entire Sequence.
Definition: Sequence.cc:1222
std::vector< BaseType * >::iterator Vars_iter
Definition: Constructor.h:56
virtual bool is_dap2_only_type()
Definition: Sequence.cc:248
virtual BaseType * get_parent()
Definition: BaseType.cc:788
vector< BaseTypeRow * > SequenceValues
Definition: Sequence.h:72
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition: BaseType.cc:117
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Definition: Sequence.cc:793
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:908
virtual void put_opaque(char *val, unsigned int len)=0
virtual void add_var_nocopy(BaseType *bt, Part part=nil)
Definition: Constructor.cc:346
virtual BaseTypeRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: Sequence.cc:479
virtual ~Sequence()
Definition: Sequence.cc:219
void timeout_off()
Definition: DDS.cc:862
virtual void set_row_number_constraint(int start, int stop, int stride=1)
Definition: Sequence.cc:1328
Holds a structure (aggregate) type.
Definition: Structure.h:85
virtual void add_var(BaseType *bt, Part part=nil)
Definition: Constructor.cc:321
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:282
virtual string toString()
Definition: BaseType.cc:205
#define DBG2(x)
Definition: debug.h:73
virtual void set_in_selection(bool state)
Definition: BaseType.cc:755
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Constructor.cc:110
virtual void print_val_by_rows(ostream &out, string space="", bool print_decl_p=true, bool print_row_numbers=true)
Definition: Sequence.cc:1425
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
Definition: Structure.cc:224
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:1013
string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:275
bool eval_selection(DDS &dds, const string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator ans is called ...
virtual bool is_linear()
Check to see whether this variable can be printed simply.
Definition: Sequence.cc:286
virtual void intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:1143
#define DBG(x)
Definition: debug.h:58
string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:296
bool get_unsent_data()
Get the unsent data property.
Definition: Sequence.h:299
virtual void set_send_p(bool state)
Definition: BaseType.cc:652
static void Indent()
Definition: DapIndent.cc:45
Sequence(const string &n)
The Sequence constructor.
Definition: Sequence.cc:165
virtual bool read()
simple implementation of read that iterates through vars and calls read on them
Definition: Constructor.cc:389
virtual void set_leaf_sequence(int lvl=1)
Mark the Sequence which holds the leaf elements.
Definition: Sequence.cc:1519
Sequence & operator=(const Sequence &rhs)
Definition: Sequence.cc:232
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:618
Holds a sequence.
Definition: Sequence.h:172
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: Constructor.cc:583
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:643
virtual int length()
Definition: Sequence.cc:605
virtual unsigned int val2buf(void *, bool)
Loads class data.
Definition: Constructor.h:99
vector< BaseType * > BaseTypeRow
Definition: Sequence.h:69
virtual void serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
Definition: Sequence.cc:876
virtual bool is_leaf_sequence()
Definition: Sequence.cc:1489
string name() const
Returns the name of the class instance.
Definition: BaseType.cc:254
virtual string toString()
Definition: Sequence.cc:254
BaseType * m_leaf_match(const string &name, btp_stack *s=0)
Definition: Constructor.cc:208
virtual BaseType * ptr_duplicate()=0
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:220
void timeout_on()
Definition: DDS.cc:854
int get_starting_row_number()
Get the starting row number.
Definition: Sequence.cc:1281
virtual unsigned int width(bool constrained=false)
Definition: Constructor.cc:165
Evaluate a constraint expression.
virtual SequenceValues value()
Definition: Sequence.cc:501
virtual int number_of_rows()
Definition: Sequence.cc:612
void reset_row_number()
Rest the row number counter.
Definition: Sequence.cc:621
virtual unsigned int buf2val(void **)
Reads the class data.
Definition: Constructor.h:102
virtual void intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:1091
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:80
The basic data type for the DODS DAP types.
Definition: BaseType.h:199
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:512
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:470
virtual void print_one_row(ostream &out, int row, string space, bool print_row_num=false)
Definition: Sequence.cc:1370
Vars_iter var_begin()
Definition: Constructor.cc:270
virtual void intern_data_parent_part_one(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:1026
BaseType * m_exact_match(const string &name, btp_stack *s=0)
Definition: Constructor.cc:235
bool unique_names(vector< BaseType * > l, const string &var_name, const string &type_name, string &msg)
Definition: util.cc:338
Vars_iter var_end()
Definition: Constructor.cc:278
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: Sequence.cc:1456
string get_protocol() const
Definition: DataDDS.h:129
virtual bool serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
Definition: Sequence.cc:810
virtual void set_leaf_p(bool state)
Definition: Sequence.cc:1483
stack< SequenceValues * > sequence_values_stack_t
Definition: Sequence.h:217
void m_duplicate(const Sequence &s)
Definition: Sequence.cc:82
A class for error processing.
Definition: Error.h:90
virtual int get_ending_row_number()
Get the ending row number.
Definition: Sequence.cc:1314
virtual void set_send_p(bool state)
Definition: Constructor.cc:124
virtual BaseType * ptr_duplicate()
Definition: Sequence.cc:197
Holds a DAP2 DDS.
Definition: DataDDS.h:77
virtual int get_row_stride()
Get the row stride.
Definition: Sequence.cc:1297
int get_protocol_major() const
Definition: DataDDS.h:133
virtual void set_value(SequenceValues &values)
Definition: Sequence.cc:493
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Constructor.cc:134
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)=0
Prints the value of the variable.
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: BaseType.cc:1153