libdap++ Updated for version 3.8.2
|
00001 // -*- mode: c++; c-basic-offset:4 -*- 00002 00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00004 // Access Protocol. 00005 00006 // Copyright (c) 2002,2003 OPeNDAP, Inc. 00007 // Author: James Gallagher <jgallagher@opendap.org> 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00024 00025 // (c) COPYRIGHT URI/MIT 1994-1999 00026 // Please read the full copyright statement in the file COPYRIGHT_URI. 00027 // 00028 // Authors: 00029 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00030 00031 // Implementation for the class Structure 00032 // 00033 // jhrg 9/14/94 00034 00035 00036 #include "config.h" 00037 00038 #include <algorithm> 00039 #include <string> 00040 #include <sstream> 00041 00042 //#define DODS_DEBUG 00043 //#define DODS_DEBUG2 00044 00045 #include "debug.h" 00046 #include "Error.h" 00047 #include "InternalErr.h" 00048 #include "Sequence.h" 00049 #include "DDS.h" 00050 #include "DataDDS.h" 00051 #include "util.h" 00052 #include "InternalErr.h" 00053 #include "escaping.h" 00054 00055 using namespace std; 00056 00057 namespace libdap { 00058 00059 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101 00060 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010 00061 00062 // Private member functions 00063 00064 void 00065 Sequence::_duplicate(const Sequence &s) 00066 { 00067 d_row_number = s.d_row_number; 00068 d_starting_row_number = s.d_starting_row_number; 00069 d_ending_row_number = s.d_ending_row_number; 00070 d_row_stride = s.d_row_stride; 00071 d_leaf_sequence = s.d_leaf_sequence; 00072 d_unsent_data = s.d_unsent_data; 00073 d_wrote_soi = s.d_wrote_soi; 00074 d_top_most = s.d_top_most; 00075 00076 Sequence &cs = const_cast<Sequence &>(s); 00077 00078 // Copy the template BaseType objects. 00079 for (Vars_iter i = cs.var_begin(); i != cs.var_end(); i++) { 00080 add_var((*i)) ; 00081 } 00082 00083 // Copy the BaseType objects used to hold values. 00084 for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin(); 00085 rows_iter != cs.d_values.end(); 00086 rows_iter++) { 00087 // Get the current BaseType Row 00088 BaseTypeRow *src_bt_row_ptr = *rows_iter; 00089 // Create a new row. 00090 BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow; 00091 // Copy the BaseType objects from a row to new BaseType objects. 00092 // Push new BaseType objects onto new row. 00093 for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin(); 00094 bt_row_iter != src_bt_row_ptr->end(); 00095 bt_row_iter++) { 00096 BaseType *src_bt_ptr = *bt_row_iter; 00097 BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate(); 00098 dest_bt_row_ptr->push_back(dest_bt_ptr); 00099 } 00100 // Push new row onto d_values. 00101 d_values.push_back(dest_bt_row_ptr); 00102 } 00103 } 00104 00105 static void 00106 write_end_of_sequence(Marshaller &m) 00107 { 00108 m.put_opaque( (char *)&end_of_sequence, 1 ) ; 00109 } 00110 00111 static void 00112 write_start_of_instance(Marshaller &m) 00113 { 00114 m.put_opaque( (char *)&start_of_instance, 1 ) ; 00115 } 00116 00117 static unsigned char 00118 read_marker(UnMarshaller &um) 00119 { 00120 unsigned char marker; 00121 um.get_opaque( (char *)&marker, 1 ) ; 00122 00123 return marker; 00124 } 00125 00126 static bool 00127 is_start_of_instance(unsigned char marker) 00128 { 00129 return (marker == start_of_instance); 00130 } 00131 00132 static bool 00133 is_end_of_sequence(unsigned char marker) 00134 { 00135 return (marker == end_of_sequence); 00136 } 00137 00138 // Public member functions 00139 00148 Sequence::Sequence(const string &n) : Constructor(n, dods_sequence_c), 00149 d_row_number(-1), d_starting_row_number(-1), 00150 d_row_stride(1), d_ending_row_number(-1), 00151 d_unsent_data(false), d_wrote_soi(false), 00152 d_leaf_sequence(false), d_top_most(false) 00153 {} 00154 00165 Sequence::Sequence(const string &n, const string &d) 00166 : Constructor(n, d, dods_sequence_c), 00167 d_row_number(-1), d_starting_row_number(-1), 00168 d_row_stride(1), d_ending_row_number(-1), 00169 d_unsent_data(false), d_wrote_soi(false), 00170 d_leaf_sequence(false), d_top_most(false) 00171 {} 00172 00174 Sequence::Sequence(const Sequence &rhs) : Constructor(rhs) 00175 { 00176 _duplicate(rhs); 00177 } 00178 00179 BaseType * 00180 Sequence::ptr_duplicate() 00181 { 00182 return new Sequence(*this); 00183 } 00184 00185 static inline void 00186 delete_bt(BaseType *bt_ptr) 00187 { 00188 DBG2(cerr << "In delete_bt: " << bt_ptr << endl); 00189 delete bt_ptr; bt_ptr = 0; 00190 } 00191 00192 static inline void 00193 delete_rows(BaseTypeRow *bt_row_ptr) 00194 { 00195 DBG2(cerr << "In delete_rows: " << bt_row_ptr << endl); 00196 00197 for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt); 00198 00199 delete bt_row_ptr; bt_row_ptr = 0; 00200 } 00201 00202 Sequence::~Sequence() 00203 { 00204 DBG2(cerr << "Entering Sequence::~Sequence" << endl); 00205 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00206 BaseType *btp = *i ; 00207 delete btp ; btp = 0; 00208 } 00209 00210 for_each(d_values.begin(), d_values.end(), delete_rows); 00211 DBG2(cerr << "exiting Sequence::~Sequence" << endl); 00212 } 00213 00214 Sequence & 00215 Sequence::operator=(const Sequence &rhs) 00216 { 00217 if (this == &rhs) 00218 return *this; 00219 00220 dynamic_cast<Constructor &>(*this) = rhs; // run Constructor= 00221 00222 _duplicate(rhs); 00223 00224 return *this; 00225 } 00226 00227 string 00228 Sequence::toString() 00229 { 00230 ostringstream oss; 00231 00232 oss << BaseType::toString(); 00233 00234 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00235 oss << (*i)->toString(); 00236 } 00237 00238 oss << endl; 00239 00240 return oss.str(); 00241 } 00242 00243 int 00244 Sequence::element_count(bool leaves) 00245 { 00246 if (!leaves) 00247 return _vars.size(); 00248 else { 00249 int i = 0; 00250 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00251 i += (*iter)->element_count(true); 00252 } 00253 return i; 00254 } 00255 } 00256 00257 bool 00258 Sequence::is_linear() 00259 { 00260 bool linear = true; 00261 bool seq_found = false; 00262 for (Vars_iter iter = _vars.begin(); linear && iter != _vars.end(); iter++) { 00263 if ((*iter)->type() == dods_sequence_c) { 00264 // A linear sequence cannot have more than one child seq. at any 00265 // one level. If we've already found a seq at this level, return 00266 // false. 00267 if (seq_found) { 00268 linear = false; 00269 break; 00270 } 00271 seq_found = true; 00272 linear = dynamic_cast<Sequence *>((*iter))->is_linear(); 00273 } 00274 else if ((*iter)->type() == dods_structure_c) { 00275 linear = dynamic_cast<Structure*>((*iter))->is_linear(); 00276 } 00277 else { 00278 // A linear sequence cannot have Arrays, Lists or Grids. 00279 linear = (*iter)->is_simple_type(); 00280 } 00281 } 00282 00283 return linear; 00284 } 00285 00286 void 00287 Sequence::set_send_p(bool state) 00288 { 00289 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00290 (*i)->set_send_p(state); 00291 } 00292 00293 BaseType::set_send_p(state); 00294 } 00295 00296 void 00297 Sequence::set_read_p(bool state) 00298 { 00299 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00300 (*i)->set_read_p(state); 00301 } 00302 00303 BaseType::set_read_p(state); 00304 } 00305 00306 void 00307 Sequence::set_in_selection(bool state) 00308 { 00309 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00310 (*i)->set_in_selection(state); 00311 } 00312 00313 BaseType::set_in_selection(state); 00314 } 00315 00325 void 00326 Sequence::add_var(BaseType *bt, Part) 00327 { 00328 if (!bt) 00329 throw InternalErr(__FILE__, __LINE__, 00330 "Cannot add variable: NULL pointer"); 00331 // Jose Garcia 00332 // We append a copy of bt so the owner of bt is free to deallocate 00333 00334 BaseType *bt_copy = bt->ptr_duplicate(); 00335 bt_copy->set_parent(this); 00336 _vars.push_back(bt_copy); 00337 } 00338 00339 // Deprecated 00340 BaseType * 00341 Sequence::var(const string &n, btp_stack &s) 00342 { 00343 string name = www2id(n); 00344 00345 BaseType *btp = m_exact_match(name, &s); 00346 if (btp) 00347 return btp; 00348 00349 return m_leaf_match(name, &s); 00350 } 00351 00352 BaseType * 00353 Sequence::var(const string &name, bool exact_match, btp_stack *s) 00354 { 00355 string n = www2id(name); 00356 00357 if (exact_match) 00358 return m_exact_match(n, s); 00359 else 00360 return m_leaf_match(n, s); 00361 } 00362 00363 BaseType * 00364 Sequence::m_leaf_match(const string &name, btp_stack *s) 00365 { 00366 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00367 if ((*i)->name() == name) { 00368 if (s) 00369 s->push(static_cast<BaseType *>(this)); 00370 return *i; 00371 } 00372 if ((*i)->is_constructor_type()) { 00373 BaseType *btp = (*i)->var(name, false, s); 00374 if (btp) { 00375 if (s) 00376 s->push(static_cast<BaseType *>(this)); 00377 return btp; 00378 } 00379 } 00380 } 00381 00382 return 0; 00383 } 00384 00385 BaseType * 00386 Sequence::m_exact_match(const string &name, btp_stack *s) 00387 { 00388 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00389 if ((*i)->name() == name) { 00390 if (s) 00391 s->push(static_cast<BaseType *>(this)); 00392 return *i; 00393 } 00394 } 00395 00396 string::size_type dot_pos = name.find("."); // zero-based index of `.' 00397 if (dot_pos != string::npos) { 00398 string aggregate = name.substr(0, dot_pos); 00399 string field = name.substr(dot_pos + 1); 00400 00401 BaseType *agg_ptr = var(aggregate); 00402 if (agg_ptr) { 00403 if (s) 00404 s->push(static_cast<BaseType *>(this)); 00405 return agg_ptr->var(field, true, s); // recurse 00406 } 00407 else 00408 return 0; // qualified names must be *fully* qualified 00409 } 00410 00411 return 0; 00412 } 00413 00418 BaseTypeRow * 00419 Sequence::row_value(size_t row) 00420 { 00421 if (row >= d_values.size()) 00422 return 0; 00423 return d_values[row]; 00424 } 00425 00432 void 00433 Sequence::set_value(SequenceValues &values) 00434 { 00435 d_values = values; 00436 } 00437 00440 SequenceValues 00441 Sequence::value() 00442 { 00443 return d_values; 00444 } 00445 00451 BaseType * 00452 Sequence::var_value(size_t row, const string &name) 00453 { 00454 BaseTypeRow *bt_row_ptr = row_value(row); 00455 if (!bt_row_ptr) 00456 return 0; 00457 00458 BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin(); 00459 BaseTypeRow::iterator bt_row_end = bt_row_ptr->end(); 00460 while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name) 00461 ++bt_row_iter; 00462 00463 if (bt_row_iter == bt_row_end) 00464 return 0; 00465 else 00466 return *bt_row_iter; 00467 } 00468 00474 BaseType * 00475 Sequence::var_value(size_t row, size_t i) 00476 { 00477 BaseTypeRow *bt_row_ptr = row_value(row); 00478 if (!bt_row_ptr) 00479 return 0; 00480 00481 if (i >= bt_row_ptr->size()) 00482 return 0; 00483 00484 return (*bt_row_ptr)[i]; 00485 } 00486 00487 unsigned int 00488 Sequence::width() 00489 { 00490 unsigned int sz = 0; 00491 00492 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00493 sz += (*i)->width(); 00494 } 00495 00496 return sz; 00497 } 00498 00499 // This version returns -1. Each API-specific subclass should define a more 00500 // reasonable version. jhrg 5/24/96 00501 00517 int 00518 Sequence::length() 00519 { 00520 return -1; 00521 } 00522 00523 00524 int 00525 Sequence::number_of_rows() 00526 { 00527 return d_values.size(); 00528 } 00529 00533 void 00534 Sequence::reset_row_number() 00535 { 00536 d_row_number = -1; 00537 } 00538 00539 // Notes: 00540 // Assume that read() is implemented so that, when reading data for a nested 00541 // sequence, only the outer most level is *actually* read. 00542 // This is a consequence of our current (12/7/99) implementation of 00543 // the JGOFS server (which is the only server to actually use nested 00544 // sequences). 12/7/99 jhrg 00545 // 00546 // Stop assuming this. This logic is being moved into the JGOFS server 00547 // itself. 6/1/2001 jhrg 00548 00549 // The read() function returns a boolean value, with TRUE 00550 // indicating that read() should be called again because there's 00551 // more data to read, and FALSE indicating there's no more data 00552 // to read. Note that this behavior is necessary to properly 00553 // handle variables that contain Sequences. Jose Garcia If an 00554 // error exists while reading, the implementers of the surrogate 00555 // library SHOULD throw an Error object which will propagate 00556 // beyond this point to to the original caller. 00557 // Jose Garcia 00558 00591 bool 00592 Sequence::read_row(int row, DDS &dds, 00593 ConstraintEvaluator &eval, bool ce_eval) 00594 { 00595 DBG2(cerr << "Entering Sequence::read_row for " << name() << endl); 00596 if (row < d_row_number) 00597 throw InternalErr("Trying to back up inside a sequence!"); 00598 00599 DBG2(cerr << "read_row: row number " << row 00600 << ", current row " << d_row_number << endl); 00601 if (row == d_row_number) 00602 { 00603 DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl); 00604 return true; 00605 } 00606 00607 dds.timeout_on(); 00608 00609 int eof = 0; // Start out assuming EOF is false. 00610 while (!eof && d_row_number < row) { 00611 if (!read_p()) { 00612 eof = (read() == false); 00613 } 00614 00615 // Advance the row number if ce_eval is false (we're not supposed to 00616 // evaluate the selection) or both ce_eval and the selection are 00617 // true. 00618 if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) 00619 d_row_number++; 00620 00621 set_read_p(false); // ...so that the next instance will be read 00622 } 00623 00624 // Once we finish the above loop, set read_p to true so that the caller 00625 // knows that data *has* been read. This is how the read() methods of the 00626 // elements of the sequence know to not call read() but instead look for 00627 // data values inside themselves. 00628 set_read_p(true); 00629 00630 dds.timeout_off(); 00631 00632 // Return true if we have valid data, false if we've read to the EOF. 00633 DBG2(cerr << "Leaving Sequence::read_row for " << name() 00634 << " with " << (eof == 0) << endl); 00635 return eof == 0; 00636 } 00637 00638 // Private. This is used to process constraints on the rows of a sequence. 00639 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This 00640 // odd-looking logic first checks if d_ending_row_number is the sentinel 00641 // value of -1. If so, the sequence was not constrained by row number and 00642 // this method should never return true (which indicates that we're at the 00643 // end of a row-number constraint). If d_ending_row_number is not -1, then is 00644 // \e i at the end point? 6/1/2001 jhrg 00645 inline bool 00646 Sequence::is_end_of_rows(int i) 00647 { 00648 return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number)); 00649 } 00650 00711 bool 00712 Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, 00713 Marshaller &m, bool ce_eval) 00714 { 00715 DBG2(cerr << "Entering Sequence::serialize for " << name() << endl); 00716 00717 // Special case leaf sequences! 00718 if (is_leaf_sequence()) 00719 return serialize_leaf(dds, eval, m, ce_eval); 00720 else 00721 return serialize_parent_part_one(dds, eval, m); 00722 } 00723 00724 // We know this is not a leaf Sequence. That means that this Sequence holds 00725 // another Sequence as one of its fields _and_ that child Sequence triggers 00726 // the actual transmission of values. 00727 00728 bool 00729 Sequence::serialize_parent_part_one(DDS &dds, 00730 ConstraintEvaluator &eval, Marshaller &m) 00731 { 00732 DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl); 00733 00734 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0; 00735 00736 // read_row returns true if valid data was read, false if the EOF was 00737 // found. 6/1/2001 jhrg 00738 // Since this is a parent sequence, read the row ignoring the CE (all of 00739 // the CE clauses will be evaluated by the leaf sequence). 00740 bool status = read_row(i, dds, eval, false); 00741 DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl); 00742 00743 while (status && !is_end_of_rows(i)) { 00744 i += d_row_stride; 00745 00746 // DBG(cerr << "Writing Start of Instance marker" << endl); 00747 // write_start_of_instance(sink); 00748 00749 // In this loop serialize will signal an error with an exception. 00750 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00751 // Only call serialize for child Sequences; the leaf sequence 00752 // will trigger the transmission of values for its parents (this 00753 // sequence and maybe others) once it gets soem valid data to 00754 // send. 00755 // Note that if the leaf sequence has no variables in the current 00756 // projection, its serialize() method will never be called and that's 00757 // the method that triggers actually sending values. Thus the leaf 00758 // sequence must be the lowest level sequence with values whose send_p 00759 // property is true. 00760 if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) 00761 (*iter)->serialize(eval, dds, m); 00762 } 00763 00764 set_read_p(false); // ...so this will read the next instance 00765 00766 status = read_row(i, dds, eval, false); 00767 DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl); 00768 } 00769 // Reset current row number for next nested sequence element. 00770 d_row_number = -1; 00771 00772 // Always write the EOS marker? 12/23/04 jhrg 00773 // Yes. According to DAP2, a completely empty response is signalled by 00774 // a return value of only the EOS marker for the outermost sequence. 00775 if (d_top_most || d_wrote_soi) { 00776 DBG(cerr << "Writing End of Sequence marker" << endl); 00777 write_end_of_sequence(m); 00778 d_wrote_soi = false; 00779 } 00780 00781 return true; // Signal errors with exceptions. 00782 } 00783 00784 // If we are here then we know that this is 'parent sequence' and that the 00785 // leaf seq has found valid data to send. We also know that 00786 // serialize_parent_part_one has been called so data are in the instance's 00787 // fields. This is wheree we send data. Whereas ..._part_one() contains a 00788 // loop to iterate over all of rows in a parent sequence, this does not. This 00789 // method assumes that the serialize_leaf() will call it each time it needs 00790 // to be called. 00791 // 00792 // NB: This code only works if the child sequences appear after all other 00793 // variables. 00794 void 00795 Sequence::serialize_parent_part_two(DDS &dds, 00796 ConstraintEvaluator &eval, Marshaller &m) 00797 { 00798 DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl); 00799 00800 BaseType *btp = get_parent(); 00801 if (btp && btp->type() == dods_sequence_c) 00802 dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m); 00803 00804 if (d_unsent_data) { 00805 DBG(cerr << "Writing Start of Instance marker" << endl); 00806 d_wrote_soi = true; 00807 write_start_of_instance(m); 00808 00809 // In this loop serialize will signal an error with an exception. 00810 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00811 // Send all the non-sequence variables 00812 DBG(cerr << "Sequence::serialize_parent_part_two(), serializing " 00813 << (*iter)->name() << endl); 00814 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) { 00815 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl); 00816 (*iter)->serialize(eval, dds, m, false); 00817 } 00818 } 00819 00820 d_unsent_data = false; // read should set this. 00821 } 00822 } 00823 00824 // This code is only run by a leaf sequence. Note that a one level sequence 00825 // is also a leaf sequence. 00826 bool 00827 Sequence::serialize_leaf(DDS &dds, 00828 ConstraintEvaluator &eval, Marshaller &m, bool ce_eval) 00829 { 00830 DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl); 00831 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0; 00832 00833 // read_row returns true if valid data was read, false if the EOF was 00834 // found. 6/1/2001 jhrg 00835 bool status = read_row(i, dds, eval, ce_eval); 00836 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl); 00837 00838 // Once the first valid (satisfies the CE) row of the leaf sequence has 00839 // been read, we know we're going to send data. Send the current instance 00840 // of the parent/ancestor sequences now, if there are any. We only need 00841 // to do this once, hence it's not inside the while loop, but we only 00842 // send the parent seq data _if_ there's data in the leaf to send, that's 00843 // why we wait until after the first call to read_row() here in the leaf 00844 // sequence. 00845 // 00846 // NB: It's important to only call serialize_parent_part_two() for a 00847 // Sequence that really is the parent of a leaf sequence. The fancy cast 00848 // will throw and exception if btp is not a Sequence, but doesn't test 00849 // that it's a parent sequence as we've defined them here. 00850 if (status && !is_end_of_rows(i)) { 00851 BaseType *btp = get_parent(); 00852 if (btp && btp->type() == dods_sequence_c) 00853 dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, 00854 eval, m); 00855 } 00856 00857 d_wrote_soi = false; 00858 while (status && !is_end_of_rows(i)) { 00859 i += d_row_stride; 00860 00861 DBG(cerr << "Writing Start of Instance marker" << endl); 00862 d_wrote_soi = true; 00863 write_start_of_instance(m); 00864 00865 // In this loop serialize will signal an error with an exception. 00866 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00867 DBG(cerr << "Sequence::serialize_leaf(), serializing " 00868 << (*iter)->name() << endl); 00869 if ((*iter)->send_p()) { 00870 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl); 00871 (*iter)->serialize(eval, dds, m, false); 00872 } 00873 } 00874 00875 set_read_p(false); // ...so this will read the next instance 00876 00877 status = read_row(i, dds, eval, ce_eval); 00878 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl); 00879 } 00880 00881 // Only write the EOS marker if there's a matching Start Of Instnace 00882 // Marker in the stream. 00883 if (d_wrote_soi || d_top_most) { 00884 DBG(cerr << "Writing End of Sequence marker" << endl); 00885 write_end_of_sequence(m); 00886 } 00887 00888 return true; // Signal errors with exceptions. 00889 } 00890 00913 void 00914 Sequence::intern_data(ConstraintEvaluator &eval, DDS &dds) 00915 { 00916 DBG(cerr << "Sequence::intern_data - for " << name() << endl); 00917 DBG2(cerr << " intern_data, values: " << &d_values << endl); 00918 00919 // Why use a stack instead of return values? We need the stack because 00920 // Sequences neted three of more levels deep will loose the middle 00921 // instances when the intern_data_parent_part_two() code is run. 00922 sequence_values_stack_t sequence_values_stack; 00923 00924 DBG2(cerr << " pushing d_values of " << name() << " (" << &d_values 00925 << ") on stack; size: " << sequence_values_stack.size() << endl); 00926 sequence_values_stack.push(&d_values); 00927 00928 intern_data_private(eval, dds, sequence_values_stack); 00929 } 00930 00931 void 00932 Sequence::intern_data_private(ConstraintEvaluator &eval, 00933 DDS &dds, 00934 sequence_values_stack_t &sequence_values_stack) 00935 { 00936 DBG(cerr << "Entering intern_data_private for " << name() << endl); 00937 00938 if (is_leaf_sequence()) 00939 intern_data_for_leaf(dds, eval, sequence_values_stack); 00940 else 00941 intern_data_parent_part_one(dds, eval, sequence_values_stack); 00942 } 00943 00944 void 00945 Sequence::intern_data_parent_part_one(DDS & dds, 00946 ConstraintEvaluator & eval, 00947 sequence_values_stack_t & 00948 sequence_values_stack) 00949 { 00950 DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl); 00951 00952 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0; 00953 00954 // read_row returns true if valid data was read, false if the EOF was 00955 // found. 6/1/2001 jhrg 00956 // Since this is a parent sequence, read the row ignoring the CE (all of 00957 // the CE clauses will be evaluated by the leaf sequence). 00958 bool status = read_row(i, dds, eval, false); 00959 00960 // Grab the current size of the value stack. We do this because it is 00961 // possible that no nested sequences for this row happened to be 00962 // selected because of a constract evaluation or the last row is not 00963 // selected because of a constraint evaluation. In either case, no 00964 // nested sequence d_values are pused onto the stack, so there is 00965 // nothing to pop at the end of this function. pcw 07/14/08 00966 SequenceValues::size_type orig_stack_size = sequence_values_stack.size() ; 00967 00968 while (status 00969 && (get_ending_row_number() == -1 00970 || i <= get_ending_row_number())) 00971 { 00972 i += get_row_stride(); 00973 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 00974 if ((*iter)->send_p()) { 00975 switch ((*iter)->type()) { 00976 case dods_sequence_c: 00977 dynamic_cast<Sequence&>(**iter).intern_data_private( 00978 eval, dds, sequence_values_stack); 00979 break; 00980 00981 default: 00982 (*iter)->intern_data(eval, dds); 00983 break; 00984 } 00985 } 00986 } 00987 00988 set_read_p(false); // ...so this will read the next instance 00989 00990 status = read_row(i, dds, eval, false); 00991 } 00992 00993 // Reset current row number for next nested sequence element. 00994 reset_row_number(); 00995 00996 // if the size of the stack is larger than the original size (retrieved 00997 // above) then pop the top set of d_values from the stack. If it's the 00998 // same, then no nested sequences, or possible the last nested sequence, 00999 // were pushed onto the stack, so there is nothing to pop. 01000 if( sequence_values_stack.size() > orig_stack_size ) 01001 { 01002 DBG2(cerr << " popping d_values (" << sequence_values_stack.top() 01003 << ") off stack; size: " << sequence_values_stack.size() << endl); 01004 sequence_values_stack.pop(); 01005 } 01006 DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl); 01007 } 01008 01009 void 01010 Sequence::intern_data_parent_part_two(DDS &dds, 01011 ConstraintEvaluator &eval, 01012 sequence_values_stack_t &sequence_values_stack) 01013 { 01014 DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl); 01015 01016 BaseType *btp = get_parent(); 01017 if (btp && btp->type() == dods_sequence_c) { 01018 dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two( 01019 dds, eval, sequence_values_stack); 01020 } 01021 01022 DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl); 01023 SequenceValues *values = sequence_values_stack.top(); 01024 DBG2(cerr << " using values = " << (void *)values << endl); 01025 01026 if (get_unsent_data()) { 01027 BaseTypeRow *row_data = new BaseTypeRow; 01028 01029 // In this loop transfer_data will signal an error with an exception. 01030 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 01031 01032 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) { 01033 row_data->push_back((*iter)->ptr_duplicate()); 01034 } 01035 else if ((*iter)->send_p()) { //Sequence; must be the last variable 01036 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate()); 01037 if (!tmp) 01038 throw InternalErr(__FILE__, __LINE__, "Expected a Sequence."); 01039 row_data->push_back(tmp); 01040 DBG2(cerr << " pushing d_values of " << tmp->name() 01041 << " (" << &(tmp->d_values) 01042 << ") on stack; size: " << sequence_values_stack.size() 01043 << endl); 01044 // This pushes the d_values field of the newly created leaf 01045 // Sequence onto the stack. The code then returns to intern 01046 // _data_for_leaf() where this value will be used. 01047 sequence_values_stack.push(&(tmp->d_values)); 01048 } 01049 } 01050 01051 DBG2(cerr << " pushing values for " << name() 01052 << " to " << values << endl); 01053 values->push_back(row_data); 01054 set_unsent_data(false); 01055 } 01056 DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl); 01057 } 01058 01059 void 01060 Sequence::intern_data_for_leaf(DDS &dds, 01061 ConstraintEvaluator &eval, 01062 sequence_values_stack_t &sequence_values_stack) 01063 { 01064 DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl); 01065 01066 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0; 01067 01068 DBG2(cerr << " reading row " << i << endl); 01069 bool status = read_row(i, dds, eval, true); 01070 DBG2(cerr << " status: " << status << endl); 01071 DBG2(cerr << " ending row number: " << get_ending_row_number() << endl); 01072 01073 if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) { 01074 BaseType *btp = get_parent(); 01075 if (btp && btp->type() == dods_sequence_c) { 01076 // This call will read the values for the parent sequences and 01077 // then allocate a new instance for the leaf and push that onto 01078 // the stack. 01079 dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two( 01080 dds, eval, sequence_values_stack); 01081 } 01082 01083 // intern_data_parent_part_two pushes the d_values field of the leaf 01084 // onto the stack, so this operation grabs that value and then loads 01085 // data into it. 01086 SequenceValues *values = sequence_values_stack.top(); 01087 DBG2(cerr << " using values = " << values << endl); 01088 01089 while (status && (get_ending_row_number() == -1 01090 || i <= get_ending_row_number())) { 01091 i += get_row_stride(); 01092 01093 // Copy data from the object's fields to this new BaeTypeRow instance 01094 BaseTypeRow *row_data = new BaseTypeRow; 01095 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 01096 if ((*iter)->send_p()) { 01097 row_data->push_back((*iter)->ptr_duplicate()); 01098 } 01099 } 01100 01101 DBG2(cerr << " pushing values for " << name() 01102 << " to " << values << endl); 01103 // Save the row_data to values(). 01104 values->push_back(row_data); 01105 01106 set_read_p(false); // ...so this will read the next instance 01107 // Read the ith row into this object's fields 01108 status = read_row(i, dds, eval, true); 01109 } 01110 01111 DBG2(cerr << " popping d_values (" << sequence_values_stack.top() 01112 << ") off stack; size: " << sequence_values_stack.size() << endl); 01113 sequence_values_stack.pop(); 01114 } 01115 DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl); 01116 } 01117 01138 bool 01139 Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 01140 { 01141 DataDDS *dd = dynamic_cast<DataDDS *>(dds); 01142 if (!dd) 01143 throw InternalErr("Expected argument 'dds' to be a DataDDS!"); 01144 01145 DBG2(cerr << "Reading from server/protocol version: " 01146 << dd->get_protocol_major() << "." << dd->get_protocol_minor() 01147 << endl); 01148 01149 // Check for old servers. 01150 if (dd->get_protocol_major() < 2) { 01151 throw Error(string("The protocl version (") + dd->get_protocol() 01152 + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator."); 01153 } 01154 01155 while (true) { 01156 // Grab the sequence stream's marker. 01157 unsigned char marker = read_marker(um); 01158 if (is_end_of_sequence(marker)) 01159 break; // EXIT the while loop here!!! 01160 else if (is_start_of_instance(marker)) { 01161 d_row_number++; 01162 DBG2(cerr << "Reading row " << d_row_number << " of " 01163 << name() << endl); 01164 BaseTypeRow *bt_row_ptr = new BaseTypeRow; 01165 // Read the instance's values, building up the row 01166 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 01167 BaseType *bt_ptr = (*iter)->ptr_duplicate(); 01168 bt_ptr->deserialize(um, dds, reuse); 01169 DBG2(cerr << "Deserialized " << bt_ptr->name() << " (" 01170 << bt_ptr << ") = "); 01171 DBG2(bt_ptr->print_val(stderr, "")); 01172 bt_row_ptr->push_back(bt_ptr); 01173 } 01174 // Append this row to those accumulated. 01175 d_values.push_back(bt_row_ptr); 01176 } 01177 else 01178 throw Error("I could not read the expected Sequence data stream marker!"); 01179 }; 01180 01181 return false; 01182 } 01183 01184 // Return the current row number. 01185 01197 int 01198 Sequence::get_starting_row_number() 01199 { 01200 return d_starting_row_number; 01201 } 01202 01213 int 01214 Sequence::get_row_stride() 01215 { 01216 return d_row_stride; 01217 } 01218 01230 int 01231 Sequence::get_ending_row_number() 01232 { 01233 return d_ending_row_number; 01234 } 01235 01244 void 01245 Sequence::set_row_number_constraint(int start, int stop, int stride) 01246 { 01247 if (stop < start) 01248 throw Error(malformed_expr, "Starting row number must precede the ending row number."); 01249 01250 d_starting_row_number = start; 01251 d_row_stride = stride; 01252 d_ending_row_number = stop; 01253 } 01254 01257 unsigned int 01258 Sequence::val2buf(void *, bool) 01259 { 01260 throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation."); 01261 return sizeof(Sequence); 01262 } 01263 01268 unsigned int 01269 Sequence::buf2val(void **) 01270 { 01271 throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()"); 01272 return sizeof(Sequence); 01273 } 01274 //#if FILE_METHODS 01275 void 01276 Sequence::print_one_row(FILE *out, int row, string space, 01277 bool print_row_num) 01278 { 01279 if (print_row_num) 01280 fprintf(out, "\n%s%d: ", space.c_str(), row) ; 01281 01282 fprintf(out, "{ ") ; 01283 01284 int elements = element_count() - 1; 01285 int j; 01286 BaseType *bt_ptr; 01287 // Print first N-1 elements of the row. 01288 for (j = 0; j < elements; ++j) { 01289 bt_ptr = var_value(row, j); 01290 if (bt_ptr) { // data 01291 if (bt_ptr->type() == dods_sequence_c) 01292 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01293 (out, space + " ", false, print_row_num); 01294 else 01295 bt_ptr->print_val(out, space, false); 01296 fprintf(out, ", ") ; 01297 } 01298 } 01299 01300 // Print Nth element; end with a `}.' 01301 bt_ptr = var_value(row, j); 01302 if (bt_ptr) { // data 01303 if (bt_ptr->type() == dods_sequence_c) 01304 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01305 (out, space + " ", false, print_row_num); 01306 else 01307 bt_ptr->print_val(out, space, false); 01308 } 01309 01310 fprintf(out, " }") ; 01311 } 01312 //#endif 01313 void 01314 Sequence::print_one_row(ostream &out, int row, string space, 01315 bool print_row_num) 01316 { 01317 if (print_row_num) 01318 out << "\n" << space << row << ": " ; 01319 01320 out << "{ " ; 01321 01322 int elements = element_count(); 01323 int j = 0; 01324 BaseType *bt_ptr = 0; 01325 01326 // This version of print_one_row() works for both data read with 01327 // deserialize(), where each variable is assumed to have valid data, and 01328 // intern_data(), where some/many variables do not. Because of that, it's 01329 // not correct to assume that all of the elements will be printed, which 01330 // is what the old code did. 01331 // Print the first value 01332 while (j < elements && !bt_ptr) { 01333 bt_ptr = var_value(row, j++); 01334 if (bt_ptr) { // data 01335 if (bt_ptr->type() == dods_sequence_c) 01336 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01337 (out, space + " ", false, print_row_num); 01338 else 01339 bt_ptr->print_val(out, space, false); 01340 } 01341 } 01342 01343 // Print the remaining values 01344 while (j < elements) { 01345 bt_ptr = var_value(row, j++); 01346 if (bt_ptr) { // data 01347 out << ", "; 01348 if (bt_ptr->type() == dods_sequence_c) 01349 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01350 (out, space + " ", false, print_row_num); 01351 else 01352 bt_ptr->print_val(out, space, false); 01353 } 01354 } 01355 01356 #if 0 01357 // old version 01358 int elements = element_count() - 1; 01359 int j; 01360 BaseType *bt_ptr; 01361 // Print first N-1 elements of the row. 01362 for (j = 0; j < elements; ++j) { 01363 bt_ptr = var_value(row, j); 01364 if (bt_ptr) { // data 01365 if (bt_ptr->type() == dods_sequence_c) 01366 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01367 (out, space + " ", false, print_row_num); 01368 else 01369 bt_ptr->print_val(out, space, false); 01370 out << ", " ; 01371 } 01372 } 01373 01374 // Print Nth element; end with a `}.' 01375 bt_ptr = var_value(row, j); 01376 if (bt_ptr) { // data 01377 if (bt_ptr->type() == dods_sequence_c) 01378 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01379 (out, space + " ", false, print_row_num); 01380 else 01381 bt_ptr->print_val(out, space, false); 01382 } 01383 #endif 01384 01385 out << " }" ; 01386 } 01387 01388 //#if FILE_METHODS 01389 void 01390 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, 01391 bool print_row_numbers) 01392 { 01393 if (print_decl_p) { 01394 print_decl(out, space, false); 01395 fprintf(out, " = ") ; 01396 } 01397 01398 fprintf(out, "{ ") ; 01399 01400 int rows = number_of_rows() - 1; 01401 int i; 01402 for (i = 0; i < rows; ++i) { 01403 print_one_row(out, i, space, print_row_numbers); 01404 fprintf(out, ", ") ; 01405 } 01406 print_one_row(out, i, space, print_row_numbers); 01407 01408 fprintf(out, " }") ; 01409 01410 if (print_decl_p) 01411 fprintf(out, ";\n") ; 01412 } 01413 //#endif 01414 void 01415 Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, 01416 bool print_row_numbers) 01417 { 01418 if (print_decl_p) { 01419 print_decl(out, space, false); 01420 out << " = " ; 01421 } 01422 01423 out << "{ " ; 01424 01425 int rows = number_of_rows() - 1; 01426 int i; 01427 for (i = 0; i < rows; ++i) { 01428 print_one_row(out, i, space, print_row_numbers); 01429 out << ", " ; 01430 } 01431 print_one_row(out, i, space, print_row_numbers); 01432 01433 out << " }" ; 01434 01435 if (print_decl_p) 01436 out << ";\n" ; 01437 } 01438 //#if FILE_METHODS 01439 void 01440 Sequence::print_val(FILE *out, string space, bool print_decl_p) 01441 { 01442 print_val_by_rows(out, space, print_decl_p, false); 01443 } 01444 //#endif 01445 void 01446 Sequence::print_val(ostream &out, string space, bool print_decl_p) 01447 { 01448 print_val_by_rows(out, space, print_decl_p, false); 01449 } 01450 01451 01452 bool 01453 Sequence::check_semantics(string &msg, bool all) 01454 { 01455 if (!BaseType::check_semantics(msg)) 01456 return false; 01457 01458 if (!unique_names(_vars, name(), type_name(), msg)) 01459 return false; 01460 01461 if (all) 01462 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 01463 if (!(*i)->check_semantics(msg, true)) { 01464 return false; 01465 } 01466 } 01467 01468 return true; 01469 } 01470 01471 void 01472 Sequence::set_leaf_p(bool state) 01473 { 01474 d_leaf_sequence = state; 01475 } 01476 01477 bool 01478 Sequence::is_leaf_sequence() 01479 { 01480 return d_leaf_sequence; 01481 } 01482 01507 void 01508 Sequence::set_leaf_sequence(int lvl) 01509 { 01510 bool has_child_sequence = false; 01511 01512 if (lvl == 1) d_top_most = true; 01513 01514 DBG2(cerr << "Processing sequence " << name() << endl); 01515 01516 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 01517 // About the test for send_p(): Only descend into a sequence if it has 01518 // fields that might be sent. Thus if, in a two-level sequence, nothing 01519 // in the lower level is to be sent, the upper level is marked as the 01520 // leaf sequence. This ensures that values _will_ be sent (see the comment 01521 // in serialize_leaf() and serialize_parent_part_one()). 01522 if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) { 01523 if (has_child_sequence) 01524 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator."); 01525 01526 has_child_sequence = true; 01527 dynamic_cast<Sequence&>(**iter).set_leaf_sequence(++lvl); 01528 } 01529 else if ((*iter)->type() == dods_structure_c) { 01530 dynamic_cast<Structure&>(**iter).set_leaf_sequence(lvl); 01531 } 01532 } 01533 01534 if (!has_child_sequence) 01535 set_leaf_p(true); 01536 else 01537 set_leaf_p(false); 01538 01539 DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl); 01540 } 01541 01550 void 01551 Sequence::dump(ostream &strm) const 01552 { 01553 strm << DapIndent::LMarg << "Sequence::dump - (" 01554 << (void *)this << ")" << endl ; 01555 DapIndent::Indent() ; 01556 Constructor::dump(strm) ; 01557 strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number 01558 << endl ; 01559 strm << DapIndent::LMarg << "bracket notation information:" << endl ; 01560 DapIndent::Indent() ; 01561 strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number 01562 << endl ; 01563 strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ; 01564 strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number 01565 << endl ; 01566 DapIndent::UnIndent() ; 01567 01568 strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ; 01569 strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ; 01570 strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence 01571 << endl ; 01572 strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most 01573 << endl ; 01574 DapIndent::UnIndent() ; 01575 } 01576 01577 } // namespace libdap 01578