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 
353 // Deprecated
354 BaseType *
355 Sequence::var(const string &n, btp_stack &s)
356 {
357  string name = www2id(n);
358 
359  BaseType *btp = m_exact_match(name, &s);
360  if (btp)
361  return btp;
362 
363  return m_leaf_match(name, &s);
364 }
365 
366 BaseType *
367 Sequence::var(const string &name, bool exact_match, btp_stack *s)
368 {
369  string n = www2id(name);
370 
371  if (exact_match)
372  return m_exact_match(n, s);
373  else
374  return m_leaf_match(n, s);
375 }
376 
377 BaseType *
378 Sequence::m_leaf_match(const string &name, btp_stack *s)
379 {
380  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
381  if ((*i)->name() == name) {
382  if (s)
383  s->push(static_cast<BaseType *>(this));
384  return *i;
385  }
386  if ((*i)->is_constructor_type()) {
387  BaseType *btp = (*i)->var(name, false, s);
388  if (btp) {
389  if (s)
390  s->push(static_cast<BaseType *>(this));
391  return btp;
392  }
393  }
394  }
395 
396  return 0;
397 }
398 
399 BaseType *
400 Sequence::m_exact_match(const string &name, btp_stack *s)
401 {
402  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
403  if ((*i)->name() == name) {
404  if (s)
405  s->push(static_cast<BaseType *>(this));
406  return *i;
407  }
408  }
409 
410  string::size_type dot_pos = name.find("."); // zero-based index of `.'
411  if (dot_pos != string::npos) {
412  string aggregate = name.substr(0, dot_pos);
413  string field = name.substr(dot_pos + 1);
414 
415  BaseType *agg_ptr = var(aggregate);
416  if (agg_ptr) {
417  if (s)
418  s->push(static_cast<BaseType *>(this));
419  return agg_ptr->var(field, true, s); // recurse
420  }
421  else
422  return 0; // qualified names must be *fully* qualified
423  }
424 
425  return 0;
426 }
427 
432 BaseTypeRow *
434 {
435  if (row >= d_values.size())
436  return 0;
437  return d_values[row];
438 }
439 
446 void
448 {
449  d_values = values;
450 }
451 
456 {
457  return d_values;
458 }
459 
465 BaseType *
466 Sequence::var_value(size_t row, const string &name)
467 {
468  BaseTypeRow *bt_row_ptr = row_value(row);
469  if (!bt_row_ptr)
470  return 0;
471 
472  BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
473  BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
474  while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
475  ++bt_row_iter;
476 
477  if (bt_row_iter == bt_row_end)
478  return 0;
479  else
480  return *bt_row_iter;
481 }
482 
488 BaseType *
489 Sequence::var_value(size_t row, size_t i)
490 {
491  BaseTypeRow *bt_row_ptr = row_value(row);
492  if (!bt_row_ptr)
493  return 0;
494 
495  if (i >= bt_row_ptr->size())
496  return 0;
497 
498  return (*bt_row_ptr)[i];
499 }
500 
501 unsigned int
503 {
504  unsigned int sz = 0;
505 
506  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
507  sz += (*i)->width();
508  }
509 
510  return sz;
511 }
512 
513 // This version returns -1. Each API-specific subclass should define a more
514 // reasonable version. jhrg 5/24/96
515 
531 int
533 {
534  return -1;
535 }
536 
537 
538 int
540 {
541  return d_values.size();
542 }
543 
547 void
549 {
550  d_row_number = -1;
551 }
552 
553 // Notes:
554 // Assume that read() is implemented so that, when reading data for a nested
555 // sequence, only the outer most level is *actually* read.
556 // This is a consequence of our current (12/7/99) implementation of
557 // the JGOFS server (which is the only server to actually use nested
558 // sequences). 12/7/99 jhrg
559 //
560 // Stop assuming this. This logic is being moved into the JGOFS server
561 // itself. 6/1/2001 jhrg
562 
563 // The read() function returns a boolean value, with TRUE
564 // indicating that read() should be called again because there's
565 // more data to read, and FALSE indicating there's no more data
566 // to read. Note that this behavior is necessary to properly
567 // handle variables that contain Sequences. Jose Garcia If an
568 // error exists while reading, the implementers of the surrogate
569 // library SHOULD throw an Error object which will propagate
570 // beyond this point to to the original caller.
571 // Jose Garcia
572 
605 bool
606 Sequence::read_row(int row, DDS &dds,
607  ConstraintEvaluator &eval, bool ce_eval)
608 {
609  DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
610  if (row < d_row_number)
611  throw InternalErr("Trying to back up inside a sequence!");
612 
613  DBG2(cerr << "read_row: row number " << row
614  << ", current row " << d_row_number << endl);
615  if (row == d_row_number)
616  {
617  DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
618  return true;
619  }
620 
621  dds.timeout_on();
622 
623  int eof = 0; // Start out assuming EOF is false.
624  while (!eof && d_row_number < row) {
625  if (!read_p()) {
626  eof = (read() == false);
627  }
628 
629  // Advance the row number if ce_eval is false (we're not supposed to
630  // evaluate the selection) or both ce_eval and the selection are
631  // true.
632  if (!eof && (!ce_eval || eval.eval_selection(dds, dataset())))
633  d_row_number++;
634 
635  set_read_p(false); // ...so that the next instance will be read
636  }
637 
638  // Once we finish the above loop, set read_p to true so that the caller
639  // knows that data *has* been read. This is how the read() methods of the
640  // elements of the sequence know to not call read() but instead look for
641  // data values inside themselves.
642  set_read_p(true);
643 
644  dds.timeout_off();
645 
646  // Return true if we have valid data, false if we've read to the EOF.
647  DBG2(cerr << "Leaving Sequence::read_row for " << name()
648  << " with " << (eof == 0) << endl);
649  return eof == 0;
650 }
651 
652 // Private. This is used to process constraints on the rows of a sequence.
653 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
654 // odd-looking logic first checks if d_ending_row_number is the sentinel
655 // value of -1. If so, the sequence was not constrained by row number and
656 // this method should never return true (which indicates that we're at the
657 // end of a row-number constraint). If d_ending_row_number is not -1, then is
658 // \e i at the end point? 6/1/2001 jhrg
659 inline bool
660 Sequence::is_end_of_rows(int i)
661 {
662  return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
663 }
664 
725 bool
727  Marshaller &m, bool ce_eval)
728 {
729  DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
730 
731  // Special case leaf sequences!
732  if (is_leaf_sequence())
733  return serialize_leaf(dds, eval, m, ce_eval);
734  else
735  return serialize_parent_part_one(dds, eval, m);
736 }
737 
738 // We know this is not a leaf Sequence. That means that this Sequence holds
739 // another Sequence as one of its fields _and_ that child Sequence triggers
740 // the actual transmission of values.
741 
742 bool
745 {
746  DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
747 
748  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
749 
750  // read_row returns true if valid data was read, false if the EOF was
751  // found. 6/1/2001 jhrg
752  // Since this is a parent sequence, read the row ignoring the CE (all of
753  // the CE clauses will be evaluated by the leaf sequence).
754  bool status = read_row(i, dds, eval, false);
755  DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
756 
757  while (status && !is_end_of_rows(i)) {
758  i += d_row_stride;
759 
760  // DBG(cerr << "Writing Start of Instance marker" << endl);
761  // write_start_of_instance(sink);
762 
763  // In this loop serialize will signal an error with an exception.
764  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
765  // Only call serialize for child Sequences; the leaf sequence
766  // will trigger the transmission of values for its parents (this
767  // sequence and maybe others) once it gets soem valid data to
768  // send.
769  // Note that if the leaf sequence has no variables in the current
770  // projection, its serialize() method will never be called and that's
771  // the method that triggers actually sending values. Thus the leaf
772  // sequence must be the lowest level sequence with values whose send_p
773  // property is true.
774  if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c)
775  (*iter)->serialize(eval, dds, m);
776  }
777 
778  set_read_p(false); // ...so this will read the next instance
779 
780  status = read_row(i, dds, eval, false);
781  DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
782  }
783  // Reset current row number for next nested sequence element.
784  d_row_number = -1;
785 
786  // Always write the EOS marker? 12/23/04 jhrg
787  // Yes. According to DAP2, a completely empty response is signalled by
788  // a return value of only the EOS marker for the outermost sequence.
789  if (d_top_most || d_wrote_soi) {
790  DBG(cerr << "Writing End of Sequence marker" << endl);
791  write_end_of_sequence(m);
792  d_wrote_soi = false;
793  }
794 
795  return true; // Signal errors with exceptions.
796 }
797 
798 // If we are here then we know that this is 'parent sequence' and that the
799 // leaf seq has found valid data to send. We also know that
800 // serialize_parent_part_one has been called so data are in the instance's
801 // fields. This is wheree we send data. Whereas ..._part_one() contains a
802 // loop to iterate over all of rows in a parent sequence, this does not. This
803 // method assumes that the serialize_leaf() will call it each time it needs
804 // to be called.
805 //
806 // NB: This code only works if the child sequences appear after all other
807 // variables.
808 void
811 {
812  DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
813 
814  BaseType *btp = get_parent();
815  if (btp && btp->type() == dods_sequence_c)
816  dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
817 
818  if (d_unsent_data) {
819  DBG(cerr << "Writing Start of Instance marker" << endl);
820  d_wrote_soi = true;
821  write_start_of_instance(m);
822 
823  // In this loop serialize will signal an error with an exception.
824  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
825  // Send all the non-sequence variables
826  DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
827  << (*iter)->name() << endl);
828  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
829  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
830  (*iter)->serialize(eval, dds, m, false);
831  }
832  }
833 
834  d_unsent_data = false; // read should set this.
835  }
836 }
837 
838 // This code is only run by a leaf sequence. Note that a one level sequence
839 // is also a leaf sequence.
840 bool
842  ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
843 {
844  DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
845  int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
846 
847  // read_row returns true if valid data was read, false if the EOF was
848  // found. 6/1/2001 jhrg
849  bool status = read_row(i, dds, eval, ce_eval);
850  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
851 
852  // Once the first valid (satisfies the CE) row of the leaf sequence has
853  // been read, we know we're going to send data. Send the current instance
854  // of the parent/ancestor sequences now, if there are any. We only need
855  // to do this once, hence it's not inside the while loop, but we only
856  // send the parent seq data _if_ there's data in the leaf to send, that's
857  // why we wait until after the first call to read_row() here in the leaf
858  // sequence.
859  //
860  // NB: It's important to only call serialize_parent_part_two() for a
861  // Sequence that really is the parent of a leaf sequence. The fancy cast
862  // will throw and exception if btp is not a Sequence, but doesn't test
863  // that it's a parent sequence as we've defined them here.
864  if (status && !is_end_of_rows(i)) {
865  BaseType *btp = get_parent();
866  if (btp && btp->type() == dods_sequence_c)
867  dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds,
868  eval, m);
869  }
870 
871  d_wrote_soi = false;
872  while (status && !is_end_of_rows(i)) {
873  i += d_row_stride;
874 
875  DBG(cerr << "Writing Start of Instance marker" << endl);
876  d_wrote_soi = true;
877  write_start_of_instance(m);
878 
879  // In this loop serialize will signal an error with an exception.
880  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
881  DBG(cerr << "Sequence::serialize_leaf(), serializing "
882  << (*iter)->name() << endl);
883  if ((*iter)->send_p()) {
884  DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
885  (*iter)->serialize(eval, dds, m, false);
886  }
887  }
888 
889  set_read_p(false); // ...so this will read the next instance
890 
891  status = read_row(i, dds, eval, ce_eval);
892  DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
893  }
894 
895  // Only write the EOS marker if there's a matching Start Of Instnace
896  // Marker in the stream.
897  if (d_wrote_soi || d_top_most) {
898  DBG(cerr << "Writing End of Sequence marker" << endl);
899  write_end_of_sequence(m);
900  }
901 
902  return true; // Signal errors with exceptions.
903 }
904 
927 void
929 {
930  DBG(cerr << "Sequence::intern_data - for " << name() << endl);
931  DBG2(cerr << " intern_data, values: " << &d_values << endl);
932 
933  // Why use a stack instead of return values? We need the stack because
934  // Sequences neted three of more levels deep will loose the middle
935  // instances when the intern_data_parent_part_two() code is run.
936  sequence_values_stack_t sequence_values_stack;
937 
938  DBG2(cerr << " pushing d_values of " << name() << " (" << &d_values
939  << ") on stack; size: " << sequence_values_stack.size() << endl);
940  sequence_values_stack.push(&d_values);
941 
942  intern_data_private(eval, dds, sequence_values_stack);
943 }
944 
945 void
947  DDS &dds,
948  sequence_values_stack_t &sequence_values_stack)
949 {
950  DBG(cerr << "Entering intern_data_private for " << name() << endl);
951 
952  if (is_leaf_sequence())
953  intern_data_for_leaf(dds, eval, sequence_values_stack);
954  else
955  intern_data_parent_part_one(dds, eval, sequence_values_stack);
956 }
957 
958 void
960  ConstraintEvaluator & eval,
962  sequence_values_stack)
963 {
964  DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
965 
966  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
967 
968  // read_row returns true if valid data was read, false if the EOF was
969  // found. 6/1/2001 jhrg
970  // Since this is a parent sequence, read the row ignoring the CE (all of
971  // the CE clauses will be evaluated by the leaf sequence).
972  bool status = read_row(i, dds, eval, false);
973 
974  // Grab the current size of the value stack. We do this because it is
975  // possible that no nested sequences for this row happened to be
976  // selected because of a constract evaluation or the last row is not
977  // selected because of a constraint evaluation. In either case, no
978  // nested sequence d_values are pused onto the stack, so there is
979  // nothing to pop at the end of this function. pcw 07/14/08
980  SequenceValues::size_type orig_stack_size = sequence_values_stack.size() ;
981 
982  while (status
983  && (get_ending_row_number() == -1
984  || i <= get_ending_row_number()))
985  {
986  i += get_row_stride();
987  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
988  if ((*iter)->send_p()) {
989  switch ((*iter)->type()) {
990  case dods_sequence_c:
991  dynamic_cast<Sequence&>(**iter).intern_data_private(
992  eval, dds, sequence_values_stack);
993  break;
994 
995  default:
996  (*iter)->intern_data(eval, dds);
997  break;
998  }
999  }
1000  }
1001 
1002  set_read_p(false); // ...so this will read the next instance
1003 
1004  status = read_row(i, dds, eval, false);
1005  }
1006 
1007  // Reset current row number for next nested sequence element.
1008  reset_row_number();
1009 
1010  // if the size of the stack is larger than the original size (retrieved
1011  // above) then pop the top set of d_values from the stack. If it's the
1012  // same, then no nested sequences, or possible the last nested sequence,
1013  // were pushed onto the stack, so there is nothing to pop.
1014  if( sequence_values_stack.size() > orig_stack_size )
1015  {
1016  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
1017  << ") off stack; size: " << sequence_values_stack.size() << endl);
1018  sequence_values_stack.pop();
1019  }
1020  DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
1021 }
1022 
1023 void
1025  ConstraintEvaluator &eval,
1026  sequence_values_stack_t &sequence_values_stack)
1027 {
1028  DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
1029 
1030  BaseType *btp = get_parent();
1031  if (btp && btp->type() == dods_sequence_c) {
1032  dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(
1033  dds, eval, sequence_values_stack);
1034  }
1035 
1036  DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl);
1037  SequenceValues *values = sequence_values_stack.top();
1038  DBG2(cerr << " using values = " << (void *)values << endl);
1039 
1040  if (get_unsent_data()) {
1041  BaseTypeRow *row_data = new BaseTypeRow;
1042 
1043  // In this loop transfer_data will signal an error with an exception.
1044  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1045 
1046  if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
1047  row_data->push_back((*iter)->ptr_duplicate());
1048  }
1049  else if ((*iter)->send_p()) { //Sequence; must be the last variable
1050  Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
1051  if (!tmp)
1052  throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
1053  row_data->push_back(tmp);
1054  DBG2(cerr << " pushing d_values of " << tmp->name()
1055  << " (" << &(tmp->d_values)
1056  << ") on stack; size: " << sequence_values_stack.size()
1057  << endl);
1058  // This pushes the d_values field of the newly created leaf
1059  // Sequence onto the stack. The code then returns to intern
1060  // _data_for_leaf() where this value will be used.
1061  sequence_values_stack.push(&(tmp->d_values));
1062  }
1063  }
1064 
1065  DBG2(cerr << " pushing values for " << name()
1066  << " to " << values << endl);
1067  values->push_back(row_data);
1068  set_unsent_data(false);
1069  }
1070  DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
1071 }
1072 
1073 void
1075  ConstraintEvaluator &eval,
1076  sequence_values_stack_t &sequence_values_stack)
1077 {
1078  DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
1079 
1080  int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
1081 
1082  DBG2(cerr << " reading row " << i << endl);
1083  bool status = read_row(i, dds, eval, true);
1084  DBG2(cerr << " status: " << status << endl);
1085  DBG2(cerr << " ending row number: " << get_ending_row_number() << endl);
1086 
1087  if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
1088  BaseType *btp = get_parent();
1089  if (btp && btp->type() == dods_sequence_c) {
1090  // This call will read the values for the parent sequences and
1091  // then allocate a new instance for the leaf and push that onto
1092  // the stack.
1093  dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(
1094  dds, eval, sequence_values_stack);
1095  }
1096 
1097  // intern_data_parent_part_two pushes the d_values field of the leaf
1098  // onto the stack, so this operation grabs that value and then loads
1099  // data into it.
1100  SequenceValues *values = sequence_values_stack.top();
1101  DBG2(cerr << " using values = " << values << endl);
1102 
1103  while (status && (get_ending_row_number() == -1
1104  || i <= get_ending_row_number())) {
1105  i += get_row_stride();
1106 
1107  // Copy data from the object's fields to this new BaeTypeRow instance
1108  BaseTypeRow *row_data = new BaseTypeRow;
1109  for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
1110  if ((*iter)->send_p()) {
1111  row_data->push_back((*iter)->ptr_duplicate());
1112  }
1113  }
1114 
1115  DBG2(cerr << " pushing values for " << name()
1116  << " to " << values << endl);
1117  // Save the row_data to values().
1118  values->push_back(row_data);
1119 
1120  set_read_p(false); // ...so this will read the next instance
1121  // Read the ith row into this object's fields
1122  status = read_row(i, dds, eval, true);
1123  }
1124 
1125  DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
1126  << ") off stack; size: " << sequence_values_stack.size() << endl);
1127  sequence_values_stack.pop();
1128  }
1129  DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
1130 }
1131 
1152 bool
1154 {
1155  DataDDS *dd = dynamic_cast<DataDDS *>(dds);
1156  if (!dd)
1157  throw InternalErr("Expected argument 'dds' to be a DataDDS!");
1158 
1159  DBG2(cerr << "Reading from server/protocol version: "
1160  << dd->get_protocol_major() << "." << dd->get_protocol_minor()
1161  << endl);
1162 
1163  // Check for old servers.
1164  if (dd->get_protocol_major() < 2) {
1165  throw Error(string("The protocl version (") + dd->get_protocol()
1166  + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
1167  }
1168 
1169  while (true) {
1170  // Grab the sequence stream's marker.
1171  unsigned char marker = read_marker(um);
1172  if (is_end_of_sequence(marker))
1173  break; // EXIT the while loop here!!!
1174  else if (is_start_of_instance(marker)) {
1175  d_row_number++;
1176  DBG2(cerr << "Reading row " << d_row_number << " of "
1177  << name() << endl);
1178  BaseTypeRow *bt_row_ptr = new BaseTypeRow;
1179  // Read the instance's values, building up the row
1180  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
1181  BaseType *bt_ptr = (*iter)->ptr_duplicate();
1182  bt_ptr->deserialize(um, dds, reuse);
1183  DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
1184  << bt_ptr << ") = ");
1185  DBG2(bt_ptr->print_val(stderr, ""));
1186  bt_row_ptr->push_back(bt_ptr);
1187  }
1188  // Append this row to those accumulated.
1189  d_values.push_back(bt_row_ptr);
1190  }
1191  else
1192  throw Error("I could not read the expected Sequence data stream marker!");
1193  };
1194 
1195  return false;
1196 }
1197 
1198 // Return the current row number.
1199 
1211 int
1213 {
1214  return d_starting_row_number;
1215 }
1216 
1227 int
1229 {
1230  return d_row_stride;
1231 }
1232 
1244 int
1246 {
1247  return d_ending_row_number;
1248 }
1249 
1258 void
1259 Sequence::set_row_number_constraint(int start, int stop, int stride)
1260 {
1261  if (stop < start)
1262  throw Error(malformed_expr, "Starting row number must precede the ending row number.");
1263 
1264  d_starting_row_number = start;
1265  d_row_stride = stride;
1266  d_ending_row_number = stop;
1267 }
1268 
1271 unsigned int
1272 Sequence::val2buf(void *, bool)
1273 {
1274  throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation.");
1275  return sizeof(Sequence);
1276 }
1277 
1282 unsigned int
1284 {
1285  throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()");
1286  return sizeof(Sequence);
1287 }
1288 
1289 #if FILE_METHODS
1290 void
1291 Sequence::print_one_row(FILE *out, int row, string space,
1292  bool print_row_num)
1293 {
1294  if (print_row_num)
1295  fprintf(out, "\n%s%d: ", space.c_str(), row) ;
1296 
1297  fprintf(out, "{ ") ;
1298 
1299  int elements = element_count() - 1;
1300  int j;
1301  BaseType *bt_ptr;
1302  // Print first N-1 elements of the row.
1303  for (j = 0; j < elements; ++j) {
1304  bt_ptr = var_value(row, j);
1305  if (bt_ptr) { // data
1306  if (bt_ptr->type() == dods_sequence_c)
1307  dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
1308  (out, space + " ", false, print_row_num);
1309  else
1310  bt_ptr->print_val(out, space, false);
1311  fprintf(out, ", ") ;
1312  }
1313  }
1314 
1315  // Print Nth element; end with a `}.'
1316  bt_ptr = var_value(row, j);
1317  if (bt_ptr) { // data
1318  if (bt_ptr->type() == dods_sequence_c)
1319  dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
1320  (out, space + " ", false, print_row_num);
1321  else
1322  bt_ptr->print_val(out, space, false);
1323  }
1324 
1325  fprintf(out, " }") ;
1326 }
1327 #endif
1328 
1329 void
1330 Sequence::print_one_row(ostream &out, int row, string space,
1331  bool print_row_num)
1332 {
1333  if (print_row_num)
1334  out << "\n" << space << row << ": " ;
1335 
1336  out << "{ " ;
1337 
1338  int elements = element_count();
1339  int j = 0;
1340  BaseType *bt_ptr = 0;
1341 
1342  // This version of print_one_row() works for both data read with
1343  // deserialize(), where each variable is assumed to have valid data, and
1344  // intern_data(), where some/many variables do not. Because of that, it's
1345  // not correct to assume that all of the elements will be printed, which
1346  // is what the old code did.
1347  // Print the first value
1348  while (j < elements && !bt_ptr) {
1349  bt_ptr = var_value(row, j++);
1350  if (bt_ptr) { // data
1351  if (bt_ptr->type() == dods_sequence_c)
1352  dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
1353  (out, space + " ", false, print_row_num);
1354  else
1355  bt_ptr->print_val(out, space, false);
1356  }
1357  }
1358 
1359  // Print the remaining values
1360  while (j < elements) {
1361  bt_ptr = var_value(row, j++);
1362  if (bt_ptr) { // data
1363  out << ", ";
1364  if (bt_ptr->type() == dods_sequence_c)
1365  dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
1366  (out, space + " ", false, print_row_num);
1367  else
1368  bt_ptr->print_val(out, space, false);
1369  }
1370  }
1371 
1372  out << " }" ;
1373 }
1374 
1375 #if FILE_METHODS
1376 void
1377 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p,
1378  bool print_row_numbers)
1379 {
1380  if (print_decl_p) {
1381  print_decl(out, space, false);
1382  fprintf(out, " = ") ;
1383  }
1384 
1385  fprintf(out, "{ ") ;
1386 
1387  int rows = number_of_rows() - 1;
1388  int i;
1389  for (i = 0; i < rows; ++i) {
1390  print_one_row(out, i, space, print_row_numbers);
1391  fprintf(out, ", ") ;
1392  }
1393  print_one_row(out, i, space, print_row_numbers);
1394 
1395  fprintf(out, " }") ;
1396 
1397  if (print_decl_p)
1398  fprintf(out, ";\n") ;
1399 }
1400 #endif
1401 
1402 void
1403 Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p,
1404  bool print_row_numbers)
1405 {
1406  if (print_decl_p) {
1407  print_decl(out, space, false);
1408  out << " = " ;
1409  }
1410 
1411  out << "{ " ;
1412 
1413  int rows = number_of_rows() - 1;
1414  int i;
1415  for (i = 0; i < rows; ++i) {
1416  print_one_row(out, i, space, print_row_numbers);
1417  out << ", " ;
1418  }
1419  print_one_row(out, i, space, print_row_numbers);
1420 
1421  out << " }" ;
1422 
1423  if (print_decl_p)
1424  out << ";\n" ;
1425 }
1426 
1427 #if FILE_METHODS
1428 void
1429 Sequence::print_val(FILE *out, string space, bool print_decl_p)
1430 {
1431  print_val_by_rows(out, space, print_decl_p, false);
1432 }
1433 #endif
1434 
1435 void
1436 Sequence::print_val(ostream &out, string space, bool print_decl_p)
1437 {
1438  print_val_by_rows(out, space, print_decl_p, false);
1439 }
1440 
1441 
1442 bool
1443 Sequence::check_semantics(string &msg, bool all)
1444 {
1445  if (!BaseType::check_semantics(msg))
1446  return false;
1447 
1448  if (!unique_names(_vars, name(), type_name(), msg))
1449  return false;
1450 
1451  if (all)
1452  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
1453  if (!(*i)->check_semantics(msg, true)) {
1454  return false;
1455  }
1456  }
1457 
1458  return true;
1459 }
1460 
1461 void
1463 {
1464  d_leaf_sequence = state;
1465 }
1466 
1467 bool
1469 {
1470  return d_leaf_sequence;
1471 }
1472 
1497 void
1499 {
1500  bool has_child_sequence = false;
1501 
1502  if (lvl == 1) d_top_most = true;
1503 
1504  DBG2(cerr << "Processing sequence " << name() << endl);
1505 
1506  for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
1507  // About the test for send_p(): Only descend into a sequence if it has
1508  // fields that might be sent. Thus if, in a two-level sequence, nothing
1509  // in the lower level is to be sent, the upper level is marked as the
1510  // leaf sequence. This ensures that values _will_ be sent (see the comment
1511  // in serialize_leaf() and serialize_parent_part_one()).
1512  if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
1513  if (has_child_sequence)
1514  throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
1515 
1516  has_child_sequence = true;
1517  dynamic_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
1518  }
1519  else if ((*iter)->type() == dods_structure_c) {
1520  dynamic_cast<Structure&>(**iter).set_leaf_sequence(lvl);
1521  }
1522  }
1523 
1524  if (!has_child_sequence)
1525  set_leaf_p(true);
1526  else
1527  set_leaf_p(false);
1528 
1529  DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
1530 }
1531 
1540 void
1541 Sequence::dump(ostream &strm) const
1542 {
1543  strm << DapIndent::LMarg << "Sequence::dump - ("
1544  << (void *)this << ")" << endl ;
1545  DapIndent::Indent() ;
1546  Constructor::dump(strm) ;
1547  strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number
1548  << endl ;
1549  strm << DapIndent::LMarg << "bracket notation information:" << endl ;
1550  DapIndent::Indent() ;
1551  strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number
1552  << endl ;
1553  strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ;
1554  strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number
1555  << endl ;
1557 
1558  strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ;
1559  strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ;
1560  strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence
1561  << endl ;
1562  strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most
1563  << endl ;
1565 }
1566 
1567 } // namespace libdap
1568 
virtual bool read()
Read data into a local buffer.
Definition: BaseType.cc:790
int get_protocol_minor() const
Definition: DataDDS.h:137
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:444
string name() const
Returns the name of the class instance.
Definition: BaseType.cc:210
virtual void intern_data(ConstraintEvaluator &eval, DDS &dds)
Definition: Sequence.cc:928
static void UnIndent()
Definition: DapIndent.cc:49
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:54
Part
Names the parts of multi-section constructor data types.
Definition: BaseType.h:98
string get_protocol() const
Definition: DataDDS.h:129
bool unique_names(vector< BaseType *> l, const string &var_name, const string &type_name, string &msg)
Definition: util.cc:119
void set_unsent_data(bool usd)
Set the unsent data property.
Definition: Sequence.h:301
#define malformed_expr
Definition: Error.h:64
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:606
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Deserialize (read from the network) the entire Sequence.
Definition: Sequence.cc:1153
std::vector< BaseType * > _vars
Definition: Constructor.h:48
std::vector< BaseType * >::iterator Vars_iter
Definition: Constructor.h:61
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Sequence.cc:258
virtual BaseType * get_parent()
Definition: BaseType.cc:655
vector< BaseTypeRow * > SequenceValues
Definition: Sequence.h:73
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Definition: Sequence.cc:726
virtual bool serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
Definition: Sequence.cc:841
virtual BaseTypeRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: Sequence.cc:433
virtual ~Sequence()
Definition: Sequence.cc:216
void timeout_off()
Definition: DDS.cc:823
virtual void set_row_number_constraint(int start, int stop, int stride=1)
Definition: Sequence.cc:1259
Holds a structure (aggregate) type.
Definition: Structure.h:100
virtual string toString()
Definition: BaseType.cc:161
#define DBG2(x)
Definition: debug.h:73
virtual void set_in_selection(bool state)
Definition: BaseType.cc:625
virtual void print_val_by_rows(ostream &out, string space="", bool print_decl_p=true, bool print_row_numbers=true)
Definition: Sequence.cc:1403
stack< BaseType * > btp_stack
Definition: BaseType.h:214
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:638
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
Definition: Structure.cc:205
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:946
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:272
virtual void intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:1074
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Returns a pointer to a member of a constructor class.
Definition: BaseType.cc:662
#define DBG(x)
Definition: debug.h:58
bool get_unsent_data()
Get the unsent data property.
Definition: Sequence.h:295
virtual void set_send_p(bool state)
Definition: BaseType.cc:517
static void Indent()
Definition: DapIndent.cc:43
Sequence(const string &n)
The Sequence constructor.
Definition: Sequence.cc:162
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:238
virtual void set_leaf_sequence(int lvl=1)
Mark the Sequence which holds the leaf elements.
Definition: Sequence.cc:1498
Sequence & operator=(const Sequence &rhs)
Definition: Sequence.cc:229
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:483
Holds a sequence.
Definition: Sequence.h:173
virtual unsigned int buf2val(void **val)
Definition: Sequence.cc:1283
virtual void set_in_selection(bool state)
Definition: Sequence.cc:321
virtual int length()
Definition: Sequence.cc:532
vector< BaseType * > BaseTypeRow
Definition: Sequence.h:70
virtual void serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
Definition: Sequence.cc:809
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:502
virtual bool is_leaf_sequence()
Definition: Sequence.cc:1468
virtual string toString()
Definition: Sequence.cc:242
virtual BaseType * ptr_duplicate()=0
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:214
void timeout_on()
Definition: DDS.cc:815
int get_starting_row_number()
Get the starting row number.
Definition: Sequence.cc:1212
Evaluate a constraint expression.
virtual SequenceValues value()
Definition: Sequence.cc:455
virtual int number_of_rows()
Definition: Sequence.cc:539
void reset_row_number()
Rest the row number counter.
Definition: Sequence.cc:548
virtual void intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:1024
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:78
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Sequence.cc:311
virtual bool check_semantics(string &msg, bool all=false)
Compare an object&#39;s current state with the semantics of its type.
Definition: Sequence.cc:1443
The basic data type for the DODS DAP types.
Definition: BaseType.h:190
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:53
virtual unsigned int val2buf(void *val, bool reuse=false)
Definition: Sequence.cc:1272
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:466
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:361
string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:252
virtual void print_one_row(ostream &out, int row, string space, bool print_row_num=false)
Definition: Sequence.cc:1330
virtual void add_var(BaseType *, Part part=nil)
Adds a variable to the Sequence.
Definition: Sequence.cc:340
Vars_iter var_begin()
Definition: Constructor.cc:101
virtual void intern_data_parent_part_one(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
Definition: Sequence.cc:959
Vars_iter var_end()
Definition: Constructor.cc:295
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: Sequence.cc:1436
int get_protocol_major() const
Definition: DataDDS.h:133
virtual bool serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
Definition: Sequence.cc:743
virtual void set_leaf_p(bool state)
Definition: Sequence.cc:1462
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Sequence.cc:1541
stack< SequenceValues * > sequence_values_stack_t
Definition: Sequence.h:219
A class for error processing.
Definition: Error.h:90
virtual int get_ending_row_number()
Get the ending row number.
Definition: Sequence.cc:1245
virtual unsigned int width()
Returns the size of the class instance data.
Definition: Sequence.cc:502
virtual void set_send_p(bool state)
Definition: Sequence.cc:301
virtual BaseType * ptr_duplicate()
Definition: Sequence.cc:194
Holds a DAP2 DDS.
Definition: DataDDS.h:77
virtual int get_row_stride()
Get the row stride.
Definition: Sequence.cc:1228
virtual BaseType * var(const string &name, bool exact_match=true, btp_stack *s=0)
Returns a pointer to a member of a constructor class.
Definition: Sequence.cc:367
virtual void set_value(SequenceValues &values)
Definition: Sequence.cc:447
string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:231
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&#39;s current state with the semantics of its type.
Definition: BaseType.cc:1036