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 "Byte.h" 00046 #include "Int16.h" 00047 #include "UInt16.h" 00048 #include "Int32.h" 00049 #include "UInt32.h" 00050 #include "Float32.h" 00051 #include "Float64.h" 00052 #include "Str.h" 00053 #include "Url.h" 00054 #include "Array.h" 00055 #include "Structure.h" 00056 #include "Sequence.h" 00057 #include "Grid.h" 00058 00059 #include "debug.h" 00060 #include "Error.h" 00061 #include "InternalErr.h" 00062 #include "Sequence.h" 00063 #include "DDS.h" 00064 #include "DataDDS.h" 00065 #include "util.h" 00066 #include "InternalErr.h" 00067 #include "escaping.h" 00068 00069 using namespace std; 00070 00071 namespace libdap { 00072 00073 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101 00074 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010 00075 00076 // Private member functions 00077 00078 void 00079 Sequence::_duplicate(const Sequence &s) 00080 { 00081 d_row_number = s.d_row_number; 00082 d_starting_row_number = s.d_starting_row_number; 00083 d_ending_row_number = s.d_ending_row_number; 00084 d_row_stride = s.d_row_stride; 00085 d_leaf_sequence = s.d_leaf_sequence; 00086 d_unsent_data = s.d_unsent_data; 00087 d_wrote_soi = s.d_wrote_soi; 00088 d_top_most = s.d_top_most; 00089 00090 Sequence &cs = const_cast<Sequence &>(s); 00091 00092 // Copy the template BaseType objects. 00093 for (Vars_iter i = cs.var_begin(); i != cs.var_end(); i++) { 00094 add_var((*i)) ; 00095 } 00096 00097 // Copy the BaseType objects used to hold values. 00098 for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin(); 00099 rows_iter != cs.d_values.end(); 00100 rows_iter++) { 00101 // Get the current BaseType Row 00102 BaseTypeRow *src_bt_row_ptr = *rows_iter; 00103 // Create a new row. 00104 BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow; 00105 // Copy the BaseType objects from a row to new BaseType objects. 00106 // Push new BaseType objects onto new row. 00107 for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin(); 00108 bt_row_iter != src_bt_row_ptr->end(); 00109 bt_row_iter++) { 00110 BaseType *src_bt_ptr = *bt_row_iter; 00111 BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate(); 00112 dest_bt_row_ptr->push_back(dest_bt_ptr); 00113 } 00114 // Push new row onto d_values. 00115 d_values.push_back(dest_bt_row_ptr); 00116 } 00117 } 00118 00119 static void 00120 write_end_of_sequence(Marshaller &m) 00121 { 00122 m.put_opaque( (char *)&end_of_sequence, 1 ) ; 00123 } 00124 00125 static void 00126 write_start_of_instance(Marshaller &m) 00127 { 00128 m.put_opaque( (char *)&start_of_instance, 1 ) ; 00129 } 00130 00131 static unsigned char 00132 read_marker(UnMarshaller &um) 00133 { 00134 unsigned char marker; 00135 um.get_opaque( (char *)&marker, 1 ) ; 00136 00137 return marker; 00138 } 00139 00140 static bool 00141 is_start_of_instance(unsigned char marker) 00142 { 00143 return (marker == start_of_instance); 00144 } 00145 00146 static bool 00147 is_end_of_sequence(unsigned char marker) 00148 { 00149 return (marker == end_of_sequence); 00150 } 00151 00152 // Public member functions 00153 00162 Sequence::Sequence(const string &n) : Constructor(n, dods_sequence_c), 00163 d_row_number(-1), d_starting_row_number(-1), 00164 d_row_stride(1), d_ending_row_number(-1), 00165 d_unsent_data(false), d_wrote_soi(false), 00166 d_leaf_sequence(false), d_top_most(false) 00167 {} 00168 00179 Sequence::Sequence(const string &n, const string &d) 00180 : Constructor(n, d, dods_sequence_c), 00181 d_row_number(-1), d_starting_row_number(-1), 00182 d_row_stride(1), d_ending_row_number(-1), 00183 d_unsent_data(false), d_wrote_soi(false), 00184 d_leaf_sequence(false), d_top_most(false) 00185 {} 00186 00188 Sequence::Sequence(const Sequence &rhs) : Constructor(rhs) 00189 { 00190 _duplicate(rhs); 00191 } 00192 00193 BaseType * 00194 Sequence::ptr_duplicate() 00195 { 00196 return new Sequence(*this); 00197 } 00198 00199 static inline void 00200 delete_bt(BaseType *bt_ptr) 00201 { 00202 DBG2(cerr << "In delete_bt: " << bt_ptr << endl); 00203 delete bt_ptr; bt_ptr = 0; 00204 } 00205 00206 static inline void 00207 delete_rows(BaseTypeRow *bt_row_ptr) 00208 { 00209 DBG2(cerr << "In delete_rows: " << bt_row_ptr << endl); 00210 00211 for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt); 00212 00213 delete bt_row_ptr; bt_row_ptr = 0; 00214 } 00215 00216 Sequence::~Sequence() 00217 { 00218 DBG2(cerr << "Entering Sequence::~Sequence" << endl); 00219 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00220 BaseType *btp = *i ; 00221 delete btp ; btp = 0; 00222 } 00223 00224 for_each(d_values.begin(), d_values.end(), delete_rows); 00225 DBG2(cerr << "exiting Sequence::~Sequence" << endl); 00226 } 00227 00228 Sequence & 00229 Sequence::operator=(const Sequence &rhs) 00230 { 00231 if (this == &rhs) 00232 return *this; 00233 00234 dynamic_cast<Constructor &>(*this) = rhs; // run Constructor= 00235 00236 _duplicate(rhs); 00237 00238 return *this; 00239 } 00240 00241 string 00242 Sequence::toString() 00243 { 00244 ostringstream oss; 00245 00246 oss << BaseType::toString(); 00247 00248 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00249 oss << (*i)->toString(); 00250 } 00251 00252 oss << endl; 00253 00254 return oss.str(); 00255 } 00256 00257 int 00258 Sequence::element_count(bool leaves) 00259 { 00260 if (!leaves) 00261 return _vars.size(); 00262 else { 00263 int i = 0; 00264 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00265 i += (*iter)->element_count(true); 00266 } 00267 return i; 00268 } 00269 } 00270 00271 bool 00272 Sequence::is_linear() 00273 { 00274 bool linear = true; 00275 bool seq_found = false; 00276 for (Vars_iter iter = _vars.begin(); linear && iter != _vars.end(); iter++) { 00277 if ((*iter)->type() == dods_sequence_c) { 00278 // A linear sequence cannot have more than one child seq. at any 00279 // one level. If we've already found a seq at this level, return 00280 // false. 00281 if (seq_found) { 00282 linear = false; 00283 break; 00284 } 00285 seq_found = true; 00286 linear = dynamic_cast<Sequence *>((*iter))->is_linear(); 00287 } 00288 else if ((*iter)->type() == dods_structure_c) { 00289 linear = dynamic_cast<Structure*>((*iter))->is_linear(); 00290 } 00291 else { 00292 // A linear sequence cannot have Arrays, Lists or Grids. 00293 linear = (*iter)->is_simple_type(); 00294 } 00295 } 00296 00297 return linear; 00298 } 00299 00300 void 00301 Sequence::set_send_p(bool state) 00302 { 00303 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00304 (*i)->set_send_p(state); 00305 } 00306 00307 BaseType::set_send_p(state); 00308 } 00309 00310 void 00311 Sequence::set_read_p(bool state) 00312 { 00313 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00314 (*i)->set_read_p(state); 00315 } 00316 00317 BaseType::set_read_p(state); 00318 } 00319 00320 void 00321 Sequence::set_in_selection(bool state) 00322 { 00323 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00324 (*i)->set_in_selection(state); 00325 } 00326 00327 BaseType::set_in_selection(state); 00328 } 00329 00339 void 00340 Sequence::add_var(BaseType *bt, Part) 00341 { 00342 if (!bt) 00343 throw InternalErr(__FILE__, __LINE__, 00344 "Cannot add variable: NULL pointer"); 00345 // Jose Garcia 00346 // We append a copy of bt so the owner of bt is free to deallocate 00347 00348 BaseType *bt_copy = bt->ptr_duplicate(); 00349 bt_copy->set_parent(this); 00350 _vars.push_back(bt_copy); 00351 } 00352 00353 // Deprecated 00354 BaseType * 00355 Sequence::var(const string &n, btp_stack &s) 00356 { 00357 string name = www2id(n); 00358 00359 BaseType *btp = m_exact_match(name, &s); 00360 if (btp) 00361 return btp; 00362 00363 return m_leaf_match(name, &s); 00364 } 00365 00366 BaseType * 00367 Sequence::var(const string &name, bool exact_match, btp_stack *s) 00368 { 00369 string n = www2id(name); 00370 00371 if (exact_match) 00372 return m_exact_match(n, s); 00373 else 00374 return m_leaf_match(n, s); 00375 } 00376 00377 BaseType * 00378 Sequence::m_leaf_match(const string &name, btp_stack *s) 00379 { 00380 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00381 if ((*i)->name() == name) { 00382 if (s) 00383 s->push(static_cast<BaseType *>(this)); 00384 return *i; 00385 } 00386 if ((*i)->is_constructor_type()) { 00387 BaseType *btp = (*i)->var(name, false, s); 00388 if (btp) { 00389 if (s) 00390 s->push(static_cast<BaseType *>(this)); 00391 return btp; 00392 } 00393 } 00394 } 00395 00396 return 0; 00397 } 00398 00399 BaseType * 00400 Sequence::m_exact_match(const string &name, btp_stack *s) 00401 { 00402 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00403 if ((*i)->name() == name) { 00404 if (s) 00405 s->push(static_cast<BaseType *>(this)); 00406 return *i; 00407 } 00408 } 00409 00410 string::size_type dot_pos = name.find("."); // zero-based index of `.' 00411 if (dot_pos != string::npos) { 00412 string aggregate = name.substr(0, dot_pos); 00413 string field = name.substr(dot_pos + 1); 00414 00415 BaseType *agg_ptr = var(aggregate); 00416 if (agg_ptr) { 00417 if (s) 00418 s->push(static_cast<BaseType *>(this)); 00419 return agg_ptr->var(field, true, s); // recurse 00420 } 00421 else 00422 return 0; // qualified names must be *fully* qualified 00423 } 00424 00425 return 0; 00426 } 00427 00432 BaseTypeRow * 00433 Sequence::row_value(size_t row) 00434 { 00435 if (row >= d_values.size()) 00436 return 0; 00437 return d_values[row]; 00438 } 00439 00446 void 00447 Sequence::set_value(SequenceValues &values) 00448 { 00449 d_values = values; 00450 } 00451 00454 SequenceValues 00455 Sequence::value() 00456 { 00457 return d_values; 00458 } 00459 00465 BaseType * 00466 Sequence::var_value(size_t row, const string &name) 00467 { 00468 BaseTypeRow *bt_row_ptr = row_value(row); 00469 if (!bt_row_ptr) 00470 return 0; 00471 00472 BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin(); 00473 BaseTypeRow::iterator bt_row_end = bt_row_ptr->end(); 00474 while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name) 00475 ++bt_row_iter; 00476 00477 if (bt_row_iter == bt_row_end) 00478 return 0; 00479 else 00480 return *bt_row_iter; 00481 } 00482 00488 BaseType * 00489 Sequence::var_value(size_t row, size_t i) 00490 { 00491 BaseTypeRow *bt_row_ptr = row_value(row); 00492 if (!bt_row_ptr) 00493 return 0; 00494 00495 if (i >= bt_row_ptr->size()) 00496 return 0; 00497 00498 return (*bt_row_ptr)[i]; 00499 } 00500 00501 unsigned int 00502 Sequence::width() 00503 { 00504 unsigned int sz = 0; 00505 00506 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00507 sz += (*i)->width(); 00508 } 00509 00510 return sz; 00511 } 00512 00513 // This version returns -1. Each API-specific subclass should define a more 00514 // reasonable version. jhrg 5/24/96 00515 00531 int 00532 Sequence::length() 00533 { 00534 return -1; 00535 } 00536 00537 00538 int 00539 Sequence::number_of_rows() 00540 { 00541 return d_values.size(); 00542 } 00543 00547 void 00548 Sequence::reset_row_number() 00549 { 00550 d_row_number = -1; 00551 } 00552 00553 // Notes: 00554 // Assume that read() is implemented so that, when reading data for a nested 00555 // sequence, only the outer most level is *actually* read. 00556 // This is a consequence of our current (12/7/99) implementation of 00557 // the JGOFS server (which is the only server to actually use nested 00558 // sequences). 12/7/99 jhrg 00559 // 00560 // Stop assuming this. This logic is being moved into the JGOFS server 00561 // itself. 6/1/2001 jhrg 00562 00563 // The read() function returns a boolean value, with TRUE 00564 // indicating that read() should be called again because there's 00565 // more data to read, and FALSE indicating there's no more data 00566 // to read. Note that this behavior is necessary to properly 00567 // handle variables that contain Sequences. Jose Garcia If an 00568 // error exists while reading, the implementers of the surrogate 00569 // library SHOULD throw an Error object which will propagate 00570 // beyond this point to to the original caller. 00571 // Jose Garcia 00572 00605 bool 00606 Sequence::read_row(int row, DDS &dds, 00607 ConstraintEvaluator &eval, bool ce_eval) 00608 { 00609 DBG2(cerr << "Entering Sequence::read_row for " << name() << endl); 00610 if (row < d_row_number) 00611 throw InternalErr("Trying to back up inside a sequence!"); 00612 00613 DBG2(cerr << "read_row: row number " << row 00614 << ", current row " << d_row_number << endl); 00615 if (row == d_row_number) 00616 { 00617 DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl); 00618 return true; 00619 } 00620 00621 dds.timeout_on(); 00622 00623 int eof = 0; // Start out assuming EOF is false. 00624 while (!eof && d_row_number < row) { 00625 if (!read_p()) { 00626 eof = (read() == false); 00627 } 00628 00629 // Advance the row number if ce_eval is false (we're not supposed to 00630 // evaluate the selection) or both ce_eval and the selection are 00631 // true. 00632 if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) 00633 d_row_number++; 00634 00635 set_read_p(false); // ...so that the next instance will be read 00636 } 00637 00638 // Once we finish the above loop, set read_p to true so that the caller 00639 // knows that data *has* been read. This is how the read() methods of the 00640 // elements of the sequence know to not call read() but instead look for 00641 // data values inside themselves. 00642 set_read_p(true); 00643 00644 dds.timeout_off(); 00645 00646 // Return true if we have valid data, false if we've read to the EOF. 00647 DBG2(cerr << "Leaving Sequence::read_row for " << name() 00648 << " with " << (eof == 0) << endl); 00649 return eof == 0; 00650 } 00651 00652 // Private. This is used to process constraints on the rows of a sequence. 00653 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This 00654 // odd-looking logic first checks if d_ending_row_number is the sentinel 00655 // value of -1. If so, the sequence was not constrained by row number and 00656 // this method should never return true (which indicates that we're at the 00657 // end of a row-number constraint). If d_ending_row_number is not -1, then is 00658 // \e i at the end point? 6/1/2001 jhrg 00659 inline bool 00660 Sequence::is_end_of_rows(int i) 00661 { 00662 return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number)); 00663 } 00664 00725 bool 00726 Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, 00727 Marshaller &m, bool ce_eval) 00728 { 00729 DBG2(cerr << "Entering Sequence::serialize for " << name() << endl); 00730 00731 // Special case leaf sequences! 00732 if (is_leaf_sequence()) 00733 return serialize_leaf(dds, eval, m, ce_eval); 00734 else 00735 return serialize_parent_part_one(dds, eval, m); 00736 } 00737 00738 // We know this is not a leaf Sequence. That means that this Sequence holds 00739 // another Sequence as one of its fields _and_ that child Sequence triggers 00740 // the actual transmission of values. 00741 00742 bool 00743 Sequence::serialize_parent_part_one(DDS &dds, 00744 ConstraintEvaluator &eval, Marshaller &m) 00745 { 00746 DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl); 00747 00748 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0; 00749 00750 // read_row returns true if valid data was read, false if the EOF was 00751 // found. 6/1/2001 jhrg 00752 // Since this is a parent sequence, read the row ignoring the CE (all of 00753 // the CE clauses will be evaluated by the leaf sequence). 00754 bool status = read_row(i, dds, eval, false); 00755 DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl); 00756 00757 while (status && !is_end_of_rows(i)) { 00758 i += d_row_stride; 00759 00760 // DBG(cerr << "Writing Start of Instance marker" << endl); 00761 // write_start_of_instance(sink); 00762 00763 // In this loop serialize will signal an error with an exception. 00764 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00765 // Only call serialize for child Sequences; the leaf sequence 00766 // will trigger the transmission of values for its parents (this 00767 // sequence and maybe others) once it gets soem valid data to 00768 // send. 00769 // Note that if the leaf sequence has no variables in the current 00770 // projection, its serialize() method will never be called and that's 00771 // the method that triggers actually sending values. Thus the leaf 00772 // sequence must be the lowest level sequence with values whose send_p 00773 // property is true. 00774 if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) 00775 (*iter)->serialize(eval, dds, m); 00776 } 00777 00778 set_read_p(false); // ...so this will read the next instance 00779 00780 status = read_row(i, dds, eval, false); 00781 DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl); 00782 } 00783 // Reset current row number for next nested sequence element. 00784 d_row_number = -1; 00785 00786 // Always write the EOS marker? 12/23/04 jhrg 00787 // Yes. According to DAP2, a completely empty response is signalled by 00788 // a return value of only the EOS marker for the outermost sequence. 00789 if (d_top_most || d_wrote_soi) { 00790 DBG(cerr << "Writing End of Sequence marker" << endl); 00791 write_end_of_sequence(m); 00792 d_wrote_soi = false; 00793 } 00794 00795 return true; // Signal errors with exceptions. 00796 } 00797 00798 // If we are here then we know that this is 'parent sequence' and that the 00799 // leaf seq has found valid data to send. We also know that 00800 // serialize_parent_part_one has been called so data are in the instance's 00801 // fields. This is wheree we send data. Whereas ..._part_one() contains a 00802 // loop to iterate over all of rows in a parent sequence, this does not. This 00803 // method assumes that the serialize_leaf() will call it each time it needs 00804 // to be called. 00805 // 00806 // NB: This code only works if the child sequences appear after all other 00807 // variables. 00808 void 00809 Sequence::serialize_parent_part_two(DDS &dds, 00810 ConstraintEvaluator &eval, Marshaller &m) 00811 { 00812 DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl); 00813 00814 BaseType *btp = get_parent(); 00815 if (btp && btp->type() == dods_sequence_c) 00816 dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m); 00817 00818 if (d_unsent_data) { 00819 DBG(cerr << "Writing Start of Instance marker" << endl); 00820 d_wrote_soi = true; 00821 write_start_of_instance(m); 00822 00823 // In this loop serialize will signal an error with an exception. 00824 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00825 // Send all the non-sequence variables 00826 DBG(cerr << "Sequence::serialize_parent_part_two(), serializing " 00827 << (*iter)->name() << endl); 00828 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) { 00829 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl); 00830 (*iter)->serialize(eval, dds, m, false); 00831 } 00832 } 00833 00834 d_unsent_data = false; // read should set this. 00835 } 00836 } 00837 00838 // This code is only run by a leaf sequence. Note that a one level sequence 00839 // is also a leaf sequence. 00840 bool 00841 Sequence::serialize_leaf(DDS &dds, 00842 ConstraintEvaluator &eval, Marshaller &m, bool ce_eval) 00843 { 00844 DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl); 00845 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0; 00846 00847 // read_row returns true if valid data was read, false if the EOF was 00848 // found. 6/1/2001 jhrg 00849 bool status = read_row(i, dds, eval, ce_eval); 00850 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl); 00851 00852 // Once the first valid (satisfies the CE) row of the leaf sequence has 00853 // been read, we know we're going to send data. Send the current instance 00854 // of the parent/ancestor sequences now, if there are any. We only need 00855 // to do this once, hence it's not inside the while loop, but we only 00856 // send the parent seq data _if_ there's data in the leaf to send, that's 00857 // why we wait until after the first call to read_row() here in the leaf 00858 // sequence. 00859 // 00860 // NB: It's important to only call serialize_parent_part_two() for a 00861 // Sequence that really is the parent of a leaf sequence. The fancy cast 00862 // will throw and exception if btp is not a Sequence, but doesn't test 00863 // that it's a parent sequence as we've defined them here. 00864 if (status && !is_end_of_rows(i)) { 00865 BaseType *btp = get_parent(); 00866 if (btp && btp->type() == dods_sequence_c) 00867 dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, 00868 eval, m); 00869 } 00870 00871 d_wrote_soi = false; 00872 while (status && !is_end_of_rows(i)) { 00873 i += d_row_stride; 00874 00875 DBG(cerr << "Writing Start of Instance marker" << endl); 00876 d_wrote_soi = true; 00877 write_start_of_instance(m); 00878 00879 // In this loop serialize will signal an error with an exception. 00880 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00881 DBG(cerr << "Sequence::serialize_leaf(), serializing " 00882 << (*iter)->name() << endl); 00883 if ((*iter)->send_p()) { 00884 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl); 00885 (*iter)->serialize(eval, dds, m, false); 00886 } 00887 } 00888 00889 set_read_p(false); // ...so this will read the next instance 00890 00891 status = read_row(i, dds, eval, ce_eval); 00892 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl); 00893 } 00894 00895 // Only write the EOS marker if there's a matching Start Of Instnace 00896 // Marker in the stream. 00897 if (d_wrote_soi || d_top_most) { 00898 DBG(cerr << "Writing End of Sequence marker" << endl); 00899 write_end_of_sequence(m); 00900 } 00901 00902 return true; // Signal errors with exceptions. 00903 } 00904 00927 void 00928 Sequence::intern_data(ConstraintEvaluator &eval, DDS &dds) 00929 { 00930 DBG(cerr << "Sequence::intern_data - for " << name() << endl); 00931 DBG2(cerr << " intern_data, values: " << &d_values << endl); 00932 00933 // Why use a stack instead of return values? We need the stack because 00934 // Sequences neted three of more levels deep will loose the middle 00935 // instances when the intern_data_parent_part_two() code is run. 00936 sequence_values_stack_t sequence_values_stack; 00937 00938 DBG2(cerr << " pushing d_values of " << name() << " (" << &d_values 00939 << ") on stack; size: " << sequence_values_stack.size() << endl); 00940 sequence_values_stack.push(&d_values); 00941 00942 intern_data_private(eval, dds, sequence_values_stack); 00943 } 00944 00945 void 00946 Sequence::intern_data_private(ConstraintEvaluator &eval, 00947 DDS &dds, 00948 sequence_values_stack_t &sequence_values_stack) 00949 { 00950 DBG(cerr << "Entering intern_data_private for " << name() << endl); 00951 00952 if (is_leaf_sequence()) 00953 intern_data_for_leaf(dds, eval, sequence_values_stack); 00954 else 00955 intern_data_parent_part_one(dds, eval, sequence_values_stack); 00956 } 00957 00958 void 00959 Sequence::intern_data_parent_part_one(DDS & dds, 00960 ConstraintEvaluator & eval, 00961 sequence_values_stack_t & 00962 sequence_values_stack) 00963 { 00964 DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl); 00965 00966 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0; 00967 00968 // read_row returns true if valid data was read, false if the EOF was 00969 // found. 6/1/2001 jhrg 00970 // Since this is a parent sequence, read the row ignoring the CE (all of 00971 // the CE clauses will be evaluated by the leaf sequence). 00972 bool status = read_row(i, dds, eval, false); 00973 00974 // Grab the current size of the value stack. We do this because it is 00975 // possible that no nested sequences for this row happened to be 00976 // selected because of a constract evaluation or the last row is not 00977 // selected because of a constraint evaluation. In either case, no 00978 // nested sequence d_values are pused onto the stack, so there is 00979 // nothing to pop at the end of this function. pcw 07/14/08 00980 SequenceValues::size_type orig_stack_size = sequence_values_stack.size() ; 00981 00982 while (status 00983 && (get_ending_row_number() == -1 00984 || i <= get_ending_row_number())) 00985 { 00986 i += get_row_stride(); 00987 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 00988 if ((*iter)->send_p()) { 00989 switch ((*iter)->type()) { 00990 case dods_sequence_c: 00991 dynamic_cast<Sequence&>(**iter).intern_data_private( 00992 eval, dds, sequence_values_stack); 00993 break; 00994 00995 default: 00996 (*iter)->intern_data(eval, dds); 00997 break; 00998 } 00999 } 01000 } 01001 01002 set_read_p(false); // ...so this will read the next instance 01003 01004 status = read_row(i, dds, eval, false); 01005 } 01006 01007 // Reset current row number for next nested sequence element. 01008 reset_row_number(); 01009 01010 // if the size of the stack is larger than the original size (retrieved 01011 // above) then pop the top set of d_values from the stack. If it's the 01012 // same, then no nested sequences, or possible the last nested sequence, 01013 // were pushed onto the stack, so there is nothing to pop. 01014 if( sequence_values_stack.size() > orig_stack_size ) 01015 { 01016 DBG2(cerr << " popping d_values (" << sequence_values_stack.top() 01017 << ") off stack; size: " << sequence_values_stack.size() << endl); 01018 sequence_values_stack.pop(); 01019 } 01020 DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl); 01021 } 01022 01023 void 01024 Sequence::intern_data_parent_part_two(DDS &dds, 01025 ConstraintEvaluator &eval, 01026 sequence_values_stack_t &sequence_values_stack) 01027 { 01028 DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl); 01029 01030 BaseType *btp = get_parent(); 01031 if (btp && btp->type() == dods_sequence_c) { 01032 dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two( 01033 dds, eval, sequence_values_stack); 01034 } 01035 01036 DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl); 01037 SequenceValues *values = sequence_values_stack.top(); 01038 DBG2(cerr << " using values = " << (void *)values << endl); 01039 01040 if (get_unsent_data()) { 01041 BaseTypeRow *row_data = new BaseTypeRow; 01042 01043 // In this loop transfer_data will signal an error with an exception. 01044 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 01045 01046 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) { 01047 row_data->push_back((*iter)->ptr_duplicate()); 01048 } 01049 else if ((*iter)->send_p()) { //Sequence; must be the last variable 01050 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate()); 01051 if (!tmp) 01052 throw InternalErr(__FILE__, __LINE__, "Expected a Sequence."); 01053 row_data->push_back(tmp); 01054 DBG2(cerr << " pushing d_values of " << tmp->name() 01055 << " (" << &(tmp->d_values) 01056 << ") on stack; size: " << sequence_values_stack.size() 01057 << endl); 01058 // This pushes the d_values field of the newly created leaf 01059 // Sequence onto the stack. The code then returns to intern 01060 // _data_for_leaf() where this value will be used. 01061 sequence_values_stack.push(&(tmp->d_values)); 01062 } 01063 } 01064 01065 DBG2(cerr << " pushing values for " << name() 01066 << " to " << values << endl); 01067 values->push_back(row_data); 01068 set_unsent_data(false); 01069 } 01070 DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl); 01071 } 01072 01073 void 01074 Sequence::intern_data_for_leaf(DDS &dds, 01075 ConstraintEvaluator &eval, 01076 sequence_values_stack_t &sequence_values_stack) 01077 { 01078 DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl); 01079 01080 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0; 01081 01082 DBG2(cerr << " reading row " << i << endl); 01083 bool status = read_row(i, dds, eval, true); 01084 DBG2(cerr << " status: " << status << endl); 01085 DBG2(cerr << " ending row number: " << get_ending_row_number() << endl); 01086 01087 if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) { 01088 BaseType *btp = get_parent(); 01089 if (btp && btp->type() == dods_sequence_c) { 01090 // This call will read the values for the parent sequences and 01091 // then allocate a new instance for the leaf and push that onto 01092 // the stack. 01093 dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two( 01094 dds, eval, sequence_values_stack); 01095 } 01096 01097 // intern_data_parent_part_two pushes the d_values field of the leaf 01098 // onto the stack, so this operation grabs that value and then loads 01099 // data into it. 01100 SequenceValues *values = sequence_values_stack.top(); 01101 DBG2(cerr << " using values = " << values << endl); 01102 01103 while (status && (get_ending_row_number() == -1 01104 || i <= get_ending_row_number())) { 01105 i += get_row_stride(); 01106 01107 // Copy data from the object's fields to this new BaeTypeRow instance 01108 BaseTypeRow *row_data = new BaseTypeRow; 01109 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 01110 if ((*iter)->send_p()) { 01111 row_data->push_back((*iter)->ptr_duplicate()); 01112 } 01113 } 01114 01115 DBG2(cerr << " pushing values for " << name() 01116 << " to " << values << endl); 01117 // Save the row_data to values(). 01118 values->push_back(row_data); 01119 01120 set_read_p(false); // ...so this will read the next instance 01121 // Read the ith row into this object's fields 01122 status = read_row(i, dds, eval, true); 01123 } 01124 01125 DBG2(cerr << " popping d_values (" << sequence_values_stack.top() 01126 << ") off stack; size: " << sequence_values_stack.size() << endl); 01127 sequence_values_stack.pop(); 01128 } 01129 DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl); 01130 } 01131 01152 bool 01153 Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 01154 { 01155 DataDDS *dd = dynamic_cast<DataDDS *>(dds); 01156 if (!dd) 01157 throw InternalErr("Expected argument 'dds' to be a DataDDS!"); 01158 01159 DBG2(cerr << "Reading from server/protocol version: " 01160 << dd->get_protocol_major() << "." << dd->get_protocol_minor() 01161 << endl); 01162 01163 // Check for old servers. 01164 if (dd->get_protocol_major() < 2) { 01165 throw Error(string("The protocl version (") + dd->get_protocol() 01166 + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator."); 01167 } 01168 01169 while (true) { 01170 // Grab the sequence stream's marker. 01171 unsigned char marker = read_marker(um); 01172 if (is_end_of_sequence(marker)) 01173 break; // EXIT the while loop here!!! 01174 else if (is_start_of_instance(marker)) { 01175 d_row_number++; 01176 DBG2(cerr << "Reading row " << d_row_number << " of " 01177 << name() << endl); 01178 BaseTypeRow *bt_row_ptr = new BaseTypeRow; 01179 // Read the instance's values, building up the row 01180 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 01181 BaseType *bt_ptr = (*iter)->ptr_duplicate(); 01182 bt_ptr->deserialize(um, dds, reuse); 01183 DBG2(cerr << "Deserialized " << bt_ptr->name() << " (" 01184 << bt_ptr << ") = "); 01185 DBG2(bt_ptr->print_val(stderr, "")); 01186 bt_row_ptr->push_back(bt_ptr); 01187 } 01188 // Append this row to those accumulated. 01189 d_values.push_back(bt_row_ptr); 01190 } 01191 else 01192 throw Error("I could not read the expected Sequence data stream marker!"); 01193 }; 01194 01195 return false; 01196 } 01197 01198 // Return the current row number. 01199 01211 int 01212 Sequence::get_starting_row_number() 01213 { 01214 return d_starting_row_number; 01215 } 01216 01227 int 01228 Sequence::get_row_stride() 01229 { 01230 return d_row_stride; 01231 } 01232 01244 int 01245 Sequence::get_ending_row_number() 01246 { 01247 return d_ending_row_number; 01248 } 01249 01258 void 01259 Sequence::set_row_number_constraint(int start, int stop, int stride) 01260 { 01261 if (stop < start) 01262 throw Error(malformed_expr, "Starting row number must precede the ending row number."); 01263 01264 d_starting_row_number = start; 01265 d_row_stride = stride; 01266 d_ending_row_number = stop; 01267 } 01268 01271 unsigned int 01272 Sequence::val2buf(void *, bool) 01273 { 01274 throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation."); 01275 return sizeof(Sequence); 01276 } 01277 01282 unsigned int 01283 Sequence::buf2val(void **) 01284 { 01285 throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()"); 01286 return sizeof(Sequence); 01287 } 01288 01289 #if FILE_METHODS 01290 void 01291 Sequence::print_one_row(FILE *out, int row, string space, 01292 bool print_row_num) 01293 { 01294 if (print_row_num) 01295 fprintf(out, "\n%s%d: ", space.c_str(), row) ; 01296 01297 fprintf(out, "{ ") ; 01298 01299 int elements = element_count() - 1; 01300 int j; 01301 BaseType *bt_ptr; 01302 // Print first N-1 elements of the row. 01303 for (j = 0; j < elements; ++j) { 01304 bt_ptr = var_value(row, j); 01305 if (bt_ptr) { // data 01306 if (bt_ptr->type() == dods_sequence_c) 01307 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01308 (out, space + " ", false, print_row_num); 01309 else 01310 bt_ptr->print_val(out, space, false); 01311 fprintf(out, ", ") ; 01312 } 01313 } 01314 01315 // Print Nth element; end with a `}.' 01316 bt_ptr = var_value(row, j); 01317 if (bt_ptr) { // data 01318 if (bt_ptr->type() == dods_sequence_c) 01319 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01320 (out, space + " ", false, print_row_num); 01321 else 01322 bt_ptr->print_val(out, space, false); 01323 } 01324 01325 fprintf(out, " }") ; 01326 } 01327 #endif 01328 01329 void 01330 Sequence::print_one_row(ostream &out, int row, string space, 01331 bool print_row_num) 01332 { 01333 if (print_row_num) 01334 out << "\n" << space << row << ": " ; 01335 01336 out << "{ " ; 01337 01338 int elements = element_count(); 01339 int j = 0; 01340 BaseType *bt_ptr = 0; 01341 01342 // This version of print_one_row() works for both data read with 01343 // deserialize(), where each variable is assumed to have valid data, and 01344 // intern_data(), where some/many variables do not. Because of that, it's 01345 // not correct to assume that all of the elements will be printed, which 01346 // is what the old code did. 01347 // Print the first value 01348 while (j < elements && !bt_ptr) { 01349 bt_ptr = var_value(row, j++); 01350 if (bt_ptr) { // data 01351 if (bt_ptr->type() == dods_sequence_c) 01352 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01353 (out, space + " ", false, print_row_num); 01354 else 01355 bt_ptr->print_val(out, space, false); 01356 } 01357 } 01358 01359 // Print the remaining values 01360 while (j < elements) { 01361 bt_ptr = var_value(row, j++); 01362 if (bt_ptr) { // data 01363 out << ", "; 01364 if (bt_ptr->type() == dods_sequence_c) 01365 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01366 (out, space + " ", false, print_row_num); 01367 else 01368 bt_ptr->print_val(out, space, false); 01369 } 01370 } 01371 01372 out << " }" ; 01373 } 01374 01375 #if FILE_METHODS 01376 void 01377 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, 01378 bool print_row_numbers) 01379 { 01380 if (print_decl_p) { 01381 print_decl(out, space, false); 01382 fprintf(out, " = ") ; 01383 } 01384 01385 fprintf(out, "{ ") ; 01386 01387 int rows = number_of_rows() - 1; 01388 int i; 01389 for (i = 0; i < rows; ++i) { 01390 print_one_row(out, i, space, print_row_numbers); 01391 fprintf(out, ", ") ; 01392 } 01393 print_one_row(out, i, space, print_row_numbers); 01394 01395 fprintf(out, " }") ; 01396 01397 if (print_decl_p) 01398 fprintf(out, ";\n") ; 01399 } 01400 #endif 01401 01402 void 01403 Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, 01404 bool print_row_numbers) 01405 { 01406 if (print_decl_p) { 01407 print_decl(out, space, false); 01408 out << " = " ; 01409 } 01410 01411 out << "{ " ; 01412 01413 int rows = number_of_rows() - 1; 01414 int i; 01415 for (i = 0; i < rows; ++i) { 01416 print_one_row(out, i, space, print_row_numbers); 01417 out << ", " ; 01418 } 01419 print_one_row(out, i, space, print_row_numbers); 01420 01421 out << " }" ; 01422 01423 if (print_decl_p) 01424 out << ";\n" ; 01425 } 01426 01427 #if FILE_METHODS 01428 void 01429 Sequence::print_val(FILE *out, string space, bool print_decl_p) 01430 { 01431 print_val_by_rows(out, space, print_decl_p, false); 01432 } 01433 #endif 01434 01435 void 01436 Sequence::print_val(ostream &out, string space, bool print_decl_p) 01437 { 01438 print_val_by_rows(out, space, print_decl_p, false); 01439 } 01440 01441 01442 bool 01443 Sequence::check_semantics(string &msg, bool all) 01444 { 01445 if (!BaseType::check_semantics(msg)) 01446 return false; 01447 01448 if (!unique_names(_vars, name(), type_name(), msg)) 01449 return false; 01450 01451 if (all) 01452 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 01453 if (!(*i)->check_semantics(msg, true)) { 01454 return false; 01455 } 01456 } 01457 01458 return true; 01459 } 01460 01461 void 01462 Sequence::set_leaf_p(bool state) 01463 { 01464 d_leaf_sequence = state; 01465 } 01466 01467 bool 01468 Sequence::is_leaf_sequence() 01469 { 01470 return d_leaf_sequence; 01471 } 01472 01497 void 01498 Sequence::set_leaf_sequence(int lvl) 01499 { 01500 bool has_child_sequence = false; 01501 01502 if (lvl == 1) d_top_most = true; 01503 01504 DBG2(cerr << "Processing sequence " << name() << endl); 01505 01506 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 01507 // About the test for send_p(): Only descend into a sequence if it has 01508 // fields that might be sent. Thus if, in a two-level sequence, nothing 01509 // in the lower level is to be sent, the upper level is marked as the 01510 // leaf sequence. This ensures that values _will_ be sent (see the comment 01511 // in serialize_leaf() and serialize_parent_part_one()). 01512 if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) { 01513 if (has_child_sequence) 01514 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator."); 01515 01516 has_child_sequence = true; 01517 dynamic_cast<Sequence&>(**iter).set_leaf_sequence(++lvl); 01518 } 01519 else if ((*iter)->type() == dods_structure_c) { 01520 dynamic_cast<Structure&>(**iter).set_leaf_sequence(lvl); 01521 } 01522 } 01523 01524 if (!has_child_sequence) 01525 set_leaf_p(true); 01526 else 01527 set_leaf_p(false); 01528 01529 DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl); 01530 } 01531 01540 void 01541 Sequence::dump(ostream &strm) const 01542 { 01543 strm << DapIndent::LMarg << "Sequence::dump - (" 01544 << (void *)this << ")" << endl ; 01545 DapIndent::Indent() ; 01546 Constructor::dump(strm) ; 01547 strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number 01548 << endl ; 01549 strm << DapIndent::LMarg << "bracket notation information:" << endl ; 01550 DapIndent::Indent() ; 01551 strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number 01552 << endl ; 01553 strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ; 01554 strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number 01555 << endl ; 01556 DapIndent::UnIndent() ; 01557 01558 strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ; 01559 strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ; 01560 strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence 01561 << endl ; 01562 strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most 01563 << endl ; 01564 DapIndent::UnIndent() ; 01565 } 01566 01567 } // namespace libdap 01568