58#include "Marshaller.h"
59#include "UnMarshaller.h"
63#include "InternalErr.h"
68#include "InternalErr.h"
71#include "D4Attributes.h"
72#include "D4Sequence.h"
74#include "Constructor.h"
78#undef CLEAR_LOCAL_DATA
84static const unsigned char end_of_sequence = 0xA5;
85static const unsigned char start_of_instance = 0x5A;
89void Sequence::m_duplicate(
const Sequence &s)
91 DBG(cerr <<
"In Sequence::m_duplicate" << endl);
93 d_row_number = s.d_row_number;
94 d_starting_row_number = s.d_starting_row_number;
95 d_ending_row_number = s.d_ending_row_number;
96 d_row_stride = s.d_row_stride;
97 d_leaf_sequence = s.d_leaf_sequence;
98 d_unsent_data = s.d_unsent_data;
99 d_wrote_soi = s.d_wrote_soi;
100 d_top_most = s.d_top_most;
105 for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin(); rows_iter != cs.d_values.end(); rows_iter++) {
112 for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin(); bt_row_iter != src_bt_row_ptr->end();
114 BaseType *src_bt_ptr = *bt_row_iter;
115 BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate();
116 dest_bt_row_ptr->push_back(dest_bt_ptr);
119 d_values.push_back(dest_bt_row_ptr);
123static void write_end_of_sequence(Marshaller &m)
125 m.put_opaque((
char *) &end_of_sequence, 1);
128static void write_start_of_instance(Marshaller &m)
130 m.put_opaque((
char *) &start_of_instance, 1);
133static unsigned char read_marker(UnMarshaller &um)
135 unsigned char marker;
136 um.get_opaque((
char *) &marker, 1);
141static bool is_start_of_instance(
unsigned char marker)
143 return (marker == start_of_instance);
146static bool is_end_of_sequence(
unsigned char marker)
148 return (marker == end_of_sequence);
162 Constructor(n, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1), d_row_stride(1), d_ending_row_number(
163 -1), d_unsent_data(false), d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
178 Constructor(n, d, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1),
179 d_row_stride(1), d_ending_row_number(-1), d_unsent_data(false),
180 d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false)
228static inline void delete_bt(
BaseType *bt_ptr)
234static inline void delete_rows(
BaseTypeRow *bt_row_ptr)
236 for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
247 catch (
const std::exception &) {
254 if (!d_values.empty()) {
255 for_each(d_values.begin(), d_values.end(), delete_rows);
263Sequence::operator=(
const Sequence &rhs)
265 if (
this == &rhs)
return *
this;
266 Constructor::operator=(rhs);
285 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
286 oss << (*i)->toString();
297 bool seq_found =
false;
298 for (Vars_iter iter = d_vars.begin(); linear && iter != d_vars.end(); iter++) {
299 if ((*iter)->type() == dods_sequence_c) {
310 else if ((*iter)->type() == dods_structure_c) {
329 if (row >= d_values.size())
return 0;
330 return d_values[row];
368 if (!bt_row_ptr)
return 0;
370 BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
371 BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
372 while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() !=
name)
375 if (bt_row_iter == bt_row_end)
390 if (!bt_row_ptr)
return 0;
392 if (i >= bt_row_ptr->size())
return 0;
394 return (*bt_row_ptr)[i];
421int Sequence::number_of_rows()
const
423 return d_values.size();
445 if ((*i)->type() == dods_sequence_c)
503 DBG2(cerr <<
"Entering Sequence::read_row for " <<
name() <<
", row number " << row <<
", current row " << d_row_number << endl);
504 if (row < d_row_number)
throw InternalErr(
"Trying to back up inside a sequence!");
506 if (row == d_row_number) {
507 DBG2(cerr <<
"Leaving Sequence::read_row for " <<
name() << endl);
512 while (!eof && d_row_number < row) {
533 DBG2(cerr <<
"Leaving Sequence::read_row for " <<
name() <<
" with eof: " << eof << endl);
544inline bool Sequence::is_end_of_rows(
int i)
546 return ((d_ending_row_number == -1) ?
false : (i > d_ending_row_number));
614 if (is_leaf_sequence())
615 status = serialize_leaf(dds, eval, m, ce_eval);
617 status = serialize_parent_part_one(dds, eval, m);
628 DBG2(cerr <<
"Entering serialize_parent_part_one for " <<
name() << endl);
630 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
636 bool status =
read_row(i, dds, eval,
false);
637 DBG2(cerr <<
"Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
639 while (status && !is_end_of_rows(i)) {
646 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
656 if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) (*iter)->serialize(eval, dds, m);
661 status =
read_row(i, dds, eval,
false);
662 DBG(cerr <<
"Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
670 if (d_top_most || d_wrote_soi) {
671 DBG(cerr <<
"Writing End of Sequence marker" << endl);
672 write_end_of_sequence(m);
689void Sequence::serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m)
691 DBG(cerr <<
"Entering serialize_parent_part_two for " <<
name() << endl);
694 if (btp && btp->type() == dods_sequence_c)
static_cast<Sequence&
>(*btp).serialize_parent_part_two(dds, eval, m);
697 DBG(cerr <<
"Writing Start of Instance marker" << endl);
699 write_start_of_instance(m);
702 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
704 DBG(cerr <<
"Sequence::serialize_parent_part_two(), serializing "
705 << (*iter)->name() << endl);
706 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
707 DBG(cerr <<
"Send P is true, sending " << (*iter)->name() << endl);
708 (*iter)->serialize(eval, dds, m,
false);
712 d_unsent_data =
false;
718bool Sequence::serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m,
bool ce_eval)
720 DBG(cerr <<
"Entering Sequence::serialize_leaf for " <<
name() << endl);
721 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
725 bool status =
read_row(i, dds, eval, ce_eval);
726 DBG(cerr <<
"Sequence::serialize_leaf::read_row() status: " << status << endl);
738 if (status && !is_end_of_rows(i)) {
740 if (btp && btp->type() == dods_sequence_c)
static_cast<Sequence&
>(*btp).serialize_parent_part_two(dds, eval, m);
744 while (status && !is_end_of_rows(i)) {
747 DBG(cerr <<
"Writing Start of Instance marker" << endl);
749 write_start_of_instance(m);
752 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
753 DBG(cerr <<
"Sequence::serialize_leaf(), serializing "
754 << (*iter)->name() << endl);
755 if ((*iter)->send_p()) {
756 DBG(cerr <<
"Send P is true, sending " << (*iter)->name() << endl);
757 (*iter)->serialize(eval, dds, m,
false);
763 status =
read_row(i, dds, eval, ce_eval);
764 DBG(cerr <<
"Sequence::serialize_leaf::read_row() status: " << status << endl);
769 if (d_wrote_soi || d_top_most) {
770 DBG(cerr <<
"Writing End of Sequence marker" << endl);
771 write_end_of_sequence(m);
801 DBG(cerr <<
"Sequence::intern_data - for " <<
name() << endl); DBG2(cerr <<
" intern_data, values: " << &d_values << endl);
803 throw Error(
string(
"A method usable only with DAP2 variables was called on a DAP4 variable (").append(
name()).append(
")."), __FILE__, __LINE__);
808 sequence_values_stack_t sequence_values_stack;
810 sequence_values_stack.push(&d_values);
812 intern_data_private(eval, dds, sequence_values_stack);
815void Sequence::intern_data_private(
ConstraintEvaluator &eval,
DDS &dds, sequence_values_stack_t &sequence_values_stack)
817 DBG(cerr <<
"Entering intern_data_private for " <<
name() << endl);
819 if (is_leaf_sequence())
820 intern_data_for_leaf(dds, eval, sequence_values_stack);
822 intern_data_parent_part_one(dds, eval, sequence_values_stack);
825void Sequence::intern_data_parent_part_one(DDS & dds, ConstraintEvaluator & eval,
826 sequence_values_stack_t & sequence_values_stack)
828 DBG(cerr <<
"Entering intern_data_parent_part_one for " <<
name() << endl);
836 bool status =
read_row(i, dds, eval,
false);
844 SequenceValues::size_type orig_stack_size = sequence_values_stack.size();
849 if ((*iter)->send_p()) {
850 switch ((*iter)->type()) {
851 case dods_sequence_c:
852 static_cast<Sequence&
>(**iter).intern_data_private(eval, dds, sequence_values_stack);
856 (*iter)->intern_data(eval, dds);
864 status =
read_row(i, dds, eval,
false);
874 if (sequence_values_stack.size() > orig_stack_size) {
875 DBG2(cerr <<
" popping d_values (" << sequence_values_stack.top()
876 <<
") off stack; size: " << sequence_values_stack.size() << endl);
877 sequence_values_stack.pop();
880 DBG(cerr <<
"Leaving intern_data_parent_part_one for " <<
name() << endl);
883void Sequence::intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval,
884 sequence_values_stack_t &sequence_values_stack)
886 DBG(cerr <<
"Entering intern_data_parent_part_two for " <<
name() << endl);
889 if (btp && btp->type() == dods_sequence_c) {
890 static_cast<Sequence&
>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
893 DBG2(cerr <<
" stack size: " << sequence_values_stack.size() << endl);
895 DBG2(cerr <<
" using values = " << (
void *)values << endl);
903 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
904 row_data->push_back((*iter)->ptr_duplicate());
906 else if ((*iter)->send_p()) {
910 throw InternalErr(__FILE__, __LINE__,
"Expected a Sequence.");
912 row_data->push_back(tmp);
913 DBG2(cerr <<
" pushing d_values of " << tmp->name()
914 <<
" (" << &(tmp->d_values)
915 <<
") on stack; size: " << sequence_values_stack.size()
920 sequence_values_stack.push(&(tmp->d_values));
924 DBG2(cerr <<
" pushing values for " <<
name()
925 <<
" to " << values << endl);
926 values->push_back(row_data);
930 DBG(cerr <<
"Leaving intern_data_parent_part_two for " <<
name() << endl);
933void Sequence::intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack)
935 DBG(cerr <<
"Entering intern_data_for_leaf for " <<
name() << endl);
939 DBG2(cerr <<
" reading row " << i << endl);
940 bool status =
read_row(i, dds, eval,
true);
941 DBG2(cerr <<
" status: " << status << endl); DBG2(cerr <<
" ending row number: " <<
get_ending_row_number() << endl);
945 if (btp && btp->type() == dods_sequence_c) {
949 static_cast<Sequence&
>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack);
956 DBG2(cerr <<
" using values = " << values << endl);
964 if ((*iter)->send_p()) {
965 row_data->push_back((*iter)->ptr_duplicate());
969 DBG2(cerr <<
" pushing values for " <<
name()
970 <<
" to " << values << endl);
972 values->push_back(row_data);
976 status =
read_row(i, dds, eval,
true);
979 DBG2(cerr <<
" popping d_values (" << sequence_values_stack.top()
980 <<
") off stack; size: " << sequence_values_stack.size() << endl);
981 sequence_values_stack.pop();
984 DBG(cerr <<
"Leaving intern_data_for_leaf for " <<
name() << endl);
1012 if (!dd)
throw InternalErr(
"Expected argument 'dds' to be a DataDDS!");
1014 DBG2(cerr <<
"Reading from server/protocol version: "
1015 << dd->get_protocol_major() <<
"." << dd->get_protocol_minor()
1019 if (dd->get_protocol_major() < 2) {
1021 string(
"The protocl version (") + dd->get_protocol()
1022 +
") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
1027 unsigned char marker = read_marker(um);
1028 if (is_end_of_sequence(marker))
1030 else if (is_start_of_instance(marker)) {
1032 DBG2(cerr <<
"Reading row " << d_row_number <<
" of "
1036 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1039 DBG2(cerr <<
"Deserialized " << bt_ptr->
name() <<
" ("
1040 << bt_ptr <<
") = "); DBG2(bt_ptr->
print_val(stderr,
""));
1041 bt_row_ptr->push_back(bt_ptr);
1044 d_values.push_back(bt_row_ptr);
1047 throw Error(
"I could not read the expected Sequence data stream marker!");
1068 return d_starting_row_number;
1083 return d_row_stride;
1099 return d_ending_row_number;
1112 if (stop < start)
throw Error(malformed_expr,
"Starting row number must precede the ending row number.");
1114 d_starting_row_number = start;
1115 d_row_stride = stride;
1116 d_ending_row_number = stop;
1119void Sequence::print_one_row(FILE *out,
int row,
string space,
bool print_row_num)
1122 print_one_row(oss, row, space, print_row_num);
1123 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
1126void Sequence::print_one_row(ostream &out,
int row,
string space,
bool print_row_num)
1128 if (print_row_num) out <<
"\n" << space << row <<
": ";
1134 BaseType *bt_ptr = 0;
1142 while (j < elements && !bt_ptr) {
1145 if (bt_ptr->type() == dods_sequence_c)
1146 static_cast<Sequence*
>(bt_ptr)->print_val_by_rows(out, space +
" ",
false, print_row_num);
1148 bt_ptr->print_val(out, space,
false);
1153 while (j < elements) {
1157 if (bt_ptr->type() == dods_sequence_c)
1158 static_cast<Sequence*
>(bt_ptr)->print_val_by_rows(out, space +
" ",
false, print_row_num);
1160 bt_ptr->print_val(out, space,
false);
1167void Sequence::print_val_by_rows(FILE *out,
string space,
bool print_decl_p,
bool print_row_numbers)
1170 print_val_by_rows(oss, space, print_decl_p, print_row_numbers);
1171 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
1174void Sequence::print_val_by_rows(ostream &out,
string space,
bool print_decl_p,
bool print_row_numbers)
1183 int rows = number_of_rows() - 1;
1185 for (i = 0; i < rows; ++i) {
1186 print_one_row(out, i, space, print_row_numbers);
1189 print_one_row(out, i, space, print_row_numbers);
1193 if (print_decl_p) out <<
";\n";
1198 print_val_by_rows(out, space, print_decl_p,
false);
1203 print_val_by_rows(out, space, print_decl_p,
false);
1206void Sequence::set_leaf_p(
bool state)
1208 d_leaf_sequence = state;
1211bool Sequence::is_leaf_sequence()
1213 return d_leaf_sequence;
1242 bool has_child_sequence =
false;
1244 if (lvl == 1) d_top_most =
true;
1246 DBG2(cerr <<
"Processing sequence " <<
name() << endl);
1248 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) {
1254 if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
1255 if (has_child_sequence)
1256 throw Error(
"This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
1258 has_child_sequence =
true;
1261 else if ((*iter)->type() == dods_structure_c) {
1266 if (!has_child_sequence)
1271 DBG2(cerr <<
"is_leaf_sequence(): " << is_leaf_sequence() <<
" (" <<
name() <<
")" << endl);
1284 strm << DapIndent::LMarg <<
"Sequence::dump - (" << (
void *)
this <<
")" << endl;
1285 DapIndent::Indent();
1287 strm << DapIndent::LMarg <<
"# rows deserialized: " << d_row_number << endl;
1288 strm << DapIndent::LMarg <<
"bracket notation information:" << endl;
1289 DapIndent::Indent();
1290 strm << DapIndent::LMarg <<
"starting row #: " << d_starting_row_number << endl;
1291 strm << DapIndent::LMarg <<
"row stride: " << d_row_stride << endl;
1292 strm << DapIndent::LMarg <<
"ending row #: " << d_ending_row_number << endl;
1293 DapIndent::UnIndent();
1295 strm << DapIndent::LMarg <<
"data been sent? " << d_unsent_data << endl;
1296 strm << DapIndent::LMarg <<
"start of instance? " << d_wrote_soi << endl;
1297 strm << DapIndent::LMarg <<
"is leaf sequence? " << d_leaf_sequence << endl;
1298 strm << DapIndent::LMarg <<
"top most in hierarchy? " << d_top_most << endl;
1299 DapIndent::UnIndent();
The basic data type for the DODS DAP types.
virtual void intern_data()
Read data into this variable.
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
virtual string name() const
Returns the name of the class instance.
virtual BaseType * get_parent() const
virtual bool read_p()
Has this variable been read?
virtual string dataset() const
Returns the name of the dataset used to create this instance.
virtual string toString()
virtual bool is_simple_type() const
Returns true if the instance is a numeric, string or URL type variable.
virtual BaseType * ptr_duplicate()=0
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
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 ...
int element_count(bool leaves=false) override
Count the members of constructor types.
void transform_to_dap4(D4Group *root, Constructor *dest) override
DAP2 to DAP4 transform.
void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false) override
Print an ASCII representation of the variable structure.
void set_read_p(bool state) override
Set the 'read_p' property for the Constructor and its members.
bool read() override
Read the elements of Constructor marked for transmission.
void add_var_nocopy(BaseType *bt, Part part=nil) override
void dump(ostream &strm) const override
dumps information about this object
void set_length(int64_t count) override
A class for error processing.
A class for software fault reporting.
abstract base class used to marshal/serialize dap data objects
virtual void transform_to_dap4(D4Group *root, Constructor *container)
virtual SequenceValues value()
virtual string toString()
virtual void dump(ostream &strm) const
dumps information about this object
virtual bool read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval=true)
virtual void set_leaf_sequence(int lvl=1)
Mark the Sequence which holds the leaf elements.
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Sequence(const string &n)
The Sequence constructor.
virtual SequenceValues & value_ref()
virtual void set_value(SequenceValues &values)
virtual BaseType * ptr_duplicate()
virtual bool is_linear()
Check to see whether this variable can be printed simply.
virtual BaseType * var_value(size_t row, const string &name)
Get the BaseType pointer to the named variable of a given row.
virtual void clear_local_data()
virtual bool is_dap2_only_type()
bool get_unsent_data() const
Get the unsent data property.
int get_starting_row_number()
Get the starting row number.
void reset_row_number()
Rest the row number counter.
void set_unsent_data(bool usd)
Set the unsent data property.
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
virtual int length() const
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Deserialize (read from the network) the entire Sequence.
virtual int get_row_stride()
Get the row stride.
virtual int get_ending_row_number()
Get the ending row number.
virtual BaseTypeRow * row_value(size_t row)
Get a whole row from the sequence.
virtual void set_row_number_constraint(int start, int stop, int stride=1)
Holds a structure (aggregate) type.
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
abstract base class used to unmarshall/deserialize dap data objects
top level DAP object to house generic methods
vector< BaseType * > BaseTypeRow
vector< BaseTypeRow * > SequenceValues