libdap Updated for version 3.18.1
Sequence.cc
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2002,2003 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
25// (c) COPYRIGHT URI/MIT 1994-1999
26// Please read the full copyright statement in the file COPYRIGHT_URI.
27//
28// Authors:
29// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
30
31// Implementation for the class Structure
32//
33// jhrg 9/14/94
34
35#include "config.h"
36
37//#define DODS_DEBUG
38//#define DODS_DEBUG2
39
40#include <algorithm>
41#include <string>
42#include <sstream>
43
44#include "Byte.h"
45#include "Int16.h"
46#include "UInt16.h"
47#include "Int32.h"
48#include "UInt32.h"
49#include "Float32.h"
50#include "Float64.h"
51#include "Str.h"
52#include "Url.h"
53#include "Array.h"
54#include "Structure.h"
55#include "Sequence.h"
56#include "Grid.h"
57
58#include "Marshaller.h"
59#include "UnMarshaller.h"
60
61#include "debug.h"
62#include "Error.h"
63#include "InternalErr.h"
64#include "Sequence.h"
65#include "DDS.h"
66#include "DataDDS.h"
67#include "util.h"
68#include "InternalErr.h"
69#include "escaping.h"
70
71#include "D4Attributes.h"
72#include "D4Sequence.h"
73#include "D4Group.h"
74#include "Constructor.h"
75#include "DMR.h"
76
77#undef CLEAR_LOCAL_DATA
78
79using namespace std;
80
81namespace libdap {
82
83static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
84static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
85
86// Private member functions
87
88void Sequence::m_duplicate(const Sequence &s)
89{
90 DBG(cerr << "In Sequence::m_duplicate" << endl);
91
92 d_row_number = s.d_row_number;
93 d_starting_row_number = s.d_starting_row_number;
94 d_ending_row_number = s.d_ending_row_number;
95 d_row_stride = s.d_row_stride;
96 d_leaf_sequence = s.d_leaf_sequence;
97 d_unsent_data = s.d_unsent_data;
98 d_wrote_soi = s.d_wrote_soi;
99 d_top_most = s.d_top_most;
100
101 Sequence &cs = const_cast<Sequence &>(s);
102
103 // Copy the BaseType objects used to hold values.
104 for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin(); rows_iter != cs.d_values.end(); rows_iter++) {
105 // Get the current BaseType Row
106 BaseTypeRow *src_bt_row_ptr = *rows_iter;
107 // Create a new row.
108 BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow;
109 // Copy the BaseType objects from a row to new BaseType objects.
110 // Push new BaseType objects onto new row.
111 for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin(); bt_row_iter != src_bt_row_ptr->end();
112 bt_row_iter++) {
113 BaseType *src_bt_ptr = *bt_row_iter;
114 BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate();
115 dest_bt_row_ptr->push_back(dest_bt_ptr);
116 }
117 // Push new row onto d_values.
118 d_values.push_back(dest_bt_row_ptr);
119 }
120}
121
122static void write_end_of_sequence(Marshaller &m)
123{
124 m.put_opaque((char *) &end_of_sequence, 1);
125}
126
127static void write_start_of_instance(Marshaller &m)
128{
129 m.put_opaque((char *) &start_of_instance, 1);
130}
131
132static unsigned char read_marker(UnMarshaller &um)
133{
134 unsigned char marker;
135 um.get_opaque((char *) &marker, 1);
136
137 return marker;
138}
139
140static bool is_start_of_instance(unsigned char marker)
141{
142 return (marker == start_of_instance);
143}
144
145static bool is_end_of_sequence(unsigned char marker)
146{
147 return (marker == end_of_sequence);
148}
149
150// Public member functions
151
160Sequence::Sequence(const string &n) :
161 Constructor(n, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(
162 -1), d_unsent_data(false), d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
163{
164}
165
176Sequence::Sequence(const string &n, const string &d) :
177 Constructor(n, d, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1),
178 d_row_stride(1), d_ending_row_number(-1), d_unsent_data(false),
179 d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
180{
181}
182
185 Constructor(rhs)
186{
187 m_duplicate(rhs);
188}
189
190BaseType *
192{
193 return new Sequence(*this);
194}
195
210BaseType *
212{
213 D4Sequence *dest = new D4Sequence(name());
214
216
217 dest->set_length(-1);
218 dest->set_parent(container);
219
220 return dest;
221}
222
223static inline void delete_bt(BaseType *bt_ptr)
224{
225 delete bt_ptr;
226 bt_ptr = 0;
227}
228
229static inline void delete_rows(BaseTypeRow *bt_row_ptr)
230{
231 for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
232
233 delete bt_row_ptr;
234 bt_row_ptr = 0;
235}
236
237Sequence::~Sequence()
238{
240}
241
243{
244 if (!d_values.empty()) {
245 for_each(d_values.begin(), d_values.end(), delete_rows);
246 d_values.resize(0);
247 }
248
249 set_read_p(false);
250}
251
252Sequence &
253Sequence::operator=(const Sequence &rhs)
254{
255 if (this == &rhs) return *this;
256
257 dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
258
259 m_duplicate(rhs);
260
261 return *this;
262}
263
268{
269 return true;
270}
271
273{
274 ostringstream oss;
275
276 oss << BaseType::toString();
277
278 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
279 oss << (*i)->toString();
280 }
281
282 oss << endl;
283
284 return oss.str();
285}
286
288{
289 bool linear = true;
290 bool seq_found = false;
291 for (Vars_iter iter = d_vars.begin(); linear && iter != d_vars.end(); iter++) {
292 if ((*iter)->type() == dods_sequence_c) {
293 // A linear sequence cannot have more than one child seq. at any
294 // one level. If we've already found a seq at this level, return
295 // false.
296 if (seq_found) {
297 linear = false;
298 break;
299 }
300 seq_found = true;
301 linear = static_cast<Sequence *>((*iter))->is_linear();
302 }
303 else if ((*iter)->type() == dods_structure_c) {
304 linear = static_cast<Structure*>((*iter))->is_linear();
305 }
306 else {
307 // A linear sequence cannot have Arrays, Lists or Grids.
308 linear = (*iter)->is_simple_type();
309 }
310 }
311
312 return linear;
313}
314
321{
322 if (row >= d_values.size()) return 0; //nullptr
323 return d_values[row];
324}
325
333{
334 d_values = values;
335}
336
340{
341 return d_values;
342}
343
348{
349 return d_values;
350}
351
357BaseType *
358Sequence::var_value(size_t row, const string &name)
359{
360 BaseTypeRow *bt_row_ptr = row_value(row);
361 if (!bt_row_ptr) return 0;
362
363 BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
364 BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
365 while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
366 ++bt_row_iter;
367
368 if (bt_row_iter == bt_row_end)
369 return 0;
370 else
371 return *bt_row_iter;
372}
373
379BaseType *
380Sequence::var_value(size_t row, size_t i)
381{
382 BaseTypeRow *bt_row_ptr = row_value(row);
383 if (!bt_row_ptr) return 0;
384
385 if (i >= bt_row_ptr->size()) return 0;
386
387 return (*bt_row_ptr)[i];
388}
389
390// This version returns -1. Each API-specific subclass should define a more
391// reasonable version. jhrg 5/24/96
392
409{
410 return -1;
411}
412
413// Hmmm. how is this different from length()?
414int Sequence::number_of_rows() const
415{
416 return d_values.size();
417}
418
423{
424 d_row_number = -1;
425}
426
433{
435
436 if (recur)
437 for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i)
438 if ((*i)->type() == dods_sequence_c)
439 reset_row_number(true);
440}
441
442// Notes:
443// Assume that read() is implemented so that, when reading data for a nested
444// sequence, only the outer most level is *actually* read.
445// This is a consequence of our current (12/7/99) implementation of
446// the JGOFS server (which is the only server to actually use nested
447// sequences). 12/7/99 jhrg
448//
449// Stop assuming this. This logic is being moved into the JGOFS server
450// itself. 6/1/2001 jhrg
451
452// The read() function returns a boolean value, with TRUE
453// indicating that read() should be called again because there's
454// more data to read, and FALSE indicating there's no more data
455// to read. Note that this behavior is necessary to properly
456// handle variables that contain Sequences. Jose Garcia If an
457// error exists while reading, the implementers of the surrogate
458// library SHOULD throw an Error object which will propagate
459// beyond this point to to the original caller.
460// Jose Garcia
461
494bool Sequence::read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval)
495{
496 DBG2(cerr << "Entering Sequence::read_row for " << name() << ", row number " << row << ", current row " << d_row_number << endl);
497 if (row < d_row_number) throw InternalErr("Trying to back up inside a sequence!");
498
499 if (row == d_row_number) {
500 DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl);
501 return false;
502 }
503
504 bool eof = false; // Start out assuming EOF is false.
505 while (!eof && d_row_number < row) {
506 if (!read_p()) {
507 // jhrg original version from 10/9/13 : eof = (read() == false);
508 eof = read();
509 }
510
511 // Advance the row number if ce_eval is false (we're not supposed to
512 // evaluate the selection) or both ce_eval and the selection are
513 // true.
514 if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) d_row_number++;
515
516 set_read_p(false); // ...so that the next instance will be read
517 }
518
519 // Once we finish the above loop, set read_p to true so that the caller
520 // knows that data *has* been read. This is how the read() methods of the
521 // elements of the sequence know to not call read() but instead look for
522 // data values inside themselves.
523 set_read_p(true);
524
525 // Return true if we have valid data, false if we've read to the EOF.
526 DBG2(cerr << "Leaving Sequence::read_row for " << name() << " with eof: " << eof << endl);
527 return !eof; // jhrg 10/10/13 was: eof == 0;
528}
529
530// Private. This is used to process constraints on the rows of a sequence.
531// Starting with 3.2 we support constraints like Sequence[10:2:20]. This
532// odd-looking logic first checks if d_ending_row_number is the sentinel
533// value of -1. If so, the sequence was not constrained by row number and
534// this method should never return true (which indicates that we're at the
535// end of a row-number constraint). If d_ending_row_number is not -1, then is
536// \e i at the end point? 6/1/2001 jhrg
537inline bool Sequence::is_end_of_rows(int i)
538{
539 return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
540}
541
602bool Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval)
603{
604 // Special case leaf sequences!
605 bool status = false;
606
607 if (is_leaf_sequence())
608 status = serialize_leaf(dds, eval, m, ce_eval);
609 else
610 status = serialize_parent_part_one(dds, eval, m);
611
612 return status;
613}
614
615// We know this is not a leaf Sequence. That means that this Sequence holds
616// another Sequence as one of its fields _and_ that child Sequence triggers
617// the actual transmission of values.
618
619bool Sequence::serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
620{
621 DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
622
623 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
624
625 // read_row returns true if valid data was read, false if the EOF was
626 // found. 6/1/2001 jhrg
627 // Since this is a parent sequence, read the row ignoring the CE (all of
628 // the CE clauses will be evaluated by the leaf sequence).
629 bool status = read_row(i, dds, eval, false);
630 DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
631
632 while (status && !is_end_of_rows(i)) {
633 i += d_row_stride;
634
635 // DBG(cerr << "Writing Start of Instance marker" << endl);
636 // write_start_of_instance(sink);
637
638 // In this loop serialize will signal an error with an exception.
639 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
640 // Only call serialize for child Sequences; the leaf sequence
641 // will trigger the transmission of values for its parents (this
642 // sequence and maybe others) once it gets some valid data to
643 // send.
644 // Note that if the leaf sequence has no variables in the current
645 // projection, its serialize() method will never be called and that's
646 // the method that triggers actually sending values. Thus the leaf
647 // sequence must be the lowest level sequence with values whose send_p
648 // property is true.
649 if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) (*iter)->serialize(eval, dds, m);
650 }
651
652 set_read_p(false); // ...so this will read the next instance
653
654 status = read_row(i, dds, eval, false);
655 DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
656 }
657 // Reset current row number for next nested sequence element.
658 d_row_number = -1;
659
660 // Always write the EOS marker? 12/23/04 jhrg
661 // Yes. According to DAP2, a completely empty response is signaled by
662 // a return value of only the EOS marker for the outermost sequence.
663 if (d_top_most || d_wrote_soi) {
664 DBG(cerr << "Writing End of Sequence marker" << endl);
665 write_end_of_sequence(m);
666 d_wrote_soi = false;
667 }
668
669 return true; // Signal errors with exceptions.
670}
671
672// If we are here then we know that this is 'parent sequence' and that the
673// leaf sequence has found valid data to send. We also know that
674// serialize_parent_part_one has been called so data are in the instance's
675// fields. This is where we send data. Whereas ..._part_one() contains a
676// loop to iterate over all of rows in a parent sequence, this does not. This
677// method assumes that the serialize_leaf() will call it each time it needs
678// to be called.
679//
680// NB: This code only works if the child sequences appear after all other
681// variables.
682void Sequence::serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
683{
684 DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
685
686 BaseType *btp = get_parent();
687 if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
688
689 if (d_unsent_data) {
690 DBG(cerr << "Writing Start of Instance marker" << endl);
691 d_wrote_soi = true;
692 write_start_of_instance(m);
693
694 // In this loop serialize will signal an error with an exception.
695 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
696 // Send all the non-sequence variables
697 DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
698 << (*iter)->name() << endl);
699 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
700 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
701 (*iter)->serialize(eval, dds, m, false);
702 }
703 }
704
705 d_unsent_data = false; // read should set this.
706 }
707}
708
709// This code is only run by a leaf sequence. Note that a one level sequence
710// is also a leaf sequence.
711bool Sequence::serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
712{
713 DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
714 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
715
716 // read_row returns true if valid data was read, false if the EOF was
717 // found. 6/1/2001 jhrg
718 bool status = read_row(i, dds, eval, ce_eval);
719 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
720
721 // Once the first valid (satisfies the CE) row of the leaf sequence has
722 // been read, we know we're going to send data. Send the current instance
723 // of the parent/ancestor sequences now, if there are any. We only need
724 // to do this once, hence it's not inside the while loop, but we only
725 // send the parent seq data _if_ there's data in the leaf to send, that's
726 // why we wait until after the first call to read_row() here in the leaf
727 // sequence.
728 //
729 // NB: It's important to only call serialize_parent_part_two() for a
730 // Sequence that really is the parent of a leaf sequence.
731 if (status && !is_end_of_rows(i)) {
732 BaseType *btp = get_parent();
733 if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m);
734 }
735
736 d_wrote_soi = false;
737 while (status && !is_end_of_rows(i)) {
738 i += d_row_stride;
739
740 DBG(cerr << "Writing Start of Instance marker" << endl);
741 d_wrote_soi = true;
742 write_start_of_instance(m);
743
744 // In this loop serialize will signal an error with an exception.
745 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
746 DBG(cerr << "Sequence::serialize_leaf(), serializing "
747 << (*iter)->name() << endl);
748 if ((*iter)->send_p()) {
749 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
750 (*iter)->serialize(eval, dds, m, false);
751 }
752 }
753
754 set_read_p(false); // ...so this will read the next instance
755
756 status = read_row(i, dds, eval, ce_eval);
757 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
758 }
759
760 // Only write the EOS marker if there's a matching Start Of Instance
761 // Marker in the stream.
762 if (d_wrote_soi || d_top_most) {
763 DBG(cerr << "Writing End of Sequence marker" << endl);
764 write_end_of_sequence(m);
765 }
766
767 return true; // Signal errors with exceptions.
768}
769
793{
794 DBG(cerr << "Sequence::intern_data - for " << name() << endl); DBG2(cerr << " intern_data, values: " << &d_values << endl);
795
796 // Why use a stack instead of return values? We need the stack because
797 // Sequences nested three of more levels deep will loose the middle
798 // instances when the intern_data_parent_part_two() code is run.
799 sequence_values_stack_t sequence_values_stack;
800
801 sequence_values_stack.push(&d_values);
802
803 intern_data_private(eval, dds, sequence_values_stack);
804}
805
806void Sequence::intern_data_private(ConstraintEvaluator &eval, DDS &dds, sequence_values_stack_t &sequence_values_stack)
807{
808 DBG(cerr << "Entering intern_data_private for " << name() << endl);
809
810 if (is_leaf_sequence())
811 intern_data_for_leaf(dds, eval, sequence_values_stack);
812 else
813 intern_data_parent_part_one(dds, eval, sequence_values_stack);
814}
815
816void Sequence::intern_data_parent_part_one(DDS & dds, ConstraintEvaluator & eval,
817 sequence_values_stack_t & sequence_values_stack)
818{
819 DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl);
820
821 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
822
823 // read_row returns true if valid data was read, false if the EOF was
824 // found. 6/1/2001 jhrg
825 // Since this is a parent sequence, read the row ignoring the CE (all of
826 // the CE clauses will be evaluated by the leaf sequence).
827 bool status = read_row(i, dds, eval, false);
828
829 // Grab the current size of the value stack. We do this because it is
830 // possible that no nested sequences for this row happened to be
831 // selected because of a constraint evaluation or the last row is not
832 // selected because of a constraint evaluation. In either case, no
833 // nested sequence d_values are pushed onto the stack, so there is
834 // nothing to pop at the end of this function. pcw 07/14/08
835 SequenceValues::size_type orig_stack_size = sequence_values_stack.size();
836
837 while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
838 i += get_row_stride();
839 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
840 if ((*iter)->send_p()) {
841 switch ((*iter)->type()) {
842 case dods_sequence_c:
843 static_cast<Sequence&>(**iter).intern_data_private(eval, dds, sequence_values_stack);
844 break;
845
846 default:
847 (*iter)->intern_data(eval, dds);
848 break;
849 }
850 }
851 }
852
853 set_read_p(false); // ...so this will read the next instance
854
855 status = read_row(i, dds, eval, false);
856 }
857
858 // Reset current row number for next nested sequence element.
860
861 // if the size of the stack is larger than the original size (retrieved
862 // above) then pop the top set of d_values from the stack. If it's the
863 // same, then no nested sequences, or possibly the last nested sequence,
864 // were pushed onto the stack, so there is nothing to pop.
865 if (sequence_values_stack.size() > orig_stack_size) {
866 DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
867 << ") off stack; size: " << sequence_values_stack.size() << endl);
868 sequence_values_stack.pop();
869 }
870
871 DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl);
872}
873
874void Sequence::intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval,
875 sequence_values_stack_t &sequence_values_stack)
876{
877 DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
878
879 BaseType *btp = get_parent();
880 if (btp && btp->type() == dods_sequence_c) {
881 static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
882 }
883
884 DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl);
885 SequenceValues *values = sequence_values_stack.top();
886 DBG2(cerr << " using values = " << (void *)values << endl);
887
888 if (get_unsent_data()) {
889 BaseTypeRow *row_data = new BaseTypeRow;
890
891 // In this loop transfer_data will signal an error with an exception.
892 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
893
894 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
895 row_data->push_back((*iter)->ptr_duplicate());
896 }
897 else if ((*iter)->send_p()) { //Sequence; must be the last variable
898 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
899 if (!tmp) {
900 delete row_data;
901 throw InternalErr(__FILE__, __LINE__, "Expected a Sequence.");
902 }
903 row_data->push_back(tmp);
904 DBG2(cerr << " pushing d_values of " << tmp->name()
905 << " (" << &(tmp->d_values)
906 << ") on stack; size: " << sequence_values_stack.size()
907 << endl);
908 // This pushes the d_values field of the newly created leaf
909 // Sequence onto the stack. The code then returns to intern
910 // _data_for_leaf() where this value will be used.
911 sequence_values_stack.push(&(tmp->d_values));
912 }
913 }
914
915 DBG2(cerr << " pushing values for " << name()
916 << " to " << values << endl);
917 values->push_back(row_data);
918 set_unsent_data(false);
919 }
920
921 DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl);
922}
923
924void Sequence::intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
925{
926 DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
927
928 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
929
930 DBG2(cerr << " reading row " << i << endl);
931 bool status = read_row(i, dds, eval, true);
932 DBG2(cerr << " status: " << status << endl); DBG2(cerr << " ending row number: " << get_ending_row_number() << endl);
933
934 if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
935 BaseType *btp = get_parent();
936 if (btp && btp->type() == dods_sequence_c) {
937 // This call will read the values for the parent sequences and
938 // then allocate a new instance for the leaf and push that onto
939 // the stack.
940 static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
941 }
942
943 // intern_data_parent_part_two pushes the d_values field of the leaf
944 // onto the stack, so this operation grabs that value and then loads
945 // data into it.
946 SequenceValues *values = sequence_values_stack.top();
947 DBG2(cerr << " using values = " << values << endl);
948
949 while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
950 i += get_row_stride();
951
952 // Copy data from the object's fields to this new BaeTypeRow instance
953 BaseTypeRow *row_data = new BaseTypeRow;
954 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
955 if ((*iter)->send_p()) {
956 row_data->push_back((*iter)->ptr_duplicate());
957 }
958 }
959
960 DBG2(cerr << " pushing values for " << name()
961 << " to " << values << endl);
962 // Save the row_data to values().
963 values->push_back(row_data);
964
965 set_read_p(false); // ...so this will read the next instance
966 // Read the ith row into this object's fields
967 status = read_row(i, dds, eval, true);
968 }
969
970 DBG2(cerr << " popping d_values (" << sequence_values_stack.top()
971 << ") off stack; size: " << sequence_values_stack.size() << endl);
972 sequence_values_stack.pop();
973 }
974
975 DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl);
976}
977
998bool Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
999{
1000#if 0
1001 // Nathan's tip - this is something that should never happen
1002 DataDDS *dd = dynamic_cast<DataDDS *>(dds);
1003 if (!dd) throw InternalErr("Expected argument 'dds' to be a DataDDS!");
1004
1005 DBG2(cerr << "Reading from server/protocol version: "
1006 << dd->get_protocol_major() << "." << dd->get_protocol_minor()
1007 << endl);
1008
1009 // Check for old servers.
1010 if (dd->get_protocol_major() < 2) {
1011 throw Error(
1012 string("The protocl version (") + dd->get_protocol()
1013 + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
1014 }
1015#endif
1016 while (true) {
1017 // Grab the sequence stream's marker.
1018 unsigned char marker = read_marker(um);
1019 if (is_end_of_sequence(marker))
1020 break; // EXIT the while loop here!!!
1021 else if (is_start_of_instance(marker)) {
1022 d_row_number++;
1023 DBG2(cerr << "Reading row " << d_row_number << " of "
1024 << name() << endl);
1025 BaseTypeRow *bt_row_ptr = new BaseTypeRow;
1026 // Read the instance's values, building up the row
1027 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1028 BaseType *bt_ptr = (*iter)->ptr_duplicate();
1029 bt_ptr->deserialize(um, dds, reuse);
1030 DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
1031 << bt_ptr << ") = "); DBG2(bt_ptr->print_val(stderr, ""));
1032 bt_row_ptr->push_back(bt_ptr);
1033 }
1034 // Append this row to those accumulated.
1035 d_values.push_back(bt_row_ptr);
1036 }
1037 else
1038 throw Error("I could not read the expected Sequence data stream marker!");
1039 };
1040
1041 return false;
1042}
1043
1044// Return the current row number.
1045
1058{
1059 return d_starting_row_number;
1060}
1061
1073{
1074 return d_row_stride;
1075}
1076
1089{
1090 return d_ending_row_number;
1091}
1092
1101void Sequence::set_row_number_constraint(int start, int stop, int stride)
1102{
1103 if (stop < start) throw Error(malformed_expr, "Starting row number must precede the ending row number.");
1104
1105 d_starting_row_number = start;
1106 d_row_stride = stride;
1107 d_ending_row_number = stop;
1108}
1109
1110void Sequence::print_one_row(FILE *out, int row, string space, bool print_row_num)
1111{
1112 ostringstream oss;
1113 print_one_row(oss, row, space, print_row_num);
1114 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1115}
1116
1117void Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num)
1118{
1119 if (print_row_num) out << "\n" << space << row << ": ";
1120
1121 out << "{ ";
1122
1123 int elements = element_count();
1124 int j = 0;
1125 BaseType *bt_ptr = 0;
1126
1127 // This version of print_one_row() works for both data read with
1128 // deserialize(), where each variable is assumed to have valid data, and
1129 // intern_data(), where some/many variables do not. Because of that, it's
1130 // not correct to assume that all of the elements will be printed, which
1131 // is what the old code did.
1132 // Print the first value
1133 while (j < elements && !bt_ptr) {
1134 bt_ptr = var_value(row, j++);
1135 if (bt_ptr) { // data
1136 if (bt_ptr->type() == dods_sequence_c)
1137 static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1138 else
1139 bt_ptr->print_val(out, space, false);
1140 }
1141 }
1142
1143 // Print the remaining values
1144 while (j < elements) {
1145 bt_ptr = var_value(row, j++);
1146 if (bt_ptr) { // data
1147 out << ", ";
1148 if (bt_ptr->type() == dods_sequence_c)
1149 static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num);
1150 else
1151 bt_ptr->print_val(out, space, false);
1152 }
1153 }
1154
1155 out << " }";
1156}
1157
1158void Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, bool print_row_numbers)
1159{
1160 ostringstream oss;
1161 print_val_by_rows(oss, space, print_decl_p, print_row_numbers);
1162 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1163}
1164
1165void Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers)
1166{
1167 if (print_decl_p) {
1168 print_decl(out, space, false);
1169 out << " = ";
1170 }
1171
1172 out << "{ ";
1173
1174 int rows = number_of_rows() - 1;
1175 int i;
1176 for (i = 0; i < rows; ++i) {
1177 print_one_row(out, i, space, print_row_numbers);
1178 out << ", ";
1179 }
1180 print_one_row(out, i, space, print_row_numbers);
1181
1182 out << " }";
1183
1184 if (print_decl_p) out << ";\n";
1185}
1186
1187void Sequence::print_val(FILE *out, string space, bool print_decl_p)
1188{
1189 print_val_by_rows(out, space, print_decl_p, false);
1190}
1191
1192void Sequence::print_val(ostream &out, string space, bool print_decl_p)
1193{
1194 print_val_by_rows(out, space, print_decl_p, false);
1195}
1196
1197void Sequence::set_leaf_p(bool state)
1198{
1199 d_leaf_sequence = state;
1200}
1201
1202bool Sequence::is_leaf_sequence()
1203{
1204 return d_leaf_sequence;
1205}
1206
1232{
1233 bool has_child_sequence = false;
1234
1235 if (lvl == 1) d_top_most = true;
1236
1237 DBG2(cerr << "Processing sequence " << name() << endl);
1238
1239 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1240 // About the test for send_p(): Only descend into a sequence if it has
1241 // fields that might be sent. Thus if, in a two-level sequence, nothing
1242 // in the lower level is to be sent, the upper level is marked as the
1243 // leaf sequence. This ensures that values _will_ be sent (see the comment
1244 // in serialize_leaf() and serialize_parent_part_one()).
1245 if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
1246 if (has_child_sequence)
1247 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
1248
1249 has_child_sequence = true;
1250 static_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
1251 }
1252 else if ((*iter)->type() == dods_structure_c) {
1253 static_cast<Structure&>(**iter).set_leaf_sequence(lvl);
1254 }
1255 }
1256
1257 if (!has_child_sequence)
1258 set_leaf_p(true);
1259 else
1260 set_leaf_p(false);
1261
1262 DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
1263}
1264
1273void Sequence::dump(ostream &strm) const
1274{
1275 strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl;
1276 DapIndent::Indent();
1277 Constructor::dump(strm);
1278 strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number << endl;
1279 strm << DapIndent::LMarg << "bracket notation information:" << endl;
1280 DapIndent::Indent();
1281 strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl;
1282 strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl;
1283 strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl;
1284 DapIndent::UnIndent();
1285
1286 strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl;
1287 strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl;
1288 strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence << endl;
1289 strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most << endl;
1290 DapIndent::UnIndent();
1291}
1292
1293} // namespace libdap
1294
The basic data type for the DODS DAP types.
Definition: BaseType.h:118
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: BaseType.cc:864
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:265
virtual BaseType * get_parent() const
Definition: BaseType.cc:672
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:425
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:303
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:654
virtual string toString()
Definition: BaseType.cc:183
virtual BaseType * ptr_duplicate()=0
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition: BaseType.cc:125
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: BaseType.cc:1011
Evaluate a constraint expression.
bool eval_selection(DDS &dds, const std::string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator and is called ...
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Constructor.cc:169
BaseType * transform_to_dap4(D4Group *root, Constructor *dest)
DAP2 to DAP4 transform.
Definition: Constructor.cc:137
virtual void intern_data()
Read data into this variable.
Definition: Constructor.cc:531
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:827
Vars_iter var_end()
Definition: Constructor.cc:339
virtual void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Print an ASCII representation of the variable structure.
Definition: Constructor.cc:601
virtual bool read()
simple implementation of read that iterates through vars and calls read on them
Definition: Constructor.cc:451
Vars_iter var_begin()
Definition: Constructor.cc:331
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Constructor.cc:193
Holds a sequence.
Definition: D4Sequence.h:134
virtual void set_length(int count)
Definition: D4Sequence.h:199
Holds a DAP2 DDS.
Definition: DataDDS.h:78
A class for error processing.
Definition: Error.h:91
A class for software fault reporting.
Definition: InternalErr.h:65
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:50
Holds a sequence.
Definition: Sequence.h:163
virtual BaseType * transform_to_dap4(D4Group *root, Constructor *container)
Definition: Sequence.cc:211
virtual SequenceValues value()
Definition: Sequence.cc:339
virtual string toString()
Definition: Sequence.cc:272
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Sequence.cc:1273
virtual bool read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval=true)
Definition: Sequence.cc:494
virtual void set_leaf_sequence(int lvl=1)
Mark the Sequence which holds the leaf elements.
Definition: Sequence.cc:1231
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: Sequence.cc:1192
Sequence(const string &n)
The Sequence constructor.
Definition: Sequence.cc:160
virtual SequenceValues & value_ref()
Definition: Sequence.cc:347
virtual void set_value(SequenceValues &values)
Definition: Sequence.cc:332
virtual BaseType * ptr_duplicate()
Definition: Sequence.cc:191
virtual bool is_linear()
Check to see whether this variable can be printed simply.
Definition: Sequence.cc:287
virtual BaseType * var_value(size_t row, const string &name)
Get the BaseType pointer to the named variable of a given row.
Definition: Sequence.cc:358
virtual void clear_local_data()
Definition: Sequence.cc:242
virtual bool is_dap2_only_type()
Definition: Sequence.cc:267
bool get_unsent_data() const
Get the unsent data property.
Definition: Sequence.h:271
int get_starting_row_number()
Get the starting row number.
Definition: Sequence.cc:1057
void reset_row_number()
Rest the row number counter.
Definition: Sequence.cc:422
void set_unsent_data(bool usd)
Set the unsent data property.
Definition: Sequence.h:277
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Definition: Sequence.cc:602
virtual int length() const
Definition: Sequence.cc:408
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Deserialize (read from the network) the entire Sequence.
Definition: Sequence.cc:998
virtual int get_row_stride()
Get the row stride.
Definition: Sequence.cc:1072
virtual int get_ending_row_number()
Get the ending row number.
Definition: Sequence.cc:1088
virtual BaseTypeRow * row_value(size_t row)
Get a whole row from the sequence.
Definition: Sequence.cc:320
virtual void set_row_number_constraint(int start, int stop, int stride=1)
Definition: Sequence.cc:1101
Holds a structure (aggregate) type.
Definition: Structure.h:84
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
Definition: Structure.cc:252
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:55
vector< BaseType * > BaseTypeRow
Definition: D4Sequence.h:50
vector< BaseTypeRow * > SequenceValues
Definition: D4Sequence.h:53